summaryrefslogtreecommitdiff
path: root/riscos/filename.c
diff options
context:
space:
mode:
authorRichard Wilson <rjw@netsurf-browser.org>2006-01-06 20:56:44 +0000
committerRichard Wilson <rjw@netsurf-browser.org>2006-01-06 20:56:44 +0000
commitef11c9537503373268c593e303950a6b1945376d (patch)
tree409ff0317fa366f67cdce88fdcf20cce29853dc3 /riscos/filename.c
parentefb0194748827c7a29783d86f50d8a795f4570df (diff)
downloadnetsurf-ef11c9537503373268c593e303950a6b1945376d.tar.gz
netsurf-ef11c9537503373268c593e303950a6b1945376d.tar.bz2
[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
Diffstat (limited to 'riscos/filename.c')
-rw-r--r--riscos/filename.c237
1 files changed, 202 insertions, 35 deletions
diff --git a/riscos/filename.c b/riscos/filename.c
index 7fb0031b7..8ec8ea217 100644
--- a/riscos/filename.c
+++ b/riscos/filename.c
@@ -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) {