mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-24 23:39:51 +03:00
[project @ 2006-01-06 20:56:44 by rjw]
Add code necessary to flush unaccounted references in the Cache directory. svn path=/import/netsurf/; revision=1995
This commit is contained in:
parent
efb0194748
commit
ef11c95375
@ -15,19 +15,20 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "oslib/osgbpb.h"
|
||||
#include "oslib/osfile.h"
|
||||
#include "netsurf/riscos/filename.h"
|
||||
#include "netsurf/utils/log.h"
|
||||
|
||||
#define FULL_WORD (unsigned int)4294967295
|
||||
/* '0' + '0' * 10 */
|
||||
#define START_PREFIX 528
|
||||
#define START_PREFIX 528
|
||||
|
||||
struct directory {
|
||||
int numeric_prefix; /** numeric representation of prefix */
|
||||
int numeric_prefix; /** numeric representation of prefix */
|
||||
char prefix[10]; /** directory prefix, eg '00.11.52.' */
|
||||
unsigned int low_used; /** first 32 files, 1 bit per file */
|
||||
unsigned int high_used; /** last 32 files, 1 bit per file */
|
||||
unsigned int low_used; /** first 32 files, 1 bit per file */
|
||||
unsigned int high_used; /** last 32 files, 1 bit per file */
|
||||
struct directory *next; /** next directory (sorted by prefix) */
|
||||
};
|
||||
|
||||
@ -37,7 +38,8 @@ static char ro_filename_buffer[12];
|
||||
static char ro_filename_directory[256];
|
||||
|
||||
static struct directory *ro_filename_create_directory(const char *prefix);
|
||||
|
||||
static bool ro_filename_flush_directory(const char *folder, int depth);
|
||||
static bool ro_filename_delete_recursive(char *folder);
|
||||
|
||||
/**
|
||||
* Request a new, unique, filename.
|
||||
@ -47,15 +49,15 @@ static struct directory *ro_filename_create_directory(const char *prefix);
|
||||
char *ro_filename_request(void) {
|
||||
struct directory *dir;
|
||||
int i = -1;
|
||||
|
||||
|
||||
for (dir = root; dir; dir = dir->next)
|
||||
if ((dir->low_used & dir->high_used) != FULL_WORD) {
|
||||
if (dir->low_used != FULL_WORD) {
|
||||
if (dir->low_used != FULL_WORD) {
|
||||
for (i = 0; (dir->low_used & (1 << i)); i++);
|
||||
} else {
|
||||
} else {
|
||||
for (i = 0; (dir->high_used & (1 << i)); i++);
|
||||
i += 32;
|
||||
}
|
||||
i += 32;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i == -1) {
|
||||
@ -86,28 +88,28 @@ bool ro_filename_claim(const char *filename) {
|
||||
char dir_prefix[9];
|
||||
int file;
|
||||
struct directory *dir;
|
||||
|
||||
|
||||
/* filename format is always '01.23.45.XX' */
|
||||
strncpy(dir_prefix, filename, 9);
|
||||
dir_prefix[9] = '\0';
|
||||
file = (filename[10] + filename[9] * 10 - START_PREFIX);
|
||||
|
||||
|
||||
/* create the directory */
|
||||
dir = ro_filename_create_directory(dir_prefix);
|
||||
if (!dir)
|
||||
return false;
|
||||
|
||||
/* update the entry */
|
||||
if (file < 32) {
|
||||
if (dir->low_used & (1 << file))
|
||||
return false;
|
||||
dir->low_used |= (1 << file);
|
||||
} else {
|
||||
if (dir->high_used & (1 << (file - 32)))
|
||||
return false;
|
||||
dir->high_used |= (1 << (file - 32));
|
||||
}
|
||||
return true;
|
||||
if (file < 32) {
|
||||
if (dir->low_used & (1 << file))
|
||||
return false;
|
||||
dir->low_used |= (1 << file);
|
||||
} else {
|
||||
if (dir->high_used & (1 << (file - 32)))
|
||||
return false;
|
||||
dir->high_used |= (1 << (file - 32));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -125,14 +127,14 @@ void ro_filename_release(const char *filename) {
|
||||
((filename[4] + filename[3] * 10 - START_PREFIX) << 6) |
|
||||
((filename[1] + filename[0] * 10 - START_PREFIX) << 12));
|
||||
file = (filename[10] + filename[9] * 10 - START_PREFIX);
|
||||
|
||||
|
||||
/* modify the correct directory entry */
|
||||
for (dir = root; dir; dir = dir->next)
|
||||
if (dir->numeric_prefix == index) {
|
||||
if (file < 32)
|
||||
dir->low_used &= ~(1 << file);
|
||||
else
|
||||
dir->high_used &= ~(1 << (file - 32));
|
||||
if (file < 32)
|
||||
dir->low_used &= ~(1 << file);
|
||||
else
|
||||
dir->high_used &= ~(1 << (file - 32));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -146,7 +148,6 @@ bool ro_filename_initialise(void) {
|
||||
xosfile_create_dir("<Wimp$ScrapDir>.WWW", 0);
|
||||
xosfile_create_dir("<Wimp$ScrapDir>.WWW.NetSurf", 0);
|
||||
xosfile_create_dir("<Wimp$ScrapDir>.WWW.NetSurf.Cache", 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -155,8 +156,174 @@ bool ro_filename_initialise(void) {
|
||||
* Deletes all files in the cache directory that are not accounted for.
|
||||
*/
|
||||
void ro_filename_flush(void) {
|
||||
// todo: delete any files that aren't known of
|
||||
// todo: delete any empty references (?)
|
||||
xhourglass_on();
|
||||
while (ro_filename_flush_directory(CACHE_FILENAME_PREFIX, 0));
|
||||
xhourglass_off();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes some files in a directory that are not accounted for.
|
||||
*
|
||||
* A single call to this function may not delete all the files in
|
||||
* a directory. It should be called until it returns false.
|
||||
*
|
||||
* \param folder the folder to search
|
||||
* \param depth the folder depth
|
||||
* \returns whether further calls may be needed
|
||||
*/
|
||||
bool ro_filename_flush_directory(const char *folder, int depth) {
|
||||
bool changed = false;
|
||||
bool del;
|
||||
int number, i;
|
||||
int prefix = 0;
|
||||
unsigned int prefix_mask = (63 << 12);
|
||||
int context = 0;
|
||||
int read_count;
|
||||
osgbpb_INFO(100) info;
|
||||
os_error *error;
|
||||
char child[256];
|
||||
const char *prefix_start = NULL;
|
||||
struct directory *dir = NULL;
|
||||
|
||||
/* find out directory details */
|
||||
if (depth > 0)
|
||||
prefix_start = folder + strlen(folder) - depth * 3 + 1;
|
||||
for (i = 0; ((i < depth) && (i < 3)); i++) {
|
||||
number = prefix_start[1] + prefix_start[0] * 10 - START_PREFIX;
|
||||
prefix |= (number << (12 - i * 6));
|
||||
prefix_mask |= (63 << (6 - i * 6));
|
||||
prefix_start += 3;
|
||||
}
|
||||
if (depth == 3) {
|
||||
for (dir = root; dir; dir = dir->next)
|
||||
if (dir->numeric_prefix == prefix)
|
||||
break;
|
||||
if ((!dir) || (dir->numeric_prefix != prefix))
|
||||
return false;
|
||||
}
|
||||
|
||||
while (context != -1) {
|
||||
/* read some directory info */
|
||||
error = xosgbpb_dir_entries_info(folder,
|
||||
(osgbpb_info_list *) &info, 1, context,
|
||||
sizeof(info), 0, &read_count, &context);
|
||||
if (error) {
|
||||
LOG(("xosgbpb_dir_entries_info: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
if (error->errnum == 0xd6) /* no such dir */
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
/* ensure we read some data */
|
||||
if (read_count == 0)
|
||||
continue;
|
||||
/* first 3 depths are directories only, then files only */
|
||||
del = false;
|
||||
if (depth < 3) {
|
||||
if (info.obj_type != fileswitch_IS_DIR)
|
||||
del = true;
|
||||
} else {
|
||||
if (info.obj_type != fileswitch_IS_FILE)
|
||||
del = true;
|
||||
}
|
||||
/* check we are a file numbered '00' -> '63' */
|
||||
if ((!del) && (info.name[0] >= '0') && (info.name[0] <= '6') &&
|
||||
(info.name[1] >= '0') && (info.name[1] <= '9') &&
|
||||
(info.name[2] == '\0')) {
|
||||
number = atoi(info.name);
|
||||
if ((number >= 0) && (number <= 63)) {
|
||||
if (depth == 3) {
|
||||
if (number < 32)
|
||||
del = !(dir->low_used &
|
||||
(1 << number));
|
||||
else
|
||||
del = !(dir->high_used &
|
||||
(1 << (number - 32)));
|
||||
} else {
|
||||
del = true;
|
||||
prefix &= ~(63 << (12 - depth * 6));
|
||||
prefix |= (number << (12 - depth * 6));
|
||||
for (dir = root; dir; dir = dir->next) {
|
||||
number = dir->numeric_prefix &
|
||||
prefix_mask;
|
||||
if (number == prefix) {
|
||||
del = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
del = true;
|
||||
}
|
||||
} else {
|
||||
del = true;
|
||||
}
|
||||
/* continue if we are a valid reference so far */
|
||||
if ((!del) && (info.obj_type != fileswitch_IS_DIR))
|
||||
continue;
|
||||
/* delete or recurse */
|
||||
snprintf(child, 256, "%s.%s", folder, info.name);
|
||||
child[255] = '\0';
|
||||
if (del) {
|
||||
if (info.obj_type == fileswitch_IS_DIR)
|
||||
ro_filename_delete_recursive(child);
|
||||
error = xosfile_delete(child, 0, 0, 0, 0, 0);
|
||||
if (error)
|
||||
LOG(("xosfile_delete: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
else
|
||||
changed = true;
|
||||
} else {
|
||||
while (ro_filename_flush_directory(child, depth + 1));
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively deletes the contents of a directory
|
||||
*
|
||||
* \param directory the directory to delete
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool ro_filename_delete_recursive(char *folder) {
|
||||
int context = 0;
|
||||
int read_count;
|
||||
osgbpb_INFO(100) info;
|
||||
os_error *error;
|
||||
char child[256];
|
||||
|
||||
while (context != -1) {
|
||||
/* read the first entry */
|
||||
error = xosgbpb_dir_entries_info(folder,
|
||||
(osgbpb_info_list *) &info, 1, 0,
|
||||
sizeof(info), 0, &read_count, &context);
|
||||
if (error) {
|
||||
LOG(("xosgbpb_dir_entries_info: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
if (error->errnum == 0xd6) /* no such dir */
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
/* ensure we read some data */
|
||||
if (read_count == 0)
|
||||
continue;
|
||||
snprintf(child, 256, "%s.%s", folder, info.name);
|
||||
/* recurse for files */
|
||||
if (info.obj_type == fileswitch_IS_DIR) {
|
||||
if (!ro_filename_delete_recursive(child))
|
||||
return false;
|
||||
}
|
||||
error = xosfile_delete(child, 0, 0, 0, 0, 0);
|
||||
if (error) {
|
||||
LOG(("xosfile_delete: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -165,7 +332,7 @@ void ro_filename_flush(void) {
|
||||
*
|
||||
* \param prefix the prefix to use, or NULL to allocate a new one
|
||||
* \return a new directory structure, or NULL on memory exhaustion
|
||||
*
|
||||
*
|
||||
* Empty directories are never deleted, except by an explicit call to
|
||||
* ro_filename_flush().
|
||||
*/
|
||||
@ -219,11 +386,11 @@ static struct directory *ro_filename_create_directory(const char *prefix) {
|
||||
new_dir->next = prev_dir->next;
|
||||
prev_dir->next = new_dir;
|
||||
}
|
||||
|
||||
|
||||
/* if the previous directory has the same parent then we can simply
|
||||
* create the child. */
|
||||
if ((prev_dir) && (!strncmp(prev_dir->prefix, new_dir->prefix, 6))) {
|
||||
new_dir->prefix[8] = '\0';
|
||||
new_dir->prefix[8] = '\0';
|
||||
sprintf(ro_filename_directory, "%s.%s",
|
||||
CACHE_FILENAME_PREFIX, new_dir->prefix);
|
||||
new_dir->prefix[8] = '.';
|
||||
@ -236,7 +403,7 @@ static struct directory *ro_filename_create_directory(const char *prefix) {
|
||||
LOG(("xosfile_create_dir: 0x%x: %s",
|
||||
error->errnum, error->errmess));
|
||||
}
|
||||
|
||||
|
||||
/* create the directory structure */
|
||||
sprintf(ro_filename_directory, "%s.", CACHE_FILENAME_PREFIX);
|
||||
last_1 = ro_filename_directory + strlen(CACHE_FILENAME_PREFIX) + 1;
|
||||
@ -245,7 +412,7 @@ static struct directory *ro_filename_create_directory(const char *prefix) {
|
||||
*last_1++ = *last_2++;
|
||||
while (*last_2 && *last_2 != '.')
|
||||
*last_1++ = *last_2++;
|
||||
if (*last_2) {
|
||||
if (*last_2) {
|
||||
last_1[0] = '\0';
|
||||
error = xosfile_create_dir(ro_filename_directory, 0);
|
||||
if (error) {
|
||||
|
Loading…
Reference in New Issue
Block a user