#include #include #include #include object new_simple_string (int l) { object s; BEGIN_NO_INTERRUPT; s = alloc_simple_string (l); s->st.st_self = alloc_relblock (l); END_NO_INTERRUPT; return s; } /* Split a numeric component into multiple directores so that there will not be too many files in one directory. For example, 6 becomes "06"; 204 becomes "a/02/04"; 714206 becomes "b/71/42/06"; and so on. This is based on a function in Raph Levien's mod_virgule. */ object integer_to_dir (int n) { object result; int log100; int tmp; char *p; log100 = 0; for (tmp = n; tmp >= 100; tmp /= 100) log100++; if (log100 == 0) { result = new_simple_string (3); result->st.st_self[0] = '0' + (n / 10); result->st.st_self[1] = '0' + (n % 10); result->st.st_self[2] = '/'; return result; } result = new_simple_string (2 + (3 * (log100 + 1))); p = result->st.st_self; *p++ = 'a' + log100 - 1; *p++ = '/'; p += 3 * log100; while (n > 0) { tmp = n % 100; p[0] = '0' + (tmp / 10); p[1] = '0' + (tmp % 10); p[2] = '/'; p -= 3; n /= 100; } return result; } int file_size (const char *path) { struct stat st; if (stat (path, &st) == 0) return st.st_size; else return 0; } /* Given a path to a file (not a directory), create any directories containing it, as needed. Return 0 on success, -1 on failure. Note that this works by modifying PATH and then undoing the modifications, so only pass a modifiable buffer. */ int ensure_dir (char *path) { char *end; char *p; struct stat st; int status = 0; end = strrchr (path, '/'); if ((end != NULL) && (end != path)) { *end = '\0'; if ((stat (path, &st) == 0) && S_ISDIR (st.st_mode)) { *end = '/'; return 0; } else *end = '/'; } else return 0; for (p = (path[0] == '/') ? (path + 1) : path; *p; p++) { if (*p == '/') { *p = '\0'; status = 0; if (stat (path, &st) == 0) { if (!S_ISDIR (st.st_mode)) { fprintf (stderr, "ensure_dir: %s: not a directory\n", path); status = -1; } } else { if (mkdir (path, 0777) != 0) { fprintf (stderr, "ensure_dir: %s: mkdir: %s\n", path, strerror (errno)); status = -1; } } *p = '/'; if (status != 0) break; } } return status; }