commit 2db62904f67a89bdc07fca1182b8f0f90920f819
parent 9903072cf148f1300844265c34a19b18d9ddd90a
Author: Tomas Hlavaty <tom@logand.com>
Date: Sun, 29 May 2011 16:28:55 +0200
odrawfs some fuse commands implemented
Diffstat:
M | odrawfs.c | | | 306 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
1 file changed, 164 insertions(+), 142 deletions(-)
diff --git a/odrawfs.c b/odrawfs.c
@@ -10,28 +10,29 @@
#include <unistd.h>
typedef uint8_t byte;
-typedef uint16_t ushort;
-typedef uint16_t wchar;
+//typedef uint16_t ushort;
+//typedef uint16_t wchar;
typedef uint32_t dword;
-typedef uint64_t filetime;
-typedef uint64_t ulonglong;
+//typedef uint64_t filetime;
+//typedef uint64_t ulonglong;
#define PATH_MAX 1024
-char *filename;
+static char *filename;
static char cwd[PATH_MAX]; // fuse changes cwd:-{
-struct shorter_stream {
+struct record_stream {
FILE *wrap;
+ off_t start;
size_t size;
off_t offset;
};
-static int shorter_stream_eof(struct shorter_stream *s) {
+static int record_stream_eof(struct record_stream *s) {
return !(s->offset < s->size);
}
-static int shorter_stream_read(struct shorter_stream *s, void *buf, size_t size) {
+static int record_stream_read(struct record_stream *s, void *buf, size_t size) {
int left = s->size - s->offset;
if(0 < left) {
int n = left < size ? left : size;
@@ -43,8 +44,17 @@ static int shorter_stream_read(struct shorter_stream *s, void *buf, size_t size)
return 0;
}
-static int read_guid(struct shorter_stream *s, byte guid[]) {
- int n = shorter_stream_read(s, guid, 16);
+static void record_stream_seek(struct record_stream *s, off_t offset) {
+ /* FILE *f = fopen("/tmp/log", "a"); */
+ /* fprintf(f, "%ld %ld %ld %ld\n", s->start, s->size, s->offset, offset); */
+ /* fclose(f); */
+ s->offset = offset;
+ if(!record_stream_eof(s))
+ fseek(s->wrap, s->start + s->offset, SEEK_SET);
+}
+
+static int read_guid(struct record_stream *s, byte guid[]) {
+ int n = record_stream_read(s, guid, 16);
if(0 < n)
assert(n == 16);
return n;
@@ -63,11 +73,6 @@ static int read_RecordHeader(FILE *stream, struct RecordHeader *x) {
return fread(x, sizeof(struct RecordHeader), 1, stream);
}
-/* static void print_RecordHeader(struct RecordHeader *x) { */
-/* printf("RecordHeader 0x%x 0x%x 0x%x %d 0x%lx\n", x->recVer, x->recInstance, */
-/* x->recType, x->recLen, ftell(stream)); */
-/* } */
-
// MS-ODRAW Office Drawing Binary File Format
struct POINT {
@@ -91,9 +96,9 @@ struct OfficeArtMetafileHeader {
byte filter; //:always #xfe))
} __attribute__((__packed__));
-static int read_OfficeArtMetafileHeader(struct shorter_stream *s,
+static int read_OfficeArtMetafileHeader(struct record_stream *s,
struct OfficeArtMetafileHeader *x) {
- return shorter_stream_read(s, x, sizeof(struct OfficeArtMetafileHeader));
+ return record_stream_read(s, x, sizeof(struct OfficeArtMetafileHeader));
}
static const struct OfficeArtBlip_config {
@@ -121,124 +126,156 @@ static int member(ushort x, const ushort a[]) { // , size_t n
return 0;
}
-static void blip(int n, ushort recType, ushort recInstance, dword recLen) {
- const struct OfficeArtBlip_config *config;
+// TODO content and meta stream, or composable head and tail stream!
+
+/* static void blip(int n, ushort recType, ushort recInstance, dword recLen) { */
+/* const struct OfficeArtBlip_config *config; */
+/* int i; */
+/* for(i = 0; i < sizeof(OfficeArtBlip_config); i++) { */
+/* config = &OfficeArtBlip_config[i]; */
+/* if(OfficeArtBlip_config[i].recType == recType) break; */
+/* } */
+/* assert(member(recInstance, config->recInstance)); */
+/* FILE *stream = fopen(filename, "r"); */
+/* struct record_stream s = {stream, recLen, 0}; */
+/* byte guid[16]; */
+/* read_guid(&s, guid); */
+/* if(member(recInstance, config->guid2)) */
+/* read_guid(&s, guid); */
+/* if(config->metafileHeader) { */
+/* struct OfficeArtMetafileHeader h; */
+/* read_OfficeArtMetafileHeader(&s, &h); */
+/* } */
+/* else { */
+/* byte b; */
+/* record_stream_read(&s, &b, 1); */
+/* } */
+/* char ofile[1024]; */
+/* //snprintf(ofile, 1024, "%s/%d.%s", dir, n, config->ext); */
+/* FILE *o = fopen(ofile, "w"); */
+/* assert(o); */
+/* while(!record_stream_eof(&s)) { */
+/* byte buf[1024]; */
+/* int n = record_stream_read(&s, buf, 1024); */
+/* if(n <= 0) break; */
+/* fwrite(buf, sizeof(char), n, o); */
+/* } */
+/* fclose(o); */
+/* fclose(stream); */
+/* //printf("<p><img src=\"%d.%s\">\n", n, config->ext); */
+/* } */
+
+struct header {
+ struct RecordHeader h;
+ int i;
+ off_t fpos;
+ struct header *next;
+};
+
+static struct header *headers;
+
+static const char *header_ext(struct header *h) {
+ char *ext;
int i;
for(i = 0; i < sizeof(OfficeArtBlip_config); i++) {
- config = &OfficeArtBlip_config[i];
- if(OfficeArtBlip_config[i].recType == recType) break;
- }
- assert(member(recInstance, config->recInstance));
- FILE *stream = fopen(filename, "r");
- struct shorter_stream s = {stream, recLen, 0};
- byte guid[16];
- read_guid(&s, guid);
- if(member(recInstance, config->guid2))
- read_guid(&s, guid);
- if(config->metafileHeader) {
- struct OfficeArtMetafileHeader h;
- read_OfficeArtMetafileHeader(&s, &h);
- }
- else {
- byte b;
- shorter_stream_read(&s, &b, 1);
- }
- char ofile[1024];
- //snprintf(ofile, 1024, "%s/%d.%s", dir, n, config->ext);
- FILE *o = fopen(ofile, "w");
- assert(o);
- while(!shorter_stream_eof(&s)) {
- byte buf[1024];
- int n = shorter_stream_read(&s, buf, 1024);
- if(n <= 0) break;
- fwrite(buf, sizeof(char), n, o);
+ const struct OfficeArtBlip_config *c = &OfficeArtBlip_config[i];
+ if(c->recType == h->h.recType) {
+ ext = c->ext;
+ break;
+ }
}
- fclose(o);
- fclose(stream);
- //printf("<p><img src=\"%d.%s\">\n", n, config->ext);
+ return ext;
}
-static int odrawfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
- off_t offset, struct fuse_file_info *fi) {
- (void) offset;
- (void) fi;
- /*
- struct entry *root = &directories[0];
- char name[32 * sizeof(wchar)];
- xconv(root->name, name, root->name_length);
- if(strcmp(path, "/") == 0) {
- filler(buf, ".", NULL, 0);
- filler(buf, "..", NULL, 0);
- filler(buf, header_path + 1, NULL, 0);
- filler(buf, name, NULL, 0);
- }
- else {
- struct readdir_walk e = {path, buf, filler, -ENOENT};
- walk_directory(&e, readdir_walk_cb, 0, "");
- return e.result;
- }*/
- return 0;
+static const char *header_path(struct header *h, char *buf, size_t len, int slash) {
+ const char *ext = header_ext(h);
+ if(ext)
+ snprintf(buf, len, "%s%d.%s", slash ? "/" : "", h->i, ext);
+ return ext;
}
static int odrawfs_getattr(const char *path, struct stat *stbuf) {
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
- /*
if(strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
}
- else if(strcmp(path, header_path) == 0) {
- stbuf->st_mode = S_IFREG | 0444;
- stbuf->st_nlink = 1;
- size_t len;
- char *header_str;
- print_header_to_string(&header_str, &len);
- free(header_str);
- stbuf->st_size = len; //0; //strlen(header_str);
- }
else {
- struct getattr_walk e = {path, stbuf, -ENOENT};
- walk_directory(&e, getattr_walk_cb, 0, "");
- return e.result;
- }*/
+ struct header *h;
+ for(h = headers; h; h = h->next) {
+ char name[PATH_MAX];
+ if(!header_path(h, name, PATH_MAX, 1))
+ continue;
+ if(!strcmp(path, name)) {
+ stbuf->st_mode = S_IFREG | 0444;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = h->h.recLen;
+ }
+ }
+ }
return res;
}
+static int odrawfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi) {
+ (void) offset;
+ (void) fi;
+ if(strcmp(path, "/") == 0) {
+ filler(buf, ".", NULL, 0);
+ filler(buf, "..", NULL, 0);
+ struct header *h;
+ for(h = headers; h; h = h->next) {
+ char name[PATH_MAX];
+ if(!header_path(h, name, PATH_MAX, 0))
+ continue;
+ filler(buf, name, NULL, 0);
+ }
+ }
+ return 0;
+}
+
static int odrawfs_open(const char *path, struct fuse_file_info *fi) {
- /*
- if(!strcmp(path, header_path)) {
+ struct header *h;
+ for(h = headers; h; h = h->next) {
+ char name[PATH_MAX];
+ if(!header_path(h, name, PATH_MAX, 1))
+ continue;
+ if(strcmp(path, name))
+ continue;
if((fi->flags & 3) != O_RDONLY)
return -EACCES;
return 0;
}
- struct open_walk e = {path, fi, -ENOENT};
- walk_directory(&e, open_walk_cb, 0, "");
- return e.result;
- */
return -EACCES;
}
static int odrawfs_read(const char *path, char *buf, size_t size, off_t offset,
- struct fuse_file_info *fi) {
- /* if(!strcmp(path, header_path)) { */
- /* size_t len; */
- /* char *header_str; */
- /* print_header_to_string(&header_str, &len); */
- /* /\* len = strlen(header_str); *\/ */
- /* if (offset < len) { */
- /* if (offset + size > len) */
- /* size = len - offset; */
- /* memcpy(buf, header_str + offset, size); */
- /* } else */
- /* size = 0; */
- /* free(header_str); */
- /* return size; */
- /* } */
- /* struct read_walk e = {path, buf, size, offset, fi, -ENOENT}; */
- /* walk_directory(&e, read_walk_cb, 0, ""); */
- /* return e.result; */
- return -EACCES;
+ struct fuse_file_info *fi) {
+ int n = -EACCES;
+ struct header *h;
+ for(h = headers; h; h = h->next) {
+ char name[PATH_MAX];
+ if(!header_path(h, name, PATH_MAX, 1))
+ continue;
+ if(strcmp(path, name))
+ continue;
+ if((fi->flags & 3) != O_RDONLY)
+ break;
+ // TODO fix path if not absolute
+ //char path[PATH_MAX];
+ //n = snprintf(path, PATH_MAX, "%s/%s", cwd, filename);
+ //n = snprintf(buf, PATH_MAX, "%s/%s", cwd, filename);
+ FILE *f = fopen(filename, "r");
+ if(f) {
+ struct record_stream s = {f, h->fpos, h->h.recLen, 0};
+ record_stream_seek(&s, offset);
+ n = record_stream_read(&s, buf, size);
+ fclose(f);
+ }
+ break;
+ }
+ return n;
}
static struct fuse_operations odrawfs_operations = {
@@ -248,44 +285,29 @@ static struct fuse_operations odrawfs_operations = {
.read = odrawfs_read,
};
-struct header {
- struct RecordHeader h;
- off_t fpos;
- struct RecordHeader *next;
-};
-
-static void read_headers(FILE *stream) {
+static struct header *read_headers(FILE *stream) {
+ struct header *head = NULL, *tail = NULL;
int i;
for(i = 0;; i++) {
- struct RecordHeader h;
- /* struct CurrentUserAtom u; */
- if(read_RecordHeader(stream, &h) <= 0) break;
- //print_RecordHeader(&h);
- switch(h.recType) {
- /* case RT_CurrentUserAtom: */
- /* assert(!x->recVer); */
- /* assert(!x->recInstance); */
- /* read_CurrentUserAtom(&u); */
- /* /\* #+nil ;; why recLen too small? *\/ */
- /* /\* (with-shorter-stream (in stream (RecordHeader.recLen x)) *\/ */
- /* /\* (list x (read-CurrentUserAtom in)))) *\/ */
- /* break; */
- case 0xF01A:
- case 0xF01B:
- case 0xF01C:
- case 0xF01D:
- case 0xF01E:
- case 0xF01F:
- case 0xF029:
- case 0xF02A:
- assert(!h.recVer);
- blip(i, h.recType, h.recInstance, h.recLen);
+ struct header *new = malloc(sizeof(struct header));
+ if(read_RecordHeader(stream, &new->h) <= 0) {
+ free(new);
break;
- default:
- fprintf(stderr, "Unknown recType 0x%x\n", h.recType);
- exit(-1);
}
+ new->i = i;
+ new->fpos = ftell(stream);
+ new->next = NULL;
+ printf("%d 0x%x 0x%x 0x%x %u %lu\n", new->i, new->h.recVer,
+ new->h.recInstance, new->h.recType, new->h.recLen, new->fpos);
+ fseek(stream, new->h.recLen, SEEK_CUR);
+ if(head) {
+ tail->next = new;
+ tail = new;
+ }
+ else
+ head = tail = new;
}
+ return head;
}
int main(int argc, char *argv[]) {
@@ -302,7 +324,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Unable to open '%s'.\n", filename);
exit(-1);
}
- read_headers(stream);
+ headers = read_headers(stream);
fclose(stream);
return fuse_main(argc, argv, &odrawfs_operations);
}