DEADSOFTWARE

Patched for Linux
[mp3cc.git] / MPC.3.5.LINUX / preverifier / sys_support.c
1 /*
2 * @(#)sys_support.c 1.7 01/01/18
3 *
4 * Copyright 1995-1999 by Sun Microsystems, Inc.,
5 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
6 * All rights reserved.
7 *
8 * This software is the confidential and proprietary information
9 * of Sun Microsystems, Inc. ("Confidential Information"). You
10 * shall not disclose such Confidential Information and shall use
11 * it only in accordance with the terms of the license agreement
12 * you entered into with Sun.
13 * Use is subject to license terms.
14 */
16 /*=========================================================================
17 * SYSTEM: Verifier
18 * SUBSYSTEM: System support functions
19 * FILE: sys_support.c
20 * OVERVIEW: Routines for system support functions. The routines
21 * are for retrieving system class path and for certain
22 * Windows specific file parsing functions.
23 *
24 * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
25 * Modifications for JAR support and comments,
26 * Tasneem Sayeed, Sun Microsystems, Inc.
27 *=======================================================================*/
29 /*=========================================================================
30 * Include files
31 *=======================================================================*/
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 //#include <errno.h>
38 #include "oobj.h"
39 #include "jar.h"
40 #include "typedefs.h"
41 #include "sys_api.h"
42 #include "path.h"
44 /*=========================================================================
45 * Globals and extern declarations
46 *=======================================================================*/
48 static cpe_t **saved_classpath;
49 static cpe_t **saved_classpath_end;
51 extern zip_t * getZipEntry(char *zipFile, int len);
53 /*=========================================================================
54 * FUNCTION: sysGetClassPath
55 * OVERVIEW: Returns the system class path using the getenv() system
56 * call for retrieving the CLASSPATH environment.
57 * INTERFACE:
58 * parameters: none
59 *
60 * returns: Pointer to cpe_t struct ptr (see path.h)
61 *=======================================================================*/
62 cpe_t **
63 sysGetClassPath(void)
64 {
65 struct stat sbuf;
66 int length;
67 zip_t *zipEntry;
68 bool_t includedDot = FALSE;
70 if (saved_classpath == 0) {
71 char *cps, *s;
72 int ncpe = 1;
73 cpe_t **cpp;
74 if ((cps = getenv("CLASSPATH")) == 0) {
75 cps = ".";
76 }
77 if ((cps = strdup(cps)) == 0) {
78 return 0;
79 }
80 for (s = cps; *s != '\0'; s++) {
81 if (*s == PATH_SEPARATOR) {
82 ncpe++;
83 }
84 }
85 /* We add 2 since we automatically append "." to the list, and we
86 * need a NULL element at the end.
87 * We add an extra 10 to allow pushing and popping of the classpath.
88 * Generally, we'll need two, at most, but we can afford to be
89 * a little extravagant.
90 */
91 cpp = saved_classpath = sysMalloc((ncpe + 2 + 10) * sizeof(cpe_t *));
92 if (cpp == 0) {
93 return 0;
94 }
95 while (cps && *cps) {
96 char *path = cps;
97 cpe_t *cpe;
98 if ((cps = strchr(cps, PATH_SEPARATOR)) != 0) {
99 *cps++ = '\0';
101 if (*path == '\0') {
102 path = ".";
104 cpe = sysMalloc(sizeof(cpe_t));
105 if (cpe == 0) {
106 return 0;
108 length = strlen(path);
109 if (JAR_DEBUG && verbose) {
110 jio_fprintf(stderr, "SysGetClassPath: Length : %d\n", length);
111 jio_fprintf(stderr, "SysGetClasspath: Path : %s\n", path);
113 if (stat(path, &sbuf) < 0) {
114 /* we don't have to do anything */
115 } else if (sbuf.st_mode & S_IFDIR) {
116 /* this is a directory */
117 cpe->type = CPE_DIR;
118 cpe->u.dir = path;
119 if (strcmp(path, ".") == 0) {
120 includedDot = TRUE;
123 /* restore only for a valid directory */
124 *cpp++ = cpe;
126 if (JAR_DEBUG && verbose)
127 jio_fprintf(stderr, "SysGetClassPath: Found directory [%s]\n", path);
129 } else if (isJARfile (path, length)) {
130 /* this looks like a JAR file */
131 /* initialize the zip structure */
133 if (JAR_DEBUG && verbose)
134 jio_fprintf(stderr, "SysGetClassPath: Found .JAR file [%s]\n", path);
136 /* Create the zip entry for searching the JAR
137 * directories. If the zip entry is NULL, it
138 * would indicate that we ran out of memory
139 * and would have exited already.
140 */
141 zipEntry = getZipEntry(path, length);
143 /* search for the JAR directories */
144 if (findJARDirectories(zipEntry, &sbuf)) {
145 /* this is a JAR file - initialize the cpe */
147 if (JAR_DEBUG && verbose)
148 jio_fprintf(stderr, "SysGetClassPath: JAR directories OK in [%s]\n", zipEntry->name);
150 zipEntry->type = 'j';
151 cpe->type = CPE_ZIP;
152 cpe->u.zip = zipEntry;
153 /* restore entry only for a valid JAR */
154 *cpp++ = cpe;
158 if (!includedDot) {
159 cpe_t *cpe = sysMalloc(sizeof(cpe_t));
160 cpe->type = CPE_DIR;
161 cpe->u.dir = ".";
162 *cpp++ = cpe;
164 *cpp = 0;
165 saved_classpath_end = cpp;
168 return saved_classpath;
172 /* Puts this directory at the beginning of the class path */
174 void
175 pushDirectoryOntoClassPath(char* directory)
176 {
177 cpe_t **ptr;
179 cpe_t *cpe = sysMalloc(sizeof(cpe_t));
180 cpe->type = CPE_DIR;
181 cpe->u.dir = directory;
183 sysGetClassPath(); /* just in case not done yet */
185 /* Note that saved_classpath_end points to the NULL at the end. */
186 saved_classpath_end++;
187 for (ptr = saved_classpath_end; ptr > saved_classpath; ptr--) {
188 ptr[0] = ptr[-1];
190 ptr[0] = cpe;
194 /* Puts this jar file at the beginning of the class path */
196 void
197 pushJarFileOntoClassPath(zip_t *zipEntry)
199 cpe_t **ptr;
201 cpe_t *cpe = sysMalloc(sizeof(cpe_t));
202 cpe->type = CPE_ZIP;
203 cpe->u.zip = zipEntry;
205 sysGetClassPath(); /* just in case not done yet */
207 /* Note that saved_classpath_end points to the NULL at the end. */
208 saved_classpath_end++;
209 for (ptr = saved_classpath_end; ptr > saved_classpath; ptr--) {
210 ptr[0] = ptr[-1];
212 ptr[0] = cpe;
216 /* Pop the first element off the class path */
217 void
218 popClassPath()
219 {
220 cpe_t **ptr;
222 sysFree(*saved_classpath);
224 --saved_classpath_end;
225 for (ptr = saved_classpath; ptr <= saved_classpath_end; ptr++) {
226 /* This copies all of the elements, including the NULL at the end */
227 ptr[0] = ptr[1];
232 /*=========================================================================
233 * Win32 file parsing functions
234 *=======================================================================*/
236 #ifdef WIN32
238 #undef DEBUG_PATH /* Define this to debug path code */
240 #define isfilesep(c) ((c) == '/' || (c) == '\\')
241 #define islb(c) (IsDBCSLeadByte((BYTE)(c)))
244 /*=========================================================================
245 * FUNCTION: sysNativePath
246 * OVERVIEW: Converts a path name to native format. On win32, this
247 * involves forcing all separators to be '\\' rather than '/'
248 * (both are legal inputs, but Win95 sometimes rejects '/')
249 * and removing redundant separators. The input path is assumed
250 * to have been converted into the character encoding used by
251 * the local system. Because this might be a double-byte
252 * encoding, care is taken to treat double-byte lead characters
253 * correctly.
254 *
255 * INTERFACE:
256 * parameters: char *path
258 * returns: char *
259 *=======================================================================*/
260 char *
261 sysNativePath(char *path)
263 char *src = path, *dst = path;
264 char *colon = NULL; /* If a drive specifier is found, this will
265 point to the colon following the drive
266 letter */
268 /* Assumption: '/', '\\', ':', and drive letters are never lead bytes */
269 sysAssert(!islb('/') && !islb('\\') && !islb(':'));
271 /* Check for leading separators */
272 while (isfilesep(*src)) src++;
273 if (!islb(*src) && src[1] == ':') {
274 /* Remove leading separators if followed by drive specifier. This
275 hack is necessary to support file URLs containing drive
276 specifiers (e.g., "file://c:/path"). As a side effect,
277 "/c:/path" can be used as an alternative to "c:/path". */
278 *dst++ = *src++;
279 colon = dst;
280 *dst++ = ':'; src++;
281 } else {
282 src = path;
283 if (isfilesep(src[0]) && isfilesep(src[1])) {
284 /* UNC pathname: Retain first separator; leave src pointed at
285 second separator so that further separators will be collapsed
286 into the second separator. The result will be a pathname
287 beginning with "\\\\" followed (most likely) by a host name. */
288 src = dst = path + 1;
289 path[0] = '\\'; /* Force first separator to '\\' */
293 /* Remove redundant separators from remainder of path, forcing all
294 separators to be '\\' rather than '/' */
295 while (*src != '\0') {
296 if (isfilesep(*src)) {
297 *dst++ = '\\'; src++;
298 while (isfilesep(*src)) src++;
299 if (*src == '\0') { /* Check for trailing separator */
300 if (colon == dst - 2) break; /* "z:\\" */
301 if (dst == path + 1) break; /* "\\" */
302 if (dst == path + 2 && isfilesep(path[0])) {
303 /* "\\\\" is not collapsed to "\\" because "\\\\" marks the
304 beginning of a UNC pathname. Even though it is not, by
305 itself, a valid UNC pathname, we leave it as is in order
306 to be consistent with sysCanonicalPath() (below) as well
307 as the win32 APIs, which treat this case as an invalid
308 UNC pathname rather than as an alias for the root
309 directory of the current drive. */
310 break;
312 dst--; /* Path does not denote a root directory, so
313 remove trailing separator */
314 break;
316 } else {
317 if (islb(*src)) { /* Copy a double-byte character */
318 *dst++ = *src++;
319 if (*src) {
320 *dst++ = *src++;
322 } else { /* Copy a single-byte character */
323 *dst++ = *src++;
328 *dst = '\0';
329 #ifdef DEBUG_PATH
330 jio_fprintf(stderr, "sysNativePath: %s\n", path);
331 #endif /* DEBUG_PATH */
332 return path;
336 /*=========================================================================
337 * FUNCTION: opendir
338 * OVERVIEW: open directory given dir pointer.
339 *
340 * INTERFACE:
341 * parameters: const char *dirarg
343 * returns: Pointer to DIR structure
344 *=======================================================================*/
345 DIR *
346 opendir(const char *dirarg)
348 DIR *dirp = (DIR *)sysMalloc(sizeof(DIR));
349 unsigned long fattr;
350 char alt_dirname[4] = { 0, 0, 0, 0 };
351 char dirname_buf[1024];
352 char *dirname = dirname_buf;
354 if (dirp == 0) {
355 // errno = ENOMEM;
356 return 0;
359 strcpy(dirname, dirarg);
360 sysNativePath(dirname);
362 /*
363 * Win32 accepts "\" in its POSIX stat(), but refuses to treat it
364 * as a directory in FindFirstFile(). We detect this case here and
365 * prepend the current drive name.
366 */
367 if (dirname[1] == '\0' && dirname[0] == '\\') {
368 alt_dirname[0] = _getdrive() + 'A' - 1;
369 alt_dirname[1] = ':';
370 alt_dirname[2] = '\\';
371 alt_dirname[3] = '\0';
372 dirname = alt_dirname;
375 dirp->path = (char *)sysMalloc(strlen(dirname) + 5);
376 if (dirp->path == 0) {
377 sysFree(dirp);
378 // errno = ENOMEM;
379 return 0;
381 strcpy(dirp->path, dirname);
383 fattr = GetFileAttributes(dirp->path);
384 if (fattr == 0xffffffff) {
385 sysFree(dirp->path);
386 sysFree(dirp);
387 // errno = ENOENT;
388 return 0;
389 } else if ((fattr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
390 sysFree(dirp->path);
391 sysFree(dirp);
392 // errno = ENOTDIR;
393 return 0;
396 /* Append "*.*", or possibly "\\*.*", to path */
397 if (dirp->path[1] == ':'
398 && (dirp->path[2] == '\0'
399 || (dirp->path[2] == '\\' && dirp->path[3] == '\0'))) {
400 /* No '\\' needed for cases like "Z:" or "Z:\" */
401 strcat(dirp->path, "*.*");
402 } else {
403 strcat(dirp->path, "\\*.*");
406 dirp->handle = FindFirstFile(dirp->path, &dirp->find_data);
407 if (dirp->handle == INVALID_HANDLE_VALUE) {
408 if (GetLastError() != ERROR_FILE_NOT_FOUND) {
409 sysFree(dirp->path);
410 sysFree(dirp);
411 // errno = EACCES;
412 return 0;
415 return dirp;
419 /*=========================================================================
420 * FUNCTION: readdir
421 * OVERVIEW: read directory given pointer to DIR structure.
422 *
423 * INTERFACE:
424 * parameters: DIR *dirp
426 * returns: Pointer to dirent structure.
427 *=======================================================================*/
428 struct dirent *
429 readdir(DIR *dirp)
431 if (dirp->handle == INVALID_HANDLE_VALUE) {
432 return 0;
435 strcpy(dirp->dirent.d_name, dirp->find_data.cFileName);
437 if (!FindNextFile(dirp->handle, &dirp->find_data)) {
438 if (GetLastError() == ERROR_INVALID_HANDLE) {
439 // errno = EBADF;
440 return 0;
442 FindClose(dirp->handle);
443 dirp->handle = INVALID_HANDLE_VALUE;
446 return &dirp->dirent;
450 /*=========================================================================
451 * FUNCTION: closedir
452 * OVERVIEW: close directory given pointer to DIR structure.
453 * Returns non-zero status if the close fails.
454 *
455 * INTERFACE:
456 * parameters: DIR: *dirp
458 * returns: int: status
459 *=======================================================================*/
460 int
461 closedir(DIR *dirp)
463 if (dirp->handle != INVALID_HANDLE_VALUE) {
464 if (!FindClose(dirp->handle)) {
465 // errno = EBADF;
466 return -1;
468 dirp->handle = INVALID_HANDLE_VALUE;
470 sysFree(dirp->path);
471 sysFree(dirp);
472 return 0;
475 #endif