chiark / gitweb /
Start of main section file save/load.
authorDan Sheppard <dan.sheppard.circle@gmail.com>
Wed, 23 Apr 2025 16:28:28 +0000 (17:28 +0100)
committerDan Sheppard <dan.sheppard.circle@gmail.com>
Wed, 23 Apr 2025 16:29:13 +0000 (17:29 +0100)
14 files changed:
.vscode/settings.json
Makefile
src/constants.h
src/coquet.c
src/coquet.h
src/main.c
src/page.c [new file with mode: 0644]
src/page.h [new file with mode: 0644]
src/superblock.c
src/superblock.h
src/test.c
src/testvfs.c
src/unix.c
src/vfs.h

index b05135a636441172e57c087931062fc1121dc7a6..73c89236ac1961ea07b1d9e7b70353bf9fe83e73 100644 (file)
@@ -9,7 +9,8 @@
     ],
     "files.associations": {
         "coquet.h": "c",
-        "superblock.h": "c"
+        "superblock.h": "c",
+        "page.h": "c"
     },
     "C_Cpp.dimInactiveRegions": false
 }
\ No newline at end of file
index 63f8bb71e1aed2c80c64709c43e851fcba6d8189..737216c1acfe9167c415686e0121a091d1523019 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ BINDIR := bin
 OBJDIR := obj/main
 TESTOBJDIR := obj/test
 
-SRCFILES := unix.c util.c coquet.c superblock.c sha2.c testvfs.c
+SRCFILES := unix.c util.c coquet.c superblock.c sha2.c testvfs.c page.c
 
 SRC := $(addprefix $(SRCDIR)/,$(SRCFILES))
 
index 55e4e7d00cab7699444cd9ecddca6e54fb540ce6..3b8e13e01f51623425533711a0e197fffc7d94be 100644 (file)
 #define COQUET_FILE_NUM  3
 
 /* remember to update messages */
-#define COQUET_RET_OK       0
-#define COQUET_RET_VFSERR   1
-#define COQUET_RET_HEAPERR  2
-#define COQUET_RET_LOCKED   3
-#define COQUET_RET_CORRUPT  4
-#define COQUET_RET_EXISTS   5
-#define COQUET_UNUSED_ERROR 6
-#define COQUET_LAST_ERROR   6
+#define COQUET_RET_OK        0
+#define COQUET_RET_VFSERR    1
+#define COQUET_RET_HEAPERR   2
+#define COQUET_RET_LOCKED    3
+#define COQUET_RET_CORRUPT   4
+#define COQUET_RET_EXISTS    5
+#define COQUET_RET_TRSMERROR 6
+#define COQUET_RET_BADARGS   7
+#define COQUET_UNUSED_ERROR  8
+#define COQUET_LAST_ERROR    8
 
 #define COQUET_CMODE_OPEN   0
 #define COQUET_CMODE_CREATE 1
index aa3e3c598585739b59780788a99cf323f5a8e0b3..6e9168248bafbc2cd728b078961daf01c92d2b4c 100644 (file)
@@ -5,6 +5,7 @@
 #include "coquet.h"
 #include "util.h"
 #include "vfs.h"
+#include "page.h"
 
 /* VFS null is used as a placeholder prior to initialisation, so that
  * subsequent tidies can be clean.
@@ -48,12 +49,16 @@ static int testvfs_wrap(coquet_t *cq) {
 }
 #endif
 
+static void choose_vfs(coquet_t *cq) {
+    cq->vfs_funcs = vfs_unix;
+    cq->vfs_data = unix_make();
+}
+
 /* Allocate and initialise vfs layer. */
 static int init_vfs(coquet_t *cq, char *basename) {
     int r;
 
-    cq->vfs_funcs = vfs_unix;
-    cq->vfs_data = unix_make();
+    choose_vfs(cq);
     if(cq->vfs_data == NULL) {
         cq->vfs_funcs = vfs_null;
         return COQUET_RET_HEAPERR;
@@ -81,9 +86,14 @@ static int init_vfs(coquet_t *cq, char *basename) {
  * content.
  */
 int coquet_init(coquet_t *cq, char * basename) {
-    int r;
+    int i,r;
 
     r = init_vfs(cq,basename);
+    cq->flags = 0;
+    for(i=0;i<COQUET_FILE_NUM;i++) {
+        cq->filemeta[i].which_file = i;
+    }
+
     if(r != COQUET_RET_OK) {
         return r;
     }
@@ -110,8 +120,9 @@ char * error_strings[COQUET_UNUSED_ERROR+1] = {
     /* COQUET_RET_LOCKED */   "Locked",
     /* COQUET_RET_CORRUPT */  "File corrupt",
     /* COQUET_RET_EXISTS */   "File already exists",
+    /* COQUET_RET_TRSMERROR */"Transaction state machine error",
+    /* COQUET_RET_BADARGS */  "Internal error: bad arguments",
     /* COQUET_UNUSED_ERROR */ "No such error code",
-
 };
 
 /* Return error string for most recent error. Returned string is owned by
@@ -127,3 +138,102 @@ char * coquet_error_string(coquet_t *cq, int error) {
         return strdup(error_strings[error]);
     }
 }
+
+/* find last block */
+/* TODO: this is not correct, but we can't do it correclty yet! */
+static int find_last_main_block(coquet_t *cq, struct cq_filemeta *fm) {
+    int r;
+    off_t offset;
+    int64_t main_size;
+
+    r = (cq->vfs_funcs.size)(cq->vfs_data,fm->which_file,&offset);
+    if(r != COQUET_RET_OK) {
+        return r;
+    }
+
+    /* subtract header */
+    main_size = offset - cq_offset_main_page(cq,fm->which_file,1);
+    if(main_size < 0)
+        main_size = 0;
+
+    /* reduce to pages */
+    main_size = main_size / (1<<(fm->super.current.block_size));
+
+    /* TODO: check validity, etc */
+
+    fm->last_main_block = main_size;
+
+    return COQUET_RET_OK;
+}
+
+static int filemeta_setup_write(coquet_t *cq, struct cq_filemeta *fm) {
+    int r;
+
+    fm->flags = 0;
+
+    /* load superblock */
+    r = cq_super_load(cq,fm->which_file,&(fm->super),1); // TODO "create mode"
+    if(r != COQUET_RET_OK) {
+        return r;
+    }
+
+    /* find last block */
+    r = find_last_main_block(cq,fm);
+    if(r != COQUET_RET_OK) {
+        return r;
+    }
+
+    fm->flags |= COQUET_FM_FLAG_WRITE;
+    return COQUET_RET_OK;
+}
+
+bool cq_writing(coquet_t *cq, int which_file) {
+    return ((cq->flags & COQUET_CQ_FILE_VALID(which_file)) &&
+            (cq->filemeta[which_file].flags & COQUET_FM_FLAG_WRITE));
+}
+
+int coquet_write_start(coquet_t *cq, int which_file, bool wait) {
+    int r;
+
+    if(cq_writing(cq,which_file)) {
+        return COQUET_RET_TRSMERROR;
+    }
+
+    /* lock */
+    r = (cq->vfs_funcs.lock)(cq->vfs_data, which_file,
+                             COQUET_LOCK_WRITE,COQUET_LMODE_EXCL,wait);
+    if(r != COQUET_RET_OK) {
+        return r;
+    }
+
+    /* setup */
+    r = filemeta_setup_write(cq,&(cq->filemeta[which_file]));
+    if(r != COQUET_RET_OK) {
+        (cq->vfs_funcs.lock)(cq->vfs_data, which_file,
+                             COQUET_LOCK_WRITE,COQUET_LMODE_UN,wait);
+        return r;
+    }
+    cq->flags |= COQUET_CQ_FILE_VALID(which_file);
+
+    return COQUET_RET_OK;
+}
+
+int coquet_write_end(coquet_t *cq, int which_file) {
+    int r;
+
+    if(!cq_writing(cq,which_file)) {
+        return COQUET_RET_TRSMERROR;
+    }
+
+    /* unlock */
+    r = (cq->vfs_funcs.lock)(cq->vfs_data, which_file,
+                             COQUET_LOCK_WRITE,COQUET_LMODE_UN,1);
+    if(r != COQUET_RET_OK) {
+        return r;
+    }
+
+    /* mark stale */
+    cq->flags &=~ COQUET_CQ_FILE_VALID(which_file);
+
+    return COQUET_RET_OK;
+}
index 4cd6547ec2424051f82d0fe3c123127f2e00139f..38b59aee26e7e66c35822fcb3e05ec5c5ad4b1fb 100644 (file)
@@ -5,14 +5,28 @@
 #include "superblock.h"
 #include "vfs.h"
 
+#define COQUET_CQ_FLAG_MAINVALID 0x00000001
+#define COQUET_CQ_FLAG_OLDVALID  0x00000002
+#define COQUET_CQ_FLAG_TMPVALID  0x00000004
+
+#define COQUET_CQ_FILE_VALID(file) (COQUET_CQ_FLAG_MAINVALID<<(file))
+
+#define COQUET_FM_FLAG_WRITE 0x01
+
+struct cq_filemeta {
+    int which_file;
+    struct cq_super super;
+    uint8_t flags;
+    uint64_t last_main_block;
+};
+
 typedef struct coquet {
-    /* superblock stuff */
-    uint64_t global_iv[GLOBAL_IV_LEN];    
+    uint32_t flags;
+    struct cq_filemeta filemeta[COQUET_FILE_NUM];
 
     /* VFS */
     vfs_t vfs_funcs;
     void *vfs_data;
-
 } coquet_t;
 
 /* Initialise whole library. Returns NULL on malloc failure. cq must
@@ -29,4 +43,14 @@ int coquet_finish(coquet_t *cq);
  */
 char * coquet_error_string(coquet_t *cq, int error);
 
+/* Prepare for a write transaction: locking, and general setup.
+ */
+int coquet_write_start(coquet_t *cq, int which_file, bool wait);
+
+/* Write has fnished, tear down. */
+int coquet_write_end(coquet_t *cq, int which_file);
+
+/* test if we're open for writing */
+bool cq_writing(coquet_t *cq, int which_file);
+
 #endif
index c7436e62d356586f77bb4e7a27b4dcfcd93fdab4..48acc2d2cda13ed351addfa35561f22c8aaf12f1 100644 (file)
@@ -30,9 +30,9 @@ int main() {
     bail(&cq,r);
     r = (cq.vfs_funcs.open)(cq.vfs_data,COQUET_FILE_MAIN,COQUET_CMODE_EITHER);
     bail(&cq,r);
-    r = cq_super_load(&cq,&super,1);
+    r = cq_super_load(&cq,COQUET_FILE_MAIN,&super,1);
     bail(&cq,r);
-    cq_super_save(&cq,&super,1);
+    cq_super_save(&cq,COQUET_FILE_MAIN,&super,1);
     r = (cq.vfs_funcs.close)(cq.vfs_data,COQUET_FILE_MAIN);
     bail(&cq,r);
     r = coquet_finish(&cq);
diff --git a/src/page.c b/src/page.c
new file mode 100644 (file)
index 0000000..fcfb46f
--- /dev/null
@@ -0,0 +1,142 @@
+#include "page.h"
+
+off_t cq_offset_main_page(coquet_t *cq, int which_file, u_int64_t pgid) {
+    struct cq_filemeta *fm;
+    off_t header;
+    off_t nursery;
+
+    fm = &(cq->filemeta[which_file]);
+    nursery = (2<<(fm->super.current.nursery_size + fm->super.current.block_size));
+    header = 2*SUPER_BYTES + nursery;
+
+    return header + (pgid-1) * (1<<fm->super.current.block_size);
+}
+
+int cq_load_page(coquet_t *cq, int which_file, uint64_t pgid, uint64_t **buffer, int *len) {
+    /* TODO nursery */
+
+    return COQUET_RET_OK;
+}
+
+int cq_save_page(coquet_t *cq, int which_file, uint64_t *pgid, uint8_t *buffer, int len) {
+    int r;
+    off_t offset;
+    struct cq_filemeta *fm;
+
+    /* TODO nursery */
+
+    fm = &(cq->filemeta[which_file]);
+
+    /* check we're open for writing */
+    if(!cq_writing(cq,which_file)) {
+        return COQUET_RET_TRSMERROR;
+    }
+
+    /* check we've got the right amount of data */
+    if(len != 1 << fm->super.current.block_size) {
+        return COQUET_RET_BADARGS;
+    }
+
+    /* write to the end of main (always, for now) */
+    offset = cq_offset_main_page(cq,which_file,fm->last_main_block+1);
+
+    /* write */
+    r = (cq->vfs_funcs.write)(cq->vfs_data,which_file,buffer,offset,len);
+    if(r != COQUET_RET_OK)
+        return r;
+
+    /* update metadata */
+    fm->last_main_block += 1;
+    *pgid = fm->last_main_block;
+
+    return COQUET_RET_OK;
+}
+
+#ifdef COQUET_TEST
+
+#include <stdio.h>
+#include <string.h>
+#include "test.h"
+
+void test_page() {
+    uint64_t pgid,pgid2;
+    uint8_t buffer[4096],buffer2[4096];
+    coquet_t cq;
+    struct cq_super super;
+    int r;
+
+    /* write two pages, one of all 0xC3, and one of all 0x3C */
+    /* TODO, when we have proper end detection, this needs to become a
+     * plausible root page.
+     */
+    memset(buffer,0xC3,4096);
+
+    r = coquet_init(&cq,"tmp/pagetest");
+    test_bail(&cq,r);
+
+    r = (cq.vfs_funcs.delete(cq.vfs_data,COQUET_FILE_MAIN));
+    test_bail(&cq,r);
+
+    /* first page */
+    r = (cq.vfs_funcs.open)(cq.vfs_data,COQUET_FILE_MAIN,COQUET_CMODE_CREATE);
+    test_bail(&cq,r);
+
+    cq_super_load(&cq,COQUET_FILE_MAIN,&super,1);
+    cq_super_save(&cq,COQUET_FILE_MAIN,&super,1);
+
+    r = coquet_write_start(&cq,COQUET_FILE_MAIN,1);
+    test_bail(&cq,r);
+
+    r = cq_save_page(&cq,COQUET_FILE_MAIN,&pgid,buffer,4096);
+    test_bail(&cq,r);
+
+    /* close and reopen to make it work it all out again */
+    r = coquet_write_end(&cq,COQUET_FILE_MAIN);
+    test_bail(&cq,r);
+
+    r = (cq.vfs_funcs.close)(cq.vfs_data,COQUET_FILE_MAIN);
+    test_bail(&cq,r);
+
+    r = (cq.vfs_funcs.open)(cq.vfs_data,COQUET_FILE_MAIN,COQUET_CMODE_OPEN);
+    test_bail(&cq,r);
+
+    r = coquet_write_start(&cq,COQUET_FILE_MAIN,1);
+    test_bail(&cq,r);
+
+    /* second page */
+    memset(buffer,0x3C,4096);
+
+    r = cq_save_page(&cq,COQUET_FILE_MAIN,&pgid2,buffer,4096);
+    test_bail(&cq,r);
+
+    test_eq_int(pgid,1,"pgid1");
+    test_eq_int(pgid2,2,"pgid2");
+
+    r = coquet_write_end(&cq,COQUET_FILE_MAIN);
+    test_bail(&cq,r);
+
+    /* nursery is (2 sets of 2^12 lots of 10-bit blocks = 2 * 2^22 bytes)
+     *
+     * File should look like this
+     * 0x00000000 - 0x00000FFF superblock
+     * 0x00001000 - 0x00002FFF lock region
+     * 0x00002000 - 0x00401FFF nursery A
+     * 0x00402000 - 0x00801FFF nursery B
+     * 0x00802000 - 0x00802FFF pgid = 1 value = 0xC3
+     * 0x00803000 - 0x00803FFF pgid = 2 value = 0x3C
+     */
+    r = (cq.vfs_funcs.read)(cq.vfs_data,COQUET_FILE_MAIN,buffer2,0x00802000,4096);
+    test_bail(&cq,r);
+    memset(buffer,0xC3,4096);
+    test_assert(!memcmp(buffer,buffer2,4096),"pgid1 data");
+
+    r = (cq.vfs_funcs.read)(cq.vfs_data,COQUET_FILE_MAIN,buffer2,0x00803000,4096);
+    test_bail(&cq,r);
+    memset(buffer,0x3C,4096);
+    test_assert(!memcmp(buffer,buffer2,4096),"pgid2 data");
+
+    r = coquet_finish(&cq);
+    test_bail(&cq,r);
+}
+
+#endif
diff --git a/src/page.h b/src/page.h
new file mode 100644 (file)
index 0000000..6b2bcf3
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef COQUET_PAGE_H
+#define COQUET_PAGE_H
+
+#include <stdint.h>
+#include "coquet.h"
+
+/* byte offset of given main page. Note pgids are 1-based */
+off_t cq_offset_main_page(coquet_t *cq, int which_file, u_int64_t pgid);
+
+/* Load/Save page with given pgid. Translation to nursery addresses (if
+ * needed) occurs immediately INSIDE these functions.
+ */
+int cq_load_page(coquet_t *cq, int which_file, uint64_t pgid, uint64_t **buffer, int *len);
+int cq_save_page(coquet_t *cq, int which_file, uint64_t *pgid, uint8_t *buffer, int len);
+
+#ifdef COQUET_TEST
+void test_page();
+#endif
+
+#endif
index 99c3e4ea5cc865438cffb1d049a848e3fb4591a5..2cd96fcbcf5871587b246fc16e0ad04ef3c086da 100644 (file)
@@ -108,14 +108,14 @@ static int super_init(coquet_t *cq, struct cq_super *super) {
  * reducing the HMAC to a simple hash in terms of guarantees. Requires the
  * main file to be open.
  */
-int cq_super_load(coquet_t *cq, struct cq_super *super, bool create) {
+int cq_super_load(coquet_t *cq, int which_file, struct cq_super *super, bool create) {
     uint8_t super_bytes[SUPER_BYTES];
     struct cq_super super_a, super_b;
     int r,r2;
     bool use_b;
 
     r = (cq->vfs_funcs.read)
-            (cq->vfs_data,COQUET_FILE_MAIN,super_bytes,0,SUPER_BYTES);
+            (cq->vfs_data,which_file,super_bytes,0,SUPER_BYTES);
     if(r != COQUET_RET_OK) {
         return r;
     }
@@ -149,9 +149,9 @@ int cq_super_load(coquet_t *cq, struct cq_super *super, bool create) {
     return COQUET_RET_OK;
 }
 
-static int lock_super(coquet_t *cq, int mode, bool wait) {
+static int lock_super(coquet_t *cq, int which_file, int mode, bool wait) {
     return (cq->vfs_funcs.lock)
-        (cq->vfs_data,COQUET_LOCK_SUPERBLOCK,mode,wait);
+        (cq->vfs_data,which_file,COQUET_LOCK_SUPERBLOCK,mode,wait);
 }
 
 static void intract_config(uint8_t *data,
@@ -194,18 +194,18 @@ static int super_write(coquet_t *cq, struct cq_super *super,
     return r;
 }
 
-int cq_super_save(coquet_t *cq, struct cq_super *super, bool wait) {
+int cq_super_save(coquet_t *cq, int which_file, struct cq_super *super, bool wait) {
     int r, ret;
     struct cq_super old;
 
     /* lock */
-    r = lock_super(cq,COQUET_LMODE_EXCL,wait);
+    r = lock_super(cq,which_file,COQUET_LMODE_EXCL,wait);
     if(r != COQUET_RET_OK) {
         return r;
     }
 
     /* load */
-    ret = cq_super_load(cq,&old,0);
+    ret = cq_super_load(cq,which_file,&old,0);
     if(ret == COQUET_RET_OK) {
         ret = super_write(cq,super,!old.from_b,old.sb_serial+1);
     } else if(ret == COQUET_RET_CORRUPT) {
@@ -218,7 +218,7 @@ int cq_super_save(coquet_t *cq, struct cq_super *super, bool wait) {
     ret = (cq->vfs_funcs.sync)(cq->vfs_data,COQUET_FILE_MAIN,1);
 
     /* unlock */
-    r = lock_super(cq,COQUET_LMODE_UN,wait);
+    r = lock_super(cq,which_file,COQUET_LMODE_UN,wait);
     if(r != COQUET_RET_OK) {
         return r;
     }
@@ -278,15 +278,15 @@ void test_superblock_main() {
 
     test_open(&cq);
 
-    r = cq_super_load(&cq,&super,1);
+    r = cq_super_load(&cq,COQUET_FILE_MAIN,&super,1);
     test_bail(&cq,r);
 
-    cq_super_save(&cq,&super,1);
+    cq_super_save(&cq,COQUET_FILE_MAIN,&super,1);
     test_bail(&cq,r);
 
     super.desired.nursery_size = 11; /* change something for B */
     cq_super_set_desc(&super,"test file");
-    cq_super_save(&cq,&super,1);
+    cq_super_save(&cq,COQUET_FILE_MAIN,&super,1);
     test_bail(&cq,r);
 
     test_close(&cq);
@@ -296,7 +296,7 @@ void test_superblock_main() {
     /* reopen to check the marshalling */
     test_open(&cq);
 
-    r = cq_super_load(&cq,&super,1);
+    r = cq_super_load(&cq,COQUET_FILE_MAIN,&super,1);
     test_bail(&cq,r);
 
     test_assert(super.version == COQUET_VERSION,"version");
@@ -338,12 +338,12 @@ void test_superblock_main() {
     /* check updated in file successfully */
     test_open(&cq);
 
-    cq_super_save(&cq,&super,1);
+    cq_super_save(&cq,COQUET_FILE_MAIN,&super,1);
 
     test_close(&cq);
     test_open(&cq);
 
-    r = cq_super_load(&cq,&super,1);
+    r = cq_super_load(&cq,COQUET_FILE_MAIN,&super,1);
     test_bail(&cq,r);
 
     desc = cq_super_get_desc(&super);
@@ -370,12 +370,12 @@ static void make_superblock(coquet_t *cq, bool also_b,
     test_bail(cq,r);
 
     test_open(cq);
-    r = cq_super_load(cq,&super,1);
+    r = cq_super_load(cq,COQUET_FILE_MAIN,&super,1);
     super.current.nursery_size = 12;
-    cq_super_save(cq,&super,1);
+    cq_super_save(cq,COQUET_FILE_MAIN,&super,1);
     if(also_b) {
         super.current.nursery_size = 11;
-        cq_super_save(cq,&super,1);
+        cq_super_save(cq,COQUET_FILE_MAIN,&super,1);
     }
     if(corrupt>-1) {
         r = (cq->vfs_funcs.read)(cq->vfs_data,COQUET_FILE_MAIN,&d,corrupt,1);
@@ -388,7 +388,7 @@ static void make_superblock(coquet_t *cq, bool also_b,
 
     /* check */
     test_open(cq);
-    r = cq_super_load(cq,&super,1);
+    r = cq_super_load(cq,COQUET_FILE_MAIN,&super,1);
     test_bail(cq,r);
     test_eq_int(super.current.nursery_size,check,"c1");
     test_close(cq);
@@ -438,7 +438,6 @@ void test_superblock() {
 
 creation
 a/b choice
-magic
 
 */
 
index abb9a5d23922473dc1d1175367442b66260a4854..82ff11adc0633a586b5d68f6a18a5b838ce3ee34 100644 (file)
@@ -33,8 +33,8 @@ struct cq_super {
 
 #include "coquet.h"
 
-int cq_super_save(coquet_t *cq, struct cq_super *super, bool wait);
-int cq_super_load(coquet_t *cq, struct cq_super *super, bool create);
+int cq_super_save(coquet_t *cq, int which_file, struct cq_super *super, bool wait);
+int cq_super_load(coquet_t *cq, int which_file, struct cq_super *super, bool create);
 void cq_super_set_desc(struct cq_super *super, char *desc);
 char * cq_super_get_desc(struct cq_super *super);
 
index 2aacc4b01727c8e2d880cc1f866fd52e1d29fcba..64bf6f47c0d92127aec91bc2fa554bfd26ab101f 100644 (file)
@@ -5,6 +5,7 @@
 #include <fcntl.h>
 #include "sha2.h"
 #include "superblock.h"
+#include "page.h"
 #include "test.h"
 
 void test_assert(int is_true, char *msg) {
@@ -108,5 +109,6 @@ int main() {
     printf("testing\n");
     test_sha2();
     test_superblock();
+    test_page();
     return 0;
 }
index 608fbc010da0bc909c71bb28cdc9ecbdcb7f6962..552536e47f3a6b1af28b4361644ec366663e73c8 100644 (file)
@@ -125,13 +125,13 @@ static int test_read(void * vfs_data, int which_file, uint8_t * data,
                                 which_file, data, offset, length);
 }
 
-static int test_lock(void * vfs_data, int which_lock, int lock_mode,
+static int test_lock(void * vfs_data, int which_file, int which_lock, int lock_mode,
                       bool wait) {
     struct test_data * td = (struct test_data *)vfs_data;
 
     if(td->virtual)
         return COQUET_RET_OK;
-    return (td->vfs_funcs.lock)(td->vfs_data,
+    return (td->vfs_funcs.lock)(td->vfs_data, which_file,
                                  which_lock, lock_mode, wait);
 }
 
index a41972c10dd9a99217737f0f13d581b1caa946c5..33bada0a5db98db3435e34c2099c0feee2a77a00 100644 (file)
@@ -293,7 +293,7 @@ static int unix_read(void * vfs_data, int which_file, uint8_t * data,
 }
 
 /* main_fd must be open */
-static int min_size(struct unix_data *pd, off_t offset) {
+static int min_size(struct unix_data *pd, int fd, off_t offset) {
     int r;
     off_t r_off;
     char buf[1] = {0};
@@ -302,13 +302,13 @@ static int min_size(struct unix_data *pd, off_t offset) {
         return COQUET_RET_OK;
     }
 
-    r_off = lseek(pd->main_fd,offset,SEEK_SET);
+    r_off = lseek(fd,offset,SEEK_SET);
     if(r_off == -1) {
         set_error(pd,"seek failed",1);
         return COQUET_RET_VFSERR;
     }
 
-    r = write(pd->main_fd,buf,1);
+    r = write(fd,buf,1);
     if(r == -1) {
         set_error(pd,"write failed",1);
         return COQUET_RET_VFSERR;
@@ -317,20 +317,21 @@ static int min_size(struct unix_data *pd, off_t offset) {
     return COQUET_RET_OK;
 }
 
-#define LOCK_BLOCK 128
-static int unix_lock(void * vfs_data, int which_lock, int lock_mode,
+#define LOCK_BLOCK (SUPER_BYTES/NUM_LOCKS)
+static int unix_lock(void * vfs_data, int which_file, int which_lock, int lock_mode,
                       bool wait) {
     struct unix_data * pd = (struct unix_data *)vfs_data;
-    int r, op;
+    int r, op, *fd;
     struct flock flk;
 
-    if(pd->main_fd==-1) {
+    fd = file_fd(pd,which_file);
+    if(*fd==-1) {
         set_error(pd,"main file closed during locking",0);
         return COQUET_RET_VFSERR;
     }
 
     /* Lock region needs to exist. We can append zeroes.*/
-    r = min_size(pd,SUPER_BYTES+LOCK_BLOCK*NUM_LOCKS);
+    r = min_size(pd,*fd,SUPER_BYTES+LOCK_BLOCK*NUM_LOCKS);
     if(r != COQUET_RET_OK) {
         return r;
     }
@@ -359,7 +360,7 @@ static int unix_lock(void * vfs_data, int which_lock, int lock_mode,
         op = F_OFD_SETLK;
     }
 
-    r = fcntl(pd->main_fd,op,&flk);
+    r = fcntl(*fd,op,&flk);
     if(r == -1) {
         set_error(pd,"flock failed",1);
         return COQUET_RET_VFSERR;
index c9744266a2ddabd5d9c2d7e35d553a1db64a2b70..d8f949c49aaa6c2c235da10a322d6e1e81098d63 100644 (file)
--- a/src/vfs.h
+++ b/src/vfs.h
@@ -30,7 +30,7 @@ typedef struct vfs {
      * purpose. COQUET_FILE_MAIN will be open when called. If wait is true,
      * function will wait, otherwise return COQUET_RET_LOCKED
      */
-    int (*lock)(void * vfs_data, int which_lock, int lock_mode, 
+    int (*lock)(void * vfs_data, int which_file, int which_lock, int lock_mode, 
                 bool wait);
 
     /* Open the given file. which_file is drawn from COQUET_FILE_*.