9fa92b20c02f956d3f01dcf4a45278d8a37a63b2
[libtar.git] / libtar / libtar.c
blob9fa92b20c02f956d3f01dcf4a45278d8a37a63b2
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))
86 return -1;
88 gzf = gzdopen(fd, gzoflags);
89 if (!gzf)
91 errno = ENOMEM;
92 return -1;
95 /* This is a bad thing to do on big-endian lp64 systems, where the
96 size and placement of integers is different than pointers.
97 However, to fix the problem 4 wrapper functions would be needed and
98 an extra bit of data associating GZF with the wrapper functions. */
99 return (int)gzf;
102 tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t) gzclose,
103 (readfunc_t) gzread, (writefunc_t) gzwrite
106 #endif /* HAVE_LIBZ */
110 create(char *tarfile, char *rootdir, libtar_list_t *l)
112 TAR *t;
113 char *pathname;
114 char buf[MAXPATHLEN];
115 libtar_listptr_t lp;
117 if (tar_open(&t, tarfile,
118 #ifdef HAVE_LIBZ
119 (use_zlib ? &gztype : NULL),
120 #else
121 NULL,
122 #endif
123 O_WRONLY | O_CREAT, 0644,
124 (verbose ? TAR_VERBOSE : 0)
125 | (use_gnu ? TAR_GNU : 0)) == -1)
127 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
128 return -1;
131 libtar_listptr_reset(&lp);
132 while (libtar_list_next(l, &lp) != 0)
134 pathname = (char *)libtar_listptr_data(&lp);
135 if (pathname[0] != '/' && rootdir != NULL)
136 snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname);
137 else
138 strlcpy(buf, pathname, sizeof(buf));
139 if (tar_append_tree(t, buf, pathname) != 0)
141 fprintf(stderr,
142 "tar_append_tree(\"%s\", \"%s\"): %s\n", buf,
143 pathname, strerror(errno));
144 tar_close(t);
145 return -1;
149 if (tar_append_eof(t) != 0)
151 fprintf(stderr, "tar_append_eof(): %s\n", strerror(errno));
152 tar_close(t);
153 return -1;
156 if (tar_close(t) != 0)
158 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
159 return -1;
162 return 0;
167 list(char *tarfile)
169 TAR *t;
170 int i;
172 if (tar_open(&t, tarfile,
173 #ifdef HAVE_LIBZ
174 (use_zlib ? &gztype : NULL),
175 #else
176 NULL,
177 #endif
178 O_RDONLY, 0,
179 (verbose ? TAR_VERBOSE : 0)
180 | (use_gnu ? TAR_GNU : 0)) == -1)
182 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
183 return -1;
186 while ((i = th_read(t)) == 0)
188 th_print_long_ls(t);
189 #ifdef DEBUG
190 th_print(t);
191 #endif
192 if (TH_ISREG(t) && tar_skip_regfile(t) != 0)
194 fprintf(stderr, "tar_skip_regfile(): %s\n",
195 strerror(errno));
196 return -1;
200 #ifdef DEBUG
201 printf("th_read() returned %d\n", i);
202 printf("EOF mark encountered after %ld bytes\n",
203 # ifdef HAVE_LIBZ
204 (use_zlib
205 ? gzseek((gzFile) t->fd, 0, SEEK_CUR)
207 # endif
208 lseek(t->fd, 0, SEEK_CUR)
209 # ifdef HAVE_LIBZ
211 # endif
213 #endif
215 if (tar_close(t) != 0)
217 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
218 return -1;
221 return 0;
226 extract(char *tarfile, char *rootdir)
228 TAR *t;
230 #ifdef DEBUG
231 puts("opening tarfile...");
232 #endif
233 if (tar_open(&t, tarfile,
234 #ifdef HAVE_LIBZ
235 (use_zlib ? &gztype : NULL),
236 #else
237 NULL,
238 #endif
239 O_RDONLY, 0,
240 (verbose ? TAR_VERBOSE : 0)
241 | (use_gnu ? TAR_GNU : 0)) == -1)
243 fprintf(stderr, "tar_open(): %s\n", strerror(errno));
244 return -1;
247 #ifdef DEBUG
248 puts("extracting tarfile...");
249 #endif
250 if (tar_extract_all(t, rootdir) != 0)
252 fprintf(stderr, "tar_extract_all(): %s\n", strerror(errno));
253 return -1;
256 #ifdef DEBUG
257 puts("closing tarfile...");
258 #endif
259 if (tar_close(t) != 0)
261 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
262 return -1;
265 return 0;
269 void
270 usage()
272 printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n",
273 progname);
274 printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n",
275 progname);
276 exit(-1);
280 #define MODE_LIST 1
281 #define MODE_CREATE 2
282 #define MODE_EXTRACT 3
285 main(int argc, char *argv[])
287 char *tarfile = NULL;
288 char *rootdir = NULL;
289 int c;
290 int mode = 0;
291 libtar_list_t *l;
293 progname = basename(argv[0]);
295 while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1)
296 switch (c)
298 case 'V':
299 printf("libtar %s by Mark D. Roth <roth@uiuc.edu>\n",
300 libtar_version);
301 break;
302 case 'C':
303 rootdir = strdup(optarg);
304 break;
305 case 'v':
306 verbose = 1;
307 break;
308 case 'g':
309 use_gnu = 1;
310 break;
311 case 'c':
312 if (mode)
313 usage();
314 mode = MODE_CREATE;
315 break;
316 case 'x':
317 if (mode)
318 usage();
319 mode = MODE_EXTRACT;
320 break;
321 case 't':
322 if (mode)
323 usage();
324 mode = MODE_LIST;
325 break;
326 #ifdef HAVE_LIBZ
327 case 'z':
328 use_zlib = 1;
329 break;
330 #endif /* HAVE_LIBZ */
331 default:
332 usage();
335 if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1)))
337 #ifdef DEBUG
338 printf("argc - optind == %d\tmode == %d\n", argc - optind,
339 mode);
340 #endif
341 usage();
344 #ifdef DEBUG
345 signal(SIGSEGV, segv_handler);
346 #endif
348 switch (mode)
350 case MODE_EXTRACT:
351 return extract(argv[optind], rootdir);
352 case MODE_CREATE:
353 tarfile = argv[optind];
354 l = libtar_list_new(LIST_QUEUE, NULL);
355 for (c = optind + 1; c < argc; c++)
356 libtar_list_add(l, argv[c]);
357 return create(tarfile, rootdir, l);
358 case MODE_LIST:
359 return list(argv[optind]);
360 default:
361 break;
364 /* NOTREACHED */
365 return -2;