< prev index next >

src/java.base/unix/native/libjava/canonicalize_md.c

Print this page
imported patch realpath-collapse


 104 
 105     for (i = 0, p = names; i < nc; i++) {
 106         if (!ix[i]) continue;
 107         if (i > 0) {
 108             p[-1] = '/';
 109         }
 110         if (p == ix[i]) {
 111             p += strlen(p) + 1;
 112         } else {
 113             char *q = ix[i];
 114             while ((*p++ = *q++));
 115         }
 116     }
 117     *p = '\0';
 118 }
 119 
 120 
 121 /* Collapse "." and ".." names in the given path wherever possible.
 122    A "." name may always be eliminated; a ".." name may be eliminated if it
 123    follows a name that is neither "." nor "..".  This is a syntactic operation
 124    that performs no filesystem queries, so it should only be used to cleanup
 125    after invoking the realpath() procedure. */
 126 
 127 static void
 128 collapse(char *path)
 129 {
 130     char *names = (path[0] == '/') ? path + 1 : path; /* Preserve first '/' */
 131     int nc;
 132     char **ix;
 133     int i, j;
 134     char *p, *q;
 135 
 136     nc = collapsible(names);
 137     if (nc < 2) return;         /* Nothing to do */
 138     ix = (char **)alloca(nc * sizeof(char *));
 139     splitNames(names, ix);
 140 
 141     for (i = 0; i < nc; i++) {
 142         int dots = 0;
 143 
 144         /* Find next occurrence of "." or ".." */
 145         do {


 165             ix[i] = 0;
 166         }
 167         else {
 168             /* If there is a preceding name, remove both that name and this
 169                instance of ".."; otherwise, leave the ".." as is */
 170             for (j = i - 1; j >= 0; j--) {
 171                 if (ix[j]) break;
 172             }
 173             if (j < 0) continue;
 174             ix[j] = 0;
 175             ix[i] = 0;
 176         }
 177         /* i will be incremented at the top of the loop */
 178     }
 179 
 180     joinNames(names, nc, ix);
 181 }
 182 
 183 
 184 /* Convert a pathname to canonical form.  The input path is assumed to contain
 185    no duplicate slashes.  On Solaris we can use realpath() to do most of the
 186    work, though once that's done we still must collapse any remaining "." and
 187    ".." names by hand. */
 188 
 189 int
 190 canonicalize(char *original, char *resolved, int len)
 191 {
 192     if (len < PATH_MAX) {
 193         errno = EINVAL;
 194         return -1;
 195     }
 196 
 197     if (strlen(original) > PATH_MAX) {
 198         errno = ENAMETOOLONG;
 199         return -1;
 200     }
 201 
 202     /* First try realpath() on the entire path */
 203     if (realpath(original, resolved)) {
 204         /* That worked, so return it */
 205         collapse(resolved);
 206         return 0;
 207     }
 208     else {
 209         /* Something's bogus in the original path, so remove names from the end
 210            until either some subpath works or we run out of names */
 211         char *p, *end, *r = NULL;
 212         char path[PATH_MAX + 1];
 213 
 214         strncpy(path, original, sizeof(path));
 215         if (path[PATH_MAX] != '\0') {
 216             errno = ENAMETOOLONG;
 217             return -1;
 218         }
 219         end = path + strlen(path);
 220 
 221         for (p = end; p > path;) {
 222 
 223             /* Skip last element */
 224             while ((--p > path) && (*p != '/'));
 225             if (p == path) break;


 241                 continue;
 242             }
 243             else {
 244                 return -1;
 245             }
 246         }
 247 
 248         if (r != NULL) {
 249             /* Append unresolved subpath to resolved subpath */
 250             int rn = strlen(r);
 251             if (rn + (int)strlen(p) >= len) {
 252                 /* Buffer overflow */
 253                 errno = ENAMETOOLONG;
 254                 return -1;
 255             }
 256             if ((rn > 0) && (r[rn - 1] == '/') && (*p == '/')) {
 257                 /* Avoid duplicate slashes */
 258                 p++;
 259             }
 260             strcpy(r + rn, p);
 261             collapse(r);
 262             return 0;
 263         }
 264         else {
 265             /* Nothing resolved, so just return the original path */
 266             strcpy(resolved, path);
 267             collapse(resolved);
 268             return 0;
 269         }
 270     }
 271 
 272 }


 104 
 105     for (i = 0, p = names; i < nc; i++) {
 106         if (!ix[i]) continue;
 107         if (i > 0) {
 108             p[-1] = '/';
 109         }
 110         if (p == ix[i]) {
 111             p += strlen(p) + 1;
 112         } else {
 113             char *q = ix[i];
 114             while ((*p++ = *q++));
 115         }
 116     }
 117     *p = '\0';
 118 }
 119 
 120 
 121 /* Collapse "." and ".." names in the given path wherever possible.
 122    A "." name may always be eliminated; a ".." name may be eliminated if it
 123    follows a name that is neither "." nor "..".  This is a syntactic operation
 124    that performs no filesystem queries, so it should only be used to clean up
 125    after symlink resolution. */
 126 
 127 static void
 128 collapse(char *path)
 129 {
 130     char *names = (path[0] == '/') ? path + 1 : path; /* Preserve first '/' */
 131     int nc;
 132     char **ix;
 133     int i, j;
 134     char *p, *q;
 135 
 136     nc = collapsible(names);
 137     if (nc < 2) return;         /* Nothing to do */
 138     ix = (char **)alloca(nc * sizeof(char *));
 139     splitNames(names, ix);
 140 
 141     for (i = 0; i < nc; i++) {
 142         int dots = 0;
 143 
 144         /* Find next occurrence of "." or ".." */
 145         do {


 165             ix[i] = 0;
 166         }
 167         else {
 168             /* If there is a preceding name, remove both that name and this
 169                instance of ".."; otherwise, leave the ".." as is */
 170             for (j = i - 1; j >= 0; j--) {
 171                 if (ix[j]) break;
 172             }
 173             if (j < 0) continue;
 174             ix[j] = 0;
 175             ix[i] = 0;
 176         }
 177         /* i will be incremented at the top of the loop */
 178     }
 179 
 180     joinNames(names, nc, ix);
 181 }
 182 
 183 
 184 /* Convert a pathname to canonical form.  The input path is assumed to contain
 185    no duplicate slashes.  We can use realpath() to do most of the
 186    work, though once that's done we still must collapse any remaining "." and
 187    ".." names in the unresolved portion of the path by hand. */
 188 
 189 int
 190 canonicalize(char *original, char *resolved, int len)
 191 {
 192     if (len < PATH_MAX) {
 193         errno = EINVAL;
 194         return -1;
 195     }
 196 
 197     if (strlen(original) > PATH_MAX) {
 198         errno = ENAMETOOLONG;
 199         return -1;
 200     }
 201 
 202     /* First try realpath() on the entire path */
 203     if (realpath(original, resolved)) {
 204         /* That worked, so return it */

 205         return 0;
 206     }
 207     else {
 208         /* Something's bogus in the original path, so remove names from the end
 209            until either some subpath works or we run out of names */
 210         char *p, *end, *r = NULL;
 211         char path[PATH_MAX + 1];
 212 
 213         strncpy(path, original, sizeof(path));
 214         if (path[PATH_MAX] != '\0') {
 215             errno = ENAMETOOLONG;
 216             return -1;
 217         }
 218         end = path + strlen(path);
 219 
 220         for (p = end; p > path;) {
 221 
 222             /* Skip last element */
 223             while ((--p > path) && (*p != '/'));
 224             if (p == path) break;


 240                 continue;
 241             }
 242             else {
 243                 return -1;
 244             }
 245         }
 246 
 247         if (r != NULL) {
 248             /* Append unresolved subpath to resolved subpath */
 249             int rn = strlen(r);
 250             if (rn + (int)strlen(p) >= len) {
 251                 /* Buffer overflow */
 252                 errno = ENAMETOOLONG;
 253                 return -1;
 254             }
 255             if ((rn > 0) && (r[rn - 1] == '/') && (*p == '/')) {
 256                 /* Avoid duplicate slashes */
 257                 p++;
 258             }
 259             strcpy(r + rn, p);
 260             collapse(r + rn);
 261             return 0;
 262         }
 263         else {
 264             /* Nothing resolved, so just return the original path, collapsed */
 265             strcpy(resolved, path);
 266             collapse(resolved);
 267             return 0;
 268         }
 269     }
 270 
 271 }
< prev index next >