Updated formatting of documentation plus a little reorganization.
[cmake.git] / Utilities / cmtar / libtar.c
blob0d031b7f8b03c948a1b8d7f03429138b99094b39
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 # ifdef HAVE_SYS_PARAM_H
23 # include <sys/param.h>
24 # endif
25 #endif
27 #ifdef STDC_HEADERS
28 # include <string.h>
29 #endif
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 # include <stdlib.h>
34 #endif
36 #ifdef DEBUG
37 # include <signal.h>
38 #endif
40 #include CMTAR_ZLIB_HEADER
42 #include <libtar/compat.h>
45 char *progname;
46 int verbose = 0;
47 int use_gnu = 0;
49 #ifdef DEBUG
50 void
51 segv_handler(int sig)
53 puts("OOPS! Caught SIGSEGV, bailing out...");
54 fflush(stdout);
55 fflush(stderr);
57 #endif
60 #ifdef HAVE_LIBZ
62 int use_zlib = 0;
64 struct gzStruct
66 gzFile* GZFile;
68 struct gzStruct GZStruct;
69 #if defined ( _MSC_VER) || defined(__WATCOMC__)
70 #include <io.h>
71 //Yogi: hack. this should work on windows where there is no O_ACCMODE defined
72 #ifndef O_ACCMODE
73 # define O_ACCMODE 0x0003
74 #endif
75 #endif
77 static int libtar_gzopen(void* call_data, const char *pathname,
78 int oflags, mode_t mode)
80 char *gzoflags;
81 int fd;
82 struct gzStruct* gzf = (struct gzStruct*)call_data;
84 switch (oflags & O_ACCMODE)
86 case O_WRONLY:
87 gzoflags = "wb";
88 break;
89 case O_RDONLY:
90 gzoflags = "rb";
91 break;
92 default:
93 case O_RDWR:
94 errno = EINVAL;
95 return -1;
98 fd = open(pathname, oflags, mode);
99 if (fd == -1)
101 return -1;
104 #if defined(__BEOS__) && !defined(__ZETA__) /* no fchmod on BeOS...do pathname instead. */
105 if ((oflags & O_CREAT) && chmod(pathname, mode & 07777))
107 return -1;
109 #elif !defined(_WIN32) || defined(__CYGWIN__)
110 if ((oflags & O_CREAT) && fchmod(fd, mode & 07777))
112 return -1;
114 #endif
116 gzf->GZFile = gzdopen(fd, gzoflags);
117 if (!gzf->GZFile)
119 errno = ENOMEM;
120 return -1;
123 return fd;
126 static int libtar_gzclose(void* call_data)
128 struct gzStruct* gzf = (struct gzStruct*)call_data;
129 return gzclose(gzf->GZFile);
132 static ssize_t libtar_gzread(void* call_data, void* buf, size_t count)
134 struct gzStruct* gzf = (struct gzStruct*)call_data;
135 return gzread(gzf->GZFile, buf, (unsigned int)count);
138 static ssize_t libtar_gzwrite(void* call_data, const void* buf, size_t count)
140 struct gzStruct* gzf = (struct gzStruct*)call_data;
141 return gzwrite(gzf->GZFile, (void*)buf, (unsigned int)count);
144 tartype_t gztype = {
145 libtar_gzopen,
146 libtar_gzclose,
147 libtar_gzread,
148 libtar_gzwrite,
149 &GZStruct
152 #endif /* HAVE_LIBZ */
155 static int
156 create(char *tarfile, char *rootdir, libtar_list_t *l)
158 TAR *t;
159 char *pathname;
160 char buf[TAR_MAXPATHLEN];
161 libtar_listptr_t lp;
163 if (tar_open(&t, tarfile,
164 #ifdef HAVE_LIBZ
165 (use_zlib ? &gztype : NULL),
166 #else
167 NULL,
168 #endif
169 O_WRONLY | O_CREAT, 0644,
170 (verbose ? TAR_VERBOSE : 0)
171 | (use_gnu ? TAR_GNU : 0)) == -1)
173 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
174 return -1;
177 libtar_listptr_reset(&lp);
178 while (libtar_list_next(l, &lp) != 0)
180 pathname = (char *)libtar_listptr_data(&lp);
181 if (pathname[0] != '/' && rootdir != NULL)
182 snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname);
183 else
184 strlcpy(buf, pathname, sizeof(buf));
185 if (tar_append_tree(t, buf, pathname) != 0)
187 fprintf(stderr,
188 "tar_append_tree(\"%s\", \"%s\"): %s\n", buf,
189 pathname, strerror(errno));
190 tar_close(t);
191 return -1;
195 if (tar_append_eof(t) != 0)
197 fprintf(stderr, "tar_append_eof(): %s\n", strerror(errno));
198 tar_close(t);
199 return -1;
202 if (tar_close(t) != 0)
204 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
205 return -1;
208 return 0;
212 static int
213 list(char *tarfile)
215 TAR *t;
216 int i;
218 if (tar_open(&t, tarfile,
219 #ifdef HAVE_LIBZ
220 (use_zlib ? &gztype : NULL),
221 #else
222 NULL,
223 #endif
224 O_RDONLY, 0,
225 (verbose ? TAR_VERBOSE : 0)
226 | (use_gnu ? TAR_GNU : 0)) == -1)
228 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
229 return -1;
232 while ((i = th_read(t)) == 0)
234 th_print_long_ls(t);
235 #ifdef DEBUG
236 th_print(t);
237 #endif
238 if (TH_ISREG(t) && tar_skip_regfile(t) != 0)
240 fprintf(stderr, "tar_skip_regfile(): %s\n",
241 strerror(errno));
242 return -1;
246 #ifdef DEBUG
247 printf("th_read() returned %d\n", i);
248 printf("EOF mark encountered after %ld bytes\n",
249 # ifdef HAVE_LIBZ
250 (use_zlib
251 ? gzseek((gzFile) t->fd, 0, SEEK_CUR)
253 # endif
254 lseek(t->fd, 0, SEEK_CUR)
255 # ifdef HAVE_LIBZ
257 # endif
259 #endif
261 if (tar_close(t) != 0)
263 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
264 return -1;
266 (void)i;
268 return 0;
272 static int
273 extract(char *tarfile, char *rootdir)
275 TAR *t;
277 #ifdef DEBUG
278 puts("opening tarfile...");
279 #endif
280 if (tar_open(&t, tarfile,
281 #ifdef HAVE_LIBZ
282 (use_zlib ? &gztype : NULL),
283 #else
284 NULL,
285 #endif
286 O_RDONLY, 0,
287 (verbose ? TAR_VERBOSE : 0)
288 | (use_gnu ? TAR_GNU : 0)) == -1)
290 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
291 return -1;
294 #ifdef DEBUG
295 puts("extracting tarfile...");
296 #endif
297 if (tar_extract_all(t, rootdir) != 0)
299 fprintf(stderr, "tar_extract_all(): %s\n", strerror(errno));
300 return -1;
303 #ifdef DEBUG
304 puts("closing tarfile...");
305 #endif
306 if (tar_close(t) != 0)
308 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
309 return -1;
312 return 0;
316 static void
317 usage()
319 printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n",
320 progname);
321 printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n",
322 progname);
323 exit(-1);
327 #define MODE_LIST 1
328 #define MODE_CREATE 2
329 #define MODE_EXTRACT 3
332 main(int argc, char *argv[])
334 char* tarfile;
335 char *rootdir = NULL;
336 int c;
337 int mode;
338 libtar_list_t *l;
339 #if defined(_WIN32) && !defined(__CYGWIN__)
340 int optind;
341 #endif
342 progname = basename(argv[0]);
344 #if !defined(_WIN32) || defined(__CYGWIN__)
345 mode = 0;
346 while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1)
347 switch (c)
349 case 'V':
350 printf("libtar %s by Mark D. Roth <roth@uiuc.edu>\n",
351 libtar_version);
352 break;
353 case 'C':
354 rootdir = strdup(optarg);
355 break;
356 case 'v':
357 verbose = 1;
358 break;
359 case 'g':
360 use_gnu = 1;
361 break;
362 case 'c':
363 if (mode)
364 usage();
365 mode = MODE_CREATE;
366 break;
367 case 'x':
368 if (mode)
369 usage();
370 mode = MODE_EXTRACT;
371 break;
372 case 't':
373 if (mode)
374 usage();
375 mode = MODE_LIST;
376 break;
377 #ifdef HAVE_LIBZ
378 case 'z':
379 use_zlib = 1;
380 break;
381 #endif /* HAVE_LIBZ */
382 default:
383 usage();
385 if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1)))
387 #ifdef DEBUG
388 printf("argc - optind == %d\tmode == %d\n", argc - optind,
389 mode);
390 #endif
391 usage();
394 #else
395 mode = MODE_EXTRACT;
396 use_zlib=1;
397 optind = 1;
398 #endif
400 #ifdef DEBUG
401 signal(SIGSEGV, segv_handler);
402 #endif
404 switch (mode)
406 case MODE_EXTRACT:
407 return extract(argv[optind], rootdir);
408 case MODE_CREATE:
409 tarfile = argv[optind];
410 l = libtar_list_new(LIST_QUEUE, NULL);
411 for (c = optind + 1; c < argc; c++)
412 libtar_list_add(l, argv[c]);
413 return create(tarfile, rootdir, l);
414 case MODE_LIST:
415 return list(argv[optind]);
416 default:
417 break;
420 /* NOTREACHED */
421 return -2;