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