libtar-1.2.11 tarball sources, taken from Debian's orig tar
[libtar.git] / libtar / libtar.c
blob947934b5618c435a80511beb1c198ad7d5c3abdf
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
13 #include <config.h>
14 #include <libtar.h>
16 #include <stdio.h>
17 #include <fcntl.h>
18 #include <errno.h>
19 #include <sys/param.h>
21 #ifdef STDC_HEADERS
22 # include <string.h>
23 #endif
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
29 #ifdef DEBUG
30 # include <signal.h>
31 #endif
33 #ifdef HAVE_LIBZ
34 # include <zlib.h>
35 #endif
37 #include <compat.h>
40 char *progname;
41 int verbose = 0;
42 int use_gnu = 0;
44 #ifdef DEBUG
45 void
46 segv_handler(int sig)
48 puts("OOPS! Caught SIGSEGV, bailing out...");
49 fflush(stdout);
50 fflush(stderr);
52 #endif
55 #ifdef HAVE_LIBZ
57 int use_zlib = 0;
59 int
60 gzopen_frontend(char *pathname, int oflags, int mode)
62 char *gzoflags;
63 gzFile gzf;
64 int fd;
66 switch (oflags & O_ACCMODE)
68 case O_WRONLY:
69 gzoflags = "wb";
70 break;
71 case O_RDONLY:
72 gzoflags = "rb";
73 break;
74 default:
75 case O_RDWR:
76 errno = EINVAL;
77 return -1;
80 fd = open(pathname, oflags, mode);
81 if (fd == -1)
82 return -1;
84 if ((oflags & O_CREAT) && fchmod(fd, mode))
85 return -1;
87 gzf = gzdopen(fd, gzoflags);
88 if (!gzf)
90 errno = ENOMEM;
91 return -1;
94 return (int)gzf;
97 tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t) gzclose,
98 (readfunc_t) gzread, (writefunc_t) gzwrite
101 #endif /* HAVE_LIBZ */
105 create(char *tarfile, char *rootdir, libtar_list_t *l)
107 TAR *t;
108 char *pathname;
109 char buf[MAXPATHLEN];
110 libtar_listptr_t lp;
112 if (tar_open(&t, tarfile,
113 #ifdef HAVE_LIBZ
114 (use_zlib ? &gztype : NULL),
115 #else
116 NULL,
117 #endif
118 O_WRONLY | O_CREAT, 0644,
119 (verbose ? TAR_VERBOSE : 0)
120 | (use_gnu ? TAR_GNU : 0)) == -1)
122 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
123 return -1;
126 libtar_listptr_reset(&lp);
127 while (libtar_list_next(l, &lp) != 0)
129 pathname = (char *)libtar_listptr_data(&lp);
130 if (pathname[0] != '/' && rootdir != NULL)
131 snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname);
132 else
133 strlcpy(buf, pathname, sizeof(buf));
134 if (tar_append_tree(t, buf, pathname) != 0)
136 fprintf(stderr,
137 "tar_append_tree(\"%s\", \"%s\"): %s\n", buf,
138 pathname, strerror(errno));
139 tar_close(t);
140 return -1;
144 if (tar_append_eof(t) != 0)
146 fprintf(stderr, "tar_append_eof(): %s\n", strerror(errno));
147 tar_close(t);
148 return -1;
151 if (tar_close(t) != 0)
153 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
154 return -1;
157 return 0;
162 list(char *tarfile)
164 TAR *t;
165 int i;
167 if (tar_open(&t, tarfile,
168 #ifdef HAVE_LIBZ
169 (use_zlib ? &gztype : NULL),
170 #else
171 NULL,
172 #endif
173 O_RDONLY, 0,
174 (verbose ? TAR_VERBOSE : 0)
175 | (use_gnu ? TAR_GNU : 0)) == -1)
177 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
178 return -1;
181 while ((i = th_read(t)) == 0)
183 th_print_long_ls(t);
184 #ifdef DEBUG
185 th_print(t);
186 #endif
187 if (TH_ISREG(t) && tar_skip_regfile(t) != 0)
189 fprintf(stderr, "tar_skip_regfile(): %s\n",
190 strerror(errno));
191 return -1;
195 #ifdef DEBUG
196 printf("th_read() returned %d\n", i);
197 printf("EOF mark encountered after %ld bytes\n",
198 # ifdef HAVE_LIBZ
199 (use_zlib
200 ? gzseek((gzFile) t->fd, 0, SEEK_CUR)
202 # endif
203 lseek(t->fd, 0, SEEK_CUR)
204 # ifdef HAVE_LIBZ
206 # endif
208 #endif
210 if (tar_close(t) != 0)
212 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
213 return -1;
216 return 0;
221 extract(char *tarfile, char *rootdir)
223 TAR *t;
225 #ifdef DEBUG
226 puts("opening tarfile...");
227 #endif
228 if (tar_open(&t, tarfile,
229 #ifdef HAVE_LIBZ
230 (use_zlib ? &gztype : NULL),
231 #else
232 NULL,
233 #endif
234 O_RDONLY, 0,
235 (verbose ? TAR_VERBOSE : 0)
236 | (use_gnu ? TAR_GNU : 0)) == -1)
238 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
239 return -1;
242 #ifdef DEBUG
243 puts("extracting tarfile...");
244 #endif
245 if (tar_extract_all(t, rootdir) != 0)
247 fprintf(stderr, "tar_extract_all(): %s\n", strerror(errno));
248 return -1;
251 #ifdef DEBUG
252 puts("closing tarfile...");
253 #endif
254 if (tar_close(t) != 0)
256 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
257 return -1;
260 return 0;
264 void
265 usage()
267 printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n",
268 progname);
269 printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n",
270 progname);
271 exit(-1);
275 #define MODE_LIST 1
276 #define MODE_CREATE 2
277 #define MODE_EXTRACT 3
280 main(int argc, char *argv[])
282 char *tarfile = NULL;
283 char *rootdir = NULL;
284 int c;
285 int mode = 0;
286 libtar_list_t *l;
288 progname = basename(argv[0]);
290 while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1)
291 switch (c)
293 case 'V':
294 printf("libtar %s by Mark D. Roth <roth@uiuc.edu>\n",
295 libtar_version);
296 break;
297 case 'C':
298 rootdir = strdup(optarg);
299 break;
300 case 'v':
301 verbose = 1;
302 break;
303 case 'g':
304 use_gnu = 1;
305 break;
306 case 'c':
307 if (mode)
308 usage();
309 mode = MODE_CREATE;
310 break;
311 case 'x':
312 if (mode)
313 usage();
314 mode = MODE_EXTRACT;
315 break;
316 case 't':
317 if (mode)
318 usage();
319 mode = MODE_LIST;
320 break;
321 #ifdef HAVE_LIBZ
322 case 'z':
323 use_zlib = 1;
324 break;
325 #endif /* HAVE_LIBZ */
326 default:
327 usage();
330 if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1)))
332 #ifdef DEBUG
333 printf("argc - optind == %d\tmode == %d\n", argc - optind,
334 mode);
335 #endif
336 usage();
339 #ifdef DEBUG
340 signal(SIGSEGV, segv_handler);
341 #endif
343 switch (mode)
345 case MODE_EXTRACT:
346 return extract(argv[optind], rootdir);
347 case MODE_CREATE:
348 tarfile = argv[optind];
349 l = libtar_list_new(LIST_QUEUE, NULL);
350 for (c = optind + 1; c < argc; c++)
351 libtar_list_add(l, argv[c]);
352 return create(tarfile, rootdir, l);
353 case MODE_LIST:
354 return list(argv[optind]);
355 default:
356 break;
359 /* NOTREACHED */
360 return -2;