bb5644cbbceeaa00ffb3f1801dd9f07738411545
[libtar.git] / libtar / libtar.c
blobbb5644cbbceeaa00ffb3f1801dd9f07738411545
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>
20 #include <stdlib.h>
22 #ifdef STDC_HEADERS
23 # include <string.h>
24 #endif
26 #ifdef HAVE_UNISTD_H
27 # include <unistd.h>
28 #endif
30 #ifdef DEBUG
31 # include <signal.h>
32 #endif
34 #ifdef HAVE_LIBZ
35 # include <zlib.h>
36 #endif
38 #include <compat.h>
41 char *progname;
42 int verbose = 0;
43 int use_gnu = 0;
45 #ifdef DEBUG
46 void
47 segv_handler(int sig)
49 puts("OOPS! Caught SIGSEGV, bailing out...");
50 fflush(stdout);
51 fflush(stderr);
53 #endif
56 #ifdef HAVE_LIBZ
58 int use_zlib = 0;
60 int
61 gzopen_frontend(char *pathname, int oflags, int mode)
63 char *gzoflags;
64 gzFile gzf;
65 int fd;
67 switch (oflags & O_ACCMODE)
69 case O_WRONLY:
70 gzoflags = "wb";
71 break;
72 case O_RDONLY:
73 gzoflags = "rb";
74 break;
75 default:
76 case O_RDWR:
77 errno = EINVAL;
78 return -1;
81 fd = open(pathname, oflags, mode);
82 if (fd == -1)
83 return -1;
85 if ((oflags & O_CREAT) && fchmod(fd, mode))
87 close(fd);
88 return -1;
91 gzf = gzdopen(fd, gzoflags);
92 if (!gzf)
94 errno = ENOMEM;
95 return -1;
98 /* This is a bad thing to do on big-endian lp64 systems, where the
99 size and placement of integers is different than pointers.
100 However, to fix the problem 4 wrapper functions would be needed and
101 an extra bit of data associating GZF with the wrapper functions. */
102 return (int)gzf;
105 tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t) gzclose,
106 (readfunc_t) gzread, (writefunc_t) gzwrite
109 #endif /* HAVE_LIBZ */
113 create(char *tarfile, char *rootdir, libtar_list_t *l)
115 TAR *t;
116 char *pathname;
117 char buf[MAXPATHLEN];
118 libtar_listptr_t lp;
120 if (tar_open(&t, tarfile,
121 #ifdef HAVE_LIBZ
122 (use_zlib ? &gztype : NULL),
123 #else
124 NULL,
125 #endif
126 O_WRONLY | O_CREAT, 0644,
127 (verbose ? TAR_VERBOSE : 0)
128 | (use_gnu ? TAR_GNU : 0)) == -1)
130 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
131 return -1;
134 libtar_listptr_reset(&lp);
135 while (libtar_list_next(l, &lp) != 0)
137 pathname = (char *)libtar_listptr_data(&lp);
138 if (pathname[0] != '/' && rootdir != NULL)
139 snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname);
140 else
141 strlcpy(buf, pathname, sizeof(buf));
142 if (tar_append_tree(t, buf, pathname) != 0)
144 fprintf(stderr,
145 "tar_append_tree(\"%s\", \"%s\"): %s\n", buf,
146 pathname, strerror(errno));
147 tar_close(t);
148 return -1;
152 if (tar_append_eof(t) != 0)
154 fprintf(stderr, "tar_append_eof(): %s\n", strerror(errno));
155 tar_close(t);
156 return -1;
159 if (tar_close(t) != 0)
161 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
162 return -1;
165 return 0;
170 list(char *tarfile)
172 TAR *t;
173 int i;
175 if (tar_open(&t, tarfile,
176 #ifdef HAVE_LIBZ
177 (use_zlib ? &gztype : NULL),
178 #else
179 NULL,
180 #endif
181 O_RDONLY, 0,
182 (verbose ? TAR_VERBOSE : 0)
183 | (use_gnu ? TAR_GNU : 0)) == -1)
185 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
186 return -1;
189 while ((i = th_read(t)) == 0)
191 th_print_long_ls(t);
192 #ifdef DEBUG
193 th_print(t);
194 #endif
195 if (TH_ISREG(t) && tar_skip_regfile(t) != 0)
197 fprintf(stderr, "tar_skip_regfile(): %s\n",
198 strerror(errno));
199 return -1;
203 #ifdef DEBUG
204 printf("th_read() returned %d\n", i);
205 printf("EOF mark encountered after %ld bytes\n",
206 # ifdef HAVE_LIBZ
207 (use_zlib
208 ? gzseek((gzFile) t->fd, 0, SEEK_CUR)
210 # endif
211 lseek(t->fd, 0, SEEK_CUR)
212 # ifdef HAVE_LIBZ
214 # endif
216 #endif
218 if (tar_close(t) != 0)
220 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
221 return -1;
224 return 0;
229 extract(char *tarfile, char *rootdir)
231 TAR *t;
233 #ifdef DEBUG
234 puts("opening tarfile...");
235 #endif
236 if (tar_open(&t, tarfile,
237 #ifdef HAVE_LIBZ
238 (use_zlib ? &gztype : NULL),
239 #else
240 NULL,
241 #endif
242 O_RDONLY, 0,
243 (verbose ? TAR_VERBOSE : 0)
244 | (use_gnu ? TAR_GNU : 0)) == -1)
246 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
247 return -1;
250 #ifdef DEBUG
251 puts("extracting tarfile...");
252 #endif
253 if (tar_extract_all(t, rootdir) != 0)
255 fprintf(stderr, "tar_extract_all(): %s\n", strerror(errno));
256 return -1;
259 #ifdef DEBUG
260 puts("closing tarfile...");
261 #endif
262 if (tar_close(t) != 0)
264 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
265 return -1;
268 return 0;
272 void
273 usage()
275 printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n",
276 progname);
277 printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n",
278 progname);
279 exit(-1);
283 #define MODE_LIST 1
284 #define MODE_CREATE 2
285 #define MODE_EXTRACT 3
288 main(int argc, char *argv[])
290 char *tarfile = NULL;
291 char *rootdir = NULL;
292 int c;
293 int mode = 0;
294 libtar_list_t *l;
296 progname = basename(argv[0]);
298 while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1)
299 switch (c)
301 case 'V':
302 printf("libtar %s by Mark D. Roth <roth@uiuc.edu>\n",
303 libtar_version);
304 break;
305 case 'C':
306 rootdir = strdup(optarg);
307 break;
308 case 'v':
309 verbose = 1;
310 break;
311 case 'g':
312 use_gnu = 1;
313 break;
314 case 'c':
315 if (mode)
316 usage();
317 mode = MODE_CREATE;
318 break;
319 case 'x':
320 if (mode)
321 usage();
322 mode = MODE_EXTRACT;
323 break;
324 case 't':
325 if (mode)
326 usage();
327 mode = MODE_LIST;
328 break;
329 #ifdef HAVE_LIBZ
330 case 'z':
331 use_zlib = 1;
332 break;
333 #endif /* HAVE_LIBZ */
334 default:
335 usage();
338 if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1)))
340 #ifdef DEBUG
341 printf("argc - optind == %d\tmode == %d\n", argc - optind,
342 mode);
343 #endif
344 usage();
347 #ifdef DEBUG
348 signal(SIGSEGV, segv_handler);
349 #endif
351 switch (mode)
353 case MODE_EXTRACT:
354 return extract(argv[optind], rootdir);
355 case MODE_CREATE:
356 tarfile = argv[optind];
357 l = libtar_list_new(LIST_QUEUE, NULL);
358 for (c = optind + 1; c < argc; c++)
359 libtar_list_add(l, argv[c]);
360 return create(tarfile, rootdir, l);
361 case MODE_LIST:
362 return list(argv[optind]);
363 default:
364 break;
367 /* NOTREACHED */
368 return -2;