1 // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/stat.h>
6 #if defined(HAVE_ZLIB)
7 #include <zlib.h>
8 #endif
9 #include "erofs/print.h"
10 #include "erofs/cache.h"
11 #include "erofs/diskbuf.h"
12 #include "erofs/inode.h"
13 #include "erofs/list.h"
14 #include "erofs/tar.h"
15 #include "erofs/io.h"
16 #include "erofs/xattr.h"
17 #include "erofs/blobchunk.h"
18 #include "erofs/rebuild.h"
19
20 /* This file is a tape/volume header. Ignore it on extraction. */
21 #define GNUTYPE_VOLHDR 'V'
22
23 struct tar_header {
24 char name[100]; /* 0-99 */
25 char mode[8]; /* 100-107 */
26 char uid[8]; /* 108-115 */
27 char gid[8]; /* 116-123 */
28 char size[12]; /* 124-135 */
29 char mtime[12]; /* 136-147 */
30 char chksum[8]; /* 148-155 */
31 char typeflag; /* 156-156 */
32 char linkname[100]; /* 157-256 */
33 char magic[6]; /* 257-262 */
34 char version[2]; /* 263-264 */
35 char uname[32]; /* 265-296 */
36 char gname[32]; /* 297-328 */
37 char devmajor[8]; /* 329-336 */
38 char devminor[8]; /* 337-344 */
39 char prefix[155]; /* 345-499 */
40 char padding[12]; /* 500-512 (pad to exactly the 512 byte) */
41 };
42
erofs_read_from_fd(int fd,void * buf,u64 bytes)43 s64 erofs_read_from_fd(int fd, void *buf, u64 bytes)
44 {
45 s64 i = 0;
46
47 while (bytes) {
48 int len = bytes > INT_MAX ? INT_MAX : bytes;
49 int ret;
50
51 ret = read(fd, buf + i, len);
52 if (ret < 1) {
53 if (ret == 0) {
54 break;
55 } else if (errno != EINTR) {
56 erofs_err("failed to read : %s\n",
57 strerror(errno));
58 return -errno;
59 }
60 }
61 bytes -= ret;
62 i += ret;
63 }
64 return i;
65 }
66
erofs_iostream_close(struct erofs_iostream * ios)67 void erofs_iostream_close(struct erofs_iostream *ios)
68 {
69 free(ios->buffer);
70 if (ios->decoder == EROFS_IOS_DECODER_GZIP) {
71 #if defined(HAVE_ZLIB)
72 gzclose(ios->handler);
73 #endif
74 return;
75 }
76 close(ios->fd);
77 }
78
erofs_iostream_open(struct erofs_iostream * ios,int fd,int decoder)79 int erofs_iostream_open(struct erofs_iostream *ios, int fd, int decoder)
80 {
81 s64 fsz;
82
83 ios->tail = ios->head = 0;
84 ios->decoder = decoder;
85 if (decoder == EROFS_IOS_DECODER_GZIP) {
86 #if defined(HAVE_ZLIB)
87 ios->handler = gzdopen(fd, "r");
88 if (!ios->handler)
89 return -ENOMEM;
90 ios->sz = fsz = 0;
91 ios->bufsize = 32768;
92 #else
93 return -EOPNOTSUPP;
94 #endif
95 } else {
96 ios->fd = fd;
97 fsz = lseek(fd, 0, SEEK_END);
98 if (fsz <= 0) {
99 ios->feof = !fsz;
100 ios->sz = 0;
101 } else {
102 ios->feof = false;
103 ios->sz = fsz;
104 if (lseek(fd, 0, SEEK_SET))
105 return -EIO;
106 #ifdef HAVE_POSIX_FADVISE
107 if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL))
108 erofs_warn("failed to fadvise: %s, ignored.",
109 erofs_strerror(errno));
110 #endif
111 }
112 ios->bufsize = 16384;
113 }
114
115 do {
116 ios->buffer = malloc(ios->bufsize);
117 if (ios->buffer)
118 break;
119 ios->bufsize >>= 1;
120 } while (ios->bufsize >= 1024);
121
122 if (!ios->buffer)
123 return -ENOMEM;
124 return 0;
125 }
126
erofs_iostream_read(struct erofs_iostream * ios,void ** buf,u64 bytes)127 int erofs_iostream_read(struct erofs_iostream *ios, void **buf, u64 bytes)
128 {
129 unsigned int rabytes = ios->tail - ios->head;
130 int ret;
131
132 if (rabytes >= bytes) {
133 *buf = ios->buffer + ios->head;
134 ios->head += bytes;
135 return bytes;
136 }
137
138 if (ios->head) {
139 memmove(ios->buffer, ios->buffer + ios->head, rabytes);
140 ios->head = 0;
141 ios->tail = rabytes;
142 }
143
144 if (!ios->feof) {
145 if (ios->decoder == EROFS_IOS_DECODER_GZIP) {
146 #if defined(HAVE_ZLIB)
147 ret = gzread(ios->handler, ios->buffer + rabytes,
148 ios->bufsize - rabytes);
149 if (!ret) {
150 int errnum;
151 const char *errstr;
152
153 errstr = gzerror(ios->handler, &errnum);
154 if (errnum != Z_STREAM_END) {
155 erofs_err("failed to gzread: %s", errstr);
156 return -EIO;
157 }
158 ios->feof = true;
159 }
160 ios->tail += ret;
161 #else
162 return -EOPNOTSUPP;
163 #endif
164 } else {
165 ret = erofs_read_from_fd(ios->fd, ios->buffer + rabytes,
166 ios->bufsize - rabytes);
167 if (ret < 0)
168 return ret;
169 ios->tail += ret;
170 if (ret < ios->bufsize - rabytes)
171 ios->feof = true;
172 }
173 }
174 *buf = ios->buffer;
175 ret = min_t(int, ios->tail, bytes);
176 ios->head = ret;
177 return ret;
178 }
179
erofs_iostream_bread(struct erofs_iostream * ios,void * buf,u64 bytes)180 int erofs_iostream_bread(struct erofs_iostream *ios, void *buf, u64 bytes)
181 {
182 u64 rem = bytes;
183 void *src;
184 int ret;
185
186 do {
187 ret = erofs_iostream_read(ios, &src, rem);
188 if (ret < 0)
189 return ret;
190 memcpy(buf, src, ret);
191 rem -= ret;
192 } while (rem && ret);
193
194 return bytes - rem;
195 }
196
erofs_iostream_lskip(struct erofs_iostream * ios,u64 sz)197 int erofs_iostream_lskip(struct erofs_iostream *ios, u64 sz)
198 {
199 unsigned int rabytes = ios->tail - ios->head;
200 int ret;
201 void *dummy;
202
203 if (rabytes >= sz) {
204 ios->head += sz;
205 return 0;
206 }
207
208 sz -= rabytes;
209 ios->head = ios->tail = 0;
210 if (ios->feof)
211 return sz;
212
213 if (ios->sz) {
214 s64 cur = lseek(ios->fd, sz, SEEK_CUR);
215
216 if (cur > ios->sz)
217 return cur - ios->sz;
218 return 0;
219 }
220
221 do {
222 ret = erofs_iostream_read(ios, &dummy, sz);
223 if (ret < 0)
224 return ret;
225 sz -= ret;
226 } while (!(ios->feof || !ret || !sz));
227
228 return sz;
229 }
230
tarerofs_otoi(const char * ptr,int len)231 static long long tarerofs_otoi(const char *ptr, int len)
232 {
233 char inp[32];
234 char *endp = inp;
235 long long val;
236
237 memcpy(inp, ptr, len);
238 inp[len] = '\0';
239
240 errno = 0;
241 val = strtol(ptr, &endp, 8);
242 if ((!val && endp == inp) |
243 (*endp && *endp != ' '))
244 errno = EINVAL;
245 return val;
246 }
247
tarerofs_parsenum(const char * ptr,int len)248 static long long tarerofs_parsenum(const char *ptr, int len)
249 {
250 /*
251 * For fields containing numbers or timestamps that are out of range
252 * for the basic format, the GNU format uses a base-256 representation
253 * instead of an ASCII octal number.
254 */
255 if (*(char *)ptr == '\200') {
256 long long res = 0;
257
258 while (--len)
259 res = (res << 8) + (u8)*(++ptr);
260 return res;
261 }
262 return tarerofs_otoi(ptr, len);
263 }
264
265 struct tarerofs_xattr_item {
266 struct list_head list;
267 char *kv;
268 unsigned int len, namelen;
269 };
270
tarerofs_insert_xattr(struct list_head * xattrs,char * kv,int namelen,int len,bool skip)271 int tarerofs_insert_xattr(struct list_head *xattrs,
272 char *kv, int namelen, int len, bool skip)
273 {
274 struct tarerofs_xattr_item *item;
275 char *nv;
276
277 DBG_BUGON(namelen >= len);
278 list_for_each_entry(item, xattrs, list) {
279 if (!strncmp(item->kv, kv, namelen + 1)) {
280 if (skip)
281 return 0;
282 goto found;
283 }
284 }
285
286 item = malloc(sizeof(*item));
287 if (!item)
288 return -ENOMEM;
289 item->kv = NULL;
290 item->namelen = namelen;
291 namelen = 0;
292 list_add_tail(&item->list, xattrs);
293 found:
294 nv = realloc(item->kv, len);
295 if (!nv)
296 return -ENOMEM;
297 item->kv = nv;
298 item->len = len;
299 memcpy(nv + namelen, kv + namelen, len - namelen);
300 return 0;
301 }
302
tarerofs_merge_xattrs(struct list_head * dst,struct list_head * src)303 int tarerofs_merge_xattrs(struct list_head *dst, struct list_head *src)
304 {
305 struct tarerofs_xattr_item *item;
306
307 list_for_each_entry(item, src, list) {
308 int ret;
309
310 ret = tarerofs_insert_xattr(dst, item->kv, item->namelen,
311 item->len, true);
312 if (ret)
313 return ret;
314 }
315 return 0;
316 }
317
tarerofs_remove_xattrs(struct list_head * xattrs)318 void tarerofs_remove_xattrs(struct list_head *xattrs)
319 {
320 struct tarerofs_xattr_item *item, *n;
321
322 list_for_each_entry_safe(item, n, xattrs, list) {
323 DBG_BUGON(!item->kv);
324 free(item->kv);
325 list_del(&item->list);
326 free(item);
327 }
328 }
329
tarerofs_apply_xattrs(struct erofs_inode * inode,struct list_head * xattrs)330 int tarerofs_apply_xattrs(struct erofs_inode *inode, struct list_head *xattrs)
331 {
332 struct tarerofs_xattr_item *item;
333 int ret;
334
335 list_for_each_entry(item, xattrs, list) {
336 const char *v = item->kv + item->namelen + 1;
337 unsigned int vsz = item->len - item->namelen - 1;
338
339 if (item->len <= item->namelen - 1) {
340 DBG_BUGON(item->len < item->namelen - 1);
341 continue;
342 }
343 item->kv[item->namelen] = '\0';
344 erofs_dbg("Recording xattr(%s)=\"%s\" (of %u bytes) to file %s",
345 item->kv, v, vsz, inode->i_srcpath);
346 ret = erofs_setxattr(inode, item->kv, v, vsz);
347 if (ret == -ENODATA)
348 erofs_err("Failed to set xattr(%s)=%s to file %s",
349 item->kv, v, inode->i_srcpath);
350 else if (ret)
351 return ret;
352 }
353 return 0;
354 }
355
356 static const char lookup_table[65] =
357 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
358
base64_decode(const char * src,int len,u8 * dst)359 static int base64_decode(const char *src, int len, u8 *dst)
360 {
361 int i, bits = 0, ac = 0;
362 const char *p;
363 u8 *cp = dst;
364
365 if(!(len % 4)) {
366 /* Check for and ignore any end padding */
367 if (src[len - 2] == '=' && src[len - 1] == '=')
368 len -= 2;
369 else if (src[len - 1] == '=')
370 --len;
371 }
372
373 for (i = 0; i < len; i++) {
374 p = strchr(lookup_table, src[i]);
375 if (p == NULL || src[i] == 0)
376 return -2;
377 ac += (p - lookup_table) << bits;
378 bits += 6;
379 if (bits >= 8) {
380 *cp++ = ac & 0xff;
381 ac >>= 8;
382 bits -= 8;
383 }
384 }
385 if (ac)
386 return -1;
387 return cp - dst;
388 }
389
tarerofs_parse_pax_header(struct erofs_iostream * ios,struct erofs_pax_header * eh,u32 size)390 int tarerofs_parse_pax_header(struct erofs_iostream *ios,
391 struct erofs_pax_header *eh, u32 size)
392 {
393 char *buf, *p;
394 int ret;
395
396 buf = malloc(size);
397 if (!buf)
398 return -ENOMEM;
399 p = buf;
400
401 ret = erofs_iostream_bread(ios, buf, size);
402 if (ret != size)
403 goto out;
404
405 while (p < buf + size) {
406 char *kv, *value;
407 int len, n;
408 /* extended records are of the format: "LEN NAME=VALUE\n" */
409 ret = sscanf(p, "%d %n", &len, &n);
410 if (ret < 1 || len <= n || len > buf + size - p) {
411 ret = -EIO;
412 goto out;
413 }
414 kv = p + n;
415 p += len;
416 len -= n;
417
418 if (p[-1] != '\n') {
419 ret = -EIO;
420 goto out;
421 }
422 p[-1] = '\0';
423
424 value = memchr(kv, '=', p - kv);
425 if (!value) {
426 ret = -EIO;
427 goto out;
428 } else {
429 long long lln;
430
431 value++;
432
433 if (!strncmp(kv, "path=", sizeof("path=") - 1)) {
434 int j = p - 1 - value;
435 free(eh->path);
436 eh->path = strdup(value);
437 while (eh->path[j - 1] == '/')
438 eh->path[--j] = '\0';
439 } else if (!strncmp(kv, "linkpath=",
440 sizeof("linkpath=") - 1)) {
441 free(eh->link);
442 eh->link = strdup(value);
443 } else if (!strncmp(kv, "mtime=",
444 sizeof("mtime=") - 1)) {
445 ret = sscanf(value, "%lld %n", &lln, &n);
446 if(ret < 1) {
447 ret = -EIO;
448 goto out;
449 }
450 eh->st.st_mtime = lln;
451 if (value[n] == '.') {
452 ret = sscanf(value + n + 1, "%d", &n);
453 if (ret < 1) {
454 ret = -EIO;
455 goto out;
456 }
457 #if ST_MTIM_NSEC
458 ST_MTIM_NSEC(&eh->st) = n;
459 #endif
460 }
461 eh->use_mtime = true;
462 } else if (!strncmp(kv, "size=",
463 sizeof("size=") - 1)) {
464 ret = sscanf(value, "%lld %n", &lln, &n);
465 if(ret < 1 || value[n] != '\0') {
466 ret = -EIO;
467 goto out;
468 }
469 eh->st.st_size = lln;
470 eh->use_size = true;
471 } else if (!strncmp(kv, "uid=", sizeof("uid=") - 1)) {
472 ret = sscanf(value, "%lld %n", &lln, &n);
473 if(ret < 1 || value[n] != '\0') {
474 ret = -EIO;
475 goto out;
476 }
477 eh->st.st_uid = lln;
478 eh->use_uid = true;
479 } else if (!strncmp(kv, "gid=", sizeof("gid=") - 1)) {
480 ret = sscanf(value, "%lld %n", &lln, &n);
481 if(ret < 1 || value[n] != '\0') {
482 ret = -EIO;
483 goto out;
484 }
485 eh->st.st_gid = lln;
486 eh->use_gid = true;
487 } else if (!strncmp(kv, "SCHILY.xattr.",
488 sizeof("SCHILY.xattr.") - 1)) {
489 char *key = kv + sizeof("SCHILY.xattr.") - 1;
490
491 --len; /* p[-1] == '\0' */
492 ret = tarerofs_insert_xattr(&eh->xattrs, key,
493 value - key - 1,
494 len - (key - kv), false);
495 if (ret)
496 goto out;
497 } else if (!strncmp(kv, "LIBARCHIVE.xattr.",
498 sizeof("LIBARCHIVE.xattr.") - 1)) {
499 char *key;
500 key = kv + sizeof("LIBARCHIVE.xattr.") - 1;
501
502 --len; /* p[-1] == '\0' */
503 ret = base64_decode(value, len - (value - kv),
504 (u8 *)value);
505 if (ret < 0) {
506 ret = -EFSCORRUPTED;
507 goto out;
508 }
509
510 ret = tarerofs_insert_xattr(&eh->xattrs, key,
511 value - key - 1,
512 value - key + ret, false);
513 if (ret)
514 goto out;
515 } else {
516 erofs_info("unrecognized pax keyword \"%s\", ignoring", kv);
517 }
518 }
519 }
520 ret = 0;
521 out:
522 free(buf);
523 return ret;
524 }
525
tarerofs_remove_inode(struct erofs_inode * inode)526 void tarerofs_remove_inode(struct erofs_inode *inode)
527 {
528 struct erofs_dentry *d;
529
530 --inode->i_nlink;
531 if (!S_ISDIR(inode->i_mode))
532 return;
533
534 /* remove all subdirss */
535 list_for_each_entry(d, &inode->i_subdirs, d_child) {
536 if (!is_dot_dotdot(d->name))
537 tarerofs_remove_inode(d->inode);
538 erofs_iput(d->inode);
539 d->inode = NULL;
540 }
541 --inode->i_parent->i_nlink;
542 }
543
tarerofs_write_file_data(struct erofs_inode * inode,struct erofs_tarfile * tar)544 static int tarerofs_write_file_data(struct erofs_inode *inode,
545 struct erofs_tarfile *tar)
546 {
547 unsigned int j;
548 void *buf;
549 int fd, nread;
550 u64 off;
551
552 if (!inode->i_diskbuf) {
553 inode->i_diskbuf = calloc(1, sizeof(*inode->i_diskbuf));
554 if (!inode->i_diskbuf)
555 return -ENOSPC;
556 } else {
557 erofs_diskbuf_close(inode->i_diskbuf);
558 }
559
560 fd = erofs_diskbuf_reserve(inode->i_diskbuf, 0, &off);
561 if (fd < 0)
562 return -EBADF;
563
564 for (j = inode->i_size; j; ) {
565 nread = erofs_iostream_read(&tar->ios, &buf, j);
566 if (nread < 0)
567 break;
568 if (write(fd, buf, nread) != nread) {
569 nread = -EIO;
570 break;
571 }
572 j -= nread;
573 }
574 erofs_diskbuf_commit(inode->i_diskbuf, inode->i_size);
575 inode->with_diskbuf = true;
576 return 0;
577 }
578
tarerofs_write_file_index(struct erofs_inode * inode,struct erofs_tarfile * tar,erofs_off_t data_offset)579 static int tarerofs_write_file_index(struct erofs_inode *inode,
580 struct erofs_tarfile *tar, erofs_off_t data_offset)
581 {
582 int ret;
583
584 ret = tarerofs_write_chunkes(inode, data_offset);
585 if (ret)
586 return ret;
587 if (erofs_iostream_lskip(&tar->ios, inode->i_size))
588 return -EIO;
589 return 0;
590 }
591
tarerofs_parse_tar(struct erofs_inode * root,struct erofs_tarfile * tar)592 int tarerofs_parse_tar(struct erofs_inode *root, struct erofs_tarfile *tar)
593 {
594 char path[PATH_MAX];
595 struct erofs_pax_header eh = tar->global;
596 struct erofs_sb_info *sbi = root->sbi;
597 bool whout, opq, e = false;
598 struct stat st;
599 erofs_off_t tar_offset, data_offset;
600
601 struct tar_header *th;
602 struct erofs_dentry *d;
603 struct erofs_inode *inode;
604 unsigned int j, csum, cksum;
605 int ckksum, ret, rem;
606
607 if (eh.path)
608 eh.path = strdup(eh.path);
609 if (eh.link)
610 eh.link = strdup(eh.link);
611 init_list_head(&eh.xattrs);
612
613 restart:
614 rem = tar->offset & 511;
615 if (rem) {
616 if (erofs_iostream_lskip(&tar->ios, 512 - rem)) {
617 ret = -EIO;
618 goto out;
619 }
620 tar->offset += 512 - rem;
621 }
622
623 tar_offset = tar->offset;
624 ret = erofs_iostream_read(&tar->ios, (void **)&th, sizeof(*th));
625 if (ret != sizeof(*th)) {
626 erofs_err("failed to read header block @ %llu", tar_offset);
627 ret = -EIO;
628 goto out;
629 }
630 tar->offset += sizeof(*th);
631 if (*th->name == '\0') {
632 if (e) { /* end of tar 2 empty blocks */
633 ret = 1;
634 goto out;
635 }
636 e = true; /* empty jump to next block */
637 goto restart;
638 }
639
640 /* chksum field itself treated as ' ' */
641 csum = tarerofs_otoi(th->chksum, sizeof(th->chksum));
642 if (errno) {
643 erofs_err("invalid chksum @ %llu", tar_offset);
644 ret = -EBADMSG;
645 goto out;
646 }
647 cksum = 0;
648 for (j = 0; j < 8; ++j)
649 cksum += (unsigned int)' ';
650 ckksum = cksum;
651 for (j = 0; j < 148; ++j) {
652 cksum += (unsigned int)((u8*)th)[j];
653 ckksum += (int)((char*)th)[j];
654 }
655 for (j = 156; j < 500; ++j) {
656 cksum += (unsigned int)((u8*)th)[j];
657 ckksum += (int)((char*)th)[j];
658 }
659 if (csum != cksum && csum != ckksum) {
660 erofs_err("chksum mismatch @ %llu", tar_offset);
661 ret = -EBADMSG;
662 goto out;
663 }
664
665 if (th->typeflag == GNUTYPE_VOLHDR) {
666 if (th->size[0])
667 erofs_warn("GNUTYPE_VOLHDR with non-zeroed size @ %llu",
668 tar_offset);
669 /* anyway, strncpy could cause some GCC warning here */
670 memcpy(sbi->volume_name, th->name, sizeof(sbi->volume_name));
671 goto restart;
672 }
673
674 if (memcmp(th->magic, "ustar", 5)) {
675 erofs_err("invalid tar magic @ %llu", tar_offset);
676 ret = -EIO;
677 goto out;
678 }
679
680 st.st_mode = tarerofs_otoi(th->mode, sizeof(th->mode));
681 if (errno)
682 goto invalid_tar;
683
684 if (eh.use_uid) {
685 st.st_uid = eh.st.st_uid;
686 } else {
687 st.st_uid = tarerofs_parsenum(th->uid, sizeof(th->uid));
688 if (errno)
689 goto invalid_tar;
690 }
691
692 if (eh.use_gid) {
693 st.st_gid = eh.st.st_gid;
694 } else {
695 st.st_gid = tarerofs_parsenum(th->gid, sizeof(th->gid));
696 if (errno)
697 goto invalid_tar;
698 }
699
700 if (eh.use_size) {
701 st.st_size = eh.st.st_size;
702 } else {
703 st.st_size = tarerofs_parsenum(th->size, sizeof(th->size));
704 if (errno)
705 goto invalid_tar;
706 }
707
708 if (eh.use_mtime) {
709 st.st_mtime = eh.st.st_mtime;
710 #if ST_MTIM_NSEC
711 ST_MTIM_NSEC(&st) = ST_MTIM_NSEC(&eh.st);
712 #endif
713 } else {
714 st.st_mtime = tarerofs_parsenum(th->mtime, sizeof(th->mtime));
715 if (errno)
716 goto invalid_tar;
717 }
718
719 if (th->typeflag <= '7' && !eh.path) {
720 eh.path = path;
721 j = 0;
722 if (*th->prefix) {
723 memcpy(path, th->prefix, sizeof(th->prefix));
724 path[sizeof(th->prefix)] = '\0';
725 j = strlen(path);
726 if (path[j - 1] != '/') {
727 path[j] = '/';
728 path[++j] = '\0';
729 }
730 }
731 memcpy(path + j, th->name, sizeof(th->name));
732 path[j + sizeof(th->name)] = '\0';
733 j = strlen(path);
734 while (path[j - 1] == '/')
735 path[--j] = '\0';
736 }
737
738 data_offset = tar->offset;
739 tar->offset += st.st_size;
740 switch(th->typeflag) {
741 case '0':
742 case '7':
743 case '1':
744 st.st_mode |= S_IFREG;
745 break;
746 case '2':
747 st.st_mode |= S_IFLNK;
748 break;
749 case '3':
750 st.st_mode |= S_IFCHR;
751 break;
752 case '4':
753 st.st_mode |= S_IFBLK;
754 break;
755 case '5':
756 st.st_mode |= S_IFDIR;
757 break;
758 case '6':
759 st.st_mode |= S_IFIFO;
760 break;
761 case 'g':
762 ret = tarerofs_parse_pax_header(&tar->ios, &tar->global,
763 st.st_size);
764 if (ret)
765 goto out;
766 if (tar->global.path) {
767 free(eh.path);
768 eh.path = strdup(tar->global.path);
769 }
770 if (tar->global.link) {
771 free(eh.link);
772 eh.link = strdup(tar->global.link);
773 }
774 goto restart;
775 case 'x':
776 ret = tarerofs_parse_pax_header(&tar->ios, &eh, st.st_size);
777 if (ret)
778 goto out;
779 goto restart;
780 case 'L':
781 free(eh.path);
782 eh.path = malloc(st.st_size + 1);
783 if (st.st_size != erofs_iostream_bread(&tar->ios, eh.path,
784 st.st_size))
785 goto invalid_tar;
786 eh.path[st.st_size] = '\0';
787 goto restart;
788 case 'K':
789 free(eh.link);
790 eh.link = malloc(st.st_size + 1);
791 if (st.st_size > PATH_MAX || st.st_size !=
792 erofs_iostream_bread(&tar->ios, eh.link, st.st_size))
793 goto invalid_tar;
794 eh.link[st.st_size] = '\0';
795 goto restart;
796 default:
797 erofs_info("unrecognized typeflag %xh @ %llu - ignoring",
798 th->typeflag, tar_offset);
799 (void)erofs_iostream_lskip(&tar->ios, st.st_size);
800 ret = 0;
801 goto out;
802 }
803
804 st.st_rdev = 0;
805 if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
806 int major, minor;
807
808 major = tarerofs_parsenum(th->devmajor, sizeof(th->devmajor));
809 if (errno) {
810 erofs_err("invalid device major @ %llu", tar_offset);
811 goto out;
812 }
813
814 minor = tarerofs_parsenum(th->devminor, sizeof(th->devminor));
815 if (errno) {
816 erofs_err("invalid device minor @ %llu", tar_offset);
817 goto out;
818 }
819
820 st.st_rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12);
821 } else if (th->typeflag == '1' || th->typeflag == '2') {
822 if (!eh.link)
823 eh.link = strndup(th->linkname, sizeof(th->linkname));
824 }
825
826 if (tar->index_mode && !tar->mapfile &&
827 erofs_blkoff(sbi, data_offset)) {
828 erofs_err("invalid tar data alignment @ %llu", tar_offset);
829 ret = -EIO;
830 goto out;
831 }
832
833 erofs_dbg("parsing %s (mode %05o)", eh.path, st.st_mode);
834
835 d = erofs_rebuild_get_dentry(root, eh.path, tar->aufs, &whout, &opq, true);
836 if (IS_ERR(d)) {
837 ret = PTR_ERR(d);
838 goto out;
839 }
840
841 if (!d) {
842 /* some tarballs include '.' which indicates the root directory */
843 if (!S_ISDIR(st.st_mode)) {
844 ret = -ENOTDIR;
845 goto out;
846 }
847 inode = root;
848 } else if (opq) {
849 DBG_BUGON(d->type == EROFS_FT_UNKNOWN);
850 DBG_BUGON(!d->inode);
851 ret = erofs_set_opaque_xattr(d->inode);
852 goto out;
853 } else if (th->typeflag == '1') { /* hard link cases */
854 struct erofs_dentry *d2;
855 bool dumb;
856
857 if (S_ISDIR(st.st_mode)) {
858 ret = -EISDIR;
859 goto out;
860 }
861
862 if (d->type != EROFS_FT_UNKNOWN) {
863 tarerofs_remove_inode(d->inode);
864 erofs_iput(d->inode);
865 }
866 d->inode = NULL;
867
868 d2 = erofs_rebuild_get_dentry(root, eh.link, tar->aufs,
869 &dumb, &dumb, false);
870 if (IS_ERR(d2)) {
871 ret = PTR_ERR(d2);
872 goto out;
873 }
874 if (d2->type == EROFS_FT_UNKNOWN) {
875 ret = -ENOENT;
876 goto out;
877 }
878 if (S_ISDIR(d2->inode->i_mode)) {
879 ret = -EISDIR;
880 goto out;
881 }
882 inode = erofs_igrab(d2->inode);
883 d->inode = inode;
884 d->type = d2->type;
885 ++inode->i_nlink;
886 ret = 0;
887 goto out;
888 } else if (d->type != EROFS_FT_UNKNOWN) {
889 if (d->type != EROFS_FT_DIR || !S_ISDIR(st.st_mode)) {
890 struct erofs_inode *parent = d->inode->i_parent;
891
892 tarerofs_remove_inode(d->inode);
893 erofs_iput(d->inode);
894 d->inode = parent;
895 goto new_inode;
896 }
897 inode = d->inode;
898 } else {
899 new_inode:
900 inode = erofs_new_inode();
901 if (IS_ERR(inode)) {
902 ret = PTR_ERR(inode);
903 goto out;
904 }
905 inode->i_parent = d->inode;
906 d->inode = inode;
907 d->type = erofs_mode_to_ftype(st.st_mode);
908 }
909
910 if (whout) {
911 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFCHR;
912 inode->u.i_rdev = EROFS_WHITEOUT_DEV;
913 d->type = EROFS_FT_CHRDEV;
914
915 /*
916 * Mark the parent directory as copied-up to avoid exposing
917 * whiteouts if mounted. See kernel commit b79e05aaa166
918 * ("ovl: no direct iteration for dir with origin xattr")
919 */
920 inode->i_parent->whiteouts = true;
921 } else {
922 inode->i_mode = st.st_mode;
923 if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
924 inode->u.i_rdev = erofs_new_encode_dev(st.st_rdev);
925 }
926
927 inode->i_srcpath = strdup(eh.path);
928 if (!inode->i_srcpath) {
929 ret = -ENOMEM;
930 goto out;
931 }
932
933 ret = __erofs_fill_inode(inode, &st, eh.path);
934 if (ret)
935 goto out;
936 inode->i_size = st.st_size;
937
938 if (!S_ISDIR(inode->i_mode)) {
939 if (S_ISLNK(inode->i_mode)) {
940 inode->i_size = strlen(eh.link);
941 inode->i_link = malloc(inode->i_size + 1);
942 memcpy(inode->i_link, eh.link, inode->i_size + 1);
943 } else if (inode->i_size) {
944 if (tar->index_mode)
945 ret = tarerofs_write_file_index(inode, tar,
946 data_offset);
947 else
948 ret = tarerofs_write_file_data(inode, tar);
949 if (ret)
950 goto out;
951 }
952 inode->i_nlink++;
953 } else if (!inode->i_nlink) {
954 ret = erofs_init_empty_dir(inode);
955 if (ret)
956 goto out;
957 }
958
959 ret = tarerofs_merge_xattrs(&eh.xattrs, &tar->global.xattrs);
960 if (ret)
961 goto out;
962
963 ret = tarerofs_apply_xattrs(inode, &eh.xattrs);
964
965 out:
966 if (eh.path != path)
967 free(eh.path);
968 free(eh.link);
969 tarerofs_remove_xattrs(&eh.xattrs);
970 return ret;
971
972 invalid_tar:
973 erofs_err("invalid tar @ %llu", tar_offset);
974 ret = -EIO;
975 goto out;
976 }
977