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