1/*-
2 * Copyright (c) 2007-2014, Juniper Networks, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/11/stand/libsa/pkgfs.c 346477 2019-04-21 03:43:27Z kevans $");
29
30#include "stand.h"
31
32#include <sys/stat.h>
33#include <sys/stdint.h>
34#include <string.h>
35#include <zlib.h>
36
37#ifdef PKGFS_DEBUG
38#define	DBG(x)	printf x
39#else
40#define	DBG(x)
41#endif
42
43static int   pkg_open(const char *, struct open_file *);
44static int   pkg_close(struct open_file *);
45static int   pkg_read(struct open_file *, void *, size_t, size_t *);
46static off_t pkg_seek(struct open_file *, off_t, int);
47static int   pkg_stat(struct open_file *, struct stat *);
48static int   pkg_readdir(struct open_file *, struct dirent *);
49
50struct fs_ops pkgfs_fsops = {
51	"pkg",
52	pkg_open,
53	pkg_close,
54	pkg_read,
55	null_write,
56	pkg_seek,
57	pkg_stat,
58	pkg_readdir
59};
60
61#define PKG_BUFSIZE	512
62#define	PKG_MAXCACHESZ	4096
63
64#define	PKG_FILEEXT	".tgz"
65
66/*
67 * Layout of POSIX 'ustar' header.
68 */
69struct ustar_hdr {
70	char	ut_name[100];
71	char	ut_mode[8];
72	char	ut_uid[8];
73	char	ut_gid[8];
74	char	ut_size[12];
75	char	ut_mtime[12];
76	char	ut_checksum[8];
77	char	ut_typeflag[1];
78	char	ut_linkname[100];
79	char	ut_magic[6];		/* For POSIX: "ustar\0" */
80	char	ut_version[2];		/* For POSIX: "00" */
81	char	ut_uname[32];
82	char	ut_gname[32];
83	char	ut_rdevmajor[8];
84	char	ut_rdevminor[8];
85	union {
86		struct {
87			char	prefix[155];
88		} posix;
89		struct {
90			char	atime[12];
91			char	ctime[12];
92			char	offset[12];
93			char	longnames[4];
94			char	unused[1];
95			struct gnu_sparse {
96				char	offset[12];
97				char	numbytes[12];
98			} sparse[4];
99			char	isextended[1];
100			char	realsize[12];
101		} gnu;
102	} u;
103	u_char __padding[12];
104};
105
106struct package;
107
108struct tarfile
109{
110	struct package *tf_pkg;
111	struct tarfile *tf_next;
112	struct ustar_hdr tf_hdr;
113	off_t	tf_ofs;
114	off_t	tf_size;
115	off_t	tf_fp;
116	size_t	tf_cachesz;
117	void	*tf_cache;
118};
119
120struct package
121{
122	struct package *pkg_chain;
123	int	pkg_fd;
124	off_t	pkg_ofs;
125	z_stream pkg_zs;
126	struct tarfile *pkg_first;
127	struct tarfile *pkg_last;
128	u_char	pkg_buf[PKG_BUFSIZE];
129};
130
131static struct package *package = NULL;
132
133static int new_package(int, struct package **);
134
135void
136pkgfs_cleanup(void)
137{
138	struct package *chain;
139	struct tarfile *tf, *tfn;
140
141	while (package != NULL) {
142		inflateEnd(&package->pkg_zs);
143		close(package->pkg_fd);
144
145		tf = package->pkg_first;
146		while (tf != NULL) {
147			tfn = tf->tf_next;
148			if (tf->tf_cachesz > 0)
149				free(tf->tf_cache);
150			free(tf);
151			tf = tfn;
152		}
153
154		chain = package->pkg_chain;
155		free(package);
156		package = chain;
157	}
158}
159
160int
161pkgfs_init(const char *pkgname, struct fs_ops *proto)
162{
163	struct package *pkg;
164	int error, fd;
165
166	pkg = NULL;
167	if (proto != &pkgfs_fsops)
168		pkgfs_cleanup();
169
170	exclusive_file_system = proto;
171
172	fd = open(pkgname, O_RDONLY);
173
174	exclusive_file_system = NULL;
175
176	if (fd == -1)
177		return (errno);
178
179	error = new_package(fd, &pkg);
180	if (error) {
181		close(fd);
182		return (error);
183	}
184
185	if (pkg == NULL)
186		return (EDOOFUS);
187
188	pkg->pkg_chain = package;
189	package = pkg;
190	exclusive_file_system = &pkgfs_fsops;
191	return (0);
192}
193
194static int get_mode(struct tarfile *);
195static int get_zipped(struct package *, void *, size_t);
196static int new_package(int, struct package **);
197static struct tarfile *scan_tarfile(struct package *, struct tarfile *);
198
199static int
200pkg_open(const char *fn, struct open_file *f)
201{
202	struct tarfile *tf;
203
204	if (fn == NULL || f == NULL)
205		return (EINVAL);
206
207	if (package == NULL)
208		return (ENXIO);
209
210	/*
211	 * We can only read from a package, so reject request to open
212	 * for write-only or read-write.
213	 */
214	if (f->f_flags != F_READ)
215		return (EPERM);
216
217	/*
218	 * Scan the file headers for the named file. We stop scanning
219	 * at the first filename that has the .pkg extension. This is
220	 * a package within a package. We assume we have all the files
221	 * we need up-front and without having to dig within nested
222	 * packages.
223	 *
224	 * Note that we preserve streaming properties as much as possible.
225	 */
226	while (*fn == '/')
227		fn++;
228
229	/*
230	 * Allow opening of the root directory for use by readdir()
231	 * to support listing files in the package.
232	 */
233	if (*fn == '\0') {
234		f->f_fsdata = NULL;
235		return (0);
236	}
237
238	tf = scan_tarfile(package, NULL);
239	while (tf != NULL) {
240		if (strcmp(fn, tf->tf_hdr.ut_name) == 0) {
241			f->f_fsdata = tf;
242			tf->tf_fp = 0;	/* Reset the file pointer. */
243			return (0);
244		}
245		tf = scan_tarfile(package, tf);
246	}
247	return (errno);
248}
249
250static int
251pkg_close(struct open_file *f)
252{
253	struct tarfile *tf;
254
255	tf = (struct tarfile *)f->f_fsdata;
256	if (tf == NULL)
257		return (0);
258
259	/*
260	 * Free up the cache if we read all of the file.
261	 */
262	if (tf->tf_fp == tf->tf_size && tf->tf_cachesz > 0) {
263		free(tf->tf_cache);
264		tf->tf_cachesz = 0;
265	}
266	return (0);
267}
268
269static int
270pkg_read(struct open_file *f, void *buf, size_t size, size_t *res)
271{
272	struct tarfile *tf;
273	char *p;
274	off_t fp;
275	size_t sz;
276
277	tf = (struct tarfile *)f->f_fsdata;
278	if (tf == NULL) {
279		if (res != NULL)
280			*res = size;
281		return (EBADF);
282	}
283
284	fp = tf->tf_fp;
285	p = buf;
286	sz = 0;
287	while (size > 0) {
288		sz = tf->tf_size - fp;
289		if (fp < tf->tf_cachesz && tf->tf_cachesz < tf->tf_size)
290			sz = tf->tf_cachesz - fp;
291		if (size < sz)
292			sz = size;
293		if (sz == 0)
294			break;
295
296		if (fp < tf->tf_cachesz) {
297			/* Satisfy the request from cache. */
298			memcpy(p, tf->tf_cache + fp, sz);
299			fp += sz;
300			p += sz;
301			size -= sz;
302			continue;
303		}
304
305		if (get_zipped(tf->tf_pkg, p, sz) == -1) {
306			sz = -1;
307			break;
308		}
309
310		fp += sz;
311		p += sz;
312		size -= sz;
313
314		if (tf->tf_cachesz != 0)
315			continue;
316
317		tf->tf_cachesz = (sz <= PKG_MAXCACHESZ) ? sz : PKG_MAXCACHESZ;
318		tf->tf_cache = malloc(tf->tf_cachesz);
319		if (tf->tf_cache != NULL)
320			memcpy(tf->tf_cache, buf, tf->tf_cachesz);
321		else
322			tf->tf_cachesz = 0;
323	}
324
325	tf->tf_fp = fp;
326	if (res != NULL)
327		*res = size;
328	return ((sz == -1) ? errno : 0);
329}
330
331static off_t
332pkg_seek(struct open_file *f, off_t ofs, int whence)
333{
334	char buf[512];
335	struct tarfile *tf;
336	off_t delta;
337	size_t sz, res;
338	int error;
339
340	tf = (struct tarfile *)f->f_fsdata;
341	if (tf == NULL) {
342		errno = EBADF;
343		return (-1);
344	}
345
346	switch (whence) {
347	case SEEK_SET:
348		delta = ofs - tf->tf_fp;
349		break;
350	case SEEK_CUR:
351		delta = ofs;
352		break;
353	case SEEK_END:
354		delta = tf->tf_size - tf->tf_fp + ofs;
355		break;
356	default:
357		errno = EINVAL;
358		return (-1);
359	}
360
361	if (delta < 0) {
362		DBG(("%s: negative file seek (%jd)\n", __func__,
363		    (intmax_t)delta));
364		errno = ESPIPE;
365		return (-1);
366	}
367
368	while (delta > 0 && tf->tf_fp < tf->tf_size) {
369		sz = (delta > sizeof(buf)) ? sizeof(buf) : delta;
370		error = pkg_read(f, buf, sz, &res);
371		if (error != 0) {
372			errno = error;
373			return (-1);
374		}
375		delta -= sz - res;
376	}
377
378	return (tf->tf_fp);
379}
380
381static int
382pkg_stat(struct open_file *f, struct stat *sb)
383{
384	struct tarfile *tf;
385
386	tf = (struct tarfile *)f->f_fsdata;
387	if (tf == NULL)
388		return (EBADF);
389	memset(sb, 0, sizeof(*sb));
390	sb->st_mode = get_mode(tf);
391	sb->st_size = tf->tf_size;
392	sb->st_blocks = (tf->tf_size + 511) / 512;
393	return (0);
394}
395
396static int
397pkg_readdir(struct open_file *f, struct dirent *d)
398{
399	struct tarfile *tf;
400
401	tf = (struct tarfile *)f->f_fsdata;
402	if (tf != NULL)
403		return (EBADF);
404
405	tf = scan_tarfile(package, NULL);
406	if (tf == NULL)
407		return (ENOENT);
408
409	d->d_fileno = 0;
410	d->d_reclen = sizeof(*d);
411	d->d_type = DT_REG;
412	memcpy(d->d_name, tf->tf_hdr.ut_name, sizeof(d->d_name));
413	return (0);
414}
415
416/*
417 * Low-level support functions.
418 */
419
420static int
421get_byte(struct package *pkg, off_t *op)
422{
423	int c;
424
425	if (pkg->pkg_zs.avail_in == 0) {
426		c = read(pkg->pkg_fd, pkg->pkg_buf, PKG_BUFSIZE);
427		if (c <= 0)
428			return (-1);
429		pkg->pkg_zs.avail_in = c;
430		pkg->pkg_zs.next_in = pkg->pkg_buf;
431	}
432
433	c = *pkg->pkg_zs.next_in;
434	pkg->pkg_zs.next_in++;
435	pkg->pkg_zs.avail_in--;
436	(*op)++;
437	return (c);
438}
439
440static int
441get_zipped(struct package *pkg, void *buf, size_t bufsz)
442{
443	int c;
444
445	pkg->pkg_zs.next_out = buf;
446	pkg->pkg_zs.avail_out = bufsz;
447
448	while (pkg->pkg_zs.avail_out) {
449		if (pkg->pkg_zs.avail_in == 0) {
450			c = read(pkg->pkg_fd, pkg->pkg_buf, PKG_BUFSIZE);
451			if (c <= 0) {
452				errno = EIO;
453				return (-1);
454			}
455			pkg->pkg_zs.avail_in = c;
456			pkg->pkg_zs.next_in = pkg->pkg_buf;
457		}
458
459		c = inflate(&pkg->pkg_zs, Z_SYNC_FLUSH);
460		if (c != Z_OK && c != Z_STREAM_END) {
461			errno = EIO;
462			return (-1);
463		}
464	}
465
466	pkg->pkg_ofs += bufsz;
467	return (0);
468}
469
470static int
471cache_data(struct tarfile *tf)
472{
473	struct package *pkg;
474	size_t sz;
475
476	if (tf == NULL) {
477		DBG(("%s: no file to cache data for?\n", __func__));
478		errno = EINVAL;
479		return (-1);
480	}
481
482	pkg = tf->tf_pkg;
483	if (pkg == NULL) {
484		DBG(("%s: no package associated with file?\n", __func__));
485		errno = EINVAL;
486		return (-1);
487	}
488
489	if (tf->tf_ofs != pkg->pkg_ofs) {
490		DBG(("%s: caching after partial read of file %s?\n",
491		    __func__, tf->tf_hdr.ut_name));
492		errno = EINVAL;
493		return (-1);
494	}
495
496	/* We don't cache everything... */
497	if (tf->tf_size > PKG_MAXCACHESZ) {
498		errno = ENOMEM;
499		return (-1);
500	}
501
502	/* All files are padded to a multiple of 512 bytes. */
503	sz = (tf->tf_size + 0x1ff) & ~0x1ff;
504
505	tf->tf_cache = malloc(sz);
506	if (tf->tf_cache == NULL) {
507		DBG(("%s: could not allocate %d bytes\n", __func__, (int)sz));
508		errno = ENOMEM;
509		return (-1);
510	}
511
512	tf->tf_cachesz = sz;
513	return (get_zipped(pkg, tf->tf_cache, sz));
514}
515
516/*
517 * Note that this implementation does not (and should not!) obey
518 * locale settings; you cannot simply substitute strtol here, since
519 * it does obey locale.
520 */
521static off_t
522pkg_atol8(const char *p, unsigned char_cnt)
523{
524        int64_t l, limit, last_digit_limit;
525        int digit, sign, base;
526
527        base = 8;
528        limit = INT64_MAX / base;
529        last_digit_limit = INT64_MAX % base;
530
531        while (*p == ' ' || *p == '\t')
532                p++;
533        if (*p == '-') {
534                sign = -1;
535                p++;
536        } else
537                sign = 1;
538
539        l = 0;
540        digit = *p - '0';
541        while (digit >= 0 && digit < base  && char_cnt-- > 0) {
542                if (l>limit || (l == limit && digit > last_digit_limit)) {
543                        l = UINT64_MAX; /* Truncate on overflow. */
544                        break;
545                }
546                l = (l * base) + digit;
547                digit = *++p - '0';
548        }
549        return (sign < 0) ? -l : l;
550}
551
552/*
553 * Parse a base-256 integer.  This is just a straight signed binary
554 * value in big-endian order, except that the high-order bit is
555 * ignored.  Remember that "int64_t" may or may not be exactly 64
556 * bits; the implementation here tries to avoid making any assumptions
557 * about the actual size of an int64_t.  It does assume we're using
558 * twos-complement arithmetic, though.
559 */
560static int64_t
561pkg_atol256(const char *_p, unsigned char_cnt)
562{
563        int64_t l, upper_limit, lower_limit;
564        const unsigned char *p = (const unsigned char *)_p;
565
566        upper_limit = INT64_MAX / 256;
567        lower_limit = INT64_MIN / 256;
568
569        /* Pad with 1 or 0 bits, depending on sign. */
570        if ((0x40 & *p) == 0x40)
571                l = (int64_t)-1;
572        else
573                l = 0;
574        l = (l << 6) | (0x3f & *p++);
575        while (--char_cnt > 0) {
576                if (l > upper_limit) {
577                        l = INT64_MAX; /* Truncate on overflow */
578                        break;
579                } else if (l < lower_limit) {
580                        l = INT64_MIN;
581                        break;
582                }
583                l = (l << 8) | (0xff & (int64_t)*p++);
584        }
585        return (l);
586}
587
588static off_t
589pkg_atol(const char *p, unsigned char_cnt)
590{
591	/*
592	 * Technically, GNU pkg considers a field to be in base-256
593	 * only if the first byte is 0xff or 0x80.
594	 */
595	if (*p & 0x80)
596		return (pkg_atol256(p, char_cnt));
597	return (pkg_atol8(p, char_cnt));
598}
599
600static int
601get_mode(struct tarfile *tf)
602{
603	return (pkg_atol(tf->tf_hdr.ut_mode, sizeof(tf->tf_hdr.ut_mode)));
604}
605
606/* GZip flag byte */
607#define ASCII_FLAG	0x01 /* bit 0 set: file probably ascii text */
608#define HEAD_CRC	0x02 /* bit 1 set: header CRC present */
609#define EXTRA_FIELD	0x04 /* bit 2 set: extra field present */
610#define ORIG_NAME	0x08 /* bit 3 set: original file name present */
611#define COMMENT		0x10 /* bit 4 set: file comment present */
612#define RESERVED	0xE0 /* bits 5..7: reserved */
613
614static int
615new_package(int fd, struct package **pp)
616{
617	struct package *pkg;
618	off_t ofs;
619	int flags, i, error;
620
621	pkg = malloc(sizeof(*pkg));
622	if (pkg == NULL)
623		return (ENOMEM);
624
625	bzero(pkg, sizeof(*pkg));
626	pkg->pkg_fd = fd;
627
628	/*
629	 * Parse the header.
630	 */
631	error = EFTYPE;
632	ofs = 0;
633
634	/* Check megic. */
635	if (get_byte(pkg, &ofs) != 0x1f || get_byte(pkg, &ofs) != 0x8b)
636		goto fail;
637	/* Check method. */
638	if (get_byte(pkg, &ofs) != Z_DEFLATED)
639		goto fail;
640	/* Check flags. */
641	flags = get_byte(pkg, &ofs);
642	if (flags & RESERVED)
643		goto fail;
644
645	/* Skip time, xflags and OS code. */
646	for (i = 0; i < 6; i++) {
647		if (get_byte(pkg, &ofs) == -1)
648			goto fail;
649	}
650
651	/* Skip extra field. */
652	if (flags & EXTRA_FIELD) {
653		i = (get_byte(pkg, &ofs) & 0xff) |
654		    ((get_byte(pkg, &ofs) << 8) & 0xff);
655		while (i-- > 0) {
656			if (get_byte(pkg, &ofs) == -1)
657				goto fail;
658		}
659	}
660
661	/* Skip original file name. */
662	if (flags & ORIG_NAME) {
663		do {
664			i = get_byte(pkg, &ofs);
665		} while (i != 0 && i != -1);
666		if (i == -1)
667			goto fail;
668	}
669
670	/* Print the comment if it's there. */
671	if (flags & COMMENT) {
672		while (1) {
673			i = get_byte(pkg, &ofs);
674			if (i == -1)
675				goto fail;
676			if (i == 0)
677				break;
678			putchar(i);
679		}
680	}
681
682	/* Skip the CRC. */
683	if (flags & HEAD_CRC) {
684		if (get_byte(pkg, &ofs) == -1)
685			goto fail;
686		if (get_byte(pkg, &ofs) == -1)
687			goto fail;
688	}
689
690	/*
691	 * Done parsing the ZIP header. Spkgt the inflation engine.
692	 */
693	error = inflateInit2(&pkg->pkg_zs, -15);
694	if (error != Z_OK)
695		goto fail;
696
697	*pp = pkg;
698	return (0);
699
700 fail:
701	free(pkg);
702	return (error);
703}
704
705static struct tarfile *
706scan_tarfile(struct package *pkg, struct tarfile *last)
707{
708	char buf[512];
709	struct tarfile *cur;
710	off_t ofs;
711	size_t sz;
712
713	cur = (last != NULL) ? last->tf_next : pkg->pkg_first;
714	if (cur == NULL) {
715		ofs = (last != NULL) ? last->tf_ofs + last->tf_size :
716		    pkg->pkg_ofs;
717		ofs = (ofs + 0x1ff) & ~0x1ff;
718
719		/* Check if we've reached EOF. */
720		if (ofs < pkg->pkg_ofs) {
721			errno = ENOSPC;
722			return (NULL);
723		}
724
725		if (ofs != pkg->pkg_ofs) {
726			if (last != NULL && pkg->pkg_ofs == last->tf_ofs) {
727				if (cache_data(last) == -1)
728					return (NULL);
729			} else {
730				sz = ofs - pkg->pkg_ofs;
731				while (sz != 0) {
732					if (sz > sizeof(buf))
733						sz = sizeof(buf);
734					if (get_zipped(pkg, buf, sz) == -1)
735						return (NULL);
736					sz = ofs - pkg->pkg_ofs;
737				}
738			}
739		}
740
741		cur = malloc(sizeof(*cur));
742		if (cur == NULL)
743			return (NULL);
744		memset(cur, 0, sizeof(*cur));
745		cur->tf_pkg = pkg;
746
747		while (1) {
748			if (get_zipped(pkg, &cur->tf_hdr,
749			    sizeof(cur->tf_hdr)) == -1) {
750				free(cur);
751				return (NULL);
752			}
753
754			/*
755			 * There are always 2 empty blocks appended to
756			 * a PKG. It marks the end of the archive.
757			 */
758			if (strncmp(cur->tf_hdr.ut_magic, "ustar", 5) != 0) {
759				free(cur);
760				errno = ENOSPC;
761				return (NULL);
762			}
763
764			cur->tf_ofs = pkg->pkg_ofs;
765			cur->tf_size = pkg_atol(cur->tf_hdr.ut_size,
766			    sizeof(cur->tf_hdr.ut_size));
767
768			if (cur->tf_hdr.ut_name[0] != '+')
769				break;
770
771			/*
772			 * Skip package meta-files.
773			 */
774			ofs = cur->tf_ofs + cur->tf_size;
775			ofs = (ofs + 0x1ff) & ~0x1ff;
776			while (pkg->pkg_ofs < ofs) {
777				if (get_zipped(pkg, buf, sizeof(buf)) == -1) {
778					free(cur);
779					return (NULL);
780				}
781			}
782		}
783
784		if (last != NULL)
785			last->tf_next = cur;
786		else
787			pkg->pkg_first = cur;
788		pkg->pkg_last = cur;
789	}
790
791	return (cur);
792}
793