xref: /illumos-gate/usr/src/contrib/ast/src/lib/libast/preroot/getpreroot.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
19*b30d1939SAndy Fiddaman *                   Phong Vo <kpv@research.att.com>                    *
20*b30d1939SAndy Fiddaman *                                                                      *
21*b30d1939SAndy Fiddaman ***********************************************************************/
22*b30d1939SAndy Fiddaman #pragma prototyped
23*b30d1939SAndy Fiddaman /*
24*b30d1939SAndy Fiddaman  * AT&T Bell Laboratories
25*b30d1939SAndy Fiddaman  * return the real absolute pathname of the preroot dir for cmd
26*b30d1939SAndy Fiddaman  * if cmd==0 then current preroot path returned
27*b30d1939SAndy Fiddaman  */
28*b30d1939SAndy Fiddaman 
29*b30d1939SAndy Fiddaman #include <ast.h>
30*b30d1939SAndy Fiddaman #include <preroot.h>
31*b30d1939SAndy Fiddaman 
32*b30d1939SAndy Fiddaman #if FS_PREROOT
33*b30d1939SAndy Fiddaman 
34*b30d1939SAndy Fiddaman #include <ast_dir.h>
35*b30d1939SAndy Fiddaman #include <ls.h>
36*b30d1939SAndy Fiddaman #include <error.h>
37*b30d1939SAndy Fiddaman #include <stdio.h>
38*b30d1939SAndy Fiddaman 
39*b30d1939SAndy Fiddaman #ifndef ERANGE
40*b30d1939SAndy Fiddaman #define ERANGE		E2BIG
41*b30d1939SAndy Fiddaman #endif
42*b30d1939SAndy Fiddaman 
43*b30d1939SAndy Fiddaman #define ERROR(e)	{errno=e;goto error;}
44*b30d1939SAndy Fiddaman 
45*b30d1939SAndy Fiddaman char*
getpreroot(char * path,const char * cmd)46*b30d1939SAndy Fiddaman getpreroot(char* path, const char* cmd)
47*b30d1939SAndy Fiddaman {
48*b30d1939SAndy Fiddaman 	register int	c;
49*b30d1939SAndy Fiddaman 	register FILE*	fp;
50*b30d1939SAndy Fiddaman 	register char*	p;
51*b30d1939SAndy Fiddaman 	char		buf[PATH_MAX];
52*b30d1939SAndy Fiddaman 
53*b30d1939SAndy Fiddaman 	if (!path) path = buf;
54*b30d1939SAndy Fiddaman 	if (cmd)
55*b30d1939SAndy Fiddaman 	{
56*b30d1939SAndy Fiddaman 		sfsprintf(buf, sizeof(buf), "set x `%s= %s - </dev/null 2>&1`\nwhile :\ndo\nshift\ncase $# in\n[012]) break ;;\nesac\ncase \"$1 $2\" in\n\"+ %s\")	echo $3; exit ;;\nesac\ndone\necho\n", PR_SILENT, cmd, PR_COMMAND);
57*b30d1939SAndy Fiddaman 		if (!(fp = popen(buf, "rug"))) return(0);
58*b30d1939SAndy Fiddaman 		for (p = path; (c = getc(fp)) != EOF && c != '\n'; *p++ = c);
59*b30d1939SAndy Fiddaman 		*p = 0;
60*b30d1939SAndy Fiddaman 		pclose(fp);
61*b30d1939SAndy Fiddaman 		if (path == p) return(0);
62*b30d1939SAndy Fiddaman 		return(path == buf ? strdup(path) : path);
63*b30d1939SAndy Fiddaman 	}
64*b30d1939SAndy Fiddaman 	else
65*b30d1939SAndy Fiddaman 	{
66*b30d1939SAndy Fiddaman 		char*		d;
67*b30d1939SAndy Fiddaman 		DIR*		dirp = 0;
68*b30d1939SAndy Fiddaman 		int		namlen;
69*b30d1939SAndy Fiddaman 		int		euid;
70*b30d1939SAndy Fiddaman 		int		ruid;
71*b30d1939SAndy Fiddaman 		struct dirent*	entry;
72*b30d1939SAndy Fiddaman 		struct stat*	cur;
73*b30d1939SAndy Fiddaman 		struct stat*	par;
74*b30d1939SAndy Fiddaman 		struct stat*	tmp;
75*b30d1939SAndy Fiddaman 		struct stat	curst;
76*b30d1939SAndy Fiddaman 		struct stat	parst;
77*b30d1939SAndy Fiddaman 		struct stat	tstst;
78*b30d1939SAndy Fiddaman 		char		dots[PATH_MAX];
79*b30d1939SAndy Fiddaman 
80*b30d1939SAndy Fiddaman 		cur = &curst;
81*b30d1939SAndy Fiddaman 		par = &parst;
82*b30d1939SAndy Fiddaman 		if ((ruid = getuid()) != (euid = geteuid())) setuid(ruid);
83*b30d1939SAndy Fiddaman 		if (stat(PR_REAL, cur) || stat("/", par) || cur->st_dev == par->st_dev && cur->st_ino == par->st_ino) ERROR(ENOTDIR);
84*b30d1939SAndy Fiddaman 
85*b30d1939SAndy Fiddaman 		/*
86*b30d1939SAndy Fiddaman 		 * like getcwd() but starting at the preroot
87*b30d1939SAndy Fiddaman 		 */
88*b30d1939SAndy Fiddaman 
89*b30d1939SAndy Fiddaman 		d = dots;
90*b30d1939SAndy Fiddaman 		*d++ = '/';
91*b30d1939SAndy Fiddaman 		p = path + PATH_MAX - 1;
92*b30d1939SAndy Fiddaman 		*p = 0;
93*b30d1939SAndy Fiddaman 		for (;;)
94*b30d1939SAndy Fiddaman 		{
95*b30d1939SAndy Fiddaman 			tmp = cur;
96*b30d1939SAndy Fiddaman 			cur = par;
97*b30d1939SAndy Fiddaman 			par = tmp;
98*b30d1939SAndy Fiddaman 			if ((d - dots) > (PATH_MAX - 4)) ERROR(ERANGE);
99*b30d1939SAndy Fiddaman 			*d++ = '.';
100*b30d1939SAndy Fiddaman 			*d++ = '.';
101*b30d1939SAndy Fiddaman 			*d = 0;
102*b30d1939SAndy Fiddaman 			if (!(dirp = opendir(dots))) ERROR(errno);
103*b30d1939SAndy Fiddaman #if !_dir_ok || _mem_dd_fd_DIR
104*b30d1939SAndy Fiddaman 			if (fstat(dirp->dd_fd, par)) ERROR(errno);
105*b30d1939SAndy Fiddaman #else
106*b30d1939SAndy Fiddaman 			if (stat(dots, par)) ERROR(errno);
107*b30d1939SAndy Fiddaman #endif
108*b30d1939SAndy Fiddaman 			*d++ = '/';
109*b30d1939SAndy Fiddaman 			if (par->st_dev == cur->st_dev)
110*b30d1939SAndy Fiddaman 			{
111*b30d1939SAndy Fiddaman 				if (par->st_ino == cur->st_ino)
112*b30d1939SAndy Fiddaman 				{
113*b30d1939SAndy Fiddaman 					closedir(dirp);
114*b30d1939SAndy Fiddaman 					*--p = '/';
115*b30d1939SAndy Fiddaman 					if (ruid != euid) setuid(euid);
116*b30d1939SAndy Fiddaman 					if (path == buf) return(strdup(p));
117*b30d1939SAndy Fiddaman 					if (path != p)
118*b30d1939SAndy Fiddaman 					{
119*b30d1939SAndy Fiddaman 						d = path;
120*b30d1939SAndy Fiddaman 						while (*d++ = *p++);
121*b30d1939SAndy Fiddaman 					}
122*b30d1939SAndy Fiddaman 					return(path);
123*b30d1939SAndy Fiddaman 				}
124*b30d1939SAndy Fiddaman #ifdef D_FILENO
125*b30d1939SAndy Fiddaman 				while (entry = readdir(dirp))
126*b30d1939SAndy Fiddaman 					if (D_FILENO(entry) == cur->st_ino)
127*b30d1939SAndy Fiddaman 					{
128*b30d1939SAndy Fiddaman 						namlen = D_NAMLEN(entry);
129*b30d1939SAndy Fiddaman 						goto found;
130*b30d1939SAndy Fiddaman 					}
131*b30d1939SAndy Fiddaman #endif
132*b30d1939SAndy Fiddaman 
133*b30d1939SAndy Fiddaman 				/*
134*b30d1939SAndy Fiddaman 				 * this fallthrough handles logical naming
135*b30d1939SAndy Fiddaman 				 */
136*b30d1939SAndy Fiddaman 
137*b30d1939SAndy Fiddaman 				rewinddir(dirp);
138*b30d1939SAndy Fiddaman 			}
139*b30d1939SAndy Fiddaman 			do
140*b30d1939SAndy Fiddaman 			{
141*b30d1939SAndy Fiddaman 				if (!(entry = readdir(dirp))) ERROR(ENOENT);
142*b30d1939SAndy Fiddaman 				namlen = D_NAMLEN(entry);
143*b30d1939SAndy Fiddaman 				if ((d - dots) > (PATH_MAX - 1 - namlen)) ERROR(ERANGE);
144*b30d1939SAndy Fiddaman 				memcpy(d, entry->d_name, namlen + 1);
145*b30d1939SAndy Fiddaman 				if (stat(dots, &tstst)) ERROR(errno);
146*b30d1939SAndy Fiddaman 			} while (tstst.st_ino != cur->st_ino || tstst.st_dev != cur->st_dev);
147*b30d1939SAndy Fiddaman 		found:
148*b30d1939SAndy Fiddaman 			if (*p) *--p = '/';
149*b30d1939SAndy Fiddaman 			if ((p -= namlen) <= (path + 1)) ERROR(ERANGE);
150*b30d1939SAndy Fiddaman 			memcpy(p, entry->d_name, namlen);
151*b30d1939SAndy Fiddaman 			closedir(dirp);
152*b30d1939SAndy Fiddaman 			dirp = 0;
153*b30d1939SAndy Fiddaman 		}
154*b30d1939SAndy Fiddaman 	error:
155*b30d1939SAndy Fiddaman 		if (dirp) closedir(dirp);
156*b30d1939SAndy Fiddaman 		if (ruid != euid) setuid(euid);
157*b30d1939SAndy Fiddaman 	}
158*b30d1939SAndy Fiddaman 	return(0);
159*b30d1939SAndy Fiddaman }
160*b30d1939SAndy Fiddaman 
161*b30d1939SAndy Fiddaman #else
162*b30d1939SAndy Fiddaman 
163*b30d1939SAndy Fiddaman NoN(getpreroot)
164*b30d1939SAndy Fiddaman 
165*b30d1939SAndy Fiddaman #endif
166