fix memleaks in libtar sample program
[libtar.git] / libtar / libtar.c
blob23f874103e31d7d56491cec6f99cddac71644492
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 tar_close(t);
257 return -1;
260 #ifdef DEBUG
261 puts("closing tarfile...");
262 #endif
263 if (tar_close(t) != 0)
265 fprintf(stderr, "tar_close(): %s\n", strerror(errno));
266 return -1;
269 return 0;
273 void
274 usage(void *rootdir)
276 printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n",
277 progname);
278 printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n",
279 progname);
280 free(rootdir);
281 exit(-1);
285 #define MODE_LIST 1
286 #define MODE_CREATE 2
287 #define MODE_EXTRACT 3
290 main(int argc, char *argv[])
292 char *tarfile = NULL;
293 char *rootdir = NULL;
294 int c;
295 int mode = 0;
296 libtar_list_t *l;
297 int return_code = -2;
299 progname = basename(argv[0]);
301 while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1)
302 switch (c)
304 case 'V':
305 printf("libtar %s by Mark D. Roth <roth@uiuc.edu>\n",
306 libtar_version);
307 break;
308 case 'C':
309 rootdir = strdup(optarg);
310 break;
311 case 'v':
312 verbose = 1;
313 break;
314 case 'g':
315 use_gnu = 1;
316 break;
317 case 'c':
318 if (mode)
319 usage(rootdir);
320 mode = MODE_CREATE;
321 break;
322 case 'x':
323 if (mode)
324 usage(rootdir);
325 mode = MODE_EXTRACT;
326 break;
327 case 't':
328 if (mode)
329 usage(rootdir);
330 mode = MODE_LIST;
331 break;
332 #ifdef HAVE_LIBZ
333 case 'z':
334 use_zlib = 1;
335 break;
336 #endif /* HAVE_LIBZ */
337 default:
338 usage(rootdir);
341 if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1)))
343 #ifdef DEBUG
344 printf("argc - optind == %d\tmode == %d\n", argc - optind,
345 mode);
346 #endif
347 usage(rootdir);
350 #ifdef DEBUG
351 signal(SIGSEGV, segv_handler);
352 #endif
354 switch (mode)
356 case MODE_EXTRACT:
357 return_code = extract(argv[optind], rootdir);
358 break;
359 case MODE_CREATE:
360 tarfile = argv[optind];
361 l = libtar_list_new(LIST_QUEUE, NULL);
362 for (c = optind + 1; c < argc; c++)
363 libtar_list_add(l, argv[c]);
364 return_code = create(tarfile, rootdir, l);
365 libtar_list_free(l, NULL);
366 break;
367 case MODE_LIST:
368 return_code = list(argv[optind]);
369 break;
370 default:
371 break;
374 free(rootdir);
375 return return_code;