summaryrefslogtreecommitdiff
path: root/navit/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'navit/file.c')
-rw-r--r--navit/file.c1242
1 files changed, 585 insertions, 657 deletions
diff --git a/navit/file.c b/navit/file.c
index 8363b6a8b..8d0365499 100644
--- a/navit/file.c
+++ b/navit/file.c
@@ -44,8 +44,6 @@
#include <netdb.h>
#endif
-extern char *version;
-
#ifdef CACHE_SIZE
static GHashTable *file_name_hash;
#endif
@@ -58,10 +56,10 @@ static struct cache *file_cache;
#endif
struct file_cache_id {
- long long offset;
- int size;
- int file_name_id;
- int method;
+ long long offset;
+ int size;
+ int file_name_id;
+ int method;
} ATTRIBUTE_PACKED;
#ifdef HAVE_PRAGMA_PACK
@@ -69,171 +67,159 @@ struct file_cache_id {
#endif
#ifdef HAVE_SOCKET
-static int
-file_socket_connect(char *host, char *service)
-{
- struct addrinfo hints;
- struct addrinfo *result, *rp;
- int fd=-1,s;
-
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = 0;
- hints.ai_protocol = 0;
- s = getaddrinfo(host, service, &hints, &result);
- if (s != 0) {
- dbg(lvl_error,"getaddrinfo error %s\n",gai_strerror(s));
- return -1;
- }
- for (rp = result; rp != NULL; rp = rp->ai_next) {
- fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if (fd != -1) {
- if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
- break;
- close(fd);
- fd=-1;
- }
- }
- freeaddrinfo(result);
- return fd;
-}
-
-static void
-file_http_request(struct file *file, char *method, char *host, char *path, char *header, int persistent)
-{
- char *request=g_strdup_printf("%s %s HTTP/1.0\r\nUser-Agent: navit %s\r\nHost: %s\r\n%s%s%s\r\n",method,path,version,host,persistent?"Connection: Keep-Alive\r\n":"",header?header:"",header?"\r\n":"");
- write(file->fd, request, strlen(request));
- dbg(lvl_debug,"%s\n",request);
- file->requests++;
-}
-
-static int
-file_request_do(struct file *file, struct attr **options, int connect)
-{
- struct attr *attr;
- char *name;
-
- if (!options)
- return 0;
- attr=attr_search(options, NULL, attr_url);
- if (!attr)
- return 0;
- name=attr->u.str;
- if (!name)
- return 0;
- g_free(file->name);
- file->name = g_strdup(name);
- if (!strncmp(name,"http://",7)) {
- char *host=g_strdup(name+7);
- char *port=strchr(host,':');
- char *path=strchr(name+7,'/');
- char *method="GET";
- char *header=NULL;
- int persistent=0;
- if ((attr=attr_search(options, NULL, attr_http_method)) && attr->u.str)
- method=attr->u.str;
- if ((attr=attr_search(options, NULL, attr_http_header)) && attr->u.str)
- header=attr->u.str;
- if ((attr=attr_search(options, NULL, attr_persistent)))
- persistent=attr->u.num;
- if (path)
- host[path-name-7]='\0';
- if (port)
- *port++='\0';
- dbg(lvl_debug,"host=%s path=%s\n",host,path);
- if (connect)
- file->fd=file_socket_connect(host,port?port:"80");
- file_http_request(file,method,host,path,header,persistent);
- file->special=1;
- g_free(host);
- }
- return 1;
+static int file_socket_connect(char *host, char *service) {
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+ int fd=-1,s;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = 0;
+ hints.ai_protocol = 0;
+ s = getaddrinfo(host, service, &hints, &result);
+ if (s != 0) {
+ dbg(lvl_error,"getaddrinfo error %s",gai_strerror(s));
+ return -1;
+ }
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if (fd != -1) {
+ if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
+ break;
+ close(fd);
+ fd=-1;
+ }
+ }
+ freeaddrinfo(result);
+ return fd;
+}
+
+static void file_http_request(struct file *file, char *method, char *host, char *path, char *header, int persistent) {
+ char *request=g_strdup_printf("%s %s HTTP/1.0\r\nUser-Agent: navit %s\r\nHost: %s\r\n%s%s%s\r\n",method,path,
+ NAVIT_VERSION,
+ host,persistent?"Connection: Keep-Alive\r\n":"",header?header:"",header?"\r\n":"");
+ write(file->fd, request, strlen(request));
+ dbg(lvl_debug,"%s",request);
+ file->requests++;
+}
+
+static int file_request_do(struct file *file, struct attr **options, int connect) {
+ struct attr *attr;
+ char *name;
+
+ if (!options)
+ return 0;
+ attr=attr_search(options, NULL, attr_url);
+ if (!attr)
+ return 0;
+ name=attr->u.str;
+ if (!name)
+ return 0;
+ g_free(file->name);
+ file->name = g_strdup(name);
+ if (!strncmp(name,"http://",7)) {
+ char *host=g_strdup(name+7);
+ char *port=strchr(host,':');
+ char *path=strchr(name+7,'/');
+ char *method="GET";
+ char *header=NULL;
+ int persistent=0;
+ if ((attr=attr_search(options, NULL, attr_http_method)) && attr->u.str)
+ method=attr->u.str;
+ if ((attr=attr_search(options, NULL, attr_http_header)) && attr->u.str)
+ header=attr->u.str;
+ if ((attr=attr_search(options, NULL, attr_persistent)))
+ persistent=attr->u.num;
+ if (path)
+ host[path-name-7]='\0';
+ if (port)
+ *port++='\0';
+ dbg(lvl_debug,"host=%s path=%s",host,path);
+ if (connect)
+ file->fd=file_socket_connect(host,port?port:"80");
+ file_http_request(file,method,host,path,header,persistent);
+ file->special=1;
+ g_free(host);
+ }
+ return 1;
}
#endif
-static unsigned char *
-file_http_header_end(unsigned char *str, int len)
-{
- int i;
- for (i=0; i+1<len; i+=2) {
- if (str[i+1]=='\n') {
- if (str[i]=='\n')
- return str+i+2;
- else if (str[i]=='\r' && i+3<len && str[i+2]=='\r' && str[i+3]=='\n')
- return str+i+4;
- --i;
- } else if (str[i+1]=='\r') {
- if (i+4<len && str[i+2]=='\n' && str[i+3]=='\r' && str[i+4]=='\n')
- return str+i+5;
- --i;
- }
- }
- return NULL;
-}
-
-int
-file_request(struct file *f, struct attr **options)
-{
+static unsigned char *file_http_header_end(unsigned char *str, int len) {
+ int i;
+ for (i=0; i+1<len; i+=2) {
+ if (str[i+1]=='\n') {
+ if (str[i]=='\n')
+ return str+i+2;
+ else if (str[i]=='\r' && i+3<len && str[i+2]=='\r' && str[i+3]=='\n')
+ return str+i+4;
+ --i;
+ } else if (str[i+1]=='\r') {
+ if (i+4<len && str[i+2]=='\n' && str[i+3]=='\r' && str[i+4]=='\n')
+ return str+i+5;
+ --i;
+ }
+ }
+ return NULL;
+}
+
+int file_request(struct file *f, struct attr **options) {
#ifdef HAVE_SOCKET
- return file_request_do(f, options, 0);
+ return file_request_do(f, options, 0);
#else
- return 0;
+ return 0;
#endif
}
-char *
-file_http_header(struct file *f, char *header)
-{
- if (!f->headers)
- return NULL;
- return g_hash_table_lookup(f->headers, header);
+char *file_http_header(struct file *f, char *header) {
+ if (!f->headers)
+ return NULL;
+ return g_hash_table_lookup(f->headers, header);
}
struct file *
-file_create(char *name, struct attr **options)
-{
- struct file *file= g_new0(struct file,1);
- struct attr *attr;
- int open_flags=O_LARGEFILE|O_BINARY;
+file_create(char *name, struct attr **options) {
+ struct file *file= g_new0(struct file,1);
+ struct attr *attr;
+ int open_flags=O_LARGEFILE|O_BINARY;
- if (options && (attr=attr_search(options, NULL, attr_url))) {
+ if (options && (attr=attr_search(options, NULL, attr_url))) {
#ifdef HAVE_SOCKET
- file_request_do(file, options, 1);
+ file_request_do(file, options, 1);
#endif
- } else {
- if (options && (attr=attr_search(options, NULL, attr_readwrite)) && attr->u.num) {
- open_flags |= O_RDWR;
- if ((attr=attr_search(options, NULL, attr_create)) && attr->u.num)
- open_flags |= O_CREAT|O_TRUNC;
- } else
- open_flags |= O_RDONLY;
- file->name = g_strdup(name);
- file->fd=open(name, open_flags, 0666);
- if (file->fd == -1) {
- g_free(file->name);
- g_free(file);
- return NULL;
- }
- dbg(lvl_debug,"fd=%d\n", file->fd);
- file->size=lseek(file->fd, 0, SEEK_END);
- if (file->size < 0)
- file->size=0;
- dbg(lvl_debug,"size="LONGLONG_FMT"\n", file->size);
- file->name_id = (long)atom(name);
- }
+ } else {
+ if (options && (attr=attr_search(options, NULL, attr_readwrite)) && attr->u.num) {
+ open_flags |= O_RDWR;
+ if ((attr=attr_search(options, NULL, attr_create)) && attr->u.num)
+ open_flags |= O_CREAT|O_TRUNC;
+ } else
+ open_flags |= O_RDONLY;
+ file->name = g_strdup(name);
+ file->fd=open(name, open_flags, 0666);
+ if (file->fd == -1) {
+ g_free(file->name);
+ g_free(file);
+ return NULL;
+ }
+ dbg(lvl_debug,"fd=%d", file->fd);
+ file->size=lseek(file->fd, 0, SEEK_END);
+ if (file->size < 0)
+ file->size=0;
+ dbg(lvl_debug,"size="LONGLONG_FMT"", file->size);
+ file->name_id = (long)atom(name);
+ }
#ifdef CACHE_SIZE
- if (!options || !(attr=attr_search(options, NULL, attr_cache)) || attr->u.num)
- file->cache=1;
+ if (!options || !(attr=attr_search(options, NULL, attr_cache)) || attr->u.num)
+ file->cache=1;
#endif
- dbg_assert(file != NULL);
- return file;
+ dbg_assert(file != NULL);
+ return file;
}
#if 0
struct file *
-file_create_url(char *url)
-{
+file_create_url(char *url) {
}
#endif
@@ -244,599 +230,541 @@ file_create_url(char *url)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
-int file_is_dir(char *name)
-{
- struct stat buf;
- if (! stat(name, &buf)) {
- return S_ISDIR(buf.st_mode);
- }
- return 0;
+/**
+ * @brief Check if a given path corresponds to a directory
+ *
+ * @param name The path to the filesystem element
+ * @return !=0 (true) if @p name is a directory
+ */
+int file_is_dir(const char *name) {
+ struct stat buf;
+ if (! stat(name, &buf)) {
+ return S_ISDIR(buf.st_mode);
+ }
+ return 0;
}
-int file_is_reg(char *name)
-{
- struct stat buf;
- if (! stat(name, &buf)) {
- return S_ISREG(buf.st_mode);
- }
- return 0;
+/**
+ * @brief Check if a given path corresponds to a regular file
+ *
+ * @param name The path to the filesystem element
+ * @return !=0 (true) if @p name is a regular file
+ */
+int file_is_reg(const char *name) {
+ struct stat buf;
+ if (! stat(name, &buf)) {
+ return S_ISREG(buf.st_mode);
+ }
+ return 0;
}
-long long
-file_size(struct file *file)
-{
- return file->size;
+long long file_size(struct file *file) {
+ return file->size;
}
-int file_mkdir(char *name, int pflag)
-{
- char *buffer=g_alloca(sizeof(char)*(strlen(name)+1));
- int ret;
- char *next;
- dbg(lvl_debug,"enter %s %d\n",name,pflag);
- if (!pflag) {
- if (file_is_dir(name))
- return 0;
+int file_mkdir(char *name, int pflag) {
+ char *buffer=g_alloca(sizeof(char)*(strlen(name)+1));
+ int ret;
+ char *next;
+ dbg(lvl_debug,"enter %s %d",name,pflag);
+ if (!pflag) {
+ if (file_is_dir(name))
+ return 0;
#if defined HAVE_API_WIN32_BASE || defined _MSC_VER
- return mkdir(name);
+ return mkdir(name);
#else
- return mkdir(name, 0777);
+ return mkdir(name, 0777);
#endif
- }
- strcpy(buffer, name);
- next=buffer;
- while ((next=strchr(next, '/'))) {
- *next='\0';
- if (*buffer) {
- ret=file_mkdir(buffer, 0);
- if (ret)
- return ret;
- }
- *next++='/';
- }
- if (pflag == 2)
- return 0;
- return file_mkdir(buffer, 0);
-}
-
-int
-file_mmap(struct file *file)
-{
+ }
+ strcpy(buffer, name);
+ next=buffer;
+ while ((next=strchr(next, '/'))) {
+ *next='\0';
+ if (*buffer) {
+ ret=file_mkdir(buffer, 0);
+ if (ret)
+ return ret;
+ }
+ *next++='/';
+ }
+ if (pflag == 2)
+ return 0;
+ return file_mkdir(buffer, 0);
+}
+
+int file_mmap(struct file *file) {
#if 0
- int mmap_size=file->size+1024*1024;
+ int mmap_size=file->size+1024*1024;
#else
- int mmap_size=file->size;
+ int mmap_size=file->size;
#endif
#ifdef HAVE_API_WIN32_BASE
- file->begin = (unsigned char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
+ file->begin = (unsigned 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;
- }
+ 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
- dbg_assert(file->begin != (void *)0xffffffff);
- file->mmap_end=file->begin+mmap_size;
- file->end=file->begin+file->size;
-
- return 1;
-}
-
-unsigned char *
-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(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);
- if (read(file->fd, ret, size) != size) {
- file_data_free(file, ret);
- ret=NULL;
- }
- return ret;
-
-}
-
-static void
-file_process_headers(struct file *file, unsigned char *headers)
-{
- char *tok;
- char *cl;
- if (file->headers)
- g_hash_table_destroy(file->headers);
- file->headers=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
- while ((tok=strtok((char*)headers, "\r\n"))) {
- char *sep;
- tok=g_strdup(tok);
- sep=strchr(tok,':');
- if (!sep)
- sep=strchr(tok,'/');
- if (!sep) {
- g_free(tok);
- continue;
- }
- *sep++='\0';
- if (*sep == ' ')
- sep++;
- strtolower(tok, tok);
- dbg(lvl_debug,"header '%s'='%s'\n",tok,sep);
- g_hash_table_insert(file->headers, tok, sep);
- headers=NULL;
- }
- cl=g_hash_table_lookup(file->headers, "content-length");
- if (cl)
+ dbg_assert(file->begin != (void *)0xffffffff);
+ file->mmap_end=file->begin+mmap_size;
+ file->end=file->begin+file->size;
+
+ return 1;
+}
+
+unsigned char *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(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);
+ if (read(file->fd, ret, size) != size) {
+ file_data_free(file, ret);
+ ret=NULL;
+ }
+ return ret;
+
+}
+
+static void file_process_headers(struct file *file, unsigned char *headers) {
+ char *tok;
+ char *cl;
+ if (file->headers)
+ g_hash_table_destroy(file->headers);
+ file->headers=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+ while ((tok=strtok((char*)headers, "\r\n"))) {
+ char *sep;
+ tok=g_strdup(tok);
+ sep=strchr(tok,':');
+ if (!sep)
+ sep=strchr(tok,'/');
+ if (!sep) {
+ g_free(tok);
+ continue;
+ }
+ *sep++='\0';
+ if (*sep == ' ')
+ sep++;
+ strtolower(tok, tok);
+ dbg(lvl_debug,"header '%s'='%s'",tok,sep);
+ g_hash_table_insert(file->headers, tok, sep);
+ headers=NULL;
+ }
+ cl=g_hash_table_lookup(file->headers, "content-length");
+ if (cl)
#ifdef HAVE__ATOI64
- file->size=_atoi64(cl);
+ file->size=_atoi64(cl);
#else
- file->size=atoll(cl);
+ file->size=atoll(cl);
#endif
}
-static void
-file_shift_buffer(struct file *file, int amount)
-{
- memmove(file->buffer, file->buffer+amount, file->buffer_len-amount);
- file->buffer_len-=amount;
-}
-
-unsigned char *
-file_data_read_special(struct file *file, int size, int *size_ret)
-{
- unsigned char *ret,*hdr;
- int rets=0,rd;
- int buffer_size=8192;
- int eof=0;
- if (!file->special)
- return NULL;
- if (!file->buffer)
- file->buffer=g_malloc(buffer_size);
- ret=g_malloc(size);
- while ((size > 0 || file->requests) && (!eof || file->buffer_len)) {
- int toread=buffer_size-file->buffer_len;
- if (toread >= 4096 && !eof) {
- if (!file->requests && toread > size)
- toread=size;
- rd=read(file->fd, file->buffer+file->buffer_len, toread);
- if (rd > 0) {
- file->buffer_len+=rd;
- } else
- eof=1;
- }
- if (file->requests) {
- dbg(lvl_debug,"checking header\n");
- if ((hdr=file_http_header_end(file->buffer, file->buffer_len))) {
- hdr[-1]='\0';
- dbg(lvl_debug,"found %s\n",file->buffer);
- file_process_headers(file, file->buffer);
- file_shift_buffer(file, hdr-file->buffer);
- file->requests--;
- if (file_http_header(file, "location"))
- break;
- }
- }
- if (!file->requests) {
- rd=file->buffer_len;
- if (rd > size)
- rd=size;
- memcpy(ret+rets, file->buffer, rd);
- file_shift_buffer(file, rd);
- rets+=rd;
- size-=rd;
- }
- }
- *size_ret=rets;
- return ret;
-}
-
-unsigned char *
-file_data_read_all(struct file *file)
-{
- return file_data_read(file, 0, file->size);
-}
-
-void
-file_data_flush(struct file *file, long long offset, int size)
-{
- if (file->cache) {
- struct file_cache_id id={offset,size,file->name_id,0};
- cache_flush(file_cache,&id);
- dbg(lvl_debug,"Flushing "LONGLONG_FMT" %d bytes\n",offset,size);
- }
-}
-
-int
-file_data_write(struct file *file, long long offset, int size, const void *data)
-{
- file_data_flush(file, offset, size);
- 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;
- file->cache=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)
-{
- z_stream stream;
- int err;
-
- stream.next_in = (Bytef*)source;
- stream.avail_in = (uInt)sourceLen;
- stream.next_out = dest;
- stream.avail_out = (uInt)*destLen;
-
- stream.zalloc = (alloc_func)0;
- stream.zfree = (free_func)0;
-
- err = inflateInit2(&stream, -MAX_WBITS);
- if (err != Z_OK) return err;
-
- err = inflate(&stream, Z_FINISH);
- if (err != Z_STREAM_END) {
- inflateEnd(&stream);
- if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
- return Z_DATA_ERROR;
- return err;
- }
- *destLen = stream.total_out;
-
- err = inflateEnd(&stream);
- return err;
-}
-
-unsigned char *
-file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp)
-{
- void *ret;
- char *buffer = 0;
- uLongf destLen=size_uncomp;
-
- if (file->cache) {
- struct file_cache_id id={offset,size,file->name_id,1};
- 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;
- } else {
- if (uncompress_int(ret, &destLen, (Bytef *)buffer, size) != Z_OK) {
- dbg(lvl_error,"uncompress failed\n");
- g_free(ret);
- ret=NULL;
- }
- }
- g_free(buffer);
-
- return ret;
-}
-
-void
-file_data_free(struct file *file, unsigned char *data)
-{
- 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_data_remove(struct file *file, unsigned char *data)
-{
- if (file->begin) {
- if (data == file->begin)
- return;
- if (data >= file->begin && data < file->end)
- return;
- }
- if (file->cache && data) {
- cache_flush_data(file_cache, data);
- } else
- g_free(data);
-}
-
-int
-file_exists(char const *name)
-{
- struct stat buf;
- if (! stat(name, &buf))
- return 1;
- return 0;
-}
-
-void
-file_remap_readonly(struct file *f)
-{
+static void file_shift_buffer(struct file *file, int amount) {
+ memmove(file->buffer, file->buffer+amount, file->buffer_len-amount);
+ file->buffer_len-=amount;
+}
+
+unsigned char *file_data_read_special(struct file *file, int size, int *size_ret) {
+ unsigned char *ret,*hdr;
+ int rets=0,rd;
+ int buffer_size=8192;
+ int eof=0;
+ if (!file->special)
+ return NULL;
+ if (!file->buffer)
+ file->buffer=g_malloc(buffer_size);
+ ret=g_malloc(size);
+ while ((size > 0 || file->requests) && (!eof || file->buffer_len)) {
+ int toread=buffer_size-file->buffer_len;
+ if (toread >= 4096 && !eof) {
+ if (!file->requests && toread > size)
+ toread=size;
+ rd=read(file->fd, file->buffer+file->buffer_len, toread);
+ if (rd > 0) {
+ file->buffer_len+=rd;
+ } else
+ eof=1;
+ }
+ if (file->requests) {
+ dbg(lvl_debug,"checking header");
+ if ((hdr=file_http_header_end(file->buffer, file->buffer_len))) {
+ hdr[-1]='\0';
+ dbg(lvl_debug,"found %s",file->buffer);
+ file_process_headers(file, file->buffer);
+ file_shift_buffer(file, hdr-file->buffer);
+ file->requests--;
+ if (file_http_header(file, "location"))
+ break;
+ }
+ }
+ if (!file->requests) {
+ rd=file->buffer_len;
+ if (rd > size)
+ rd=size;
+ memcpy(ret+rets, file->buffer, rd);
+ file_shift_buffer(file, rd);
+ rets+=rd;
+ size-=rd;
+ }
+ }
+ *size_ret=rets;
+ return ret;
+}
+
+unsigned char *file_data_read_all(struct file *file) {
+ return file_data_read(file, 0, file->size);
+}
+
+void file_data_flush(struct file *file, long long offset, int size) {
+ if (file->cache) {
+ struct file_cache_id id= {offset,size,file->name_id,0};
+ cache_flush(file_cache,&id);
+ dbg(lvl_debug,"Flushing "LONGLONG_FMT" %d bytes",offset,size);
+ }
+}
+
+int file_data_write(struct file *file, long long offset, int size, const void *data) {
+ file_data_flush(file, offset, size);
+ 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;
+ file->cache=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) {
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+
+ err = inflateInit2(&stream, -MAX_WBITS);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
+ return Z_DATA_ERROR;
+ return err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
+
+unsigned char *file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp) {
+ void *ret;
+ char *buffer = 0;
+ uLongf destLen=size_uncomp;
+
+ if (file->cache) {
+ struct file_cache_id id= {offset,size,file->name_id,1};
+ 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;
+ } else {
+ if (uncompress_int(ret, &destLen, (Bytef *)buffer, size) != Z_OK) {
+ dbg(lvl_error,"uncompress failed");
+ g_free(ret);
+ ret=NULL;
+ }
+ }
+ g_free(buffer);
+
+ return ret;
+}
+
+void file_data_free(struct file *file, unsigned char *data) {
+ 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_data_remove(struct file *file, unsigned char *data) {
+ if (file->begin) {
+ if (data == file->begin)
+ return;
+ if (data >= file->begin && data < file->end)
+ return;
+ }
+ if (file->cache && data) {
+ cache_flush_data(file_cache, data);
+ } else
+ g_free(data);
+}
+
+int file_exists(char const *name) {
+ struct stat buf;
+ if (! stat(name, &buf))
+ return 1;
+ return 0;
+}
+
+void file_remap_readonly(struct file *f) {
#if defined(_WIN32) || defined(__CEGCC__)
#else
- void *begin;
- munmap(f->begin, f->size);
- begin=mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
- if (f->begin != begin)
- printf("remap failed\n");
+ void *begin;
+ munmap(f->begin, f->size);
+ begin=mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
+ if (f->begin != begin)
+ printf("remap failed\n");
#endif
}
-void
-file_unmap(struct file *f)
-{
+void file_unmap(struct file *f) {
#if defined(_WIN32) || defined(__CEGCC__)
- mmap_unmap_win32( f->begin, f->map_handle , f->map_file );
+ mmap_unmap_win32( f->begin, f->map_handle, f->map_file );
#else
- munmap(f->begin, f->size);
+ munmap(f->begin, f->size);
#endif
}
#ifndef _MSC_VER
-void *
-file_opendir(char *dir)
-{
- return opendir(dir);
-}
-#else
-void *
-file_opendir(char *dir)
-{
- WIN32_FIND_DATAA FindFileData;
- HANDLE hFind = INVALID_HANDLE_VALUE;
+void *file_opendir(char *dir) {
+ return opendir(dir);
+}
+#else
+void *file_opendir(char *dir) {
+ WIN32_FIND_DATAA FindFileData;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
#undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string
- char* fname=g_alloca(sizeof(char)*(strlen(dir)+4));
- sprintf(fname,"%s\\*",dir);
- hFind = FindFirstFileA(fname, &FindFileData);
- return hFind;
+ char* fname=g_alloca(sizeof(char)*(strlen(dir)+4));
+ sprintf(fname,"%s\\*",dir);
+ hFind = FindFirstFileA(fname, &FindFileData);
+ return hFind;
}
#endif
#ifndef _MSC_VER
-char *
-file_readdir(void *hnd)
-{
- struct dirent *ent;
+char *file_readdir(void *hnd) {
+ struct dirent *ent;
- ent=readdir(hnd);
- if (! ent)
- return NULL;
- return ent->d_name;
+ ent=readdir(hnd);
+ if (! ent)
+ return NULL;
+ return ent->d_name;
}
#else
-char *
-file_readdir(void *hnd)
-{
- WIN32_FIND_DATA FindFileData;
+char *file_readdir(void *hnd) {
+ WIN32_FIND_DATA FindFileData;
- if (FindNextFile(hnd, &FindFileData) ) {
- return FindFileData.cFileName;
- } else {
- return NULL;
- }
+ if (FindNextFile(hnd, &FindFileData) ) {
+ return FindFileData.cFileName;
+ } else {
+ return NULL;
+ }
}
#endif /* _MSC_VER */
#ifndef _MSC_VER
-void
-file_closedir(void *hnd)
-{
- closedir(hnd);
+void file_closedir(void *hnd) {
+ closedir(hnd);
}
#else
-void
-file_closedir(void *hnd)
-{
- FindClose(hnd);
+void file_closedir(void *hnd) {
+ FindClose(hnd);
}
#endif /* _MSC_VER */
struct file *
-file_create_caseinsensitive(char *name, struct attr **options)
-{
- char *dirname=g_alloca(sizeof(char)*(strlen(name)+1));
- char *filename;
- char *p;
- void *d;
- struct file *ret;
-
- ret=file_create(name, options);
- if (ret)
- return ret;
-
- strcpy(dirname, name);
- p=dirname+strlen(name);
- while (p > dirname) {
- if (*p == '/')
- break;
- p--;
- }
- *p=0;
- d=file_opendir(dirname);
- if (d) {
- *p++='/';
- while ((filename=file_readdir(d))) {
- if (!g_ascii_strcasecmp(filename, p)) {
- strcpy(p, filename);
- ret=file_create(dirname, options);
- if (ret)
- break;
- }
- }
- file_closedir(d);
- }
- return ret;
-}
-
-void
-file_fsync(struct file *f)
-{
+file_create_caseinsensitive(char *name, struct attr **options) {
+ char *dirname=g_alloca(sizeof(char)*(strlen(name)+1));
+ char *filename;
+ char *p;
+ void *d;
+ struct file *ret;
+
+ ret=file_create(name, options);
+ if (ret)
+ return ret;
+
+ strcpy(dirname, name);
+ p=dirname+strlen(name);
+ while (p > dirname) {
+ if (*p == '/')
+ break;
+ p--;
+ }
+ *p=0;
+ d=file_opendir(dirname);
+ if (d) {
+ *p++='/';
+ while ((filename=file_readdir(d))) {
+ if (!g_ascii_strcasecmp(filename, p)) {
+ strcpy(p, filename);
+ ret=file_create(dirname, options);
+ if (ret)
+ break;
+ }
+ }
+ file_closedir(d);
+ }
+ return ret;
+}
+
+void file_fsync(struct file *f) {
#ifdef HAVE_FSYNC
- fsync(f->fd);
+ fsync(f->fd);
#endif
}
-void
-file_destroy(struct file *f)
-{
- if (f->headers)
- g_hash_table_destroy(f->headers);
- switch (f->special) {
- case 0:
- case 1:
- close(f->fd);
- break;
- }
-
- if ( f->begin != NULL )
- {
+void file_destroy(struct file *f) {
+ if (f->headers)
+ g_hash_table_destroy(f->headers);
+ switch (f->special) {
+ case 0:
+ case 1:
+ close(f->fd);
+ break;
+ }
+
+ if ( f->begin != NULL ) {
file_unmap( f );
}
- g_free(f->buffer);
- g_free(f->name);
- g_free(f);
+ g_free(f->buffer);
+ g_free(f->name);
+ g_free(f);
}
struct file_wordexp {
- int err;
- char *pattern;
- wordexp_t we;
+ int err;
+ char *pattern;
+ wordexp_t we;
};
struct file_wordexp *
-file_wordexp_new(const char *pattern)
-{
- struct file_wordexp *ret=g_new0(struct file_wordexp, 1);
+file_wordexp_new(const char *pattern) {
+ struct file_wordexp *ret=g_new0(struct file_wordexp, 1);
- ret->pattern=g_strdup(pattern);
- ret->err=wordexp(pattern, &ret->we, 0);
- if (ret->err)
- dbg(lvl_debug,"wordexp('%s') returned %d\n", pattern, ret->err);
- return ret;
+ ret->pattern=g_strdup(pattern);
+ ret->err=wordexp(pattern, &ret->we, 0);
+ if (ret->err)
+ dbg(lvl_debug,"wordexp('%s') returned %d", pattern, ret->err);
+ return ret;
}
-int
-file_wordexp_get_count(struct file_wordexp *wexp)
-{
- if (wexp->err)
- return 1;
- return wexp->we.we_wordc;
+int file_wordexp_get_count(struct file_wordexp *wexp) {
+ if (wexp->err)
+ return 1;
+ return wexp->we.we_wordc;
}
-char **
-file_wordexp_get_array(struct file_wordexp *wexp)
-{
- if (wexp->err)
- return &wexp->pattern;
- return wexp->we.we_wordv;
+char ** file_wordexp_get_array(struct file_wordexp *wexp) {
+ if (wexp->err)
+ return &wexp->pattern;
+ return wexp->we.we_wordv;
}
-void
-file_wordexp_destroy(struct file_wordexp *wexp)
-{
- if (! wexp->err)
- wordfree(&wexp->we);
- g_free(wexp->pattern);
- g_free(wexp);
+void file_wordexp_destroy(struct file_wordexp *wexp) {
+ if (! wexp->err)
+ wordfree(&wexp->we);
+ g_free(wexp->pattern);
+ g_free(wexp);
}
-int
-file_version(struct file *file, int mode)
-{
+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(lvl_debug,"%s now version %d\n", file->name, file->version);
- }
- }
- return file->version;
+ 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(lvl_debug,"%s now version %d", file->name, file->version);
+ }
+ }
+ return file->version;
#else
- return 0;
+ return 0;
#endif
}
-void *
-file_get_os_handle(struct file *file)
-{
- return GINT_TO_POINTER(file->fd);
+void *file_get_os_handle(struct file *file) {
+ return GINT_TO_POINTER(file->fd);
}
-int
-file_set_cache_size(int cache_size)
-{
+int file_set_cache_size(int cache_size) {
#ifdef CACHE_SIZE
- cache_resize(file_cache, cache_size);
- return 1;
+ cache_resize(file_cache, cache_size);
+ return 1;
#else
- return 0;
+ return 0;
#endif
}
-void
-file_init(void)
-{
+void file_init(void) {
#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), CACHE_SIZE);
+ file_name_hash=g_hash_table_new(g_str_hash, g_str_equal);
+ file_cache=cache_new(sizeof(struct file_cache_id), CACHE_SIZE);
#endif
- if(sizeof(off_t)<8)
- dbg(lvl_error,"Maps larger than 2GB are not supported by this binary, sizeof(off_t)=%zu\n",sizeof(off_t));
+ if(sizeof(off_t)<8)
+ dbg(lvl_error,"Maps larger than 2GB are not supported by this binary, sizeof(off_t)=%zu",sizeof(off_t));
}