/* * Empty a local directory */ static void empty_dir(VMG_ const char *dir) { /* open the directory search */ osdirhdl_t dirhdl; if (os_open_dir(dir, &dirhdl)) { err_try { /* keep going until we're out of files */ char fname[OSFNMAX]; while (os_read_dir(dirhdl, fname, sizeof(fname))) { /* get the full path */ char path[OSFNMAX]; os_build_full_path(path, sizeof(path), dir, fname); /* get the mode */ unsigned long fmode; unsigned long fattr; if (osfmode(path, FALSE, &fmode, &fattr)) { /* check whether it's a directory or an ordinary file */ if ((fmode & OSFMODE_DIR) != 0) { /* * directory - skip the special '.' and '..' links, * since they'd get us stuck in a loop */ os_specfile_t st = os_is_special_file(fname); if (st != OS_SPECFILE_SELF && st != OS_SPECFILE_PARENT) { /* recursively empty the directory */ empty_dir(vmg_ path); /* remove this directory */ if (!os_rmdir(path)) err_throw(VMERR_DELETE_FILE); } } else { /* ordinary file - delete it */ if (osfdel(path)) err_throw(VMERR_DELETE_FILE); } } } } err_finally { /* close the directory search handle */ os_close_dir(dirhdl); } err_end; }
int CVmNetFile::get_file_mode( VMG_ unsigned long *mode, unsigned long *attr, int follow_links) { return osfmode(lclfname, follow_links, mode, attr); }
/* Get the local time zone name, as a zoneinfo database key. Many * modern Unix systems use zoneinfo keys as they native timezone * setting, but there are several different ways of storing this on a * per-process and system-wide basis. We'll try looking for the common * mechanisms. */ int os_get_zoneinfo_key( char *buf, size_t buflen ) { /* First, try the TZ environment variable. This is used on nearly * all Unix-alikes for a per-process timezone setting, although * it will only contain a zoneinfo key in newer versions. There * are several possible formats for specifying a zoneinfo key: * * TZ=/usr/share/zoneinfo/America/Los_Angeles * - A full absolute path name to a tzinfo file. We'll sense * this by looking for "/zoneinfo/" in the string, and if we * find it, we'll return the portion after /zoneinfo/. * * TZ=America/Los_Angeles * - Just the zoneinfo key, without a path. If we find a string * that contains all alphabetics, undersores, and slashes, and * has at least one internal slash but doesn't start with a * slash, we probably have a zoneinfo key. We'll see if we * can find a matching file in the usual zoneinfo database * locations: /etc/zoneinfo, /usr/share/zoneinfo; if we can, * we'll return the key name, otherwise we'll assume this * isn't actually a zoneinfo key but just happens to look like * one in terms of format. * * TZ=:America/Los_Angeles * TZ=:/etc/zoneinfo/America/Los_Angeles * - POSIX systems generally use the ":" prefix to signify that * this is a zoneinfo path rather than the old-style "EST5EDT" * type of self-contained zone description. If we see a colon * prefix with a relative path (properly formed in terms of * its character content), we'll simply assume this is a * zoneinfo key without even checking for an existing file, * since there's not much else it could be. If we see an * absolute path, we'll search it for /zoneinfo/ and return * the portion after this, again without checking for an * existing file. */ const char *tz = getenv("TZ"); if (tz != 0 && tz[0] != '\0') { /* check that the string is formatted like a zoneinfo key */ #define tzcharok(c) (isalpha(c) != 0 || (c) == '/' || (c) == '_') int fmt_ok = TRUE; const char *p; fmt_ok &= (tz[0] == ':' || tzcharok(tz[0])); for (p = tz + 1 ; *p != '\0' ; ++p) fmt_ok &= tzcharok(*p); /* proceed only if it has the right format */ if (fmt_ok) { /* check for a leading ':', per POSIX */ if (tz[0] == ':') { /* yes, we have a leading ':', so it's almost certainly * a zoneinfo key; if it's an absolute path, find the * part after /zoneinfo/ */ if (tz[1] == '/') { /* absolute form - look for /zoneinfo/ */ const char *z = strstr(tz, "/zoneinfo/"); if (z != 0) { /* found it - return the part after /zoneinfo/ */ safe_strcpy(buf, buflen, z + 10); return TRUE; } } else { /* relative path - return as-is minus the colon */ safe_strcpy(buf, buflen, tz + 1); return TRUE; } } else { /* There's no colon, so it *might* be a zoneinfo key. * If it's an absolute path containing /zoneinfo/, it's * a solid bet. If it's a relative path, look to see * if we can find a file in one of the usual zoneinfo * database locations. */ if (tz[0] == '/') { /* absolute path - check for /zoneinfo/ */ const char *z = strstr(tz, "/zoneinfo/"); if (z != 0) { /* found it - return the part after /zoneinfo/ */ safe_strcpy(buf, buflen, z + 10); return TRUE; } } else { /* relative path - look for a tzinfo file in the * usual locations */ static const char *dirs[] = { "/etc/zoneinfo", "/usr/share/zoneinfo", 0 }; const char **dir; for (dir = dirs ; *dir != 0 ; ++dir) { /* build this full path */ char fbuf[OSFNMAX]; os_build_full_path(fbuf, sizeof(fbuf), *dir, tz); /* check for a file at this location */ if (!osfacc(fbuf)) { /* got it - looks like a good zoneinfo key */ safe_strcpy(buf, buflen, tz); return TRUE; } } } } } } /* No luck with TZ, so try the system-wide settings next. * * If a file called /etc/timezone exists, it's usually a one-line * text file containing the zoneinfo key. Read and return its * contents. */ FILE *fp; if ((fp = fopen("/etc/timezone", "r")) != 0) { /* read the one-liner */ char lbuf[256]; int ok = FALSE; if (fgets(lbuf, sizeof(lbuf), fp) != 0) { /* strip any trailing newline */ size_t l = strlen(lbuf); if (l != 0 && lbuf[l-1] == '\n') lbuf[l-1] = '\0'; /* if it's in absolute format, return the part after * /zoneinfo/; otherwise just return the string */ if (lbuf[0] == '/') { /* absoltue path - find /zoneinfo/ */ const char *z = strstr(lbuf, "/zoneinfo/"); if (z != 0) { safe_strcpy(buf, buflen, z + 10); ok = TRUE; } } else { /* relative notation - return it as-is */ safe_strcpy(buf, buflen, lbuf); ok = TRUE; } } /* we're done with the file */ fclose(fp); /* if we got our result, return success */ if (ok) return TRUE; } /* If /etc/sysconfig/clock exists, read it and look for a line * starting with ZONE=. This contains the zoneinfo key. */ if ((fp = fopen("/etc/sysconfig/clock", "r")) != 0) { /* scan the file for ZONE=... */ int ok = FALSE; for (;;) { /* read the next line */ char lbuf[256]; if (fgets(lbuf, sizeof(lbuf), fp) == 0) break; /* skip leading spaces */ const char *p; for (p = lbuf ; isspace(*p) ; ++p) ; /* check for ZONE */ if (memicmp(p, "zone", 4) != 0) continue; /* skip spaces after ZONE */ for (p += 4 ; isspace(*p) ; ++p) ; /* check for '=' */ if (*p != '=') continue; /* skip spaces after the '=' */ for (++p ; isspace(*p) ; ++p) ; /* if it's in absolute form, look for /zoneinfo/ */ if (*p == '/') { const char *z = strstr(p, "/zoneinfo/"); if (z != 0) { safe_strcpy(buf, buflen, z + 10); ok = TRUE; } } else { /* relative notation - it's the zoneinfo key */ safe_strcpy(buf, buflen, p); ok = TRUE; } /* that's our ZONE line, so we're done scanning the file */ break; } /* done with the file */ fclose(fp); /* if we got our result, return success */ if (ok) return TRUE; } /* If /etc/localtime is a symbolic link, the linked file is the * actual zoneinfo file. Resolve the link and return the portion * of the path after "/zoneinfo/". */ #if 0 static const char *elt = "/etc/localtime"; unsigned long mode; char linkbuf[OSFNMAX]; const char *zi; if (osfmode(elt, FALSE, &mode, NULL) && (mode & OSFMODE_LINK) != 0 && os_resolve_symlink(elt, linkbuf, sizeof(linkbuf)) && (zi = strstr(linkbuf, "/zoneinfo/")) != 0) { /* it's a link containing /zoneinfo/, so return the portion * after /zoneinfo/ */ safe_strcpy(buf, buflen, zi + 10); return TRUE; } #endif /* well, we're out of ideas - return failure */ return FALSE; }