1 /*
2  * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "FileSystemSupport_md.h"
31 
32 /*
33  * Solaris/Linux implementation of the file system support functions.
34  */
35 
36 #define slash           '/'
37 
pathSeparator()38 char pathSeparator() {
39     return ':';
40 }
41 
42 /* Filenames are case senstitive */
filenameStrcmp(const char * s1,const char * s2)43 int filenameStrcmp(const char* s1, const char* s2) {
44   return strcmp(s1, s2);
45 }
46 
basePath(const char * path)47 char* basePath(const char* path) {
48     char* last = strrchr(path, slash);
49     if (last == NULL) {
50         return (char*)path;
51     } else {
52         int len = last - path;
53         char* str = (char*)malloc(len+1);
54         if (str == NULL) {
55             fprintf(stderr, "OOM error in native tmp buffer allocation");
56             return NULL;
57         }
58         if (len > 0) {
59             memcpy(str, path, len);
60         }
61         str[len] = '\0';
62         return str;
63     }
64 }
65 
isAbsolute(const char * path)66 int isAbsolute(const char* path) {
67     return (path[0] == slash) ? 1 : 0;
68 }
69 
70 /* Ported from src/solaris/classes/java/io/UnixFileSystem.java */
71 
72 /* A normal Unix pathname contains no duplicate slashes and does not end
73    with a slash.  It may be the empty string. */
74 
75 /* Normalize the given pathname, whose length is len, starting at the given
76    offset; everything before this offset is already normal. */
normalizePath(const char * pathname,int len,int off)77 static char* normalizePath(const char* pathname, int len, int off) {
78     char* sb;
79     int sbLen, i, n;
80     char prevChar;
81 
82     if (len == 0) return (char*)pathname;
83     n = len;
84     while ((n > 0) && (pathname[n - 1] == slash)) n--;
85     if (n == 0) return strdup("/");
86 
87     sb = (char*)malloc(strlen(pathname)+1);
88     if (sb == NULL) {
89         fprintf(stderr, "OOM error in native tmp buffer allocation");
90         return NULL;
91     }
92     sbLen = 0;
93 
94     if (off > 0) {
95         memcpy(sb, pathname, off);
96         sbLen = off;
97     }
98 
99     prevChar = 0;
100     for (i = off; i < n; i++) {
101         char c = pathname[i];
102         if ((prevChar == slash) && (c == slash)) continue;
103         sb[sbLen++] = c;
104         prevChar = c;
105     }
106     return sb;
107 }
108 
109 /* Check that the given pathname is normal.  If not, invoke the real
110    normalizer on the part of the pathname that requires normalization.
111    This way we iterate through the whole pathname string only once. */
normalize(const char * pathname)112 char* normalize(const char* pathname) {
113     int i;
114     int n = strlen(pathname);
115     char prevChar = 0;
116     for (i = 0; i < n; i++) {
117         char c = pathname[i];
118         if ((prevChar == slash) && (c == slash))
119             return normalizePath(pathname, n, i - 1);
120         prevChar = c;
121     }
122     if (prevChar == slash) return normalizePath(pathname, n, n - 1);
123     return (char*)pathname;
124 }
125 
resolve(const char * parent,const char * child)126 char* resolve(const char* parent, const char* child) {
127     int len;
128     char* theChars;
129     int pn = strlen(parent);
130     int cn = strlen(child);
131     int childStart = 0;
132     int parentEnd = pn;
133 
134     if (pn > 0 && parent[pn-1] == slash) {
135         parentEnd--;
136     }
137     len = parentEnd + cn - childStart;
138     if (child[0] == slash) {
139         theChars = (char*)malloc(len+1);
140         if (theChars == NULL) {
141             fprintf(stderr, "OOM error in native tmp buffer allocation");
142             return NULL;
143         }
144         if (parentEnd > 0)
145             memcpy(theChars, parent, parentEnd);
146         if (cn > 0)
147             memcpy(theChars+parentEnd, child, cn);
148         theChars[len] = '\0';
149     } else {
150         theChars = (char*)malloc(len+2);
151         if (theChars == NULL) {
152             fprintf(stderr, "OOM error in native tmp buffer allocation");
153             return NULL;
154         }
155         if (parentEnd > 0)
156             memcpy(theChars, parent, parentEnd);
157         theChars[parentEnd] = slash;
158         if (cn > 0)
159             memcpy(theChars+parentEnd+1, child, cn);
160         theChars[len+1] = '\0';
161     }
162     return theChars;
163 }
164 
fromURIPath(const char * path)165 char* fromURIPath(const char* path) {
166     int len = strlen(path);
167     if (len > 1 && path[len-1] == slash) {
168         // "/foo/" --> "/foo", but "/" --> "/"
169         char* str = (char*)malloc(len);
170         if (str == NULL)
171         {
172             fprintf(stderr, "OOM error in native tmp buffer allocation");
173             return NULL;
174         }
175         memcpy(str, path, len-1);
176         str[len-1] = '\0';
177         return str;
178     } else {
179         return (char*)path;
180     }
181 }
182