commit 8a8666933e51d1a56b8facaffa1445ecc92f3045
parent 2db62904f67a89bdc07fca1182b8f0f90920f819
Author: Tomas Hlavaty <tom@logand.com>
Date:   Sun, 29 May 2011 16:30:10 +0200
odrawfs fuse read command implemented using peep_stream
Diffstat:
| M | odrawfs.c |  |  | 146 | +++++++++++++++++++++++++++++++++++-------------------------------------------- | 
1 file changed, 65 insertions(+), 81 deletions(-)
diff --git a/odrawfs.c b/odrawfs.c
@@ -1,38 +1,34 @@
+// ls -v1 /tmp/a4 | awk '{print "<p><img src=\"/tmp/a4/" $0 "\"><p>" $0}' >/tmp/index.html
+
 // TODO proper little endian read_
 
 #include <fuse.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <unistd.h>
 
 typedef uint8_t byte;
-//typedef uint16_t ushort;
-//typedef uint16_t wchar;
 typedef uint32_t dword;
-//typedef uint64_t filetime;
-//typedef uint64_t ulonglong;
 
 #define PATH_MAX 1024
 
 static char *filename;
 static char cwd[PATH_MAX]; // fuse changes cwd:-{
 
-struct record_stream {
+struct peep_stream {
   FILE *wrap;
   off_t start;
   size_t size;
   off_t offset;
 };
 
-static int record_stream_eof(struct record_stream *s) {
+static int peep_stream_eof(struct peep_stream *s) {
   return !(s->offset < s->size);
 }
 
-static int record_stream_read(struct record_stream *s, void *buf, size_t size) {
+static int peep_stream_read(struct peep_stream *s, void *buf, size_t size) {
   int left = s->size - s->offset;
   if(0 < left) {
     int n = left < size ? left : size;
@@ -44,20 +40,14 @@ static int record_stream_read(struct record_stream *s, void *buf, size_t size) {
   return 0;
 }
 
-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); */
+static void peep_stream_seek(struct peep_stream *s, off_t offset) {
   s->offset = offset;
-  if(!record_stream_eof(s))
+  if(!peep_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;
+static size_t read_guid(FILE *s, byte guid[]) {
+  return fread(guid, 16, 1, s);
 }
 
 // MS-PPT PowerPoint (.ppt) Binary File Format
@@ -69,7 +59,7 @@ struct RecordHeader {
   dword recLen;
 } __attribute__((__packed__));
 
-static int read_RecordHeader(FILE *stream, struct RecordHeader *x) {
+static size_t read_RecordHeader(FILE *stream, struct RecordHeader *x) {
   return fread(x, sizeof(struct RecordHeader), 1, stream);
 }
 
@@ -96,9 +86,9 @@ struct OfficeArtMetafileHeader {
   byte filter; //:always #xfe))
 } __attribute__((__packed__));
 
-static int read_OfficeArtMetafileHeader(struct record_stream *s,
+static size_t read_OfficeArtMetafileHeader(FILE *s,
                                         struct OfficeArtMetafileHeader *x) {
-  return record_stream_read(s, x, sizeof(struct OfficeArtMetafileHeader));
+  return fread(x, sizeof(struct OfficeArtMetafileHeader), 1, s);
 }
 
 static const struct OfficeArtBlip_config {
@@ -118,7 +108,7 @@ static const struct OfficeArtBlip_config {
   {0xF02A, {0x46A, 0x46B, 0x6E2, 0x6E3}, "jpeg", {0x46B, 0x6E3}, 0},
 };
 
-static int member(ushort x, const ushort a[]) { // , size_t n
+static int member(ushort x, const ushort a[]) {
   int i;
   for(i = 0; i < sizeof(a); i++)
     if(a[i] == x)
@@ -126,45 +116,6 @@ static int member(ushort x, const ushort a[]) { // , size_t n
   return 0;
 }
 
-// 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;
@@ -174,17 +125,19 @@ struct header {
 
 static struct header *headers;
 
-static const char *header_ext(struct header *h) {
-  char *ext;
+static const struct OfficeArtBlip_config *header_config(struct header *h) {
   int i;
   for(i = 0; i < sizeof(OfficeArtBlip_config); i++) {
     const struct OfficeArtBlip_config *c = &OfficeArtBlip_config[i];
-    if(c->recType == h->h.recType) {
-      ext = c->ext;
-      break;
-    }
+    if(c->recType == h->h.recType)
+      return c;
   }
-  return ext;
+  return NULL;
+}
+
+static const char *header_ext(struct header *h) {
+  const struct OfficeArtBlip_config *c = header_config(h);
+  return c ? c->ext : NULL;
 }
 
 static const char *header_path(struct header *h, char *buf, size_t len, int slash) {
@@ -250,6 +203,41 @@ static int odrawfs_open(const char *path, struct fuse_file_info *fi) {
   return -EACCES;
 }
 
+static size_t read_blib_header(FILE *s, struct header *h) {
+  size_t n = 0;
+  const struct OfficeArtBlip_config *c = header_config(h);
+  if(c) {
+    byte guid[16];
+    n += read_guid(s, guid);
+    if(member(h->h.recInstance, c->guid2))
+      n += read_guid(s, guid);
+    if(c->metafileHeader) {
+      struct OfficeArtMetafileHeader h2;
+      n += read_OfficeArtMetafileHeader(s, &h2);
+    }
+    else {
+      byte b;
+      n += fread(&b, 1, 1, s);
+    }
+  }
+  return n;
+}
+
+static int read_blib(char *filename, struct header *h,
+                     char *buf, size_t size, off_t offset) {
+  int n = -EACCES;
+  FILE *f = fopen(filename, "r");
+  if(f) {
+    fseek(f, h->fpos, SEEK_SET);
+    size_t hlen = read_blib_header(f, h); // TODO expose header as txt file?
+    struct peep_stream s = {f, ftell(f), h->h.recLen - hlen, 0};
+    peep_stream_seek(&s, offset);
+    n = peep_stream_read(&s, buf, size);
+    fclose(f);
+  }
+  return n;
+}
+
 static int odrawfs_read(const char *path, char *buf, size_t size, off_t offset,
                         struct fuse_file_info *fi) {
   int n = -EACCES;
@@ -262,16 +250,12 @@ static int odrawfs_read(const char *path, char *buf, size_t size, off_t offset,
       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);
+    if('/' == filename[0])
+      n = read_blib(filename, h, buf, size, offset);
+    else {
+      char x[PATH_MAX];
+      snprintf(x, PATH_MAX, "%s/%s", cwd, filename);
+      n = read_blib(x, h, buf, size, offset);
     }
     break;
   }
@@ -297,8 +281,8 @@ static struct header *read_headers(FILE *stream) {
     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);
+    /* 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;