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 #include <afsconfig.h>
11 #include <afs/param.h>
25 #ifdef AFS_PTHREAD_ENV
27 static pthread_once_t dirInit_once = PTHREAD_ONCE_INIT;
31 #include <WINNT\afssw.h>
38 /* static storage for path strings */
39 static char dirPathArray[AFSDIR_PATHSTRING_MAX][AFSDIR_PATH_MAX];
41 /* indicate if and how the dirpath module initialized. */
42 static int initFlag = 0;
43 static unsigned int initStatus = 0;
46 /* storage for dynamically-determined install dir (NT only; long and short) */
48 static char ntServerInstallDirLong[AFSDIR_PATH_MAX];
49 static char ntServerInstallDirShort[AFSDIR_PATH_MAX];
50 static char ntClientConfigDirLong[AFSDIR_PATH_MAX];
51 static char ntClientConfigDirShort[AFSDIR_PATH_MAX];
54 /* storage for local afs server/client paths (top-level) */
55 static char afsSrvDirPath[AFSDIR_PATH_MAX];
56 static char afsClntDirPath[AFSDIR_PATH_MAX];
58 /* internal array init function */
59 static void initDirPathArray(void);
61 /* Additional macros for ease of use */
62 /* buf is expected to be atleast AFS_PATH_MAX bytes long */
63 #define AFSDIR_SERVER_DIRPATH(buf, dir) \
64 strcompose(buf, AFSDIR_PATH_MAX, serverPrefix, dir, NULL)
66 #define AFSDIR_SERVER_FILEPATH(buf, dir, file) \
67 strcompose(buf, AFSDIR_PATH_MAX, serverPrefix, dir, "/", file, NULL)
69 #define AFSDIR_CLIENT_DIRPATH(buf, dir) \
70 strcompose(buf, AFSDIR_PATH_MAX, clientPrefix, dir, NULL)
72 #define AFSDIR_CLIENT_FILEPATH(buf, dir, file) \
73 strcompose(buf, AFSDIR_PATH_MAX, clientPrefix, dir, "/", file, NULL)
76 /* initAFSDirPath() -- External users call this function to initialize
77 * the dirpath module and/or to determine the initialization status.
79 unsigned int initAFSDirPath(void)
81 if (initFlag == 0) { /* not yet init'ed, so initialize */
82 #ifdef AFS_PTHREAD_ENV
83 pthread_once(&dirInit_once, initDirPathArray);
92 /* initDirPathArray() -- Initializes the afs dir paths for the
93 * server and client installations.
95 * For NT these are determined dynamically; for Unix they are static.
97 * NT NOTE: If a particular component (client/server) is not installed
98 * then we may not be able to initialize the paths to anything
99 * meaningful. In this case the paths are set to the local
100 * temp directory to avoid later reference to an uninitialized
101 * variable. The initStatus flag is set to indicate which
102 * paths (client/server) initialized properly for callers of
103 * initAFSDirPath() who would like to know this information.
105 static void initDirPathArray(void)
108 const char * clientPrefix = "";
109 const char * serverPrefix = "";
115 /* get the afs server software installation dir from the registry */
116 if (afssw_GetServerInstallDir(&buf)) {
117 /* failed; server not installed; use temp directory */
118 strcpy(ntServerInstallDirLong, gettmpdir());
120 strcpy(ntServerInstallDirLong, buf);
122 initStatus |= AFSDIR_SERVER_PATHS_OK;
124 FilepathNormalize(ntServerInstallDirLong);
125 status = GetShortPathName(ntServerInstallDirLong,
126 ntServerInstallDirShort, AFSDIR_PATH_MAX);
127 if (status == 0 || status > AFSDIR_PATH_MAX) {
128 /* can't convert path to short version; just use long version */
129 strcpy(ntServerInstallDirShort, ntServerInstallDirLong);
131 FilepathNormalize(ntServerInstallDirShort);
133 /* get the afs client configuration directory (/usr/vice/etc equivalent) */
134 status = GetWindowsDirectory(ntClientConfigDirLong, AFSDIR_PATH_MAX);
135 if (status == 0 || status > AFSDIR_PATH_MAX) {
136 /* failed to get canonical Windows directory; use temp directory */
137 strcpy(ntClientConfigDirLong, gettmpdir());
139 initStatus |= AFSDIR_CLIENT_PATHS_OK;
141 FilepathNormalize(ntClientConfigDirLong);
143 status = GetShortPathName(ntClientConfigDirLong,
144 ntClientConfigDirShort, AFSDIR_PATH_MAX);
145 if (status == 0 || status > AFSDIR_PATH_MAX) {
146 /* can't convert path to short version; just use long version */
147 strcpy(ntClientConfigDirShort, ntClientConfigDirLong);
149 FilepathNormalize(ntClientConfigDirShort);
150 clientPrefix = ntClientConfigDirShort;
152 /* setup the root server directory path (/usr/afs equivalent) */
153 strcpy(afsSrvDirPath, ntServerInstallDirShort);
154 strcat(afsSrvDirPath, AFSDIR_CANONICAL_SERVER_AFS_DIRPATH);
156 /* there is no root client directory path (/usr/vice equivalent) */
157 afsClntDirPath[0] = '\0';
159 /* setup top level dirpath (/usr equivalent); valid for server ONLY */
160 strcpy(dirPathArray[AFSDIR_USR_DIRPATH_ID], ntServerInstallDirShort);
161 serverPrefix = ntServerInstallDirShort;
162 strcat(dirPathArray[AFSDIR_USR_DIRPATH_ID], AFSDIR_CANONICAL_USR_DIRPATH);
164 #else /* AFS_NT40_ENV */
165 /* setup the root server directory path */
166 strcpy(afsSrvDirPath, AFSDIR_CANONICAL_SERVER_AFS_DIRPATH);
168 /* setup the root client directory path */
169 #ifdef AFS_DARWIN_ENV
170 if (access(AFSDIR_ALTERNATE_CLIENT_VICE_DIRPATH, F_OK) == 0)
171 strcpy(afsClntDirPath, AFSDIR_ALTERNATE_CLIENT_VICE_DIRPATH);
174 strcpy(afsClntDirPath, AFSDIR_CANONICAL_CLIENT_VICE_DIRPATH);
176 /* setup top level dirpath; valid for both server and client */
177 strcpy(dirPathArray[AFSDIR_USR_DIRPATH_ID], AFSDIR_CANONICAL_USR_DIRPATH);
179 initStatus |= (AFSDIR_CLIENT_PATHS_OK | AFSDIR_SERVER_PATHS_OK);
180 #endif /* AFS_NT40_ENV */
182 /* now initialize various dir and file paths exported by dirpath module */
184 /* server dir paths */
186 strcpy(dirPathArray[AFSDIR_SERVER_AFS_DIRPATH_ID], afsSrvDirPath);
188 pathp = dirPathArray[AFSDIR_SERVER_ETC_DIRPATH_ID];
189 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_SERVER_ETC_DIR);
191 pathp = dirPathArray[AFSDIR_SERVER_BIN_DIRPATH_ID];
192 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_SERVER_BIN_DIR);
194 pathp = dirPathArray[AFSDIR_SERVER_CORES_DIRPATH_ID];
195 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_CORES_DIR);
197 pathp = dirPathArray[AFSDIR_SERVER_DB_DIRPATH_ID];
198 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_DB_DIR);
200 pathp = dirPathArray[AFSDIR_SERVER_LOGS_DIRPATH_ID];
201 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_LOGS_DIR);
203 pathp = dirPathArray[AFSDIR_SERVER_LOCAL_DIRPATH_ID];
204 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_LOCAL_DIR);
206 pathp = dirPathArray[AFSDIR_SERVER_BACKUP_DIRPATH_ID];
207 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_BACKUP_DIR);
209 pathp = dirPathArray[AFSDIR_SERVER_MIGRATE_DIRPATH_ID];
210 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_MIGR_DIR);
212 pathp = dirPathArray[AFSDIR_SERVER_BIN_FILE_DIRPATH_ID];
213 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_BIN_FILE_DIR);
215 /* client dir path */
218 strcpy(dirPathArray[AFSDIR_CLIENT_VICE_DIRPATH_ID],
219 "/NoUsrViceDirectoryOnWindows");
220 strcpy(dirPathArray[AFSDIR_CLIENT_ETC_DIRPATH_ID], ntClientConfigDirShort);
222 strcpy(dirPathArray[AFSDIR_CLIENT_VICE_DIRPATH_ID], afsClntDirPath);
224 pathp = dirPathArray[AFSDIR_CLIENT_ETC_DIRPATH_ID];
225 #ifdef AFS_DARWIN_ENV
226 if (access(AFSDIR_ALTERNATE_CLIENT_ETC_DIR, F_OK) == 0)
227 AFSDIR_CLIENT_DIRPATH(pathp, AFSDIR_ALTERNATE_CLIENT_ETC_DIR);
230 AFSDIR_CLIENT_DIRPATH(pathp, AFSDIR_CLIENT_ETC_DIR);
231 #endif /* AFS_NT40_ENV */
233 /* server file paths */
235 pathp = dirPathArray[AFSDIR_SERVER_THISCELL_FILEPATH_ID];
236 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_THISCELL_FILE);
238 pathp = dirPathArray[AFSDIR_SERVER_CELLSERVDB_FILEPATH_ID];
239 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_CELLSERVDB_FILE);
241 pathp = dirPathArray[AFSDIR_SERVER_NOAUTH_FILEPATH_ID];
242 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_NOAUTH_FILE);
244 pathp = dirPathArray[AFSDIR_SERVER_BUDBLOG_FILEPATH_ID];
245 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_BUDBLOG_FILE);
247 pathp = dirPathArray[AFSDIR_SERVER_TAPECONFIG_FILEPATH_ID];
248 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BACKUP_DIR, AFSDIR_TAPECONFIG_FILE);
250 pathp = dirPathArray[AFSDIR_SERVER_KALOGDB_FILEPATH_ID];
251 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_KALOGDB_FILE);
253 pathp = dirPathArray[AFSDIR_SERVER_KALOG_FILEPATH_ID];
254 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_KALOG_FILE);
256 pathp = dirPathArray[AFSDIR_SERVER_KADB_FILEPATH_ID];
257 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_DB_DIR, AFSDIR_KADB_FILE);
259 pathp = dirPathArray[AFSDIR_SERVER_NTPD_FILEPATH_ID];
260 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_BIN_DIR, AFSDIR_NTPD_FILE);
262 pathp = dirPathArray[AFSDIR_SERVER_PRDB_FILEPATH_ID];
263 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_DB_DIR, AFSDIR_PRDB_FILE);
265 pathp = dirPathArray[AFSDIR_SERVER_PTLOG_FILEPATH_ID];
266 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_PTLOG_FILE);
268 pathp = dirPathArray[AFSDIR_SERVER_KCONF_FILEPATH_ID];
269 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_KCONF_FILE);
271 pathp = dirPathArray[AFSDIR_SERVER_VLDB_FILEPATH_ID];
272 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_DB_DIR, AFSDIR_VLDB_FILE);
274 pathp = dirPathArray[AFSDIR_SERVER_VLOG_FILEPATH_ID];
275 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_VLOG_FILE);
277 pathp = dirPathArray[AFSDIR_SERVER_CORELOG_FILEPATH_ID];
278 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_CORE_FILE);
280 pathp = dirPathArray[AFSDIR_SERVER_SLVGLOG_FILEPATH_ID];
281 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_SLVGLOG_FILE);
283 pathp = dirPathArray[AFSDIR_SERVER_SALVAGER_FILEPATH_ID];
284 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_BIN_DIR, AFSDIR_SALVAGER_FILE);
286 pathp = dirPathArray[AFSDIR_SERVER_SLVGLOCK_FILEPATH_ID];
287 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_SLVGLOCK_FILE);
289 pathp = dirPathArray[AFSDIR_SERVER_KEY_FILEPATH_ID];
290 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_KEY_FILE);
292 pathp = dirPathArray[AFSDIR_SERVER_ULIST_FILEPATH_ID];
293 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_ULIST_FILE);
295 pathp = dirPathArray[AFSDIR_SERVER_BOZCONF_FILEPATH_ID];
296 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BOSCONFIG_DIR, AFSDIR_BOZCONF_FILE);
298 pathp = dirPathArray[AFSDIR_SERVER_BOZCONFNEW_FILEPATH_ID];
299 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BOSCONFIG_DIR, AFSDIR_BOZCONFNEW_FILE);
301 pathp = dirPathArray[AFSDIR_SERVER_BOZLOG_FILEPATH_ID];
302 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_BOZLOG_FILE);
304 pathp = dirPathArray[AFSDIR_SERVER_BOZINIT_FILEPATH_ID];
305 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BOSCONFIG_DIR, AFSDIR_BOZINIT_FILE);
307 pathp = dirPathArray[AFSDIR_SERVER_BOSVR_FILEPATH_ID];
308 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BOSSERVER_DIR, AFSDIR_BOSVR_FILE);
310 pathp = dirPathArray[AFSDIR_SERVER_VOLSERLOG_FILEPATH_ID];
311 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_VOLSERLOG_FILE);
313 pathp = dirPathArray[AFSDIR_SERVER_ROOTVOL_FILEPATH_ID];
314 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_ROOTVOL_FILE);
316 pathp = dirPathArray[AFSDIR_SERVER_HOSTDUMP_FILEPATH_ID];
317 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_HOSTDUMP_FILE);
319 pathp = dirPathArray[AFSDIR_SERVER_CLNTDUMP_FILEPATH_ID];
320 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_CLNTDUMP_FILE);
322 pathp = dirPathArray[AFSDIR_SERVER_CBKDUMP_FILEPATH_ID];
323 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_CBKDUMP_FILE);
325 pathp = dirPathArray[AFSDIR_SERVER_OLDSYSID_FILEPATH_ID];
326 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_OLDSYSID_FILE);
328 pathp = dirPathArray[AFSDIR_SERVER_SYSID_FILEPATH_ID];
329 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_SYSID_FILE);
331 pathp = dirPathArray[AFSDIR_SERVER_FILELOG_FILEPATH_ID];
332 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_FILELOG_FILE);
334 pathp = dirPathArray[AFSDIR_SERVER_AUDIT_FILEPATH_ID];
335 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_AUDIT_FILE);
337 pathp = dirPathArray[AFSDIR_SERVER_NETINFO_FILEPATH_ID];
338 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_NETINFO_FILE);
340 pathp = dirPathArray[AFSDIR_SERVER_NETRESTRICT_FILEPATH_ID];
341 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_NETRESTRICT_FILE);
343 pathp = dirPathArray[AFSDIR_SERVER_WEIGHTING_CONSTANTS_FILEPATH_ID];
344 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_MIGR_DIR, AFSDIR_WEIGHTINGCONST_FILE);
346 pathp = dirPathArray[AFSDIR_SERVER_THRESHOLD_CONSTANTS_FILEPATH_ID];
347 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_MIGR_DIR, AFSDIR_THRESHOLDCONST_FILE);
349 pathp = dirPathArray[AFSDIR_SERVER_MIGRATELOG_FILEPATH_ID];
350 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_MIGR_DIR, AFSDIR_MIGRATE_LOGNAME);
353 /* client file paths */
356 strcpy(dirPathArray[AFSDIR_CLIENT_THISCELL_FILEPATH_ID],
357 "/NoUsrViceEtcThisCellFileOnWindows");
358 sprintf(dirPathArray[AFSDIR_CLIENT_CELLSERVDB_FILEPATH_ID], "%s/%s",
359 ntClientConfigDirShort, AFSDIR_CELLSERVDB_FILE_NTCLIENT);
360 strcpy(dirPathArray[AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID],
361 "/NoCellAliasOnWindows");
363 pathp = dirPathArray[AFSDIR_CLIENT_THISCELL_FILEPATH_ID];
364 AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR, AFSDIR_THISCELL_FILE);
366 pathp = dirPathArray[AFSDIR_CLIENT_CELLSERVDB_FILEPATH_ID];
367 AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR, AFSDIR_CELLSERVDB_FILE);
369 pathp = dirPathArray[AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID];
370 AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR, AFSDIR_CELLALIAS_FILE);
371 #endif /* AFS_NT40_ENV */
373 pathp = dirPathArray[AFSDIR_CLIENT_NETINFO_FILEPATH_ID];
374 AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR, AFSDIR_NETINFO_FILE);
376 pathp = dirPathArray[AFSDIR_CLIENT_NETRESTRICT_FILEPATH_ID];
377 AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR, AFSDIR_NETRESTRICT_FILE);
379 initFlag = 1; /* finished dirpath initialization */
383 /* getDirPath - returns a const char pointer to the requested string
384 * from the internal path array.
385 * string_id - index into the path array
387 const char *getDirPath(afsdir_id_t string_id)
389 /* check if the array has been initialized */
390 if (initFlag == 0) { /* no it's not, so initialize */
391 #ifdef AFS_PTHREAD_ENV
392 pthread_once(&dirInit_once, initDirPathArray);
397 return (const char *)dirPathArray[string_id];
400 * LocalizePathHead() -- Make path relative to local part
402 * ConstructLocalPath takes a path and a directory that path should
403 * be considered relative to. This function checks the given path
404 * for a prefix that represents a canonical path. If such a prefix
405 * is found, the path is adjusted to remove the prefix and the path
406 * is considered relative to the local version of that path.
409 /* The following array maps cannonical parts to local parts. It
410 * might seem reasonable to simply construct an array in parallel to
411 * dirpatharray but it turns out you don't want translations for all
415 struct canonmapping {
416 const char * canonical;
419 static struct canonmapping CanonicalTranslations[] = {
420 {AFSDIR_CANONICAL_SERVER_ETC_DIRPATH, AFSDIR_SERVER_ETC_DIR},
421 { AFSDIR_CANONICAL_SERVER_LOGS_DIRPATH, AFSDIR_LOGS_DIR},
422 { AFSDIR_CANONICAL_SERVER_LOCAL_DIRPATH, AFSDIR_LOCAL_DIR},
423 {AFSDIR_CANONICAL_SERVER_BIN_DIRPATH, AFSDIR_SERVER_BIN_DIR },
427 static void LocalizePathHead ( const char **path, const char **relativeTo)
429 struct canonmapping *current;
430 for (current = CanonicalTranslations; current->local != NULL ; current++) {
431 int canonlength = strlen (current->canonical);
432 if (strncmp (*path, current->canonical, canonlength) == 0 ) {
433 (*path) += canonlength;
436 *relativeTo = current->local;
444 /* NT version of ConstructLocalPath() */
447 * ConstructLocalPath() -- Convert a canonical (wire-format) path to a fully
448 * specified local path. Upon successful completion, *fullPathBufp is
449 * set to an allocated buffer containing the fully specified local path
450 * constructed from the cpath argument.
452 * On NT, path construction proceeds as follows:
453 * 1) If cpath is fully qualified (i.e., starts with 'X:/') then the
454 * path returned is equivalent to cpath.
455 * 2) If cpath begins with a drive letter but is not fully qualified,
456 * i.e., it is drive relative, then the function fails with EINVAL.
457 * 3) If cpath begins with '/' (or '\') then the path returned is the
458 * concatenation AFS-server-install-dir + cpath after translating for localization.
459 * 4) Otherwise the path returned is the concatenation
460 * AFS-server-install-dir + relativeTo + cpath.
462 * Leading whitespace in cpath is ignored; the constructed path is
463 * normalized (FilepathNormalize()).
465 * RETURN CODES: 0 if successful; errno code otherwise.
468 ConstructLocalPath(const char *cpath,
469 const char *relativeTo,
473 char *newPath = NULL;
475 if (initFlag == 0) { /* dirpath module not yet initialized */
476 #ifdef AFS_PTHREAD_ENV
477 pthread_once(&dirInit_once, initDirPathArray);
483 *fullPathBufp = NULL;
485 while (isspace(*cpath)) {
489 LocalizePathHead (&cpath,&relativeTo);
490 if ((((*cpath >= 'a') && (*cpath <= 'z')) ||
491 ((*cpath >= 'A') && (*cpath <= 'Z'))) &&
492 (*(cpath+1) == ':')) {
494 /* cpath has a leading drive letter */
495 if ((*(cpath+2) != '/') && (*(cpath+2) != '\\')) {
496 /* drive letter relative path; this is not allowed */
499 /* fully qualified path; just make a copy */
500 newPath = (char *)malloc(strlen(cpath)+1);
504 (void)strcpy(newPath, cpath);
509 /* cpath has NO leading drive letter; make relative to install dir */
510 size_t pathSize = strlen(ntServerInstallDirShort) + 2;
512 if ((*cpath == '/') || (*cpath == '\\')) {
513 /* construct path relative to install directory only */
514 pathSize += strlen(cpath);
516 newPath = (char *)malloc(pathSize);
520 sprintf(newPath, "%s/%s", ntServerInstallDirShort, cpath);
523 /* construct path relative to 'relativeTo' (and install dir) */
524 pathSize += strlen(relativeTo) + 1 + strlen(cpath);
526 newPath = (char *)malloc(pathSize);
530 sprintf(newPath, "%s/%s/%s",
531 ntServerInstallDirShort, relativeTo, cpath);
537 FilepathNormalize(newPath);
539 /* return buffer containing fully specified path */
540 *fullPathBufp = newPath;
547 /* Unix version of ConstructLocalPath() */
550 * ConstructLocalPath() -- Convert a canonical (wire-format) path to a fully
551 * specified local path. Upon successful completion, *fullPathBufp is
552 * set to an allocated buffer containing the fully specified local path
553 * constructed from the cpath argument.
555 * On Unix, path construction proceeds as follows:
556 * 1) If cpath begins with '/' then the path returned is equivalent
558 * 2) Otherwise the path returned is the concatenation
559 * relativeTo + cpath.
561 * Leading whitespace in cpath is ignored; the constructed path is
562 * normalized (FilepathNormalize()).
564 * RETURN CODES: 0 if successful; errno code otherwise.
567 ConstructLocalPath(const char *cpath,
568 const char *relativeTo,
572 char *newPath = NULL;
574 if (initFlag == 0) { /* dirpath module not yet initialized */
575 #ifdef AFS_PTHREAD_ENV
576 pthread_once(&dirInit_once, initDirPathArray);
582 *fullPathBufp = NULL;
584 while (isspace(*cpath)) {
588 LocalizePathHead (&cpath, &relativeTo);
590 newPath = (char *)malloc(strlen(cpath) + 1);
594 strcpy(newPath, cpath);
597 newPath = (char *)malloc(strlen(relativeTo) + 1 + strlen(cpath) + 1);
601 sprintf(newPath, "%s/%s", relativeTo, cpath);
606 FilepathNormalize(newPath);
608 /* return buffer containing fully specified path */
609 *fullPathBufp = newPath;
614 #endif /* AFS_NT40_ENV */
618 * ConstructLocalBinPath() -- A convenience wrapper for ConstructLocalPath()
619 * that specifies the canonical AFS server binary directory as the relative
623 ConstructLocalBinPath(const char *cpath,
626 return ConstructLocalPath(cpath,
627 AFSDIR_CANONICAL_SERVER_BIN_DIRPATH,
633 * ConstructLocalLogPath() -- A convenience wrapper for ConstructLocalPath()
634 * that specifies the canonical AFS server logs directory as the relative
638 ConstructLocalLogPath(const char *cpath,
641 return ConstructLocalPath(cpath,
642 AFSDIR_CANONICAL_SERVER_LOGS_DIRPATH,