#include "debug.h"
#include "cache.h"
#include "file.h"
+#include "atom.h"
#include "config.h"
#ifndef O_LARGEFILE
#define O_BINARY 0
#endif
-static struct file *file_list;
-
+#ifdef CACHE_SIZE
static GHashTable *file_name_hash;
-static int file_name_id;
+#endif
+
static struct cache *file_cache;
struct file_cache_id {
int size;
int file_name_id;
int method;
-};
+} __attribute__ ((packed));
struct file *
-file_create(char *name)
+file_create(char *name, enum file_flags flags)
{
struct stat stat;
struct file *file= g_new0(struct file,1);
- if (! file)
- return file;
file->fd=open(name, O_RDONLY|O_LARGEFILE | O_BINARY);
- if (file->fd < 0) {
+ if (file->fd == -1) {
g_free(file);
return NULL;
}
+ dbg(1,"fd=%d\n", file->fd);
fstat(file->fd, &stat);
file->size=stat.st_size;
+ dbg(1,"size=%Ld\n", file->size);
file->name = g_strdup(name);
- g_assert(file != NULL);
- file->next=file_list;
- file_list=file;
+ file->name_id = (int)atom(name);
+ if (file_cache && !(flags & file_flag_nocache))
+ file->cache=1;
+ dbg_assert(file != NULL);
+ return file;
+}
+
+#if 0
+struct file *
+file_create_url(char *url)
+{
+ struct file *file= g_new0(struct file,1);
+ char *cmd=g_strdup_printf("curl %s",url);
+ file->name = g_strdup(url);
+ file->stdfile=popen(cmd,"r");
+ file->fd=fileno(file->stdfile);
+ file->special=1;
+ g_free(cmd);
return file;
}
+#endif
int file_is_dir(char *name)
{
}
+long long
+file_size(struct file *file)
+{
+ return file->size;
+}
+
int file_mkdir(char *name, int pflag)
{
char buffer[strlen(name)+1];
if (!pflag) {
if (file_is_dir(name))
return 0;
+#ifdef HAVE_API_WIN32_BASE
+ return mkdir(name);
+#else
return mkdir(name, 0777);
+#endif
}
strcpy(buffer, name);
next=buffer;
int
file_mmap(struct file *file)
{
-#if defined(_WIN32) || defined(__CEGCC__)
- file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
+#if 0
+ int mmap_size=file->size+1024*1024;
#else
- file->begin=mmap(NULL, file->size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0);
- g_assert(file->begin != NULL);
+ int mmap_size=file->size;
+#endif
+#ifdef HAVE_API_WIN32_BASE
+ file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
+#else
+ file->begin=mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0);
+ dbg_assert(file->begin != NULL);
if (file->begin == (void *)0xffffffff) {
perror("mmap");
return 0;
}
#endif
- g_assert(file->begin != (void *)0xffffffff);
+ dbg_assert(file->begin != (void *)0xffffffff);
+ file->mmap_end=file->begin+mmap_size;
file->end=file->begin+file->size;
return 1;
file_data_read(struct file *file, long long offset, int size)
{
void *ret;
+ if (file->special)
+ return NULL;
if (file->begin)
return file->begin+offset;
if (file_cache) {
struct file_cache_id id={offset,size,file->name_id,0};
- ret=cache_lookup_or_insert(file_cache,&id,size);
+ ret=cache_lookup(file_cache,&id);
+ if (ret)
+ return ret;
+ ret=cache_insert_new(file_cache,&id,size);
} else
ret=g_malloc(size);
lseek(file->fd, offset, SEEK_SET);
}
+unsigned char *
+file_data_read_special(struct file *file, int size, int *size_ret)
+{
+ void *ret;
+ if (!file->special)
+ return NULL;
+ ret=g_malloc(size);
+ *size_ret=read(file->fd, ret, size);
+ return ret;
+}
+
+unsigned char *
+file_data_read_all(struct file *file)
+{
+ return file_data_read(file, 0, file->size);
+}
+
+int
+file_data_write(struct file *file, long long offset, int size, unsigned char *data)
+{
+ if (file_cache) {
+ struct file_cache_id id={offset,size,file->name_id,0};
+ cache_flush(file_cache,&id);
+ }
+ lseek(file->fd, offset, SEEK_SET);
+ if (write(file->fd, data, size) != size)
+ return 0;
+ if (file->size < offset+size)
+ file->size=offset+size;
+ return 1;
+}
+
+int
+file_get_contents(char *name, unsigned char **buffer, int *size)
+{
+ struct file *file;
+ file=file_create(name, 0);
+ if (!file)
+ return 0;
+ *size=file_size(file);
+ *buffer=file_data_read_all(file);
+ file_destroy(file);
+ return 1;
+}
+
+
static int
uncompress_int(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
{
file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp)
{
void *ret;
- char buffer[size];
+ char *buffer = 0;
uLongf destLen=size_uncomp;
if (file_cache) {
struct file_cache_id id={offset,size,file->name_id,1};
- ret=cache_lookup_or_insert(file_cache,&id,size_uncomp);
+ ret=cache_lookup(file_cache,&id);
+ if (ret)
+ return ret;
+ ret=cache_insert_new(file_cache,&id,size_uncomp);
} else
ret=g_malloc(size_uncomp);
lseek(file->fd, offset, SEEK_SET);
+
+ buffer = (char *)g_malloc(size);
if (read(file->fd, buffer, size) != size) {
g_free(ret);
ret=NULL;
ret=NULL;
}
}
+ g_free(buffer);
+
return ret;
}
void
file_data_free(struct file *file, unsigned char *data)
{
- if (file->begin && data >= file->begin && data < file->end)
- return;
- if (file_cache) {
+ if (file->begin) {
+ if (data == file->begin)
+ return;
+ if (data >= file->begin && data < file->end)
+ return;
+ }
+ if (file->cache && data) {
cache_entry_destroy(file_cache, data);
} else
g_free(data);
}
void
-file_remap_readonly_all(void)
-{
- struct file *f=file_list;
- int limit=1000;
-
- while (f && limit-- > 0) {
- file_remap_readonly(f);
- f=f->next;
- }
-}
-
-void
file_unmap(struct file *f)
{
#if defined(_WIN32) || defined(__CEGCC__)
#endif
}
-void
-file_unmap_all(void)
-{
- struct file *f=file_list;
- int limit=1000;
-
- while (f && limit-- > 0) {
- file_unmap(f);
- f=f->next;
- }
-}
-
-
-
void *
file_opendir(char *dir)
{
}
struct file *
-file_create_caseinsensitive(char *name)
+file_create_caseinsensitive(char *name, enum file_flags flags)
{
char dirname[strlen(name)+1];
char *filename;
void *d;
struct file *ret;
- ret=file_create(name);
+ ret=file_create(name, flags);
if (ret)
return ret;
while ((filename=file_readdir(d))) {
if (!strcasecmp(filename, p)) {
strcpy(p, filename);
- ret=file_create(dirname);
+ ret=file_create(dirname, flags);
if (ret)
break;
}
void
file_destroy(struct file *f)
{
- close(f->fd);
+ switch (f->special) {
+ case 0:
+ close(f->fd);
+ break;
+#if 0
+ case 1:
+ pclose(f->stdfile);
+ break;
+#endif
+ }
if ( f->begin != NULL )
{
return i-count;
}
+int
+file_version(struct file *file, int mode)
+{
+#ifndef HAVE_API_WIN32_BASE
+ struct stat st;
+ int error;
+ if (mode == 3) {
+ long long size=lseek(file->fd, 0, SEEK_END);
+ if (file->begin && file->begin+size > file->mmap_end) {
+ file->version++;
+ } else {
+ file->size=size;
+ if (file->begin)
+ file->end=file->begin+file->size;
+ }
+ } else {
+ if (mode == 2)
+ error=stat(file->name, &st);
+ else
+ error=fstat(file->fd, &st);
+ if (error || !file->version || file->mtime != st.st_mtime || file->ctime != st.st_ctime) {
+ file->mtime=st.st_mtime;
+ file->ctime=st.st_ctime;
+ file->version++;
+ dbg(1,"%s now version %d\n", file->name, file->version);
+ }
+ }
+ return file->version;
+#else
+ return 0;
+#endif
+}
+
+void *
+file_get_os_handle(struct file *file)
+{
+ return GINT_TO_POINTER(file->fd);
+}
+
void
file_init(void)
{
-#if 0
+#ifdef CACHE_SIZE
file_name_hash=g_hash_table_new(g_str_hash, g_str_equal);
- file_cache=cache_new(sizeof(struct file_cache_id), 2*1024*1024);
+ file_cache=cache_new(sizeof(struct file_cache_id), CACHE_SIZE);
#endif
}