1 /* @(#)open.c	1.5 18/05/17 Copyright 2017-2018 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)open.c	1.5 18/05/17 Copyright 2017-2018 J. Schilling";
6 #endif
7 /*
8  *	Open a StreamArchive
9  *
10  *	Copyright (c) 2017-2018 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 #include <schily/stdio.h>
27 #include <schily/utypes.h>
28 #include <schily/schily.h>
29 #include <schily/errno.h>
30 #include <schily/strar.h>
31 #include "header.h"
32 
33 #define	my_uid		strar_my_uid
34 #define	mode_mask	strar_mode_mask
35 #define	old_umask	strar_old_umask
36 
37 #define	ROOT_UID	0
38 
39 EXPORT	uid_t	my_uid;
40 
41 /*
42  * This is used to allow extracting archives as non root when they
43  * contain read only directories. It tries to stay as close as possible
44  * to the user's umask when creating intermediate directories.
45  * We do not modify the umask in a way that would even grant unepected
46  * permissions to others for a short time.
47  */
48 EXPORT	mode_t	mode_mask;
49 EXPORT	mode_t	old_umask;
50 
51 #define	PERM_BITS	(S_IRWXU|S_IRWXG|S_IRWXO)	/* u/g/o basic perm */
52 
53 LOCAL	void	init_umask	__PR((void));
54 
55 LOCAL void
init_umask()56 init_umask()
57 {
58 	old_umask = umask((mode_t)0);
59 	mode_mask = PERM_BITS & ~old_umask;
60 	if (my_uid != ROOT_UID)
61 		umask(old_umask & ~S_IRWXU);
62 	else
63 		umask(old_umask);
64 }
65 
66 int
strar_open(info,arname,arfd,mode,codeset)67 strar_open(info, arname, arfd, mode, codeset)
68 	register FINFO	*info;
69 	const	char	*arname;
70 		int	arfd;
71 		int	mode;
72 	const	char	*codeset;
73 {
74 	strar_init(info);
75 
76 	if (arname) {
77 		info->f_fpname = arname;
78 		if (mode & OM_ARFD) {
79 			if ((info->f_fp = fileluopen(arfd,
80 					(mode & OM_READ) ? "r":"wct")) == NULL)
81 				return (-1);
82 		} else if ((info->f_fp = fileopen(arname,
83 					(mode & OM_READ) ? "r":"wct")) == NULL)
84 			return (-1);
85 	} else {
86 		if (mode & OM_READ) {
87 			info->f_fpname = "stdin";
88 			info->f_fp = stdin;
89 		} else if (mode & OM_WRITE) {
90 			info->f_fpname = "stdout";
91 			info->f_fp = stdout;
92 		} else {
93 			seterrno(EINVAL);
94 			return (-1);
95 		}
96 	}
97 	my_uid = geteuid();
98 	init_umask();
99 	utf8_codeset(codeset);
100 	if (mode & OM_READ) {
101 		utf8_init(S_EXTRACT);
102 	} else if (mode & OM_WRITE) {
103 		utf8_init(S_CREATE);
104 	}
105 
106 	return (0);
107 }
108