xref: /onnv-gate/usr/src/lib/libast/common/preroot/getpreroot.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin  * AT&T Bell Laboratories
254887Schin  * return the real absolute pathname of the preroot dir for cmd
264887Schin  * if cmd==0 then current preroot path returned
274887Schin  */
284887Schin 
294887Schin #include <ast.h>
304887Schin #include <preroot.h>
314887Schin 
324887Schin #if FS_PREROOT
334887Schin 
344887Schin #include <ast_dir.h>
354887Schin #include <ls.h>
364887Schin #include <error.h>
374887Schin #include <stdio.h>
384887Schin 
394887Schin #ifndef ERANGE
404887Schin #define ERANGE		E2BIG
414887Schin #endif
424887Schin 
434887Schin #define ERROR(e)	{errno=e;goto error;}
444887Schin 
454887Schin char*
getpreroot(char * path,const char * cmd)464887Schin getpreroot(char* path, const char* cmd)
474887Schin {
484887Schin 	register int	c;
494887Schin 	register FILE*	fp;
504887Schin 	register char*	p;
514887Schin 	char		buf[PATH_MAX];
524887Schin 
534887Schin 	if (!path) path = buf;
544887Schin 	if (cmd)
554887Schin 	{
564887Schin 		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);
574887Schin 		if (!(fp = popen(buf, "rug"))) return(0);
584887Schin 		for (p = path; (c = getc(fp)) != EOF && c != '\n'; *p++ = c);
594887Schin 		*p = 0;
604887Schin 		pclose(fp);
614887Schin 		if (path == p) return(0);
624887Schin 		return(path == buf ? strdup(path) : path);
634887Schin 	}
644887Schin 	else
654887Schin 	{
664887Schin 		char*		d;
674887Schin 		DIR*		dirp = 0;
684887Schin 		int		namlen;
694887Schin 		int		euid;
704887Schin 		int		ruid;
714887Schin 		struct dirent*	entry;
724887Schin 		struct stat*	cur;
734887Schin 		struct stat*	par;
744887Schin 		struct stat*	tmp;
754887Schin 		struct stat	curst;
764887Schin 		struct stat	parst;
774887Schin 		struct stat	tstst;
784887Schin 		char		dots[PATH_MAX];
794887Schin 
804887Schin 		cur = &curst;
814887Schin 		par = &parst;
824887Schin 		if ((ruid = getuid()) != (euid = geteuid())) setuid(ruid);
834887Schin 		if (stat(PR_REAL, cur) || stat("/", par) || cur->st_dev == par->st_dev && cur->st_ino == par->st_ino) ERROR(ENOTDIR);
844887Schin 
854887Schin 		/*
864887Schin 		 * like getcwd() but starting at the preroot
874887Schin 		 */
884887Schin 
894887Schin 		d = dots;
904887Schin 		*d++ = '/';
914887Schin 		p = path + PATH_MAX - 1;
924887Schin 		*p = 0;
934887Schin 		for (;;)
944887Schin 		{
954887Schin 			tmp = cur;
964887Schin 			cur = par;
974887Schin 			par = tmp;
984887Schin 			if ((d - dots) > (PATH_MAX - 4)) ERROR(ERANGE);
994887Schin 			*d++ = '.';
1004887Schin 			*d++ = '.';
1014887Schin 			*d = 0;
1024887Schin 			if (!(dirp = opendir(dots))) ERROR(errno);
1034887Schin #if !_dir_ok || _mem_dd_fd_DIR
1044887Schin 			if (fstat(dirp->dd_fd, par)) ERROR(errno);
1054887Schin #else
1064887Schin 			if (stat(dots, par)) ERROR(errno);
1074887Schin #endif
1084887Schin 			*d++ = '/';
1094887Schin 			if (par->st_dev == cur->st_dev)
1104887Schin 			{
1114887Schin 				if (par->st_ino == cur->st_ino)
1124887Schin 				{
1134887Schin 					closedir(dirp);
1144887Schin 					*--p = '/';
1154887Schin 					if (ruid != euid) setuid(euid);
1164887Schin 					if (path == buf) return(strdup(p));
1174887Schin 					if (path != p)
1184887Schin 					{
1194887Schin 						d = path;
1204887Schin 						while (*d++ = *p++);
1214887Schin 					}
1224887Schin 					return(path);
1234887Schin 				}
1244887Schin #ifdef D_FILENO
1254887Schin 				while (entry = readdir(dirp))
1264887Schin 					if (D_FILENO(entry) == cur->st_ino)
1274887Schin 					{
1284887Schin 						namlen = D_NAMLEN(entry);
1294887Schin 						goto found;
1304887Schin 					}
1314887Schin #endif
1324887Schin 
1334887Schin 				/*
1344887Schin 				 * this fallthrough handles logical naming
1354887Schin 				 */
1364887Schin 
1374887Schin 				rewinddir(dirp);
1384887Schin 			}
1394887Schin 			do
1404887Schin 			{
1414887Schin 				if (!(entry = readdir(dirp))) ERROR(ENOENT);
1424887Schin 				namlen = D_NAMLEN(entry);
1434887Schin 				if ((d - dots) > (PATH_MAX - 1 - namlen)) ERROR(ERANGE);
1444887Schin 				memcpy(d, entry->d_name, namlen + 1);
1454887Schin 				if (stat(dots, &tstst)) ERROR(errno);
1464887Schin 			} while (tstst.st_ino != cur->st_ino || tstst.st_dev != cur->st_dev);
1474887Schin 		found:
1484887Schin 			if (*p) *--p = '/';
1494887Schin 			if ((p -= namlen) <= (path + 1)) ERROR(ERANGE);
1504887Schin 			memcpy(p, entry->d_name, namlen);
1514887Schin 			closedir(dirp);
1524887Schin 			dirp = 0;
1534887Schin 		}
1544887Schin 	error:
1554887Schin 		if (dirp) closedir(dirp);
1564887Schin 		if (ruid != euid) setuid(euid);
1574887Schin 	}
1584887Schin 	return(0);
1594887Schin }
1604887Schin 
1614887Schin #else
1624887Schin 
1634887Schin NoN(getpreroot)
1644887Schin 
1654887Schin #endif
166