]> git.tuebingen.mpg.de Git - osl.git/commitdiff
Merge branch 'refs/heads/t/sha3' into master
authorAndre Noll <maan@tuebingen.mpg.de>
Thu, 15 Oct 2020 14:20:54 +0000 (16:20 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Thu, 15 Oct 2020 14:20:54 +0000 (16:20 +0200)
This code was written long ago and was sitting in a development branch
for some years. As such it was part of the pu branch and so has seen
some testing.

There's an easy conflict in fsck.c where one side added a function
parameter and the other renamed some variables.

* refs/heads/t/sha3:
  Version 3 tables.
  Add sha3 implementation, introduce version-2 tables.
  Prepare hash_function() for multiple hash algorithms.
  Store table version in struct osl_table.
  Initialize column name hash *after* table version is known.
  osl_open_table(): Remove pointless directory check.
  Remove sha1.h.
  Remove COMPAT_TABLE_VERSION.

1  2 
Makefile
fsck.c
osl.c
osl_core.h

diff --combined Makefile
index 87c7d29a0c35afa394764d523911a7d9d9c661d7,f787fe57f3d88dc1ff5871f56697150f98a9884e..fd10f436d864a6a34383950ffbb6e1d59e5811d4
+++ b/Makefile
@@@ -1,13 -1,3 +1,13 @@@
 +# Implicit rules are implemented in make as suffix rules. The following rule
 +# empties the suffix list to disable the predefined implicit rules. This
 +# increases performance and avoids hard-to-debug behaviour.
 +.SUFFIXES:
 +MAKEFLAGS += -Rr
 +CC := $(CC)
 +ifeq ($(strip $(CC)),)
 +      CC := cc
 +endif
 +
  # where to install
  PREFIX ?= /usr/local
  libdir := $(PREFIX)/lib
@@@ -15,19 -5,21 +15,19 @@@ includedir := $(PREFIX)/includ
  bindir := $(PREFIX)/bin
  mandir := $(PREFIX)/man/man1
  
- objects := osl.o util.o rbtree.o sha1.o
- fsck_objects := fsck.o osl.o util.o rbtree.o sha1.o oslfsck.lsg.o
+ objects := osl.o util.o rbtree.o sha1.o sha3.o sha256.o
+ fsck_objects := fsck.o osl.o util.o rbtree.o sha1.o sha3.o sha256.o oslfsck.lsg.o
  deps := $(sort $(objects:.o=.d) $(fsck_objects:.o=.d))
  headers := osl.h
  executables := oslfsck
  man_pages := oslfsck.1
  
  INSTALL := install
 -ifeq "$(origin CC)" "default"
 -        CC := cc
 -endif
  MKDIR := mkdir -p
  RM := rm -f
  LN := ln
  LD := ld
 +M4 := m4 -g
  OBJCOPY := objcopy
  
  # libosl's versioning consists of three numbers. Let's call them x, y and z.
@@@ -38,7 -30,7 +38,7 @@@ VERSION := $(x).$(y).$(z
  
  OSL_CPPFLAGS += -DOSL_VERSION='"$(VERSION)"'
  
 -OSL_CFLAGS += -Wno-sign-compare -g -Wunused -Wundef -W
 +OSL_CFLAGS += -g -Wunused -Wundef -W
  OSL_CFLAGS += -Wredundant-decls
  OSL_CFLAGS += -Os
  OSL_CFLAGS += -Wall
@@@ -80,27 -72,15 +80,27 @@@ shared: $(realname
  ifeq ($(findstring clean, $(MAKECMDGOALS)),)
  -include $(deps)
  endif
 -%.o: %.c Makefile errtab.h
 +
 +# The files to generate before attempting to run the compiler. These
 +# are the order-only prerequisites in the rule below.
 +pre_deps := osl.h errtab.h oslfsck.lsg.h
 +
 +# The .d and .o files are both created from a single cc invocation.
 +define CC_CMD
        $(CC) $(OSL_CPPFLAGS) $(CPPFLAGS) \
 -              -c -MMD -MF $(*F).d -MT $@ \
 +              -c -MMD -MF $(*F).d -MT $(*F).o \
                $(OSL_CFLAGS) $(CFLAGS) $<
 +endef
 +%.o: %.c Makefile | $(pre_deps)
 +      $(CC_CMD)
 +%.d: %.c Makefile | $(pre_deps)
 +      $(CC_CMD)
  
  fsck.o: oslfsck.lsg.h
  oslfsck: $(fsck_objects)
        $(CC) -o $@ $(fsck_objects) $(LDFLAGS) -llopsub
  
 +.PRECIOUS: %.lsg.h %.lsg.c
  %.lsg.c: %.suite
        lopsubgen --gen-c < $<
  
  $(realname): $(objects)
        $(CC) $(OSL_LDFLAGS) $(LDFLAGS) -o $@ $(objects)
  
 -$(libname).sym: osl.h.in
 -      sed -Ene '/^int|^const/{s/.*(osl_.*)\(.*/\1/; p;}' $< > $@
 -$(libname).ga: $(objects)
 -      $(LD) -r -o $@ $(objects)
 -lib$(libname).a: $(libname).ga $(libname).sym
 -      $(OBJCOPY) --keep-global-symbols $(libname).sym $(libname).ga $@
 -
 -osl_errors.h: errlist
 -      echo '/** public error codes of the osl library. */' > $@
 -      sed -e 's/\([A-Z_]*\)   .*/     E_OSL_\1/' \
 -              -e '1s/^/enum osl_errors {/1' \
 -              -e '1s/$$/=1/1' \
 -              -e '$$!s/$$/,/g' \
 -              -e '$$s/$$/};/1' $< >> $@
 -
  errtab.h: errlist
        sed -e 's/^\([A-Z_]*\)\s*\(.*\)/OSL_ERROR(E_OSL_\1, \2)/g' $< > $@
  
 -osl.h: osl.h.in osl_errors.h Makefile
 +osl.h: osl.h.m4 errlist Makefile
        echo '#ifndef _OSL_H' > $@
        echo '#define _OSL_H' >> $@
 -      cat osl.h.in osl_errors.h >> $@
 +      $(M4) -DOUTPUT_MODE=C gendoc.m4 $< >> $@
 +      echo '/** public error codes of the osl library. */' >> $@
 +      sed -e 's/\([A-Z_]*\)   .*/     E_OSL_\1/' \
 +              -e '1s/^/enum osl_errors {/1' \
 +              -e '1s/$$/=1/1' \
 +              -e '$$!s/$$/,/g' \
 +              -e '$$s/$$/};/1' errlist >> $@
        echo '#endif /* _OSL_H */' >> $@
  clean:
 -      rm -f *.o $(realname) osl.h osl_errors.h errtab.h \
 -              oslfsck *.a *.ga *.sym *.lsg.* *.d
 +      rm -f *.o $(realname) osl.h errtab.h oslfsck *.lsg.* *.d
  
  distclean: clean
        rm -f web/index.html web/oslfsck.1.html web/osl.png
 -      rm -rf web/doxygen
  
  install-bin: $(executables)
        $(MKDIR) $(bindir)
@@@ -149,26 -140,22 +149,26 @@@ install-lib: $(realname) $(headers
        $(INSTALL) -m 644 $(headers) $(includedir)
  
  install: all install-bin install-man install-lib
 -www: web/index.html web/osl.png web/doxygen/index.html
 +www: web/index.html web/osl.png web/api.html
  
  .PHONY: all shared clean install install-bin install-man install-lib www
  
  web/osl.png: web/osl.pdf Makefile
        convert -scale 200x200 $< $@
  
 -web/index.html: oslfsck.1 web/index.html.in INSTALL README
 -      sed -e '/@README@/,$$d' web/index.html.in > $@
 +web/index.html: oslfsck.1 web/header.html web/index.html.in INSTALL README QUICK_START
 +      cat web/header.html > $@
 +      sed -e '/@README@/,$$d' web/index.html.in >> $@
        markdown < README >> $@
        sed -e '1,/@README@/d' -e '/@INSTALL@/,$$d' web/index.html.in >> $@
        markdown < INSTALL >> $@
 -      sed -e '1,/@INSTALL@/d' -e '/@MAN_PAGE@/,$$d' web/index.html.in >> $@
 +      sed -e '1,/@INSTALL@/d' -e '/@QUICK_START@/,$$d' web/index.html.in >> $@
 +      markdown < QUICK_START >> $@
 +      sed -e '1,/@QUICK_START@/d' -e '/@MAN_PAGE@/,$$d' web/index.html.in >> $@
        groff -m man -Thtml -P -l oslfsck.1 | sed -e '1,/^<body>/d; /^<\/body>/,$$d' >> $@
        sed -e '1,/@MAN_PAGE@/d' web/index.html.in >> $@
  
 -web/doxygen/index.html: $(wildcard *.c *.h) web/Doxyfile web/header.html \
 -              web/footer.html
 -      doxygen web/Doxyfile
 +web/api.html: osl.h.m4 web/header.html web/footer.html
 +      cat web/header.html > $@
 +      $(M4) -DOUTPUT_MODE=HTML gendoc.m4 $< >> $@
 +      cat web/footer.html >> $@
diff --combined fsck.c
index e814df55e866529328608d5acd39c5e2e9c76366,42312d9fb472463963b84b3fb93c7190a05ddc7c..53b4a9b345b04db83cb7a314c37afed2ebfd24ac
--- 1/fsck.c
--- 2/fsck.c
+++ b/fsck.c
@@@ -393,25 -393,24 +393,25 @@@ static int fsck_mark_row_invalid(struc
   */
  static int check_index_ranges(struct osl_table *t)
  {
 -      int i, j, ret;
 +      int ret;
 +      unsigned k, n;
  
        INFO_LOG("checking for range violations in index\n");
        //DEBUG_LOG("%d rows. %d columns\n", t->num_rows, t->desc->num_columns);
        t->num_invalid_rows = 0;
 -      for (i = 0; i < t->num_rows; i++) {
 +      for (n = 0; n < t->num_rows; n++) {
                const struct osl_column_description *cd;
  
 -              if (row_is_invalid(t, i)) {
 +              if (row_is_invalid(t, n)) {
                        t->num_invalid_rows++;
                        continue;
                }
 -              FOR_EACH_MAPPED_COLUMN(j, t, cd) {
 -                      ret = check_range(t, i, j);
 +              FOR_EACH_MAPPED_COLUMN(k, t, cd) {
 +                      ret = check_range(t, n, k);
                        if (ret < 0) {
                                if (ret != -E_FSCK_RANGE_VIOLATION)
                                        goto err;
 -                              ret = fsck_mark_row_invalid(t, i);
 +                              ret = fsck_mark_row_invalid(t, n);
                                if (ret < 0)
                                        goto err;
                                t->num_invalid_rows++;
@@@ -506,30 -505,29 +506,30 @@@ static int prune_invalid_rows_from_inde
  
  static int check_for_invalid_objects(struct osl_table *t, uint32_t **lost_bytes)
  {
 -      int i, j, ret;
 +      int ret;
 +      unsigned k, n;
        const struct osl_column_description *cd;
        uint32_t *loss = fsck_malloc(sizeof(uint32_t) * t->desc->num_columns);
  
        INFO_LOG("looking for mapped objects not contained in index\n");
        /* first count used bytes */
 -      FOR_EACH_MAPPED_COLUMN(i, t, cd) {
 -              loss[i] = t->columns[i].data_map.size;
 -              DEBUG_LOG("column %i data map: %zu bytes\n", i,
 -                      t->columns[i].data_map.size);
 -              for (j = 0; j < t->num_rows; j++) {
 +      FOR_EACH_MAPPED_COLUMN(k, t, cd) {
 +              loss[k] = t->columns[k].data_map.size;
 +              DEBUG_LOG("column %i data map: %zu bytes\n", k,
 +                      t->columns[k].data_map.size);
 +              for (n = 0; n < t->num_rows; n++) {
                        struct osl_object obj;
 -                      ret = get_mapped_object(t, i, j, &obj);
 +                      ret = get_mapped_object(t, k, n, &obj);
                        if (ret < 0)
                                goto err;
 -                      loss[i] -= obj.size;
 +                      loss[k] -= obj.size;
                }
        }
        ret = 0;
 -      FOR_EACH_MAPPED_COLUMN(i, t, cd) {
 -              if (loss[i]) {
 +      FOR_EACH_MAPPED_COLUMN(k, t, cd) {
 +              if (loss[k]) {
                        NOTICE_LOG("column %u contains %u lost bytes\n",
 -                              i, loss[i]);
 +                              k, loss[k]);
                        ret = 1;
                }
        }
@@@ -545,25 -543,24 +545,25 @@@ err
  /* prune_invalid_rows() must be run on the table before calling this */
  static int prune_mapped_column(struct osl_table *t, uint32_t col_num, int fd)
  {
 -      int i, ret;
 +      int ret;
 +      unsigned n;
        uint32_t written = 0;
        struct osl_column *col = t->columns + col_num;
  
        INFO_LOG("pruning col %u\n", col_num);
 -      for (i = 0; i < t->num_rows; i++) {
 +      for (n = 0; n < t->num_rows; n++) {
                struct osl_object obj;
                char *index_entry;
  
 -              DEBUG_LOG("checking row %u/%u\n", i, t->num_rows);
 -              ret = get_mapped_object(t, col_num, i, &obj);
 +              DEBUG_LOG("checking row %u/%u\n", n, t->num_rows);
 +              ret = get_mapped_object(t, col_num, n, &obj);
                if (ret < 0)
                        return ret;
                ret = _write_all(fd, (char *)(obj.data), obj.size);
                if (ret < 0)
                        return ret;
                written += obj.size;
 -              ret = get_row_index(t, i, &index_entry);
 +              ret = get_row_index(t, n, &index_entry);
                if (ret < 0)
                        return ret;
                update_cell_index(index_entry, col, written, obj.size);
@@@ -705,8 -702,7 +705,8 @@@ out
  
  static int check_disk_storage_presence(struct osl_table *t)
  {
 -      int ret, i, j;
 +      int ret;
 +      unsigned k, n;
        struct osl_object obj, hash_obj = {.size = HASH_SIZE};
        char *ds_name;
        const struct osl_column_description *cd;
                return 1;
        hashes = fsck_malloc(t->num_rows * HASH_SIZE);
        INFO_LOG("looking for missing disk storage objects\n");
 -      for (i = 0; i < t->num_rows; i++) {
 -              if (row_is_invalid(t, i))
 +      for (k = 0; k < t->num_rows; k++) {
 +              if (row_is_invalid(t, k))
                        continue;
 -              ret = get_mapped_object(t, dsnc, i, &obj);
 +              ret = get_mapped_object(t, dsnc, k, &obj);
                if (ret < 0)
                        return ret;
-               hash_object(&obj, hashes + k * HASH_SIZE);
 -              hash_object(t, &obj, hashes + i * HASH_SIZE);
 -              hash_obj.data = hashes + i * HASH_SIZE;
++              hash_object(t, &obj, hashes + k * HASH_SIZE);
 +              hash_obj.data = hashes + k * HASH_SIZE;
                osl_add_row(hash_tree_table, &hash_obj);
 -              ds_name = disk_storage_name_of_hash(t, hashes + i * HASH_SIZE);
 -              FOR_EACH_DISK_STORAGE_COLUMN(j, t, cd) {
 -                      ret = check_disk_storage_column(t, i, j, ds_name,
 +              ds_name = disk_storage_name_of_hash(t, hashes + k * HASH_SIZE);
 +              FOR_EACH_DISK_STORAGE_COLUMN(n, t, cd) {
 +                      ret = check_disk_storage_column(t, k, n, ds_name,
                                &missing_objects);
                        if (ret < 0)
                                goto err;
@@@ -876,21 -872,23 +876,23 @@@ static void set_dummy_contents(struct o
  static int fsck_init(struct osl_table_description *desc, struct osl_table **t)
  {
        struct osl_object map;
-       int ret = map_index(desc, &map);
+       int version, ret = map_index(desc, &map);
  
        if (ret < 0)
                goto out;
-       ret = read_table_desc(&map, desc);
+       ret = read_table_desc(&map, desc); /* checks table version */
        if (ret < 0) {
                osl_munmap(map.data, map.size);
                goto out;
        }
+       version = ret;
        set_dummy_contents(desc);
        ret = init_table_structure(desc, t);
        if (ret < 0) {
                osl_munmap(map.data, map.size);
                goto out;
        }
+       (*t)->version = version;
        DEBUG_LOG("unmapping index\n");
        osl_munmap(map.data, map.size);
        if (OPT_GIVEN(FORCE))
@@@ -1043,7 -1041,7 +1045,7 @@@ static int dump_row(struct osl_table *t
        ret = get_mapped_object(t, dsnc, row_num, &obj);
        if (ret < 0)
                return ret;
-       hash_object(&obj, hash);
+       hash_object(t, &obj, hash);
        ds_name = disk_storage_name_of_hash(t, hash);
        FOR_EACH_DISK_STORAGE_COLUMN(i, t, cd) {
                filename = disk_storage_path(t, i, ds_name);
@@@ -1227,8 -1225,7 +1229,8 @@@ static int check_all_tables(const char 
  
  int main(int argc, char **argv)
  {
 -      int i, ret;
 +      int ret;
 +      unsigned n;
        char *errctx = NULL;
        const char *dd;
  
                ret = check_all_tables(dd);
                goto out;
        }
 -      for (i = 0; i < lls_num_inputs(lpr); i++) {
 -              ret = check_table(dd, lls_input(i, lpr));
 +      for (n = 0; n < lls_num_inputs(lpr); n++) {
 +              ret = check_table(dd, lls_input(n, lpr));
                if (ret < 0)
                        break;
        }
diff --combined osl.c
index 17bddeb5db58b821931bd808f8ab0511ff78b3d9,8e19bc403ae79f1ff94ee7e0fafe04af8598e42a..9480325ea8ab3c81977bfd33c892e11f3b524eb9
--- 1/osl.c
--- 2/osl.c
+++ b/osl.c
@@@ -168,7 -168,7 +168,7 @@@ static char *disk_storage_name_of_objec
        const struct osl_object *obj)
  {
        HASH_TYPE hash[HASH_SIZE];
-       hash_object(obj, hash);
+       hash_object(t, obj, hash);
        return disk_storage_name_of_hash(t, hash);
  }
  
@@@ -186,9 -186,10 +186,10 @@@ static int disk_storage_name_of_row(con
        return -E_OSL_NOMEM;
  }
  
- static void column_name_hash(const char *col_name, HASH_TYPE *hash)
+ static void column_name_hash(const struct osl_table *t, const char *col_name,
+               HASH_TYPE *hash)
  {
-       hash_function(col_name, strlen(col_name), hash);
+       hash_function(t->version, col_name, strlen(col_name), hash);
  }
  
  static int init_column_descriptions(struct osl_table *t)
        /* the size of the index header without column descriptions */
        t->index_header_size = IDX_COLUMN_DESCRIPTIONS;
        FOR_EACH_COLUMN(i, t->desc, cd) {
-               struct osl_column *col = t->columns + i;
                if (cd->storage_flags & OSL_RBTREE) {
                        if (!cd->compare_function)
                                return -E_OSL_NO_COMPARE_FUNC;
                if (ret < 0)
                        goto err;
                t->index_header_size += index_column_description_size(cd->name);
-               column_name_hash(cd->name, col->name_hash);
                ret = -E_OSL_DUPLICATE_COL_NAME;
                for (j = i + 1; j < t->desc->num_columns; j++) {
                        const char *name2 = get_column_description(t->desc,
@@@ -342,14 -341,14 +341,14 @@@ err
   * Read the index header, check for the osl magic string and the table version
   * number.  Read all information stored in the index header into \a desc.
   *
-  * \return Standard.
+  * \return The on-disk table version number on success, negative on errors.
   *
   * \sa struct osl_table_description, osl_create_table.
   */
  int read_table_desc(struct osl_object *map, struct osl_table_description *desc)
  {
        char *buf = map->data;
-       uint8_t version, compat_version, create_version;
+       uint8_t table_version;
        uint16_t header_size;
        int ret, i;
        unsigned offset;
                return -E_OSL_SHORT_TABLE;
        if (strncmp(buf + IDX_OSL_MAGIC, OSL_MAGIC, strlen(OSL_MAGIC)))
                return -E_OSL_NO_MAGIC;
-       version = read_u8(buf + IDX_VERSION);
-       /*
-        * The on-disk version consists of two version numbers: the
-        * create_version (low 4 bits) is the CURRENT_TABLE_VERSION version
-        * number of the library that created the table, and compat_version
-        * (high 4 bits) tells us the lowest version of the library that can
-        * still read this table.
-        */
-       create_version = version & 0xf;
-       compat_version = version >> 4;
-       INFO_LOG("create_version: %u, compat_version: %u\n", create_version,
-               compat_version);
-       if (create_version < MIN_TABLE_VERSION /* table too old */
-               || compat_version > CURRENT_TABLE_VERSION) /* libosl too old */
+       table_version = read_u8(buf + IDX_VERSION);
+       INFO_LOG("osl versions (table/min/current): %u/%u/%u\n",
+               table_version, MIN_TABLE_VERSION, CURRENT_TABLE_VERSION);
+       if (table_version < MIN_TABLE_VERSION /* table too old */
+               || table_version > CURRENT_TABLE_VERSION) /* libosl too old */
                return -E_OSL_VERSION_MISMATCH;
        desc->flags = read_u8(buf + IDX_TABLE_FLAGS);
        desc->num_columns = read_u16(buf + IDX_NUM_COLUMNS);
                        offset, header_size);
                goto err;
        }
-       return 1;
+       return table_version;
  err:
        FOR_EACH_COLUMN(i, desc, cd)
                free(cd->name);
@@@ -438,6 -428,7 +428,7 @@@ static int compare_table_descriptions(s
        ret = read_table_desc(&t->index_map, &desc);
        if (ret < 0)
                return ret;
+       t->version = ret;
        ret = -E_OSL_BAD_TABLE_FLAGS;
        if (desc.flags != t->desc->flags)
                goto out;
@@@ -507,8 -498,7 +498,7 @@@ static int create_table_index(struct os
        sprintf(buf + IDX_OSL_MAGIC, "%s", OSL_MAGIC);
        write_u8(buf + IDX_TABLE_FLAGS, t->desc->flags);
        write_u8(buf + IDX_DIRTY_FLAG, 0);
-       write_u8(buf + IDX_VERSION, CURRENT_TABLE_VERSION
-               + (COMPAT_TABLE_VERSION << 4));
+       write_u8(buf + IDX_VERSION, t->version);
        write_u16(buf + IDX_NUM_COLUMNS, t->num_mapped_columns + t->num_disk_storage_columns);
        write_u16(buf + IDX_HEADER_SIZE, t->index_header_size);
        offset = IDX_COLUMN_DESCRIPTIONS;
@@@ -546,7 -536,8 +536,8 @@@ __export int osl_create_table(const str
  
        if (ret < 0)
                return ret;
-       INFO_LOG("creating %s\n", desc->name);
+       t->version = CURRENT_TABLE_VERSION;
+       INFO_LOG("creating version %u table %s\n", t->version, desc->name);
        FOR_EACH_COLUMN(i, t->desc, cd) {
                if (cd->storage_type == OSL_NO_STORAGE)
                        continue;
                        if (ret < 0)
                                goto out;
                }
+               column_name_hash(t, cd->name, t->columns[i].name_hash);
                ret = -E_OSL_NOMEM;
                filename = column_filename(t, i);
                if (!filename)
@@@ -729,13 -721,16 +721,16 @@@ int map_table(struct osl_table *t, enu
        }
        mark_table_dirty(t);
        num_rows = table_num_rows(t);
-       if (!num_rows)
-               return num_rows;
        /* map data files */
-       FOR_EACH_MAPPED_COLUMN(i, t, cd) {
-               ret = map_column(t, i);
-               if (ret < 0)
-                       goto err;
+       FOR_EACH_COLUMN(i, t->desc, cd) {
+               if (cd->storage_type == OSL_NO_STORAGE)
+                       continue;
+               column_name_hash(t, cd->name, t->columns[i].name_hash);
+               if (num_rows > 0 && cd->storage_type == OSL_MAPPED_STORAGE) {
+                       ret = map_column(t, i);
+                       if (ret < 0)
+                               goto err;
+               }
        }
        return num_rows;
  err:  /* unmap what is already mapped */
@@@ -1002,13 -997,12 +997,13 @@@ __export int osl_close_table(struct osl
  int row_is_invalid(struct osl_table *t, uint32_t row_num)
  {
        char *row_index;
 -      int i, ret = get_row_index(t, row_num, &row_index);
 +      int ret = get_row_index(t, row_num, &row_index);
 +      unsigned n;
  
        if (ret < 0)
                return ret;
 -      for (i = 0; i < t->row_index_size; i++) {
 -              if ((unsigned char)row_index[i] != 0xff)
 +      for (n = 0; n < t->row_index_size; n++) {
 +              if ((unsigned char)row_index[n] != 0xff)
                        return 0;
        }
        INFO_LOG("row %d is invalid\n", row_num);
@@@ -1047,18 -1041,17 +1042,18 @@@ int mark_row_invalid(struct osl_table *
   */
  int init_rbtrees(struct osl_table *t)
  {
 -      int i, ret;
 +      int ret;
 +      unsigned n;
        const struct osl_column_description *cd;
  
        /* create rbtrees */
 -      FOR_EACH_RBTREE_COLUMN(i, t, cd)
 -              t->columns[i].rbtree = RB_ROOT;
 +      FOR_EACH_RBTREE_COLUMN(n, t, cd)
 +              t->columns[n].rbtree = RB_ROOT;
        /* add valid rows to rbtrees */
        t->num_invalid_rows = 0;
 -      for (i = 0; i < t->num_rows; i++) {
 +      for (n = 0; n < t->num_rows; n++) {
                struct osl_object *volatile_objs;
 -              ret = row_is_invalid(t, i);
 +              ret = row_is_invalid(t, n);
                if (ret < 0)
                        return ret;
                if (ret) {
                                return -E_OSL_NOMEM;
                } else
                        volatile_objs = NULL;
 -              ret = add_row_to_rbtrees(t, i, volatile_objs, NULL);
 +              ret = add_row_to_rbtrees(t, n, volatile_objs, NULL);
                if (ret < 0)
                        return ret;
        }
  __export int osl_open_table(const struct osl_table_description *table_desc,
                struct osl_table **result)
  {
-       int i, ret;
+       int ret;
        struct osl_table *t;
-       const struct osl_column_description *cd;
  
        NOTICE_LOG("opening table %s\n", table_desc->name);
        ret = init_table_structure(table_desc, &t);
        if (ret < 0)
                return ret;
-       FOR_EACH_DISK_STORAGE_COLUMN(i, t, cd) {
-               struct stat statbuf;
-               char *dirname = column_filename(t, i);
-               ret = -E_OSL_NOMEM;
-               if (!dirname)
-                       goto err;
-               /* check if directory exists */
-               ret = osl_stat(dirname, &statbuf);
-               free(dirname);
-               if (ret < 0)
-                       goto err;
-               ret = -E_OSL_NOTDIR;
-               if (!S_ISDIR(statbuf.st_mode))
-                       goto err;
-       }
        ret = map_table(t, MAP_TBL_FL_VERIFY_INDEX);
        if (ret < 0)
                goto err;
diff --combined osl_core.h
index bdc584b9215c3708a8807970cceac881eedb05bf,9c86e0893c7e14d8c6af39b5136340b89b83f20b..e98c33538bfff043b2ae94145e9dee2b836f28bc
@@@ -38,6 -38,13 +38,13 @@@ struct osl_column 
  struct osl_table {
        /** Pointer to the table description */
        const struct osl_table_description *desc;
+       /**
+        * The CURRENT_TABLE_VERSION value of the library which created the
+        * table. This value is stored in the index header at table creation
+        * time. When the table is opened, the field is initialized from the
+        * on-disk value.
+        */
+       uint8_t version;
        /** The size of the index header of this table. */
        uint16_t index_header_size;
        /** Contains the mapping of the table's index file */
@@@ -194,14 -201,7 +201,7 @@@ _static_inline_ size_t index_column_des
   * The version used by this instance of the library. Written to the index of
   * newly created tables.
   */
- #define CURRENT_TABLE_VERSION 1
- /*
-  * The lowest library version that is able to use tables of version
-  * CURRENT_TABLE_VERSION. Also written to the index of new tables. If
-  * compat_version(table) > current_version(lib) the table can not be opened.
-  */
- #define COMPAT_TABLE_VERSION 0
+ #define CURRENT_TABLE_VERSION 3
  
  /*
   * The lowest table version this library understands. On open, if
@@@ -363,8 -363,8 +363,8 @@@ _static_inline_ char *disk_storage_path
   * \sa FOR_EACH_COLUMN_OF_TYPE, FOR_EACH_MAPPED_COLUMN, FOR_EACH_RBTREE_COLUMN,
   * FOR_EACH_DISK_STORAGE_COLUMN, FOR_EACH_VOLATILE_COLUMN, osl_storage_type.
   */
 -_static_inline_ int next_column_of_type(enum osl_storage_type type, int col_num,
 -              const struct osl_table *t,
 +_static_inline_ unsigned next_column_of_type(enum osl_storage_type type,
 +              unsigned col_num, const struct osl_table *t,
                const struct osl_column_description **cd)
  {
        *cd = NULL;
@@@ -456,12 -456,14 +456,14 @@@ _static_inline_ struct osl_row *get_row
  /**
   * Compute a cryptographic hash of an osl object.
   *
+  * \param t Determines the hash function to use.
   * \param obj the Object to compute the hash value from.
   * \param hash Result is returned here.
   */
- _static_inline_ void hash_object(const struct osl_object *obj, HASH_TYPE *hash)
+ _static_inline_ void hash_object(const struct osl_table *t,
+               const struct osl_object *obj, HASH_TYPE *hash)
  {
-       hash_function(obj->data, obj->size, hash);
+       hash_function(t->version, obj->data, obj->size, hash);
  }
  
  /**