blob: 6a63ff73818f0f8703c689f1bb5cc4481469d8d6 [file] [log] [blame]
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001/*
2** Copyright 1998-2003 University of Illinois Board of Trustees
3** Copyright 1998-2003 Mark D. Roth
4** All rights reserved.
5**
6** extract.c - libtar code to extract a file from a tar archive
7**
8** Mark D. Roth <roth@uiuc.edu>
9** Campus Information Technologies and Educational Services
10** University of Illinois at Urbana-Champaign
11*/
12
13#include <internal.h>
14
15#include <stdio.h>
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050016#include <string.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050017#include <sys/param.h>
18#include <sys/types.h>
19#include <fcntl.h>
20#include <errno.h>
21#include <utime.h>
22
bigbiff bigbiff9c754052013-01-09 09:09:08 -050023#ifdef STDC_HEADERS
24# include <stdlib.h>
25#endif
26
27#ifdef HAVE_UNISTD_H
28# include <unistd.h>
29#endif
30
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050031#ifdef HAVE_SELINUX
32# include "selinux/selinux.h"
33#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -050034
Ethan Yonker472f5062016-02-25 13:47:30 -060035const unsigned long long progress_size = (unsigned long long)(T_BLOCKSIZE);
36
bigbiff bigbiff9c754052013-01-09 09:09:08 -050037static int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050038tar_set_file_perms(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -050039{
40 mode_t mode;
41 uid_t uid;
42 gid_t gid;
43 struct utimbuf ut;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050044 const char *filename;
45 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -050046
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050047 pn = th_get_pathname(t);
48 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -050049 mode = th_get_mode(t);
50 uid = th_get_uid(t);
51 gid = th_get_gid(t);
52 ut.modtime = ut.actime = th_get_mtime(t);
53
Dees_Troy71796592013-03-14 20:16:29 +000054#ifdef DEBUG
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050055 printf("tar_set_file_perms(): setting perms: %s (mode %04o, uid %d, gid %d)\n",
56 filename, mode, uid, gid);
Dees_Troy71796592013-03-14 20:16:29 +000057#endif
58
bigbiff bigbiff9c754052013-01-09 09:09:08 -050059 /* change owner/group */
60 if (geteuid() == 0)
61#ifdef HAVE_LCHOWN
62 if (lchown(filename, uid, gid) == -1)
63 {
64# ifdef DEBUG
65 fprintf(stderr, "lchown(\"%s\", %d, %d): %s\n",
66 filename, uid, gid, strerror(errno));
67# endif
68#else /* ! HAVE_LCHOWN */
69 if (!TH_ISSYM(t) && chown(filename, uid, gid) == -1)
70 {
71# ifdef DEBUG
72 fprintf(stderr, "chown(\"%s\", %d, %d): %s\n",
73 filename, uid, gid, strerror(errno));
74# endif
75#endif /* HAVE_LCHOWN */
76 return -1;
77 }
78
79 /* change access/modification time */
80 if (!TH_ISSYM(t) && utime(filename, &ut) == -1)
81 {
82#ifdef DEBUG
83 perror("utime()");
84#endif
85 return -1;
86 }
87
88 /* change permissions */
89 if (!TH_ISSYM(t) && chmod(filename, mode) == -1)
90 {
91#ifdef DEBUG
92 perror("chmod()");
93#endif
94 return -1;
95 }
96
97 return 0;
98}
99
100
101/* switchboard */
102int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500103tar_extract_file(TAR *t, const char *realname, const char *prefix, const int *progress_fd)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500104{
105 int i;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500106#ifdef LIBTAR_FILE_HASH
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500107 char *lnp;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500108 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500109 int pathname_len;
110 int realname_len;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500111#endif
bigbiff bigbiff71e5aa42013-02-26 20:10:16 -0500112
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500113 if (t->options & TAR_NOOVERWRITE)
114 {
115 struct stat s;
116
117 if (lstat(realname, &s) == 0 || errno != ENOENT)
118 {
119 errno = EEXIST;
120 return -1;
121 }
122 }
123
124 if (TH_ISDIR(t))
125 {
126 i = tar_extract_dir(t, realname);
127 if (i == 1)
128 i = 0;
129 }
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500130 else if (TH_ISLNK(t))
Dees_Troyee6632c2013-02-27 18:07:32 +0000131 i = tar_extract_hardlink(t, realname, prefix);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500132 else if (TH_ISSYM(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500133 i = tar_extract_symlink(t, realname);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500134 else if (TH_ISCHR(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500135 i = tar_extract_chardev(t, realname);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500136 else if (TH_ISBLK(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500137 i = tar_extract_blockdev(t, realname);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500138 else if (TH_ISFIFO(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500139 i = tar_extract_fifo(t, realname);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500140 else /* if (TH_ISREG(t)) */
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500141 i = tar_extract_regfile(t, realname, progress_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500142
143 if (i != 0) {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500144 fprintf(stderr, "tar_extract_file(): failed to extract %s !!!\n", realname);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500145 return i;
146 }
147
148 i = tar_set_file_perms(t, realname);
149 if (i != 0) {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500150 fprintf(stderr, "tar_extract_file(): failed to set permissions on %s !!!\n", realname);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500151 return i;
152 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200153
154#ifdef HAVE_SELINUX
155 if((t->options & TAR_STORE_SELINUX) && t->th_buf.selinux_context != NULL)
156 {
157#ifdef DEBUG
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500158 printf("tar_extract_file(): restoring SELinux context %s to file %s\n", t->th_buf.selinux_context, realname);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200159#endif
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500160 if (lsetfilecon(realname, t->th_buf.selinux_context) < 0)
161 fprintf(stderr, "tar_extract_file(): failed to restore SELinux context %s to file %s !!!\n", t->th_buf.selinux_context, realname);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200162 }
163#endif
164
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500165#ifdef LIBTAR_FILE_HASH
166 pn = th_get_pathname(t);
167 pathname_len = strlen(pn) + 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500168 realname_len = strlen(realname) + 1;
169 lnp = (char *)calloc(1, pathname_len + realname_len);
170 if (lnp == NULL)
171 return -1;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500172 strcpy(&lnp[0], pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500173 strcpy(&lnp[pathname_len], realname);
174#ifdef DEBUG
175 printf("tar_extract_file(): calling libtar_hash_add(): key=\"%s\", "
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500176 "value=\"%s\"\n", pn, realname);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500177#endif
178 if (libtar_hash_add(t->h, lnp) != 0)
179 return -1;
180 free(lnp);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500181#endif
182
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500183 return 0;
184}
185
186
187/* extract regular file */
188int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500189tar_extract_regfile(TAR *t, const char *realname, const int *progress_fd)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500190{
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500191 int64_t size, i;
192 ssize_t k;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500193 int fdout;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500194 char buf[T_BLOCKSIZE];
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500195 const char *filename;
196 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500197
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500198#ifdef DEBUG
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500199 printf(" ==> tar_extract_regfile(realname=\"%s\")\n", realname);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500200#endif
201
202 if (!TH_ISREG(t))
203 {
204 errno = EINVAL;
205 return -1;
206 }
207
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500208 pn = th_get_pathname(t);
209 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500210 size = th_get_size(t);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500211
212 if (mkdirhier(dirname(filename)) == -1)
213 return -1;
214
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500215 printf(" ==> extracting: %s (file size %lld bytes)\n",
216 filename, size);
217
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500218 fdout = open(filename, O_WRONLY | O_CREAT | O_TRUNC
219#ifdef O_BINARY
220 | O_BINARY
221#endif
222 , 0666);
223 if (fdout == -1)
224 {
225#ifdef DEBUG
226 perror("open()");
227#endif
228 return -1;
229 }
230
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500231 /* extract the file */
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500232 for (i = size; i > 0; i -= T_BLOCKSIZE)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500233 {
234 k = tar_block_read(t, buf);
235 if (k != T_BLOCKSIZE)
236 {
237 if (k != -1)
238 errno = EINVAL;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500239 close(fdout);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500240 return -1;
241 }
242
243 /* write block to output file */
244 if (write(fdout, buf,
245 ((i > T_BLOCKSIZE) ? T_BLOCKSIZE : i)) == -1)
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500246 {
247 close(fdout);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500248 return -1;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500249 }
Ethan Yonker472f5062016-02-25 13:47:30 -0600250 else
251 {
252 if (*progress_fd != 0)
253 write(*progress_fd, &progress_size, sizeof(progress_size));
254 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500255 }
256
257 /* close output file */
258 if (close(fdout) == -1)
259 return -1;
260
261#ifdef DEBUG
262 printf("### done extracting %s\n", filename);
263#endif
264
265 return 0;
266}
267
268
269/* skip regfile */
270int
271tar_skip_regfile(TAR *t)
272{
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500273 int64_t size, i;
274 ssize_t k;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500275 char buf[T_BLOCKSIZE];
276
277 if (!TH_ISREG(t))
278 {
279 errno = EINVAL;
280 return -1;
281 }
282
283 size = th_get_size(t);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500284 for (i = size; i > 0; i -= T_BLOCKSIZE)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500285 {
286 k = tar_block_read(t, buf);
287 if (k != T_BLOCKSIZE)
288 {
289 if (k != -1)
290 errno = EINVAL;
291 return -1;
292 }
293 }
294
295 return 0;
296}
297
298
299/* hardlink */
300int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500301tar_extract_hardlink(TAR * t, const char *realname, const char *prefix)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500302{
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500303 const char *filename;
304 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500305 char *linktgt = NULL;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500306 char *newtgt = NULL;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500307 char *lnp;
308 libtar_hashptr_t hp;
309
310 if (!TH_ISLNK(t))
311 {
312 errno = EINVAL;
313 return -1;
314 }
315
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500316 pn = th_get_pathname(t);
317 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500318 if (mkdirhier(dirname(filename)) == -1)
319 return -1;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500320 if (unlink(filename) == -1 && errno != ENOENT)
321 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500322 libtar_hashptr_reset(&hp);
323 if (libtar_hash_getkey(t->h, &hp, th_get_linkname(t),
324 (libtar_matchfunc_t)libtar_str_match) != 0)
325 {
326 lnp = (char *)libtar_hashptr_data(&hp);
327 linktgt = &lnp[strlen(lnp) + 1];
328 }
329 else
330 linktgt = th_get_linkname(t);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500331
332 newtgt = strdup(linktgt);
Dees_Troyee6632c2013-02-27 18:07:32 +0000333 sprintf(linktgt, "%s/%s", prefix, newtgt);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500334
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500335 printf(" ==> extracting: %s (link to %s)\n", filename, linktgt);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500336
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500337 if (link(linktgt, filename) == -1)
338 {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500339 fprintf(stderr, "tar_extract_hardlink(): failed restore of hardlink '%s' but returning as if nothing bad happened\n", filename);
Dees_Troyf96fb972013-03-01 22:34:25 +0000340 return 0; // Used to be -1
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500341 }
342
343 return 0;
344}
345
346
347/* symlink */
348int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500349tar_extract_symlink(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500350{
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500351 const char *filename;
352 char *pn;
bigbiff bigbiff71e5aa42013-02-26 20:10:16 -0500353
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500354 if (!TH_ISSYM(t))
355 {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500356 errno = EINVAL;
357 return -1;
358 }
359
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500360 pn = th_get_pathname(t);
361 filename = (realname ? realname : pn);
362 if (mkdirhier(dirname(filename)) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500363 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500364
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500365 if (unlink(filename) == -1 && errno != ENOENT)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500366 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500367
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500368 printf(" ==> extracting: %s (symlink to %s)\n",
369 filename, th_get_linkname(t));
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500370
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500371 if (symlink(th_get_linkname(t), filename) == -1)
372 {
373#ifdef DEBUG
374 perror("symlink()");
375#endif
376 return -1;
377 }
378
379 return 0;
380}
381
382
383/* character device */
384int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500385tar_extract_chardev(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500386{
387 mode_t mode;
388 unsigned long devmaj, devmin;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500389 const char *filename;
390 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500391
392 if (!TH_ISCHR(t))
393 {
394 errno = EINVAL;
395 return -1;
396 }
397
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500398 pn = th_get_pathname(t);
399 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500400 mode = th_get_mode(t);
401 devmaj = th_get_devmajor(t);
402 devmin = th_get_devminor(t);
403
404 if (mkdirhier(dirname(filename)) == -1)
405 return -1;
406
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500407 printf(" ==> extracting: %s (character device %ld,%ld)\n",
408 filename, devmaj, devmin);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500409
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500410 if (mknod(filename, mode | S_IFCHR,
411 compat_makedev(devmaj, devmin)) == -1)
412 {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500413 fprintf(stderr, "tar_extract_chardev(): failed restore of character device '%s' but returning as if nothing bad happened\n", filename);
414 return 0; // Used to be -1
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500415 }
416
417 return 0;
418}
419
420
421/* block device */
422int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500423tar_extract_blockdev(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500424{
425 mode_t mode;
426 unsigned long devmaj, devmin;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500427 const char *filename;
428 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500429
430 if (!TH_ISBLK(t))
431 {
432 errno = EINVAL;
433 return -1;
434 }
435
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500436 pn = th_get_pathname(t);
437 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500438 mode = th_get_mode(t);
439 devmaj = th_get_devmajor(t);
440 devmin = th_get_devminor(t);
441
442 if (mkdirhier(dirname(filename)) == -1)
443 return -1;
444
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500445 printf(" ==> extracting: %s (block device %ld,%ld)\n",
446 filename, devmaj, devmin);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500447
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500448 if (mknod(filename, mode | S_IFBLK,
449 compat_makedev(devmaj, devmin)) == -1)
450 {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500451 fprintf(stderr, "tar_extract_blockdev(): failed restore of block device '%s' but returning as if nothing bad happened\n", filename);
452 return 0; // Used to be -1
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500453 }
454
455 return 0;
456}
457
458
459/* directory */
460int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500461tar_extract_dir(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500462{
463 mode_t mode;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500464 const char *filename;
465 char *pn;
466
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500467 if (!TH_ISDIR(t))
468 {
469 errno = EINVAL;
470 return -1;
471 }
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500472 pn = th_get_pathname(t);
473 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500474 mode = th_get_mode(t);
475
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500476 if (mkdirhier(dirname(filename)) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500477 return -1;
478
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500479 printf(" ==> extracting: %s (mode %04o, directory)\n", filename,
480 mode);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500481
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500482 if (mkdir(filename, mode) == -1)
483 {
484 if (errno == EEXIST)
485 {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500486 if (chmod(filename, mode) == -1)
487 {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500488#ifdef DEBUG
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500489 perror("chmod()");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500490#endif
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500491 return -1;
492 }
493 else
494 {
495#ifdef DEBUG
496 puts(" *** using existing directory");
497#endif
498 return 1;
499 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500500 }
501 else
502 {
503#ifdef DEBUG
504 perror("mkdir()");
505#endif
506 return -1;
507 }
508 }
509
510 return 0;
511}
512
513
514/* FIFO */
515int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500516tar_extract_fifo(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500517{
518 mode_t mode;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500519 const char *filename;
520 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500521
522 if (!TH_ISFIFO(t))
523 {
524 errno = EINVAL;
525 return -1;
526 }
527
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500528 pn = th_get_pathname(t);
529 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500530 mode = th_get_mode(t);
531
532 if (mkdirhier(dirname(filename)) == -1)
533 return -1;
534
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500535
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500536 printf(" ==> extracting: %s (fifo)\n", filename);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500537
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500538 if (mkfifo(filename, mode) == -1)
539 {
540#ifdef DEBUG
541 perror("mkfifo()");
542#endif
543 return -1;
544 }
545
546 return 0;
547}
548
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500549/* extract file contents from a tarchive */
550int
551tar_extract_file_contents(TAR *t, void *buf, size_t *lenp)
552{
553 char block[T_BLOCKSIZE];
554 int64_t size, i;
555 ssize_t k;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500556
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500557#ifdef DEBUG
558 printf(" ==> tar_extract_file_contents\n");
559#endif
560
561 if (!TH_ISREG(t))
562 {
563 errno = EINVAL;
564 return -1;
565 }
566
567 size = th_get_size(t);
568 if ((uint64_t)size > *lenp)
569 {
570 errno = ENOSPC;
571 return -1;
572 }
573
574 /* extract the file */
575 for (i = size; i >= T_BLOCKSIZE; i -= T_BLOCKSIZE)
576 {
577 k = tar_block_read(t, buf);
578 if (k != T_BLOCKSIZE)
579 {
580 if (k != -1)
581 errno = EINVAL;
582 return -1;
583 }
584 buf = (char *)buf + T_BLOCKSIZE;
585 }
586 if (i > 0) {
587 k = tar_block_read(t, block);
588 if (k != T_BLOCKSIZE)
589 {
590 if (k != -1)
591 errno = EINVAL;
592 return -1;
593 }
594 memcpy(buf, block, i);
595 }
596 *lenp = (size_t)size;
597
598#ifdef DEBUG
599 printf("### done extracting contents\n");
600#endif
601 return 0;
602}