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 <afs/param.h>
21 #ifdef AFS_PTHREAD_ENV
23 static pthread_once_t dirInit_once = PTHREAD_ONCE_INIT;
27 #include <WINNT\afssw.h>
31 /* static storage for path strings */
32 static char dirPathArray[AFSDIR_PATHSTRING_MAX][AFSDIR_PATH_MAX];
34 /* indicate if and how the dirpath module initialized. */
35 static int initFlag = 0;
36 static unsigned int initStatus = 0;
39 /* storage for dynamically-determined install dir (NT only; long and short) */
41 static char ntServerInstallDirLong[AFSDIR_PATH_MAX];
42 static char ntServerInstallDirShort[AFSDIR_PATH_MAX];
43 static char ntClientConfigDirLong[AFSDIR_PATH_MAX];
44 static char ntClientConfigDirShort[AFSDIR_PATH_MAX];
47 /* storage for local afs server/client paths (top-level) */
48 static char afsSrvDirPath[AFSDIR_PATH_MAX];
49 static char afsClntDirPath[AFSDIR_PATH_MAX];
51 /* internal array init function */
52 static void initDirPathArray(void);
54 /* Additional macros for ease of use */
55 /* buf is expected to be atleast AFS_PATH_MAX bytes long */
56 #define AFSDIR_SERVER_DIRPATH(buf, dir) \
57 strcompose(buf, AFSDIR_PATH_MAX, dirPathArray[AFSDIR_SERVER_AFS_DIRPATH_ID], "/", dir, NULL)
59 #define AFSDIR_SERVER_FILEPATH(buf, dir, file) \
60 strcompose(buf, AFSDIR_PATH_MAX, dirPathArray[AFSDIR_SERVER_AFS_DIRPATH_ID], "/", dir, "/", file, NULL)
62 #define AFSDIR_CLIENT_DIRPATH(buf, dir) \
63 strcompose(buf, AFSDIR_PATH_MAX, dirPathArray[AFSDIR_CLIENT_VICE_DIRPATH_ID], "/", dir, NULL)
65 #define AFSDIR_CLIENT_FILEPATH(buf, dir, file) \
66 strcompose(buf, AFSDIR_PATH_MAX, dirPathArray[AFSDIR_CLIENT_VICE_DIRPATH_ID], "/", dir, "/", file, NULL)
69 /* initAFSDirPath() -- External users call this function to initialize
70 * the dirpath module and/or to determine the initialization status.
72 unsigned int initAFSDirPath(void)
74 if (initFlag == 0) { /* not yet init'ed, so initialize */
75 #ifdef AFS_PTHREAD_ENV
76 pthread_once(&dirInit_once, initDirPathArray);
85 /* initDirPathArray() -- Initializes the afs dir paths for the
86 * server and client installations.
88 * For NT these are determined dynamically; for Unix they are static.
90 * NT NOTE: If a particular component (client/server) is not installed
91 * then we may not be able to initialize the paths to anything
92 * meaningful. In this case the paths are set to the local
93 * temp directory to avoid later reference to an uninitialized
94 * variable. The initStatus flag is set to indicate which
95 * paths (client/server) initialized properly for callers of
96 * initAFSDirPath() who would like to know this information.
98 static void initDirPathArray(void)
104 /* get the afs server software installation dir from the registry */
105 if (afssw_GetServerInstallDir(&buf)) {
106 /* failed; server not installed; use temp directory */
107 strcpy(ntServerInstallDirLong, gettmpdir());
109 strcpy(ntServerInstallDirLong, buf);
111 initStatus |= AFSDIR_SERVER_PATHS_OK;
113 FilepathNormalize(ntServerInstallDirLong);
114 status = GetShortPathName(ntServerInstallDirLong,
115 ntServerInstallDirShort, AFSDIR_PATH_MAX);
116 if (status == 0 || status > AFSDIR_PATH_MAX) {
117 /* can't convert path to short version; just use long version */
118 strcpy(ntServerInstallDirShort, ntServerInstallDirLong);
120 FilepathNormalize(ntServerInstallDirShort);
122 /* get the afs client configuration directory (/usr/vice/etc equivalent) */
123 status = GetWindowsDirectory(ntClientConfigDirLong, AFSDIR_PATH_MAX);
124 if (status == 0 || status > AFSDIR_PATH_MAX) {
125 /* failed to get canonical Windows directory; use temp directory */
126 strcpy(ntClientConfigDirLong, gettmpdir());
128 initStatus |= AFSDIR_CLIENT_PATHS_OK;
130 FilepathNormalize(ntClientConfigDirLong);
132 status = GetShortPathName(ntClientConfigDirLong,
133 ntClientConfigDirShort, AFSDIR_PATH_MAX);
134 if (status == 0 || status > AFSDIR_PATH_MAX) {
135 /* can't convert path to short version; just use long version */
136 strcpy(ntClientConfigDirShort, ntClientConfigDirLong);
138 FilepathNormalize(ntClientConfigDirShort);
140 /* setup the root server directory path (/usr/afs equivalent) */
141 strcpy(afsSrvDirPath, ntServerInstallDirShort);
142 strcat(afsSrvDirPath, AFSDIR_CANONICAL_SERVER_AFS_DIRPATH);
144 /* there is no root client directory path (/usr/vice equivalent) */
145 afsClntDirPath[0] = '\0';
147 /* setup top level dirpath (/usr equivalent); valid for server ONLY */
148 strcpy(dirPathArray[AFSDIR_USR_DIRPATH_ID], ntServerInstallDirShort);
149 strcat(dirPathArray[AFSDIR_USR_DIRPATH_ID], AFSDIR_CANONICAL_USR_DIRPATH);
151 #else /* AFS_NT40_ENV */
152 /* setup the root server directory path */
153 strcpy(afsSrvDirPath, AFSDIR_CANONICAL_SERVER_AFS_DIRPATH);
155 /* setup the root client directory path */
156 strcpy(afsClntDirPath, AFSDIR_CANONICAL_CLIENT_VICE_DIRPATH);
158 /* setup top level dirpath; valid for both server and client */
159 strcpy(dirPathArray[AFSDIR_USR_DIRPATH_ID], AFSDIR_CANONICAL_USR_DIRPATH);
161 initStatus |= (AFSDIR_CLIENT_PATHS_OK | AFSDIR_SERVER_PATHS_OK);
162 #endif /* AFS_NT40_ENV */
164 /* now initialize various dir and file paths exported by dirpath module */
166 /* server dir paths */
168 strcpy(dirPathArray[AFSDIR_SERVER_AFS_DIRPATH_ID], afsSrvDirPath);
170 pathp = dirPathArray[AFSDIR_SERVER_ETC_DIRPATH_ID];
171 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_ETC_DIR);
173 pathp = dirPathArray[AFSDIR_SERVER_BIN_DIRPATH_ID];
174 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_BIN_DIR);
176 pathp = dirPathArray[AFSDIR_SERVER_CORES_DIRPATH_ID];
177 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_CORES_DIR);
179 pathp = dirPathArray[AFSDIR_SERVER_DB_DIRPATH_ID];
180 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_DB_DIR);
182 pathp = dirPathArray[AFSDIR_SERVER_LOGS_DIRPATH_ID];
183 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_LOGS_DIR);
185 pathp = dirPathArray[AFSDIR_SERVER_LOCAL_DIRPATH_ID];
186 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_LOCAL_DIR);
188 pathp = dirPathArray[AFSDIR_SERVER_BACKUP_DIRPATH_ID];
189 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_BACKUP_DIR);
191 pathp = dirPathArray[AFSDIR_SERVER_MIGRATE_DIRPATH_ID];
192 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_MIGR_DIR);
194 pathp = dirPathArray[AFSDIR_SERVER_BIN_FILE_DIRPATH_ID];
195 AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_BIN_FILE_DIR);
197 /* client dir path */
200 strcpy(dirPathArray[AFSDIR_CLIENT_VICE_DIRPATH_ID],
201 "/NoUsrViceDirectoryOnWindows");
202 strcpy(dirPathArray[AFSDIR_CLIENT_ETC_DIRPATH_ID], ntClientConfigDirShort);
204 strcpy(dirPathArray[AFSDIR_CLIENT_VICE_DIRPATH_ID], afsClntDirPath);
206 pathp = dirPathArray[AFSDIR_CLIENT_ETC_DIRPATH_ID];
207 AFSDIR_CLIENT_DIRPATH(pathp, AFSDIR_ETC_DIR);
208 #endif /* AFS_NT40_ENV */
210 /* server file paths */
212 pathp = dirPathArray[AFSDIR_SERVER_THISCELL_FILEPATH_ID];
213 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_THISCELL_FILE);
215 pathp = dirPathArray[AFSDIR_SERVER_CELLSERVDB_FILEPATH_ID];
216 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_CELLSERVDB_FILE);
218 pathp = dirPathArray[AFSDIR_SERVER_NOAUTH_FILEPATH_ID];
219 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_NOAUTH_FILE);
221 pathp = dirPathArray[AFSDIR_SERVER_BUDBLOG_FILEPATH_ID];
222 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_BUDBLOG_FILE);
224 pathp = dirPathArray[AFSDIR_SERVER_TAPECONFIG_FILEPATH_ID];
225 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BACKUP_DIR, AFSDIR_TAPECONFIG_FILE);
227 pathp = dirPathArray[AFSDIR_SERVER_KALOGDB_FILEPATH_ID];
228 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_KALOGDB_FILE);
230 pathp = dirPathArray[AFSDIR_SERVER_KALOG_FILEPATH_ID];
231 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_KALOG_FILE);
233 pathp = dirPathArray[AFSDIR_SERVER_KADB_FILEPATH_ID];
234 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_DB_DIR, AFSDIR_KADB_FILE);
236 pathp = dirPathArray[AFSDIR_SERVER_NTPD_FILEPATH_ID];
237 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BIN_DIR, AFSDIR_NTPD_FILE);
239 pathp = dirPathArray[AFSDIR_SERVER_PRDB_FILEPATH_ID];
240 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_DB_DIR, AFSDIR_PRDB_FILE);
242 pathp = dirPathArray[AFSDIR_SERVER_PTLOG_FILEPATH_ID];
243 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_PTLOG_FILE);
245 pathp = dirPathArray[AFSDIR_SERVER_KCONF_FILEPATH_ID];
246 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_KCONF_FILE);
248 pathp = dirPathArray[AFSDIR_SERVER_VLDB_FILEPATH_ID];
249 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_DB_DIR, AFSDIR_VLDB_FILE);
251 pathp = dirPathArray[AFSDIR_SERVER_VLOG_FILEPATH_ID];
252 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_VLOG_FILE);
254 pathp = dirPathArray[AFSDIR_SERVER_CORELOG_FILEPATH_ID];
255 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_CORE_FILE);
257 pathp = dirPathArray[AFSDIR_SERVER_SLVGLOG_FILEPATH_ID];
258 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_SLVGLOG_FILE);
260 pathp = dirPathArray[AFSDIR_SERVER_SALVAGER_FILEPATH_ID];
261 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BIN_DIR, AFSDIR_SALVAGER_FILE);
263 pathp = dirPathArray[AFSDIR_SERVER_SLVGLOCK_FILEPATH_ID];
264 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_SLVGLOCK_FILE);
266 pathp = dirPathArray[AFSDIR_SERVER_KEY_FILEPATH_ID];
267 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_KEY_FILE);
269 pathp = dirPathArray[AFSDIR_SERVER_ULIST_FILEPATH_ID];
270 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_ULIST_FILE);
272 pathp = dirPathArray[AFSDIR_SERVER_BOZCONF_FILEPATH_ID];
273 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_BOZCONF_FILE);
275 pathp = dirPathArray[AFSDIR_SERVER_BOZCONFNEW_FILEPATH_ID];
276 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_BOZCONFNEW_FILE);
278 pathp = dirPathArray[AFSDIR_SERVER_BOZLOG_FILEPATH_ID];
279 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_BOZLOG_FILE);
281 pathp = dirPathArray[AFSDIR_SERVER_BOZINIT_FILEPATH_ID];
282 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_BOZINIT_FILE);
284 pathp = dirPathArray[AFSDIR_SERVER_BOSVR_FILEPATH_ID];
285 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BIN_DIR, AFSDIR_BOSVR_FILE);
287 pathp = dirPathArray[AFSDIR_SERVER_VOLSERLOG_FILEPATH_ID];
288 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_VOLSERLOG_FILE);
290 pathp = dirPathArray[AFSDIR_SERVER_ROOTVOL_FILEPATH_ID];
291 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_ROOTVOL_FILE);
293 pathp = dirPathArray[AFSDIR_SERVER_HOSTDUMP_FILEPATH_ID];
294 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_HOSTDUMP_FILE);
296 pathp = dirPathArray[AFSDIR_SERVER_CLNTDUMP_FILEPATH_ID];
297 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_CLNTDUMP_FILE);
299 pathp = dirPathArray[AFSDIR_SERVER_CBKDUMP_FILEPATH_ID];
300 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_CBKDUMP_FILE);
302 pathp = dirPathArray[AFSDIR_SERVER_OLDSYSID_FILEPATH_ID];
303 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_OLDSYSID_FILE);
305 pathp = dirPathArray[AFSDIR_SERVER_SYSID_FILEPATH_ID];
306 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_SYSID_FILE);
308 pathp = dirPathArray[AFSDIR_SERVER_FILELOG_FILEPATH_ID];
309 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_FILELOG_FILE);
311 pathp = dirPathArray[AFSDIR_SERVER_AUDIT_FILEPATH_ID];
312 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_AUDIT_FILE);
314 pathp = dirPathArray[AFSDIR_SERVER_NETINFO_FILEPATH_ID];
315 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_NETINFO_FILE);
317 pathp = dirPathArray[AFSDIR_SERVER_NETRESTRICT_FILEPATH_ID];
318 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_NETRESTRICT_FILE);
320 pathp = dirPathArray[AFSDIR_SERVER_WEIGHTING_CONSTANTS_FILEPATH_ID];
321 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_MIGR_DIR, AFSDIR_WEIGHTINGCONST_FILE);
323 pathp = dirPathArray[AFSDIR_SERVER_THRESHOLD_CONSTANTS_FILEPATH_ID];
324 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_MIGR_DIR, AFSDIR_THRESHOLDCONST_FILE);
326 pathp = dirPathArray[AFSDIR_SERVER_MIGRATELOG_FILEPATH_ID];
327 AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_MIGR_DIR, AFSDIR_MIGRATE_LOGNAME);
330 /* client file paths */
333 strcpy(dirPathArray[AFSDIR_CLIENT_THISCELL_FILEPATH_ID],
334 "/NoUsrViceEtcThisCellFileOnWindows");
335 sprintf(dirPathArray[AFSDIR_CLIENT_CELLSERVDB_FILEPATH_ID], "%s/%s",
336 ntClientConfigDirShort, AFSDIR_CELLSERVDB_FILE_NTCLIENT);
338 pathp = dirPathArray[AFSDIR_CLIENT_THISCELL_FILEPATH_ID];
339 AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_THISCELL_FILE);
341 pathp = dirPathArray[AFSDIR_CLIENT_CELLSERVDB_FILEPATH_ID];
342 AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_CELLSERVDB_FILE);
343 #endif /* AFS_NT40_ENV */
345 pathp = dirPathArray[AFSDIR_CLIENT_NETINFO_FILEPATH_ID];
346 AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_NETINFO_FILE);
348 pathp = dirPathArray[AFSDIR_CLIENT_NETRESTRICT_FILEPATH_ID];
349 AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_ETC_DIR, AFSDIR_NETRESTRICT_FILE);
351 initFlag = 1; /* finished dirpath initialization */
355 /* getDirPath - returns a const char pointer to the requested string
356 * from the internal path array.
357 * string_id - index into the path array
359 const char *getDirPath(afsdir_id_t string_id)
361 /* check if the array has been initialized */
362 if (initFlag == 0) { /* no it's not, so initialize */
363 #ifdef AFS_PTHREAD_ENV
364 pthread_once(&dirInit_once, initDirPathArray);
369 return (const char *)dirPathArray[string_id];
374 /* NT version of ConstructLocalPath() */
377 * ConstructLocalPath() -- Convert a canonical (wire-format) path to a fully
378 * specified local path. Upon successful completion, *fullPathBufp is
379 * set to an allocated buffer containing the fully specified local path
380 * constructed from the cpath argument.
382 * On NT, path construction proceeds as follows:
383 * 1) If cpath is fully qualified (i.e., starts with 'X:/') then the
384 * path returned is equivalent to cpath.
385 * 2) If cpath begins with a drive letter but is not fully qualified,
386 * i.e., it is drive relative, then the function fails with EINVAL.
387 * 3) If cpath begins with '/' (or '\') then the path returned is the
388 * concatenation AFS-server-install-dir + cpath.
389 * 4) Otherwise the path returned is the concatenation
390 * AFS-server-install-dir + relativeTo + cpath.
392 * Leading whitespace in cpath is ignored; the constructed path is
393 * normalized (FilepathNormalize()).
395 * RETURN CODES: 0 if successful; errno code otherwise.
398 ConstructLocalPath(const char *cpath,
399 const char *relativeTo,
403 char *newPath = NULL;
405 if (initFlag == 0) { /* dirpath module not yet initialized */
406 #ifdef AFS_PTHREAD_ENV
407 pthread_once(&dirInit_once, initDirPathArray);
413 *fullPathBufp = NULL;
415 while (isspace(*cpath)) {
419 if ((((*cpath >= 'a') && (*cpath <= 'z')) ||
420 ((*cpath >= 'A') && (*cpath <= 'Z'))) &&
421 (*(cpath+1) == ':')) {
423 /* cpath has a leading drive letter */
424 if ((*(cpath+2) != '/') && (*(cpath+2) != '\\')) {
425 /* drive letter relative path; this is not allowed */
428 /* fully qualified path; just make a copy */
429 newPath = (char *)malloc(strlen(cpath)+1);
433 (void)strcpy(newPath, cpath);
438 /* cpath has NO leading drive letter; make relative to install dir */
439 size_t pathSize = strlen(ntServerInstallDirShort) + 2;
441 if ((*cpath == '/') || (*cpath == '\\')) {
442 /* construct path relative to install directory only */
443 pathSize += strlen(cpath);
445 newPath = (char *)malloc(pathSize);
449 sprintf(newPath, "%s/%s", ntServerInstallDirShort, cpath);
452 /* construct path relative to 'relativeTo' (and install dir) */
453 pathSize += strlen(relativeTo) + 1 + strlen(cpath);
455 newPath = (char *)malloc(pathSize);
459 sprintf(newPath, "%s/%s/%s",
460 ntServerInstallDirShort, relativeTo, cpath);
466 FilepathNormalize(newPath);
468 /* return buffer containing fully specified path */
469 *fullPathBufp = newPath;
476 /* Unix version of ConstructLocalPath() */
479 * ConstructLocalPath() -- Convert a canonical (wire-format) path to a fully
480 * specified local path. Upon successful completion, *fullPathBufp is
481 * set to an allocated buffer containing the fully specified local path
482 * constructed from the cpath argument.
484 * On Unix, path construction proceeds as follows:
485 * 1) If cpath begins with '/' then the path returned is equivalent
487 * 2) Otherwise the path returned is the concatenation
488 * relativeTo + cpath.
490 * Leading whitespace in cpath is ignored; the constructed path is
491 * normalized (FilepathNormalize()).
493 * RETURN CODES: 0 if successful; errno code otherwise.
496 ConstructLocalPath(const char *cpath,
497 const char *relativeTo,
501 char *newPath = NULL;
503 if (initFlag == 0) { /* dirpath module not yet initialized */
504 #ifdef AFS_PTHREAD_ENV
505 pthread_once(&dirInit_once, initDirPathArray);
511 *fullPathBufp = NULL;
513 while (isspace(*cpath)) {
518 newPath = (char *)malloc(strlen(cpath) + 1);
522 strcpy(newPath, cpath);
525 newPath = (char *)malloc(strlen(relativeTo) + 1 + strlen(cpath) + 1);
529 sprintf(newPath, "%s/%s", relativeTo, cpath);
534 FilepathNormalize(newPath);
536 /* return buffer containing fully specified path */
537 *fullPathBufp = newPath;
542 #endif /* AFS_NT40_ENV */
546 * ConstructLocalBinPath() -- A convenience wrapper for ConstructLocalPath()
547 * that specifies the canonical AFS server binary directory as the relative
551 ConstructLocalBinPath(const char *cpath,
554 return ConstructLocalPath(cpath,
555 AFSDIR_CANONICAL_SERVER_BIN_DIRPATH,
561 * ConstructLocalLogPath() -- A convenience wrapper for ConstructLocalPath()
562 * that specifies the canonical AFS server logs directory as the relative
566 ConstructLocalLogPath(const char *cpath,
569 return ConstructLocalPath(cpath,
570 AFSDIR_CANONICAL_SERVER_LOGS_DIRPATH,