43#define FULL_WORD (unsigned int)0xffffffffu
44#define START_PREFIX ('0' + '0' * 10)
73 for (dir =
root; dir; dir = dir->
next) {
76 for (i = 0; (dir->
low_used & (1 << i)); i++);
78 for (i = 0; (dir->
high_used & (1 << i)); i++);
90 "Failed to create a new directory.");
122 strncpy(dir_prefix, filename, 9);
123 dir_prefix[8] =
'\0';
124 file = (filename[10] + filename[9] * 10 -
START_PREFIX);
157 index = ((filename[7] + filename[6] * 10 -
START_PREFIX) |
158 ((filename[4] + filename[3] * 10 -
START_PREFIX) << 6) |
159 ((filename[1] + filename[0] * 10 -
START_PREFIX) << 12));
160 file = (filename[10] + filename[9] * 10 -
START_PREFIX);
163 for (dir =
root; dir; dir = dir->
next) {
187 for (start =
directory; *start !=
'\0'; start++) {
192 if (ret != 0 && errno != EEXIST) {
194 "Failed to create directory \"%s\"",
204 NSLOG(netsurf, INFO,
"Temporary directory location: %s",
directory);
238 struct dirent *entry;
239 bool changed =
false;
243 unsigned int prefix_mask = (0x3f << 12);
245 const char *prefix_start = NULL;
254 prefix_start = folder + strlen(folder) - depth * 3 + 1;
258 for (i = 0; i < depth; i++) {
259 number = prefix_start[1] + prefix_start[0] * 10 -
START_PREFIX;
260 prefix |= (number << (12 - i * 6));
261 prefix_mask |= (0x3f << (12 - i * 6));
267 for (dir =
root; dir; dir = dir->
next) {
280 while ((entry = readdir(
parent))) {
285 if (strcmp(entry->d_name,
".") == 0 ||
286 strcmp(entry->d_name,
"..") == 0)
289 written = snprintf(child,
sizeof(child),
"%s/%s",
290 folder, entry->d_name);
291 if (written ==
sizeof(child)) {
292 child[
sizeof(child) - 1] =
'\0';
295#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT))
296 if (fstatat(dirfd(
parent), entry->d_name, &statbuf,
297 AT_SYMLINK_NOFOLLOW) == -1) {
299 if (stat(child, &statbuf) == -1) {
301 NSLOG(netsurf, INFO,
"Unable to stat %s: %s", child,
309 del = !S_ISDIR(statbuf.st_mode);
312 del = S_ISDIR(statbuf.st_mode);
316 if (del ==
false && (entry->d_name[0] >=
'0') &&
317 (entry->d_name[0] <=
'6') &&
318 (entry->d_name[1] >=
'0') &&
319 (entry->d_name[1] <=
'9') &&
320 (entry->d_name[2] ==
'\0')) {
321 number = atoi(entry->d_name);
323 if (number >= 0 && number <= 63) {
331 (1 << (number - 32)));
337 prefix &= ~(0x3f << (12 - depth * 6));
338 prefix |= (number << (12 - depth * 6));
341 for (dir =
root; dir; dir = dir->
next) {
344 if (number == prefix) {
361 if (del ==
false && (!S_ISDIR(statbuf.st_mode)))
366 if (S_ISDIR(statbuf.st_mode)) {
370#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT))
371 if (unlinkat(dirfd(
parent), entry->d_name, 0)) {
376 "Failed to remove '%s'", child);
403 char *last_1, *last_2;
405 struct directory *old_dir, *new_dir, *prev_dir = NULL;
411 for (index = 0, old_dir =
root; old_dir;
412 index++, old_dir = old_dir->
next) {
413 if (old_dir->numeric_prefix != index)
419 sprintf(dir_prefix,
"%.2i/%.2i/%.2i/",
420 ((index >> 12) & 63),
422 ((index >> 0) & 63));
431 for (old_dir =
root; old_dir; old_dir = old_dir->
next) {
443 new_dir = malloc(
sizeof(
struct directory));
444 if (new_dir == NULL) {
445 NSLOG(netsurf, INFO,
"No memory for malloc()");
450 new_dir->
prefix[9] =
'\0';
454 if (prev_dir == NULL) {
459 prev_dir->
next = new_dir;
464 if (prev_dir && strncmp(prev_dir->
prefix, new_dir->
prefix, 6) == 0) {
465 new_dir->
prefix[8] =
'\0';
480 "Failed to create optimised structure '%s'",
491 for (i = 0; i < 3 && *last_2; i++) {
492 *last_1++ = *last_2++;
493 while (*last_2 && *last_2 !=
'/')
494 *last_1++ = *last_2++;
502 "Failed to create directory '%s'",
directory traversal and entry
void filename_release(const char *filename)
Releases a filename for future use.
static char filename_directory[256]
static char filename_buffer[12]
const char * filename_request(void)
Request a new, unique, filename.
static bool filename_flush_directory(const char *folder, int depth)
Deletes some files in a directory that are not accounted for.
static struct directory * filename_create_directory(const char *prefix)
Creates a new directory.
static struct directory * root
void filename_flush(void)
Deletes all files in the cache directory that are not accounted for.
bool filename_claim(const char *filename)
Claim a specific filename.
bool filename_initialise(void)
Initialise the filename provider.
#define TEMP_FILENAME_PREFIX
#define NSLOG(catname, level, logmsg, args...)
Interface to utility string handling.
char prefix[10]
numeric representation of prefix
unsigned int high_used
first 32 files, 1 bit per file
unsigned int low_used
directory prefix, eg '00/11/52/'
struct directory * next
last 32 files, 1 bit per file
nserror netsurf_recursive_rm(const char *path)
Recursively remove a directory.
Default operations table for files.
Interface to a number of general purpose functionality.
#define nsmkdir(dir, mode)
POSIX mkdir function.
#define SLEN(x)
Calculate length of constant C string.
bool is_dir(const char *path)
Check if a directory exists.