2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /*------------------------------------------------------------------------
14 * Check the integrity of the configuration tree for package, the
15 * AFS workstation configuration tool.
17 *------------------------------------------------------------------------*/
19 #include <afs/param.h>
21 #include <sys/types.h>
23 #include <sys/param.h>
30 CTREEPTR LocateChildNode();
32 static char path2[MAXPATHLEN + 1]; /* $$get rid of this */
33 static char path3[MAXPATHLEN + 1]; /* $$get rid of this */
35 /*------------------------------------------------------------------------
39 * Check the assertion that the given path is a Unix mountpoint.
42 * char *path : Path to check.
46 * Exit from package on failure.
49 * This routine is private to the module.
52 * May exit from package.
53 *------------------------------------------------------------------------*/
56 CheckMount(char *path)
58 struct stat stb; /*Parent's stat block */
59 struct stat stb2; /*Child's stat block */
60 char dir[MAXPATHLEN]; /*Pathname of candidate mount point */
61 char parent[MAXPATHLEN]; /*Parent's pathname */
62 register char *ep, *dp, *sp; /*Sliding ptr to above strings */
63 int ret; /*Return value */
65 debug_message("%% CheckMount called on path %s", path);
69 * Copy out the candidate mountpoint's pathname into dir, throwing
70 * off any leaf component from the original path.
72 ep = strrchr(path, '/');
73 for (sp = path, dp = dir; sp < ep; *dp++ = *sp++);
79 * Copy out the parent's pathname into parent.
81 ep = strrchr(dir, '/');
82 for (sp = dir, dp = parent; sp < ep; *dp++ = *sp++);
88 * Only perform the following test if the candidate mountpoint is
89 * something other than `/', which we know is a mountpoint.
91 if (strcmp(dir, "/")) {
93 * Stat the given directory and its parent. If either is not a
94 * directory or if the device numbers are the same, then the
95 * candidate has failed and is not a Unix mountpoint.
97 if (stat(dir, &stb) < 0)
99 if (stat(parent, &stb2) < 0)
101 if ((stb.st_mode & S_IFMT) != S_IFDIR)
103 if ((stb2.st_mode & S_IFMT) != S_IFDIR)
105 if (stb2.st_dev == stb.st_dev)
111 * Our assertion that the given path is a mountpoint is false.
112 * Tell our caller, then croak off.
114 fatal("** %s is not a Unix mountpoint, as was expected!", dir);
118 * The candidate mountpoint has passed the test. If we're being
119 * verbose, tell everyone.
121 verbose_message("Found Unix mountpoint %s", dir);
124 /*------------------------------------------------------------------------
128 * Check the validity of the given node compared to the associated
132 * CTREEPTR np : Node pointer to check.
133 * char *path : Associated pathname.
137 * Exits the program otherwise.
140 * This is one of the routines applied to the entire configuration
144 * May exit from package.
145 *------------------------------------------------------------------------*/
148 check(register CTREEPTR np, char *path)
151 register CTREEPTR np2; /*Node ptr for np's child */
152 register struct dirent *de; /*Ptr to directory entry */
153 DIR *dp; /*Ptr to directory being read */
154 struct stat stb; /*Stat block for path2 */
155 int retval; /*Return value */
158 debug_message("[check] Checking pathname %s", path, np);
160 if ((np->flag & F_TYPE) && (np->updtspec & U_LOSTFOUND))
162 if (!(np->flag & F_PROTO)) {
163 if (!(np->flag & F_TYPE))
164 fatal("** Incomplete: %s", path);
165 else if ((np->type == S_IFCHR) || (np->type == S_IFBLK))
166 /* $$Note: Actually, the parser takes care of this */
167 fatal("** No device numbers specified for device %s\n", path);
172 * No checks needed for character & block special devices (& sockets
175 if ((np->type == S_IFCHR)
176 || (np->type == S_IFBLK)
178 || (np->type == S_IFSOCK)
179 #endif /* AFS_AIX_ENV */
181 || (np->type == S_IFIFO)
187 * Construct the target path, either absolute or prefixed.
189 if (np->updtspec & U_ABSPATH)
193 sprintf(path2, "%s", np->proto.info.path);
198 sprintf(path2, "%s%s", np->proto.info.path, path);
200 debug_message("[check] Statting %s", path2);
203 * If this is a symlink, lstat the guy and warn people if it
206 if ((np->flag & F_TYPE) && (np->type == S_IFLNK)) {
207 if (lstat(path2, &stb) < 0)
208 verbose_message("* Warning: symlink %s not found", path2);
213 * Do a normal stat, failing if it does.
215 if (stat(path2, &stb) < 0)
216 fatal("** Stat failed for %s; %m", path2);
218 if (np->flag & F_TYPE) {
219 if (np->type == S_IFLNK)
221 if ((stb.st_mode & S_IFMT) != np->type)
222 fatal("** Type conflict for %s", path2);
224 np->type = stb.st_mode & S_IFMT;
228 if (!(np->flag & F_MODE)) {
229 /*Fill in the mode (protection) info from the stat block */
230 np->mode |= stb.st_mode & ~S_IFMT;
234 if (!(np->flag & F_UID)) {
235 /*Fill in the user info from the stat block */
236 np->uid = stb.st_uid;
240 if (!(np->flag & F_GID)) {
241 /*Fill in the group info from the stat block */
243 np->gid = (stb.st_gid == 32767) ? 0 : stb.st_gid;
245 np->gid = stb.st_gid;
250 if (!(np->flag & F_MTIME)) {
251 /*Fill in the last modified time from the stat block */
252 np->mtime = stb.st_mtime;
257 * If we've reached a non-directory, we're all done.
259 if (np->type != S_IFDIR) {
260 debug_message("[check] Reached leaf node, returning");
265 * Open up the directory and sweep through it, checking all its
268 verbose_message("Scanning directory %s", path2);
269 if ((dp = opendir(path2)) == 0)
270 fatal("** Opendir failed on %s; %m", path2);
272 while ((de = readdir(dp)) != 0) {
273 if (de->d_name[0] == '.') {
275 * Don't process dot, the current directory, or dotdot, the
278 if (de->d_name[1] == 0)
280 if (de->d_name[1] == '.' && de->d_name[2] == 0)
285 LocateChildNode(np, de->d_name, C_LOCATE | C_CREATE)) == NULL)
286 fatal("** Bad path: %s/%s", path, de->d_name);
288 if (!(np2->flag & F_PROTO)) {
289 if (np->updtspec & U_ABSPATH) {
290 np2->updtspec |= U_ABSPATH;
291 sprintf(path3, "%s/%s", np->proto.info.path, de->d_name);
292 np2->proto.info.path = emalloc((unsigned)(strlen(path3) + 1));
293 (void)strcpy(np2->proto.info.path, path3);
295 np2->proto.info.path = np->proto.info.path;
297 np2->flag |= F_PROTO;
300 if ((np2->updtspec & U_ABSPATH) != (np->updtspec & U_ABSPATH))
302 ("** Prototype conflict: %s/%s: Absolute & relative paths given",
304 if (np->updtspec & U_ABSPATH) {
305 sprintf(path3, "%s/%s", np->proto, de->d_name);
306 if (strcmp(path3, np2->proto.info.path))
307 fatal("** Prototype conflict: %s/%s: Previously %s", path,
308 de->d_name, np2->proto.info.path);
310 if (strcmp(np->proto.info.path, np2->proto.info.path))
311 fatal("** Prototype conflict: %s/%s: Mismatch for %s and %s",
312 path, de->d_name, np->proto.info.path,
313 np2->proto.info.path);
315 } /*For each directory entry */
318 * Make sure to close the directory before we leave.