1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 ** Pathname subroutines.
8 ** Brendan Eich, 8/29/95
11 #include <sys/types.h>
22 #ifdef USE_REENTRANT_LIBC
32 void fail(const char* format
, ...) {
36 #ifdef USE_REENTRANT_LIBC
41 fprintf(stderr
, "%s: ", program
);
43 vfprintf(stderr
, format
, ap
);
46 #ifdef USE_REENTRANT_LIBC
48 fprintf(stderr
, ": %s", r_strerror_r
);
50 fprintf(stderr
, ": %s", strerror(errno
));
58 char* getcomponent(char* path
, char* name
) {
59 if (*path
== '\0') return 0;
65 } while (*path
!= '/' && *path
!= '\0');
68 while (*path
== '/') path
++;
73 # include <sys/param.h>
75 ** The static buffer in Unixware's readdir is too small.
77 struct dirent
* readdir(DIR* d
) {
78 static struct dirent
* buf
= NULL
;
81 buf
= (struct dirent
*)malloc(sizeof(struct dirent
) + MAXPATHLEN
);
82 return (readdir_r(d
, buf
));
86 char* ino2name(ino_t ino
) {
92 if (!dp
) fail("cannot read parent directory");
94 if (!(ep
= readdir(dp
))) fail("cannot find current directory");
95 if (ep
->d_ino
== ino
) break;
97 name
= xstrdup(ep
->d_name
);
102 void* xmalloc(size_t size
) {
103 void* p
= malloc(size
);
104 if (!p
) fail("cannot allocate %u bytes", size
);
108 char* xstrdup(char* s
) { return strcpy(xmalloc(strlen(s
) + 1), s
); }
110 char* xbasename(char* path
) {
113 while ((cp
= strrchr(path
, '/')) && cp
[1] == '\0') *cp
= '\0';
114 if (!cp
) return path
;
118 void xchdir(const char* dir
) {
119 if (chdir(dir
) < 0) fail("cannot change directory to %s", dir
);
122 int relatepaths(char* from
, char* to
, char* outpath
) {
127 assert(*from
== '/' && *to
== '/');
128 for (cp
= to
, cp2
= from
; *cp
== *cp2
; cp
++, cp2
++)
129 if (*cp
== '\0') break;
130 while (cp
[-1] != '/') cp
--, cp2
--;
132 /* closest common ancestor is /, so use full pathname */
133 len
= strlen(strcpy(outpath
, to
));
134 if (outpath
[len
] != '/') {
135 outpath
[len
++] = '/';
140 while ((cp2
= getcomponent(cp2
, buf
)) != 0) {
141 strcpy(outpath
+ len
, "../");
144 while ((cp
= getcomponent(cp
, buf
)) != 0) {
145 sprintf(outpath
+ len
, "%s/", buf
);
146 len
+= strlen(outpath
+ len
);
152 void reversepath(char* inpath
, char* name
, int len
, char* outpath
) {
157 cp
= strcpy(outpath
+ PATH_MAX
- (len
+ 1), name
);
159 while ((cp2
= getcomponent(cp2
, buf
)) != 0) {
160 if (strcmp(buf
, ".") == 0) continue;
161 if (strcmp(buf
, "..") == 0) {
162 if (stat(".", &sb
) < 0) fail("cannot stat current directory");
163 name
= ino2name(sb
.st_ino
);
172 strncpy(cp
, "../", 3);