2005-06-21 18:17:51 +04:00
|
|
|
/*
|
2006-04-22 03:50:36 +04:00
|
|
|
* Copyright 2006 Richard Wilson <info@tinct.net>
|
2007-08-08 20:16:03 +04:00
|
|
|
*
|
|
|
|
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
|
|
|
*
|
|
|
|
* NetSurf is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; version 2 of the License.
|
|
|
|
*
|
|
|
|
* NetSurf is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2005-06-21 18:17:51 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
* Provides a central method of obtaining unique filenames.
|
|
|
|
*
|
|
|
|
* A maximum of 2^24 files can be allocated at any point in time.
|
|
|
|
*/
|
|
|
|
|
2009-05-29 17:26:58 +04:00
|
|
|
#include <assert.h>
|
Merged revisions 5309-5406,5409-5422 via svnmerge from
svn://svn.netsurf-browser.org/branches/vince/netsurf-fb
........
r5309 | vince | 2008-09-13 10:59:10 +0100 (Sat, 13 Sep 2008) | 2 lines
first stab at framebuffer frontend
........
r5313 | vince | 2008-09-14 15:08:52 +0100 (Sun, 14 Sep 2008) | 2 lines
add line plotters
........
r5314 | vince | 2008-09-14 15:28:12 +0100 (Sun, 14 Sep 2008) | 2 lines
add rectangle plot to 16bpp plotters
........
r5315 | vince | 2008-09-14 19:58:57 +0100 (Sun, 14 Sep 2008) | 2 lines
improve 16bpp image plot
........
r5316 | vince | 2008-09-15 00:35:32 +0100 (Mon, 15 Sep 2008) | 2 lines
abstract the os specific framebuffer init
........
r5317 | vince | 2008-09-15 11:18:51 +0100 (Mon, 15 Sep 2008) | 2 lines
first cut of linux frontend
........
r5318 | vince | 2008-09-15 12:01:00 +0100 (Mon, 15 Sep 2008) | 2 lines
remove junk includes
........
r5319 | vince | 2008-09-15 12:09:02 +0100 (Mon, 15 Sep 2008) | 2 lines
make plotters OS agnostic again
........
r5322 | vince | 2008-09-15 15:55:01 +0100 (Mon, 15 Sep 2008) | 2 lines
Linux frontend operates
........
r5323 | vince | 2008-09-15 16:32:47 +0100 (Mon, 15 Sep 2008) | 2 lines
abstract out OS specific input
........
r5326 | vince | 2008-09-15 19:21:01 +0100 (Mon, 15 Sep 2008) | 2 lines
Improve linux mode setting
........
r5329 | vince | 2008-09-15 21:13:33 +0100 (Mon, 15 Sep 2008) | 2 lines
improve text clipping
........
r5339 | vince | 2008-09-16 00:07:57 +0100 (Tue, 16 Sep 2008) | 2 lines
possibly fix text clipping issue
........
r5342 | vince | 2008-09-16 00:39:36 +0100 (Tue, 16 Sep 2008) | 2 lines
consolidate polygon plotters
........
r5344 | dsilvers | 2008-09-16 10:21:06 +0100 (Tue, 16 Sep 2008) | 1 line
Fix up the framebuffer target makefile a bit more, add some config options for it
........
r5345 | dsilvers | 2008-09-16 10:22:19 +0100 (Tue, 16 Sep 2008) | 1 line
Ensure the appropriate frontend is selected when building framebuffer
........
r5346 | dsilvers | 2008-09-16 10:27:16 +0100 (Tue, 16 Sep 2008) | 1 line
Update build system to support targetting separate framebuffer frontends in different build trees, update executable to be nsfb-blah
........
r5350 | vince | 2008-09-16 17:15:04 +0100 (Tue, 16 Sep 2008) | 1 line
Add -g to provide symbols for framebuffer link
........
r5351 | vince | 2008-09-16 17:17:09 +0100 (Tue, 16 Sep 2008) | 1 line
framebuffer scheduler now works, plotters tweaked, gui tracks window redraw requirements better, keypresses not duplicated under linux fb
........
r5352 | dsilvers | 2008-09-16 17:38:53 +0100 (Tue, 16 Sep 2008) | 1 line
Ensure we only allow one fetcher at a time
........
r5361 | vince | 2008-09-17 11:48:44 +0100 (Wed, 17 Sep 2008) | 2 lines
initial cursor support
........
r5362 | vince | 2008-09-17 13:56:47 +0100 (Wed, 17 Sep 2008) | 2 lines
add mouse handling
........
r5363 | vince | 2008-09-17 14:14:44 +0100 (Wed, 17 Sep 2008) | 2 lines
add framebuffer resources
........
r5364 | vince | 2008-09-17 17:12:21 +0100 (Wed, 17 Sep 2008) | 2 lines
add reasonable pointer
........
r5366 | vince | 2008-09-17 17:17:25 +0100 (Wed, 17 Sep 2008) | 2 lines
fix pointer alpha
........
r5370 | vince | 2008-09-18 13:43:53 +0100 (Thu, 18 Sep 2008) | 2 lines
warning squash and cleanup ready for trunk merge
........
r5375 | vince | 2008-09-19 14:58:43 +0100 (Fri, 19 Sep 2008) | 2 lines
Working mouse navigation
........
r5377 | vince | 2008-09-20 14:06:22 +0100 (Sat, 20 Sep 2008) | 2 lines
Improve scrolling
........
r5378 | vince | 2008-09-20 14:46:46 +0100 (Sat, 20 Sep 2008) | 2 lines
fix redraw issues with scrolling
........
r5380 | vince | 2008-09-20 17:08:43 +0100 (Sat, 20 Sep 2008) | 3 lines
Alter panning to use its own flag so it doesnt cause invalid redraw
operations
........
r5381 | vince | 2008-09-20 21:52:45 +0100 (Sat, 20 Sep 2008) | 2 lines
add dummy framebuffer
........
r5383 | vince | 2008-09-21 00:00:15 +0100 (Sun, 21 Sep 2008) | 2 lines
fix segfault when cursor is off teh bottom of teh screen
........
r5384 | vince | 2008-09-21 00:06:08 +0100 (Sun, 21 Sep 2008) | 2 lines
fix off by one in pointer fix
........
r5385 | vince | 2008-09-21 00:25:09 +0100 (Sun, 21 Sep 2008) | 2 lines
when fixing bloody silly off by one errors remember to fix *both* references
........
r5387 | vince | 2008-09-21 00:38:13 +0100 (Sun, 21 Sep 2008) | 2 lines
last try at stopping the pointer segfault
........
r5388 | vince | 2008-09-21 16:24:18 +0100 (Sun, 21 Sep 2008) | 2 lines
improve vertical text clipping
........
r5392 | vince | 2008-09-21 23:11:51 +0100 (Sun, 21 Sep 2008) | 2 lines
Improve text plotters
........
r5393 | vince | 2008-09-21 23:34:38 +0100 (Sun, 21 Sep 2008) | 2 lines
fix 32bpp line plotting
........
r5394 | vince | 2008-09-22 00:00:03 +0100 (Mon, 22 Sep 2008) | 2 lines
Fix off by one error in line plotting clipping
........
r5397 | vince | 2008-09-22 13:46:22 +0100 (Mon, 22 Sep 2008) | 2 lines
Fix bitmap tileing
........
r5398 | vince | 2008-09-22 17:46:02 +0100 (Mon, 22 Sep 2008) | 2 lines
enable knockout renderer
........
r5399 | vince | 2008-09-22 18:43:48 +0100 (Mon, 22 Sep 2008) | 2 lines
ensure clipping region lies within window, caused by knockout renderer
........
r5400 | vince | 2008-09-22 19:20:25 +0100 (Mon, 22 Sep 2008) | 2 lines
update cursor to one swiped from X windows
........
r5405 | vince | 2008-09-23 09:09:05 +0100 (Tue, 23 Sep 2008) | 2 lines
fix vertical scroll limit
........
r5412 | dsilvers | 2008-09-23 10:53:14 +0100 (Tue, 23 Sep 2008) | 1 line
Revert noisy fetcher patch
........
r5413 | dsilvers | 2008-09-23 10:58:00 +0100 (Tue, 23 Sep 2008) | 1 line
Add header guards
........
r5414 | dsilvers | 2008-09-23 11:31:31 +0100 (Tue, 23 Sep 2008) | 1 line
Tidy the region clipping slightly
........
r5416 | dsilvers | 2008-09-23 12:05:00 +0100 (Tue, 23 Sep 2008) | 1 line
Rationalise how the framebuffer frontend finds resources and options
........
r5418 | dsilvers | 2008-09-23 13:59:00 +0100 (Tue, 23 Sep 2008) | 1 line
Ensure options are overridden after load, and squash an fb_gui.c warning
........
r5419 | dsilvers | 2008-09-23 14:20:07 +0100 (Tue, 23 Sep 2008) | 1 line
Support fb_mode and fb_device options
........
r5420 | dsilvers | 2008-09-23 14:21:48 +0100 (Tue, 23 Sep 2008) | 1 line
Support option_fb_device in the able frontend
........
r5421 | dsilvers | 2008-09-23 14:25:17 +0100 (Tue, 23 Sep 2008) | 1 line
Ensure target_blank is disabled
........
r5422 | dsilvers | 2008-09-23 14:39:00 +0100 (Tue, 23 Sep 2008) | 1 line
Rework linux fb frontend to support scanning and opening all event devices for input
........
svn path=/trunk/netsurf/; revision=5423
2008-09-23 18:00:40 +04:00
|
|
|
#include <sys/types.h>
|
2006-04-22 03:50:36 +04:00
|
|
|
#include <dirent.h>
|
2005-06-21 18:17:51 +04:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2007-06-10 15:28:44 +04:00
|
|
|
#include <errno.h>
|
2006-04-22 03:50:36 +04:00
|
|
|
#include <sys/stat.h>
|
2007-06-10 15:11:46 +04:00
|
|
|
#include <unistd.h>
|
2010-01-31 03:36:02 +03:00
|
|
|
|
|
|
|
#include "utils/config.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "utils/filename.h"
|
|
|
|
#include "utils/log.h"
|
|
|
|
#include "utils/utils.h"
|
2005-06-21 18:17:51 +04:00
|
|
|
|
2009-05-29 17:26:58 +04:00
|
|
|
#define FULL_WORD (unsigned int)0xffffffffu
|
|
|
|
#define START_PREFIX ('0' + '0' * 10)
|
2005-06-21 18:17:51 +04:00
|
|
|
|
|
|
|
struct directory {
|
2006-01-06 23:56:44 +03:00
|
|
|
int numeric_prefix; /** numeric representation of prefix */
|
2006-04-22 03:50:36 +04:00
|
|
|
char prefix[10]; /** directory prefix, eg '00/11/52/' */
|
2006-01-06 23:56:44 +03:00
|
|
|
unsigned int low_used; /** first 32 files, 1 bit per file */
|
|
|
|
unsigned int high_used; /** last 32 files, 1 bit per file */
|
2005-06-21 18:17:51 +04:00
|
|
|
struct directory *next; /** next directory (sorted by prefix) */
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static struct directory *root = NULL;
|
2006-04-22 03:50:36 +04:00
|
|
|
static char filename_buffer[12];
|
|
|
|
static char filename_directory[256];
|
2005-06-21 18:17:51 +04:00
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
static struct directory *filename_create_directory(const char *prefix);
|
|
|
|
static bool filename_flush_directory(const char *folder, int depth);
|
|
|
|
static bool filename_delete_recursive(char *folder);
|
2005-06-21 18:17:51 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Request a new, unique, filename.
|
|
|
|
*
|
2009-05-29 17:26:58 +04:00
|
|
|
* \return a pointer to a shared buffer containing the new filename,
|
|
|
|
* NULL on failure
|
2005-06-21 18:17:51 +04:00
|
|
|
*/
|
2009-05-29 17:26:58 +04:00
|
|
|
const char *filename_request(void)
|
|
|
|
{
|
2005-06-21 18:17:51 +04:00
|
|
|
struct directory *dir;
|
|
|
|
int i = -1;
|
2006-01-06 23:56:44 +03:00
|
|
|
|
2009-05-29 17:26:58 +04:00
|
|
|
for (dir = root; dir; dir = dir->next) {
|
2005-06-21 18:17:51 +04:00
|
|
|
if ((dir->low_used & dir->high_used) != FULL_WORD) {
|
2006-01-06 23:56:44 +03:00
|
|
|
if (dir->low_used != FULL_WORD) {
|
2005-06-21 18:17:51 +04:00
|
|
|
for (i = 0; (dir->low_used & (1 << i)); i++);
|
2006-01-06 23:56:44 +03:00
|
|
|
} else {
|
2005-06-21 18:17:51 +04:00
|
|
|
for (i = 0; (dir->high_used & (1 << i)); i++);
|
2006-01-06 23:56:44 +03:00
|
|
|
i += 32;
|
|
|
|
}
|
2005-06-21 18:17:51 +04:00
|
|
|
break;
|
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
}
|
|
|
|
|
2005-06-21 18:17:51 +04:00
|
|
|
if (i == -1) {
|
|
|
|
/* no available slots - create a new directory */
|
2006-04-22 03:50:36 +04:00
|
|
|
dir = filename_create_directory(NULL);
|
2009-05-29 17:26:58 +04:00
|
|
|
if (dir == NULL) {
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Failed to create a new directory.");
|
2005-06-21 18:17:51 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
i = 63;
|
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2005-06-23 21:17:56 +04:00
|
|
|
if (i < 32)
|
2005-06-21 18:17:51 +04:00
|
|
|
dir->low_used |= (1 << i);
|
2005-06-23 21:17:56 +04:00
|
|
|
else
|
2005-06-21 18:17:51 +04:00
|
|
|
dir->high_used |= (1 << (i - 32));
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
sprintf(filename_buffer, "%s%.2i", dir->prefix, i);
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
return filename_buffer;
|
2005-06-21 18:17:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-06-23 21:17:56 +04:00
|
|
|
/**
|
|
|
|
* Claim a specific filename.
|
|
|
|
*
|
|
|
|
* \param filename the filename to claim
|
|
|
|
* \return whether the claim was successful
|
|
|
|
*/
|
2009-05-29 17:26:58 +04:00
|
|
|
bool filename_claim(const char *filename)
|
|
|
|
{
|
2006-01-02 02:54:02 +03:00
|
|
|
char dir_prefix[9];
|
|
|
|
int file;
|
2005-06-23 21:17:56 +04:00
|
|
|
struct directory *dir;
|
2006-01-06 23:56:44 +03:00
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
/* filename format is always '01/23/45/XX' */
|
2006-01-03 01:15:28 +03:00
|
|
|
strncpy(dir_prefix, filename, 9);
|
2008-09-23 13:14:40 +04:00
|
|
|
dir_prefix[8] = '\0';
|
2006-01-02 02:54:02 +03:00
|
|
|
file = (filename[10] + filename[9] * 10 - START_PREFIX);
|
2006-01-06 23:56:44 +03:00
|
|
|
|
2005-06-23 21:17:56 +04:00
|
|
|
/* create the directory */
|
2006-04-22 03:50:36 +04:00
|
|
|
dir = filename_create_directory(dir_prefix);
|
2009-05-29 17:26:58 +04:00
|
|
|
if (dir == NULL)
|
2005-06-23 21:17:56 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
/* update the entry */
|
2006-01-06 23:56:44 +03:00
|
|
|
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));
|
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-01-06 23:56:44 +03:00
|
|
|
return true;
|
2005-06-23 21:17:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-06-21 18:17:51 +04:00
|
|
|
/**
|
|
|
|
* Releases a filename for future use.
|
|
|
|
*
|
|
|
|
* \param filename the filename to release
|
|
|
|
*/
|
2009-05-29 17:26:58 +04:00
|
|
|
void filename_release(const char *filename)
|
|
|
|
{
|
2005-06-21 18:17:51 +04:00
|
|
|
struct directory *dir;
|
2006-01-02 02:54:02 +03:00
|
|
|
int index, file;
|
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
/* filename format is always '01/23/45/XX' */
|
2006-01-02 02:54:02 +03:00
|
|
|
index = ((filename[7] + filename[6] * 10 - START_PREFIX) |
|
|
|
|
((filename[4] + filename[3] * 10 - START_PREFIX) << 6) |
|
|
|
|
((filename[1] + filename[0] * 10 - START_PREFIX) << 12));
|
|
|
|
file = (filename[10] + filename[9] * 10 - START_PREFIX);
|
2006-01-06 23:56:44 +03:00
|
|
|
|
2005-06-21 18:17:51 +04:00
|
|
|
/* modify the correct directory entry */
|
2009-05-29 17:26:58 +04:00
|
|
|
for (dir = root; dir; dir = dir->next) {
|
2006-01-02 02:54:02 +03:00
|
|
|
if (dir->numeric_prefix == index) {
|
2006-01-06 23:56:44 +03:00
|
|
|
if (file < 32)
|
|
|
|
dir->low_used &= ~(1 << file);
|
|
|
|
else
|
|
|
|
dir->high_used &= ~(1 << (file - 32));
|
2005-06-21 18:17:51 +04:00
|
|
|
return;
|
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
}
|
2005-06-21 18:17:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2005-06-23 21:17:56 +04:00
|
|
|
* Initialise the filename provider.
|
2005-06-21 18:17:51 +04:00
|
|
|
*/
|
2009-05-29 17:26:58 +04:00
|
|
|
bool filename_initialise(void)
|
|
|
|
{
|
2006-04-22 03:50:36 +04:00
|
|
|
char *directory, *start;
|
2013-11-28 02:35:42 +04:00
|
|
|
int ret;
|
2006-04-22 03:50:36 +04:00
|
|
|
|
|
|
|
directory = strdup(TEMP_FILENAME_PREFIX);
|
2009-05-29 17:26:58 +04:00
|
|
|
if (directory == NULL)
|
2006-04-22 03:50:36 +04:00
|
|
|
return false;
|
|
|
|
|
2006-10-12 18:01:14 +04:00
|
|
|
for (start = directory; *start != '\0'; start++) {
|
2006-04-22 03:50:36 +04:00
|
|
|
if (*start == '/') {
|
|
|
|
*start = '\0';
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Creating \"%s\"", directory);
|
2013-11-29 03:10:29 +04:00
|
|
|
ret = nsmkdir(directory, S_IRWXU);
|
2014-04-18 20:12:52 +04:00
|
|
|
if (ret != 0 && errno != EEXIST) {
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Failed to create directory \"%s\"", directory);
|
2013-11-29 03:10:29 +04:00
|
|
|
free(directory);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
*start = '/';
|
|
|
|
}
|
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Temporary directory location: %s", directory);
|
2013-11-28 02:35:42 +04:00
|
|
|
ret = nsmkdir(directory, S_IRWXU);
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
free(directory);
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2013-11-28 02:35:42 +04:00
|
|
|
if (ret != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
2005-06-21 18:17:51 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes all files in the cache directory that are not accounted for.
|
|
|
|
*/
|
2009-05-29 17:26:58 +04:00
|
|
|
void filename_flush(void)
|
|
|
|
{
|
2006-04-22 03:50:36 +04:00
|
|
|
while (filename_flush_directory(TEMP_FILENAME_PREFIX, 0));
|
2006-01-06 23:56:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2009-05-29 17:26:58 +04:00
|
|
|
bool filename_flush_directory(const char *folder, int depth)
|
|
|
|
{
|
2006-04-22 03:50:36 +04:00
|
|
|
DIR *parent;
|
|
|
|
struct dirent *entry;
|
2006-01-06 23:56:44 +03:00
|
|
|
bool changed = false;
|
|
|
|
bool del;
|
|
|
|
int number, i;
|
|
|
|
int prefix = 0;
|
2009-05-29 17:26:58 +04:00
|
|
|
unsigned int prefix_mask = (0x3f << 12);
|
2006-01-06 23:56:44 +03:00
|
|
|
char child[256];
|
|
|
|
const char *prefix_start = NULL;
|
|
|
|
struct directory *dir = NULL;
|
|
|
|
|
2009-05-29 17:26:58 +04:00
|
|
|
/* Maximum permissible depth is 3 */
|
|
|
|
assert(depth <= 3);
|
|
|
|
|
|
|
|
if (depth > 0) {
|
|
|
|
/* Not a top-level directory, so determine the prefix
|
|
|
|
* by removing the last /XX component */
|
2006-01-06 23:56:44 +03:00
|
|
|
prefix_start = folder + strlen(folder) - depth * 3 + 1;
|
2009-05-29 17:26:58 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate the numeric prefix */
|
|
|
|
for (i = 0; i < depth; i++) {
|
2006-04-22 03:50:36 +04:00
|
|
|
number = prefix_start[1] + prefix_start[0] * 10 - START_PREFIX;
|
2006-01-06 23:56:44 +03:00
|
|
|
prefix |= (number << (12 - i * 6));
|
2009-05-29 17:26:58 +04:00
|
|
|
prefix_mask |= (0x3f << (12 - i * 6));
|
2006-01-06 23:56:44 +03:00
|
|
|
prefix_start += 3;
|
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
/* If we're flushing a leaf directory, find it in the list */
|
2006-01-06 23:56:44 +03:00
|
|
|
if (depth == 3) {
|
2009-05-29 17:26:58 +04:00
|
|
|
for (dir = root; dir; dir = dir->next) {
|
2006-01-06 23:56:44 +03:00
|
|
|
if (dir->numeric_prefix == prefix)
|
|
|
|
break;
|
2009-05-29 17:26:58 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dir == NULL)
|
2006-01-06 23:56:44 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
parent = opendir(folder);
|
|
|
|
|
|
|
|
while ((entry = readdir(parent))) {
|
2007-06-10 15:11:46 +04:00
|
|
|
struct stat statbuf;
|
|
|
|
|
2009-05-29 17:26:58 +04:00
|
|
|
/* Ignore '.' and '..' */
|
|
|
|
if (strcmp(entry->d_name, ".") == 0 ||
|
|
|
|
strcmp(entry->d_name, "..") == 0)
|
2006-01-06 23:56:44 +03:00
|
|
|
continue;
|
2006-04-22 03:50:36 +04:00
|
|
|
|
2009-05-29 17:26:58 +04:00
|
|
|
snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
|
|
|
|
child[sizeof(child) - 1] = '\0';
|
|
|
|
|
2007-06-10 15:28:44 +04:00
|
|
|
if (stat(child, &statbuf) == -1) {
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Unable to stat %s: %s", child, strerror(errno));
|
2007-06-10 15:28:44 +04:00
|
|
|
continue;
|
|
|
|
}
|
2007-06-10 15:11:46 +04:00
|
|
|
|
2006-01-06 23:56:44 +03:00
|
|
|
/* first 3 depths are directories only, then files only */
|
2009-05-29 17:26:58 +04:00
|
|
|
if (depth < 3) {
|
|
|
|
/* Delete any unexpected files */
|
2007-06-10 15:11:46 +04:00
|
|
|
del = !S_ISDIR(statbuf.st_mode);
|
2009-05-29 17:26:58 +04:00
|
|
|
} else {
|
|
|
|
/* Delete any unexpected directories */
|
2007-06-10 15:11:46 +04:00
|
|
|
del = S_ISDIR(statbuf.st_mode);
|
2009-05-29 17:26:58 +04:00
|
|
|
}
|
2006-04-22 03:50:36 +04:00
|
|
|
|
2006-01-06 23:56:44 +03:00
|
|
|
/* check we are a file numbered '00' -> '63' */
|
2009-05-29 17:26:58 +04:00
|
|
|
if (del == false && (entry->d_name[0] >= '0') &&
|
2006-04-22 03:50:36 +04:00
|
|
|
(entry->d_name[0] <= '6') &&
|
|
|
|
(entry->d_name[1] >= '0') &&
|
|
|
|
(entry->d_name[1] <= '9') &&
|
|
|
|
(entry->d_name[2] == '\0')) {
|
|
|
|
number = atoi(entry->d_name);
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
if (number >= 0 && number <= 63) {
|
2006-01-06 23:56:44 +03:00
|
|
|
if (depth == 3) {
|
2009-05-29 17:26:58 +04:00
|
|
|
/* File: delete if not in bitfield */
|
2006-01-06 23:56:44 +03:00
|
|
|
if (number < 32)
|
|
|
|
del = !(dir->low_used &
|
|
|
|
(1 << number));
|
|
|
|
else
|
|
|
|
del = !(dir->high_used &
|
|
|
|
(1 << (number - 32)));
|
|
|
|
} else {
|
2009-05-29 17:26:58 +04:00
|
|
|
/* Directory: delete unless in list */
|
2006-04-22 03:50:36 +04:00
|
|
|
del = true;
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
/* Insert into numeric prefix */
|
|
|
|
prefix &= ~(0x3f << (12 - depth * 6));
|
2006-01-06 23:56:44 +03:00
|
|
|
prefix |= (number << (12 - depth * 6));
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
/* Find in dir list */
|
2006-01-06 23:56:44 +03:00
|
|
|
for (dir = root; dir; dir = dir->next) {
|
|
|
|
number = dir->numeric_prefix &
|
|
|
|
prefix_mask;
|
|
|
|
if (number == prefix) {
|
2009-05-29 17:26:58 +04:00
|
|
|
/* In list: retain */
|
2006-01-06 23:56:44 +03:00
|
|
|
del = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2009-05-29 17:26:58 +04:00
|
|
|
/* Unexpected name: delete */
|
2006-01-06 23:56:44 +03:00
|
|
|
del = true;
|
|
|
|
}
|
|
|
|
} else {
|
2009-05-29 17:26:58 +04:00
|
|
|
/* Unexpected name: delete */
|
2006-01-06 23:56:44 +03:00
|
|
|
del = true;
|
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
/* continue if this is a file we want to retain */
|
|
|
|
if (del == false && (!S_ISDIR(statbuf.st_mode)))
|
2007-06-10 15:11:46 +04:00
|
|
|
continue;
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-01-06 23:56:44 +03:00
|
|
|
/* delete or recurse */
|
|
|
|
if (del) {
|
2007-06-10 15:11:46 +04:00
|
|
|
if (S_ISDIR(statbuf.st_mode))
|
2006-04-22 03:50:36 +04:00
|
|
|
filename_delete_recursive(child);
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
if (remove(child))
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Failed to remove '%s'", child);
|
2006-01-06 23:56:44 +03:00
|
|
|
else
|
|
|
|
changed = true;
|
|
|
|
} else {
|
2006-04-22 03:50:36 +04:00
|
|
|
while (filename_flush_directory(child, depth + 1));
|
2006-01-06 23:56:44 +03:00
|
|
|
}
|
|
|
|
}
|
2006-04-22 03:50:36 +04:00
|
|
|
|
|
|
|
closedir(parent);
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-01-06 23:56:44 +03:00
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Recursively deletes the contents of a directory
|
|
|
|
*
|
2014-11-13 02:27:13 +03:00
|
|
|
* \param folder the directory to delete
|
2006-01-06 23:56:44 +03:00
|
|
|
* \return true on success, false otherwise
|
|
|
|
*/
|
2009-05-29 17:26:58 +04:00
|
|
|
bool filename_delete_recursive(char *folder)
|
|
|
|
{
|
2006-04-22 03:50:36 +04:00
|
|
|
DIR *parent;
|
|
|
|
struct dirent *entry;
|
2006-01-06 23:56:44 +03:00
|
|
|
char child[256];
|
2007-06-10 15:11:46 +04:00
|
|
|
struct stat statbuf;
|
2006-01-06 23:56:44 +03:00
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
parent = opendir(folder);
|
|
|
|
|
|
|
|
while ((entry = readdir(parent))) {
|
2009-05-29 17:26:58 +04:00
|
|
|
/* Ignore '.' and '..' */
|
|
|
|
if (strcmp(entry->d_name, ".") == 0 ||
|
|
|
|
strcmp(entry->d_name, "..") == 0)
|
2006-01-06 23:56:44 +03:00
|
|
|
continue;
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
snprintf(child, sizeof(child), "%s/%s", folder, entry->d_name);
|
|
|
|
child[sizeof(child) - 1] = '\0';
|
|
|
|
|
2007-06-10 15:28:44 +04:00
|
|
|
if (stat(child, &statbuf) == -1) {
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Unable to stat %s: %s", child, strerror(errno));
|
2007-06-10 15:28:44 +04:00
|
|
|
continue;
|
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2007-06-10 15:11:46 +04:00
|
|
|
if (S_ISDIR(statbuf.st_mode)) {
|
2006-04-22 03:50:36 +04:00
|
|
|
if (!filename_delete_recursive(child)) {
|
|
|
|
closedir(parent);
|
|
|
|
return false;
|
|
|
|
}
|
2006-01-06 23:56:44 +03:00
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
if (remove(child)) {
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Failed to remove '%s'", child);
|
2006-04-22 03:50:36 +04:00
|
|
|
closedir(parent);
|
2006-01-06 23:56:44 +03:00
|
|
|
return false;
|
|
|
|
}
|
2006-04-22 03:50:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
closedir(parent);
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
return true;
|
2005-06-21 18:17:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new directory.
|
|
|
|
*
|
|
|
|
* \param prefix the prefix to use, or NULL to allocate a new one
|
2006-06-21 02:58:36 +04:00
|
|
|
* \return a new directory structure, or NULL on memory exhaustion or
|
|
|
|
* creation failure
|
2006-01-06 23:56:44 +03:00
|
|
|
*
|
2005-06-21 18:17:51 +04:00
|
|
|
* Empty directories are never deleted, except by an explicit call to
|
2006-04-22 03:50:36 +04:00
|
|
|
* filename_flush().
|
2005-06-21 18:17:51 +04:00
|
|
|
*/
|
2009-05-29 17:26:58 +04:00
|
|
|
static struct directory *filename_create_directory(const char *prefix)
|
|
|
|
{
|
2005-06-21 18:17:51 +04:00
|
|
|
char *last_1, *last_2;
|
2006-01-02 02:54:02 +03:00
|
|
|
int index;
|
2005-06-21 18:17:51 +04:00
|
|
|
struct directory *old_dir, *new_dir, *prev_dir = NULL;
|
|
|
|
char dir_prefix[16];
|
2008-07-29 13:34:43 +04:00
|
|
|
int i;
|
2005-10-02 03:28:46 +04:00
|
|
|
|
2005-06-21 18:17:51 +04:00
|
|
|
/* get the lowest unique prefix, or use the provided one */
|
2009-05-29 17:26:58 +04:00
|
|
|
if (prefix == NULL) {
|
|
|
|
for (index = 0, old_dir = root; old_dir;
|
|
|
|
index++, old_dir = old_dir->next) {
|
2006-01-02 02:54:02 +03:00
|
|
|
if (old_dir->numeric_prefix != index)
|
2005-06-21 18:17:51 +04:00
|
|
|
break;
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
prev_dir = old_dir;
|
|
|
|
}
|
|
|
|
|
2006-04-22 03:50:36 +04:00
|
|
|
sprintf(dir_prefix, "%.2i/%.2i/%.2i/",
|
2006-01-02 02:54:02 +03:00
|
|
|
((index >> 12) & 63),
|
|
|
|
((index >> 6) & 63),
|
|
|
|
((index >> 0) & 63));
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2005-10-02 03:28:46 +04:00
|
|
|
prefix = dir_prefix;
|
2006-01-02 02:54:02 +03:00
|
|
|
} else {
|
2006-04-22 03:50:36 +04:00
|
|
|
/* prefix format is always '01/23/45/' */
|
2006-01-02 02:54:02 +03:00
|
|
|
index = ((prefix[7] + prefix[6] * 10 - START_PREFIX) |
|
|
|
|
((prefix[4] + prefix[3] * 10 - START_PREFIX) << 6) |
|
|
|
|
((prefix[1] + prefix[0] * 10 - START_PREFIX) << 12));
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
for (old_dir = root; old_dir; old_dir = old_dir->next) {
|
2006-01-02 02:54:02 +03:00
|
|
|
if (old_dir->numeric_prefix == index)
|
|
|
|
return old_dir;
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-01-02 02:54:02 +03:00
|
|
|
else if (old_dir->numeric_prefix > index)
|
|
|
|
break;
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
prev_dir = old_dir;
|
2006-01-02 02:54:02 +03:00
|
|
|
}
|
2005-06-21 18:17:51 +04:00
|
|
|
}
|
2005-10-02 03:28:46 +04:00
|
|
|
|
2005-06-21 18:17:51 +04:00
|
|
|
/* allocate a new directory */
|
2009-05-29 17:26:58 +04:00
|
|
|
new_dir = malloc(sizeof(struct directory));
|
|
|
|
if (new_dir == NULL) {
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("No memory for malloc()");
|
2005-06-21 18:17:51 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2005-10-02 03:28:46 +04:00
|
|
|
strncpy(new_dir->prefix, prefix, 9);
|
|
|
|
new_dir->prefix[9] = '\0';
|
2006-01-02 02:54:02 +03:00
|
|
|
new_dir->low_used = new_dir->high_used = 0;
|
|
|
|
new_dir->numeric_prefix = index;
|
2005-06-21 18:17:51 +04:00
|
|
|
|
2009-05-29 17:26:58 +04:00
|
|
|
if (prev_dir == NULL) {
|
2005-06-21 18:17:51 +04:00
|
|
|
new_dir->next = root;
|
|
|
|
root = new_dir;
|
|
|
|
} else {
|
|
|
|
new_dir->next = prev_dir->next;
|
|
|
|
prev_dir->next = new_dir;
|
|
|
|
}
|
2006-01-06 23:56:44 +03:00
|
|
|
|
2006-01-05 01:59:49 +03:00
|
|
|
/* if the previous directory has the same parent then we can simply
|
|
|
|
* create the child. */
|
2009-05-29 17:26:58 +04:00
|
|
|
if (prev_dir && strncmp(prev_dir->prefix, new_dir->prefix, 6) == 0) {
|
2006-01-06 23:56:44 +03:00
|
|
|
new_dir->prefix[8] = '\0';
|
2006-04-22 03:50:36 +04:00
|
|
|
sprintf(filename_directory, "%s/%s",
|
|
|
|
TEMP_FILENAME_PREFIX,
|
|
|
|
new_dir->prefix);
|
|
|
|
new_dir->prefix[8] = '/';
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-06-21 02:58:36 +04:00
|
|
|
if (!is_dir(filename_directory)) {
|
2010-01-31 03:36:02 +03:00
|
|
|
if (!nsmkdir(filename_directory, S_IRWXU))
|
2006-06-21 02:58:36 +04:00
|
|
|
return new_dir;
|
|
|
|
|
|
|
|
/* the user has probably deleted the parent directory
|
|
|
|
* whilst we are running if there is an error, so we
|
|
|
|
* don't report this yet and try to create the
|
|
|
|
* structure normally. */
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Failed to create optimised structure '%s'", filename_directory);
|
2006-06-21 02:58:36 +04:00
|
|
|
}
|
2006-01-05 01:59:49 +03:00
|
|
|
}
|
2006-01-06 23:56:44 +03:00
|
|
|
|
2005-06-21 18:17:51 +04:00
|
|
|
/* create the directory structure */
|
2009-05-29 17:26:58 +04:00
|
|
|
sprintf(filename_directory, "%s/", TEMP_FILENAME_PREFIX);
|
|
|
|
last_1 = filename_directory + SLEN(TEMP_FILENAME_PREFIX) + 1;
|
2005-06-21 18:17:51 +04:00
|
|
|
last_2 = new_dir->prefix;
|
2009-05-29 17:26:58 +04:00
|
|
|
|
|
|
|
/* create each subdirectory, up to the maximum depth of 3 */
|
2008-07-29 13:34:43 +04:00
|
|
|
for (i = 0; i < 3 && *last_2; i++) {
|
2005-06-21 18:17:51 +04:00
|
|
|
*last_1++ = *last_2++;
|
2006-04-22 03:50:36 +04:00
|
|
|
while (*last_2 && *last_2 != '/')
|
2005-06-21 18:17:51 +04:00
|
|
|
*last_1++ = *last_2++;
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-01-06 23:56:44 +03:00
|
|
|
if (*last_2) {
|
2005-10-02 03:28:46 +04:00
|
|
|
last_1[0] = '\0';
|
2009-05-29 17:26:58 +04:00
|
|
|
|
2006-06-21 02:58:36 +04:00
|
|
|
if (!is_dir(filename_directory)) {
|
2010-01-31 03:36:02 +03:00
|
|
|
if (nsmkdir(filename_directory, S_IRWXU)) {
|
2015-05-28 18:08:46 +03:00
|
|
|
LOG("Failed to create directory '%s'", filename_directory);
|
2006-06-21 02:58:36 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
2006-01-05 01:59:49 +03:00
|
|
|
}
|
2005-10-02 03:28:46 +04:00
|
|
|
}
|
2005-06-21 18:17:51 +04:00
|
|
|
}
|
2006-06-21 02:58:36 +04:00
|
|
|
|
2005-06-21 18:17:51 +04:00
|
|
|
return new_dir;
|
|
|
|
}
|