File: | jdk/src/java.base/unix/native/libjava/path_util.c |
Warning: | line 134, column 13 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (c) 2021, 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 <stdlib.h> | |||
27 | #include <string.h> | |||
28 | #if !defined(_ALLBSD_SOURCE) | |||
29 | #include <alloca.h> | |||
30 | #endif | |||
31 | ||||
32 | #include "path_util.h" | |||
33 | ||||
34 | /* Check the given name sequence to see if it can be further collapsed. | |||
35 | Return zero if not, otherwise return the number of names in the sequence. */ | |||
36 | ||||
37 | static int | |||
38 | collapsible(char *names) | |||
39 | { | |||
40 | char *p = names; | |||
41 | int dots = 0, n = 0; | |||
42 | ||||
43 | while (*p) { | |||
44 | if ((p[0] == '.') && ((p[1] == '\0') | |||
45 | || (p[1] == '/') | |||
46 | || ((p[1] == '.') && ((p[2] == '\0') | |||
47 | || (p[2] == '/'))))) { | |||
48 | dots = 1; | |||
49 | } | |||
50 | n++; | |||
51 | while (*p) { | |||
52 | if (*p == '/') { | |||
53 | p++; | |||
54 | break; | |||
55 | } | |||
56 | p++; | |||
57 | } | |||
58 | } | |||
59 | return (dots ? n : 0); | |||
60 | } | |||
61 | ||||
62 | ||||
63 | /* Split the names in the given name sequence, | |||
64 | replacing slashes with nulls and filling in the given index array */ | |||
65 | ||||
66 | static void | |||
67 | splitNames(char *names, char **ix) | |||
68 | { | |||
69 | char *p = names; | |||
70 | int i = 0; | |||
71 | ||||
72 | while (*p) { | |||
73 | ix[i++] = p++; | |||
74 | while (*p) { | |||
75 | if (*p == '/') { | |||
76 | *p++ = '\0'; | |||
77 | break; | |||
78 | } | |||
79 | p++; | |||
80 | } | |||
81 | } | |||
82 | } | |||
83 | ||||
84 | ||||
85 | /* Join the names in the given name sequence, ignoring names whose index | |||
86 | entries have been cleared and replacing nulls with slashes as needed */ | |||
87 | ||||
88 | static void | |||
89 | joinNames(char *names, int nc, char **ix) | |||
90 | { | |||
91 | int i; | |||
92 | char *p; | |||
93 | ||||
94 | for (i = 0, p = names; i < nc; i++) { | |||
95 | if (!ix[i]) continue; | |||
96 | if (i > 0) { | |||
97 | p[-1] = '/'; | |||
98 | } | |||
99 | if (p == ix[i]) { | |||
100 | p += strlen(p) + 1; | |||
101 | } else { | |||
102 | char *q = ix[i]; | |||
103 | while ((*p++ = *q++)); | |||
104 | } | |||
105 | } | |||
106 | *p = '\0'; | |||
107 | } | |||
108 | ||||
109 | /* Collapse "." and ".." names in the given path wherever possible. | |||
110 | A "." name may always be eliminated; a ".." name may be eliminated if it | |||
111 | follows a name that is neither "." nor "..". This is a syntactic operation | |||
112 | that performs no filesystem queries, so it should only be used to cleanup | |||
113 | after invoking the realpath() procedure. */ | |||
114 | ||||
115 | void | |||
116 | collapse(char *path) | |||
117 | { | |||
118 | char *names = (path[0] == '/') ? path + 1 : path; /* Preserve first '/' */ | |||
| ||||
119 | int nc; | |||
120 | char **ix; | |||
121 | int i, j; | |||
122 | char *p, *q; | |||
123 | ||||
124 | nc = collapsible(names); | |||
125 | if (nc < 2) return; /* Nothing to do */ | |||
126 | ix = (char **)alloca(nc * sizeof(char *))__builtin_alloca (nc * sizeof(char *)); | |||
127 | splitNames(names, ix); | |||
128 | ||||
129 | for (i = 0; i
| |||
130 | int dots = 0; | |||
131 | ||||
132 | /* Find next occurrence of "." or ".." */ | |||
133 | do { | |||
134 | char *p = ix[i]; | |||
| ||||
135 | if (p[0] == '.') { | |||
136 | if (p[1] == '\0') { | |||
137 | dots = 1; | |||
138 | break; | |||
139 | } | |||
140 | if ((p[1] == '.') && (p[2] == '\0')) { | |||
141 | dots = 2; | |||
142 | break; | |||
143 | } | |||
144 | } | |||
145 | i++; | |||
146 | } while (i < nc); | |||
147 | if (i >= nc) break; | |||
148 | ||||
149 | /* At this point i is the index of either a "." or a "..", so take the | |||
150 | appropriate action and then continue the outer loop */ | |||
151 | if (dots == 1) { | |||
152 | /* Remove this instance of "." */ | |||
153 | ix[i] = 0; | |||
154 | } | |||
155 | else { | |||
156 | /* If there is a preceding name, remove both that name and this | |||
157 | instance of ".."; otherwise, leave the ".." as is */ | |||
158 | for (j = i - 1; j >= 0; j--) { | |||
159 | if (ix[j]) break; | |||
160 | } | |||
161 | if (j < 0) continue; | |||
162 | ix[j] = 0; | |||
163 | ix[i] = 0; | |||
164 | } | |||
165 | /* i will be incremented at the top of the loop */ | |||
166 | } | |||
167 | ||||
168 | joinNames(names, nc, ix); | |||
169 | } |