olefs

command line tools to extract data from OLE documents like doc, ppt, xls, msg
git clone https://logand.com/git/olefs.git/
Log | Files | Refs

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:
Modrawfs.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); }