ENH: make this work for older versions of OSX
[cmake.git] / Utilities / cmtar / libtar.c
blobb50934935ddfe8ed302b4ae30402fe10d0245df1
1 /*
2 ** Copyright 1998-2003 University of Illinois Board of Trustees
3 ** Copyright 1998-2003 Mark D. Roth
4 ** All rights reserved.
5 **
6 ** libtar.c - demo driver program for libtar
7 **
8 ** Mark D. Roth <roth@uiuc.edu>
9 ** Campus Information Technologies and Educational Services
10 ** University of Illinois at Urbana-Champaign
12 #include <libtar/config.h>
13 #include <libtar/libtar.h>
15 #include <stdio.h>
16 #include <fcntl.h>
17 #include <errno.h>
18 #if defined(_WIN32) && !defined(__CYGWIN__)
19 #include <libtar/compat.h>
20 #include <io.h>
21 #else
22 #include <sys/param.h>
23 #endif
25 #ifdef STDC_HEADERS
26 # include <string.h>
27 #endif
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 # include <stdlib.h>
32 #endif
34 #ifdef DEBUG
35 # include <signal.h>
36 #endif
38 #include CMTAR_ZLIB_HEADER
40 #include <libtar/compat.h>
43 char *progname;
44 int verbose = 0;
45 int use_gnu = 0;
47 #ifdef DEBUG
48 void
49 segv_handler(int sig)
51 puts("OOPS! Caught SIGSEGV, bailing out...");
52 fflush(stdout);
53 fflush(stderr);
55 #endif
58 #ifdef HAVE_LIBZ
60 int use_zlib = 0;
62 struct gzStruct
64 gzFile* GZFile;
66 struct gzStruct GZStruct;
67 #if defined ( _MSC_VER) || defined(__WATCOMC__)
68 #include <io.h>
69 //Yogi: hack. this should work on windows where there is no O_ACCMODE defined
70 #ifndef O_ACCMODE
71 # define O_ACCMODE 0x0003
72 #endif
73 #endif
75 static int libtar_gzopen(void* call_data, const char *pathname,
76 int oflags, mode_t mode)
78 char *gzoflags;
79 int fd;
80 struct gzStruct* gzf = (struct gzStruct*)call_data;
82 switch (oflags & O_ACCMODE)
84 case O_WRONLY:
85 gzoflags = "wb";
86 break;
87 case O_RDONLY:
88 gzoflags = "rb";
89 break;
90 default:
91 case O_RDWR:
92 errno = EINVAL;
93 return -1;
96 fd = open(pathname, oflags, mode);
97 if (fd == -1)
99 return -1;
102 #if defined(__BEOS__) && !defined(__ZETA__) /* no fchmod on BeOS...do pathname instead. */
103 if ((oflags & O_CREAT) && chmod(pathname, mode & 07777))
105 return -1;
107 #elif !defined(_WIN32) || defined(__CYGWIN__)
108 if ((oflags & O_CREAT) && fchmod(fd, mode & 07777))
110 return -1;
112 #endif
114 gzf->GZFile = gzdopen(fd, gzoflags);
115 if (!gzf->GZFile)
117 errno = ENOMEM;
118 return -1;
121 return fd;
124 static int libtar_gzclose(void* call_data)
126 struct gzStruct* gzf = (struct gzStruct*)call_data;
127 return gzclose(gzf->GZFile);
130 static ssize_t libtar_gzread(void* call_data, void* buf, size_t count)
132 struct gzStruct* gzf = (struct gzStruct*)call_data;
133 return gzread(gzf->GZFile, buf, (unsigned int)count);
136 static ssize_t libtar_gzwrite(void* call_data, const void* buf, size_t count)
138 struct gzStruct* gzf = (struct gzStruct*)call_data;
139 return gzwrite(gzf->GZFile, (void*)buf, (unsigned int)count);
142 tartype_t gztype = {
143 libtar_gzopen,
144 libtar_gzclose,
145 libtar_gzread,
146 libtar_gzwrite,
147 &GZStruct
150 #endif /* HAVE_LIBZ */
153 static int
154 create(char *tarfile, char *rootdir, libtar_list_t *l)
156 TAR *t;
157 char *pathname;
158 char buf[TAR_MAXPATHLEN];
159 libtar_listptr_t lp;
161 if (tar_open(&t, tarfile,
162 #ifdef HAVE_LIBZ
163 (use_zlib ? &gztype : NULL),
164 #else
165 NULL,
166 #endif
167 O_WRONLY | O_CREAT, 0644,
168 (verbose ? TAR_VERBOSE : 0)
169 | (use_gnu ? TAR_GNU : 0)) == -1)
171 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
172 return -1;
175 libtar_listptr_reset(&lp);
176 while (libtar_list_next(l, &lp) != 0)
178 pathname = (char *)libtar_listptr_data(&lp);
179 if (pathname[0] != '/' && rootdir != NULL)
180 snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname);
181 else
182 strlcpy(buf, pathname, sizeof(buf));
183 if (tar_append_tree(t, buf, pathname) != 0)
185 fprintf(stderr,
186 "tar_append_tree(\"%s\", \"%s\"): %s\n", buf,
187 pathname, strerror(errno));
188 tar_close(t);
189 return -1;
193 if (tar_append_eof(t) != 0)
195 fprintf(stderr, "tar_append_eof(): %s\n", strerror(errno));
196 tar_close(t);
197 return -1;
200 if (tar_close(t) != 0)
202 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
203 return -1;
206 return 0;
210 static int
211 list(char *tarfile)
213 TAR *t;
214 int i;
216 if (tar_open(&t, tarfile,
217 #ifdef HAVE_LIBZ
218 (use_zlib ? &gztype : NULL),
219 #else
220 NULL,
221 #endif
222 O_RDONLY, 0,
223 (verbose ? TAR_VERBOSE : 0)
224 | (use_gnu ? TAR_GNU : 0)) == -1)
226 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
227 return -1;
230 while ((i = th_read(t)) == 0)
232 th_print_long_ls(t);
233 #ifdef DEBUG
234 th_print(t);
235 #endif
236 if (TH_ISREG(t) && tar_skip_regfile(t) != 0)
238 fprintf(stderr, "tar_skip_regfile(): %s\n",
239 strerror(errno));
240 return -1;
244 #ifdef DEBUG
245 printf("th_read() returned %d\n", i);
246 printf("EOF mark encountered after %ld bytes\n",
247 # ifdef HAVE_LIBZ
248 (use_zlib
249 ? gzseek((gzFile) t->fd, 0, SEEK_CUR)
251 # endif
252 lseek(t->fd, 0, SEEK_CUR)
253 # ifdef HAVE_LIBZ
255 # endif
257 #endif
259 if (tar_close(t) != 0)
261 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
262 return -1;
264 (void)i;
266 return 0;
270 static int
271 extract(char *tarfile, char *rootdir)
273 TAR *t;
275 #ifdef DEBUG
276 puts("opening tarfile...");
277 #endif
278 if (tar_open(&t, tarfile,
279 #ifdef HAVE_LIBZ
280 (use_zlib ? &gztype : NULL),
281 #else
282 NULL,
283 #endif
284 O_RDONLY, 0,
285 (verbose ? TAR_VERBOSE : 0)
286 | (use_gnu ? TAR_GNU : 0)) == -1)
288 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
289 return -1;
292 #ifdef DEBUG
293 puts("extracting tarfile...");
294 #endif
295 if (tar_extract_all(t, rootdir) != 0)
297 fprintf(stderr, "tar_extract_all(): %s\n", strerror(errno));
298 return -1;
301 #ifdef DEBUG
302 puts("closing tarfile...");
303 #endif
304 if (tar_close(t) != 0)
306 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
307 return -1;
310 return 0;
314 static void
315 usage()
317 printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n",
318 progname);
319 printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n",
320 progname);
321 exit(-1);
325 #define MODE_LIST 1
326 #define MODE_CREATE 2
327 #define MODE_EXTRACT 3
330 main(int argc, char *argv[])
332 char* tarfile;
333 char *rootdir = NULL;
334 int c;
335 int mode;
336 libtar_list_t *l;
337 #if defined(_WIN32) && !defined(__CYGWIN__)
338 int optind;
339 #endif
340 progname = basename(argv[0]);
342 #if !defined(_WIN32) || defined(__CYGWIN__)
343 mode = 0;
344 while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1)
345 switch (c)
347 case 'V':
348 printf("libtar %s by Mark D. Roth <roth@uiuc.edu>\n",
349 libtar_version);
350 break;
351 case 'C':
352 rootdir = strdup(optarg);
353 break;
354 case 'v':
355 verbose = 1;
356 break;
357 case 'g':
358 use_gnu = 1;
359 break;
360 case 'c':
361 if (mode)
362 usage();
363 mode = MODE_CREATE;
364 break;
365 case 'x':
366 if (mode)
367 usage();
368 mode = MODE_EXTRACT;
369 break;
370 case 't':
371 if (mode)
372 usage();
373 mode = MODE_LIST;
374 break;
375 #ifdef HAVE_LIBZ
376 case 'z':
377 use_zlib = 1;
378 break;
379 #endif /* HAVE_LIBZ */
380 default:
381 usage();
383 if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1)))
385 #ifdef DEBUG
386 printf("argc - optind == %d\tmode == %d\n", argc - optind,
387 mode);
388 #endif
389 usage();
392 #else
393 mode = MODE_EXTRACT;
394 use_zlib=1;
395 optind = 1;
396 #endif
398 #ifdef DEBUG
399 signal(SIGSEGV, segv_handler);
400 #endif
402 switch (mode)
404 case MODE_EXTRACT:
405 return extract(argv[optind], rootdir);
406 case MODE_CREATE:
407 tarfile = argv[optind];
408 l = libtar_list_new(LIST_QUEUE, NULL);
409 for (c = optind + 1; c < argc; c++)
410 libtar_list_add(l, argv[c]);
411 return create(tarfile, rootdir, l);
412 case MODE_LIST:
413 return list(argv[optind]);
414 default:
415 break;
418 /* NOTREACHED */
419 return -2;