blob: ba29a77719f84b78b300ad37d304e7da949d98d8 [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 Yonker79f88bd2016-12-09 14:52:12 -060035#ifdef HAVE_EXT4_CRYPT
36# include "ext4crypt_tar.h"
37#endif
38
Ethan Yonker472f5062016-02-25 13:47:30 -060039const unsigned long long progress_size = (unsigned long long)(T_BLOCKSIZE);
40
bigbiff bigbiff9c754052013-01-09 09:09:08 -050041static int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050042tar_set_file_perms(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -050043{
44 mode_t mode;
45 uid_t uid;
46 gid_t gid;
47 struct utimbuf ut;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050048 const char *filename;
49 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -050050
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050051 pn = th_get_pathname(t);
52 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -050053 mode = th_get_mode(t);
54 uid = th_get_uid(t);
55 gid = th_get_gid(t);
56 ut.modtime = ut.actime = th_get_mtime(t);
57
Dees_Troy71796592013-03-14 20:16:29 +000058#ifdef DEBUG
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -050059 printf("tar_set_file_perms(): setting perms: %s (mode %04o, uid %d, gid %d)\n",
60 filename, mode, uid, gid);
Dees_Troy71796592013-03-14 20:16:29 +000061#endif
62
bigbiff bigbiff9c754052013-01-09 09:09:08 -050063 /* change owner/group */
64 if (geteuid() == 0)
65#ifdef HAVE_LCHOWN
66 if (lchown(filename, uid, gid) == -1)
67 {
68# ifdef DEBUG
69 fprintf(stderr, "lchown(\"%s\", %d, %d): %s\n",
70 filename, uid, gid, strerror(errno));
71# endif
72#else /* ! HAVE_LCHOWN */
73 if (!TH_ISSYM(t) && chown(filename, uid, gid) == -1)
74 {
75# ifdef DEBUG
76 fprintf(stderr, "chown(\"%s\", %d, %d): %s\n",
77 filename, uid, gid, strerror(errno));
78# endif
79#endif /* HAVE_LCHOWN */
80 return -1;
81 }
82
83 /* change access/modification time */
84 if (!TH_ISSYM(t) && utime(filename, &ut) == -1)
85 {
86#ifdef DEBUG
87 perror("utime()");
88#endif
89 return -1;
90 }
91
92 /* change permissions */
93 if (!TH_ISSYM(t) && chmod(filename, mode) == -1)
94 {
95#ifdef DEBUG
96 perror("chmod()");
97#endif
98 return -1;
99 }
100
101 return 0;
102}
103
104
105/* switchboard */
106int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500107tar_extract_file(TAR *t, const char *realname, const char *prefix, const int *progress_fd)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500108{
109 int i;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500110#ifdef LIBTAR_FILE_HASH
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500111 char *lnp;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500112 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500113 int pathname_len;
114 int realname_len;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500115#endif
bigbiff bigbiff71e5aa42013-02-26 20:10:16 -0500116
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500117 if (t->options & TAR_NOOVERWRITE)
118 {
119 struct stat s;
120
121 if (lstat(realname, &s) == 0 || errno != ENOENT)
122 {
123 errno = EEXIST;
124 return -1;
125 }
126 }
127
128 if (TH_ISDIR(t))
129 {
130 i = tar_extract_dir(t, realname);
131 if (i == 1)
132 i = 0;
133 }
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500134 else if (TH_ISLNK(t))
Dees_Troyee6632c2013-02-27 18:07:32 +0000135 i = tar_extract_hardlink(t, realname, prefix);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500136 else if (TH_ISSYM(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500137 i = tar_extract_symlink(t, realname);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500138 else if (TH_ISCHR(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500139 i = tar_extract_chardev(t, realname);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500140 else if (TH_ISBLK(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500141 i = tar_extract_blockdev(t, realname);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500142 else if (TH_ISFIFO(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500143 i = tar_extract_fifo(t, realname);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500144 else /* if (TH_ISREG(t)) */
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500145 i = tar_extract_regfile(t, realname, progress_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500146
147 if (i != 0) {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500148 fprintf(stderr, "tar_extract_file(): failed to extract %s !!!\n", realname);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500149 return i;
150 }
151
152 i = tar_set_file_perms(t, realname);
153 if (i != 0) {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500154 fprintf(stderr, "tar_extract_file(): failed to set permissions on %s !!!\n", realname);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500155 return i;
156 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200157
158#ifdef HAVE_SELINUX
159 if((t->options & TAR_STORE_SELINUX) && t->th_buf.selinux_context != NULL)
160 {
161#ifdef DEBUG
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500162 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 +0200163#endif
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500164 if (lsetfilecon(realname, t->th_buf.selinux_context) < 0)
165 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 +0200166 }
167#endif
168
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500169#ifdef LIBTAR_FILE_HASH
170 pn = th_get_pathname(t);
171 pathname_len = strlen(pn) + 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500172 realname_len = strlen(realname) + 1;
173 lnp = (char *)calloc(1, pathname_len + realname_len);
174 if (lnp == NULL)
175 return -1;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500176 strcpy(&lnp[0], pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500177 strcpy(&lnp[pathname_len], realname);
178#ifdef DEBUG
179 printf("tar_extract_file(): calling libtar_hash_add(): key=\"%s\", "
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500180 "value=\"%s\"\n", pn, realname);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500181#endif
182 if (libtar_hash_add(t->h, lnp) != 0)
183 return -1;
184 free(lnp);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500185#endif
186
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500187 return 0;
188}
189
190
191/* extract regular file */
192int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500193tar_extract_regfile(TAR *t, const char *realname, const int *progress_fd)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500194{
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500195 int64_t size, i;
196 ssize_t k;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500197 int fdout;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500198 char buf[T_BLOCKSIZE];
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500199 const char *filename;
200 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500201
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500202#ifdef DEBUG
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500203 printf(" ==> tar_extract_regfile(realname=\"%s\")\n", realname);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500204#endif
205
206 if (!TH_ISREG(t))
207 {
208 errno = EINVAL;
209 return -1;
210 }
211
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500212 pn = th_get_pathname(t);
213 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500214 size = th_get_size(t);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500215
216 if (mkdirhier(dirname(filename)) == -1)
217 return -1;
218
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500219 printf(" ==> extracting: %s (file size %lld bytes)\n",
220 filename, size);
221
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500222 fdout = open(filename, O_WRONLY | O_CREAT | O_TRUNC
223#ifdef O_BINARY
224 | O_BINARY
225#endif
226 , 0666);
227 if (fdout == -1)
228 {
229#ifdef DEBUG
230 perror("open()");
231#endif
232 return -1;
233 }
234
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500235 /* extract the file */
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500236 for (i = size; i > 0; i -= T_BLOCKSIZE)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500237 {
238 k = tar_block_read(t, buf);
239 if (k != T_BLOCKSIZE)
240 {
241 if (k != -1)
242 errno = EINVAL;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500243 close(fdout);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500244 return -1;
245 }
246
247 /* write block to output file */
248 if (write(fdout, buf,
249 ((i > T_BLOCKSIZE) ? T_BLOCKSIZE : i)) == -1)
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500250 {
251 close(fdout);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500252 return -1;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500253 }
Ethan Yonker472f5062016-02-25 13:47:30 -0600254 else
255 {
256 if (*progress_fd != 0)
257 write(*progress_fd, &progress_size, sizeof(progress_size));
258 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500259 }
260
261 /* close output file */
262 if (close(fdout) == -1)
263 return -1;
264
265#ifdef DEBUG
266 printf("### done extracting %s\n", filename);
267#endif
268
269 return 0;
270}
271
272
273/* skip regfile */
274int
275tar_skip_regfile(TAR *t)
276{
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500277 int64_t size, i;
278 ssize_t k;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500279 char buf[T_BLOCKSIZE];
280
281 if (!TH_ISREG(t))
282 {
283 errno = EINVAL;
284 return -1;
285 }
286
287 size = th_get_size(t);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500288 for (i = size; i > 0; i -= T_BLOCKSIZE)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500289 {
290 k = tar_block_read(t, buf);
291 if (k != T_BLOCKSIZE)
292 {
293 if (k != -1)
294 errno = EINVAL;
295 return -1;
296 }
297 }
298
299 return 0;
300}
301
302
303/* hardlink */
304int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500305tar_extract_hardlink(TAR * t, const char *realname, const char *prefix)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500306{
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500307 const char *filename;
308 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500309 char *linktgt = NULL;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500310 char *newtgt = NULL;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500311 char *lnp;
312 libtar_hashptr_t hp;
313
314 if (!TH_ISLNK(t))
315 {
316 errno = EINVAL;
317 return -1;
318 }
319
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500320 pn = th_get_pathname(t);
321 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500322 if (mkdirhier(dirname(filename)) == -1)
323 return -1;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500324 if (unlink(filename) == -1 && errno != ENOENT)
325 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500326 libtar_hashptr_reset(&hp);
327 if (libtar_hash_getkey(t->h, &hp, th_get_linkname(t),
328 (libtar_matchfunc_t)libtar_str_match) != 0)
329 {
330 lnp = (char *)libtar_hashptr_data(&hp);
331 linktgt = &lnp[strlen(lnp) + 1];
332 }
333 else
334 linktgt = th_get_linkname(t);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500335
336 newtgt = strdup(linktgt);
Dees_Troyee6632c2013-02-27 18:07:32 +0000337 sprintf(linktgt, "%s/%s", prefix, newtgt);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500338
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500339 printf(" ==> extracting: %s (link to %s)\n", filename, linktgt);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500340
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500341 if (link(linktgt, filename) == -1)
342 {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500343 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 +0000344 return 0; // Used to be -1
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500345 }
346
347 return 0;
348}
349
350
351/* symlink */
352int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500353tar_extract_symlink(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500354{
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500355 const char *filename;
356 char *pn;
bigbiff bigbiff71e5aa42013-02-26 20:10:16 -0500357
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500358 if (!TH_ISSYM(t))
359 {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500360 errno = EINVAL;
361 return -1;
362 }
363
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500364 pn = th_get_pathname(t);
365 filename = (realname ? realname : pn);
366 if (mkdirhier(dirname(filename)) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500367 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500368
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500369 if (unlink(filename) == -1 && errno != ENOENT)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500370 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500371
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500372 printf(" ==> extracting: %s (symlink to %s)\n",
373 filename, th_get_linkname(t));
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500374
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500375 if (symlink(th_get_linkname(t), filename) == -1)
376 {
377#ifdef DEBUG
378 perror("symlink()");
379#endif
380 return -1;
381 }
382
383 return 0;
384}
385
386
387/* character device */
388int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500389tar_extract_chardev(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500390{
391 mode_t mode;
392 unsigned long devmaj, devmin;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500393 const char *filename;
394 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500395
396 if (!TH_ISCHR(t))
397 {
398 errno = EINVAL;
399 return -1;
400 }
401
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500402 pn = th_get_pathname(t);
403 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500404 mode = th_get_mode(t);
405 devmaj = th_get_devmajor(t);
406 devmin = th_get_devminor(t);
407
408 if (mkdirhier(dirname(filename)) == -1)
409 return -1;
410
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500411 printf(" ==> extracting: %s (character device %ld,%ld)\n",
412 filename, devmaj, devmin);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500413
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500414 if (mknod(filename, mode | S_IFCHR,
415 compat_makedev(devmaj, devmin)) == -1)
416 {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500417 fprintf(stderr, "tar_extract_chardev(): failed restore of character device '%s' but returning as if nothing bad happened\n", filename);
418 return 0; // Used to be -1
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500419 }
420
421 return 0;
422}
423
424
425/* block device */
426int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500427tar_extract_blockdev(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500428{
429 mode_t mode;
430 unsigned long devmaj, devmin;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500431 const char *filename;
432 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500433
434 if (!TH_ISBLK(t))
435 {
436 errno = EINVAL;
437 return -1;
438 }
439
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500440 pn = th_get_pathname(t);
441 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500442 mode = th_get_mode(t);
443 devmaj = th_get_devmajor(t);
444 devmin = th_get_devminor(t);
445
446 if (mkdirhier(dirname(filename)) == -1)
447 return -1;
448
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500449 printf(" ==> extracting: %s (block device %ld,%ld)\n",
450 filename, devmaj, devmin);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500451
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500452 if (mknod(filename, mode | S_IFBLK,
453 compat_makedev(devmaj, devmin)) == -1)
454 {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500455 fprintf(stderr, "tar_extract_blockdev(): failed restore of block device '%s' but returning as if nothing bad happened\n", filename);
456 return 0; // Used to be -1
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500457 }
458
459 return 0;
460}
461
462
463/* directory */
464int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500465tar_extract_dir(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500466{
467 mode_t mode;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500468 const char *filename;
469 char *pn;
470
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500471 if (!TH_ISDIR(t))
472 {
473 errno = EINVAL;
474 return -1;
475 }
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500476 pn = th_get_pathname(t);
477 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500478 mode = th_get_mode(t);
479
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500480 if (mkdirhier(dirname(filename)) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500481 return -1;
482
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500483 printf(" ==> extracting: %s (mode %04o, directory)\n", filename,
484 mode);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500485
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500486 if (mkdir(filename, mode) == -1)
487 {
488 if (errno == EEXIST)
489 {
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500490 if (chmod(filename, mode) == -1)
491 {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500492#ifdef DEBUG
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500493 perror("chmod()");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500494#endif
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500495 return -1;
496 }
497 else
498 {
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600499#if 1 //def DEBUG
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500500 puts(" *** using existing directory");
501#endif
502 return 1;
503 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500504 }
505 else
506 {
507#ifdef DEBUG
508 perror("mkdir()");
509#endif
510 return -1;
511 }
512 }
513
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600514#ifdef HAVE_EXT4_CRYPT
515 if(t->th_buf.e4crypt_policy != NULL)
516 {
517#ifdef DEBUG
518 printf("tar_extract_file(): restoring EXT4 crypt policy %s to dir %s\n", t->th_buf.e4crypt_policy, realname);
519#endif
520 char binary_policy[EXT4_KEY_DESCRIPTOR_SIZE];
521 if (!lookup_ref_tar(t->th_buf.e4crypt_policy, &binary_policy)) {
522 printf("error looking up proper e4crypt policy for '%s' - %s\n", realname, t->th_buf.e4crypt_policy);
523 return -1;
524 }
525 char policy_hex[EXT4_KEY_DESCRIPTOR_HEX];
526 policy_to_hex(binary_policy, policy_hex);
527 printf("restoring policy %s > '%s' to '%s'\n", t->th_buf.e4crypt_policy, policy_hex, realname);
528 if (!e4crypt_policy_set(realname, binary_policy, EXT4_KEY_DESCRIPTOR_SIZE, 0))
529 {
530 printf("tar_extract_file(): failed to restore EXT4 crypt policy %s to dir '%s' '%s'!!!\n", t->th_buf.e4crypt_policy, realname, policy_hex);
531 //return -1; // This may not be an error in some cases, so log and ignore
532 }
533 }
534#endif
535
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500536 return 0;
537}
538
539
540/* FIFO */
541int
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500542tar_extract_fifo(TAR *t, const char *realname)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500543{
544 mode_t mode;
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500545 const char *filename;
546 char *pn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500547
548 if (!TH_ISFIFO(t))
549 {
550 errno = EINVAL;
551 return -1;
552 }
553
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500554 pn = th_get_pathname(t);
555 filename = (realname ? realname : pn);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500556 mode = th_get_mode(t);
557
558 if (mkdirhier(dirname(filename)) == -1)
559 return -1;
560
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500561
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500562 printf(" ==> extracting: %s (fifo)\n", filename);
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500563
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500564 if (mkfifo(filename, mode) == -1)
565 {
566#ifdef DEBUG
567 perror("mkfifo()");
568#endif
569 return -1;
570 }
571
572 return 0;
573}
574
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500575/* extract file contents from a tarchive */
576int
577tar_extract_file_contents(TAR *t, void *buf, size_t *lenp)
578{
579 char block[T_BLOCKSIZE];
580 int64_t size, i;
581 ssize_t k;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500582
James Christopher Adduono6f57f7c2016-03-01 16:01:53 -0500583#ifdef DEBUG
584 printf(" ==> tar_extract_file_contents\n");
585#endif
586
587 if (!TH_ISREG(t))
588 {
589 errno = EINVAL;
590 return -1;
591 }
592
593 size = th_get_size(t);
594 if ((uint64_t)size > *lenp)
595 {
596 errno = ENOSPC;
597 return -1;
598 }
599
600 /* extract the file */
601 for (i = size; i >= T_BLOCKSIZE; i -= T_BLOCKSIZE)
602 {
603 k = tar_block_read(t, buf);
604 if (k != T_BLOCKSIZE)
605 {
606 if (k != -1)
607 errno = EINVAL;
608 return -1;
609 }
610 buf = (char *)buf + T_BLOCKSIZE;
611 }
612 if (i > 0) {
613 k = tar_block_read(t, block);
614 if (k != T_BLOCKSIZE)
615 {
616 if (k != -1)
617 errno = EINVAL;
618 return -1;
619 }
620 memcpy(buf, block, i);
621 }
622 *lenp = (size_t)size;
623
624#ifdef DEBUG
625 printf("### done extracting contents\n");
626#endif
627 return 0;
628}