fade.c: Don't include curses.h.
[paraslash.git] / osl.c
diff --git a/osl.c b/osl.c
index 6e3eeca65db2a07d308f0fd2a30995867b29dbc9..b99f3826d7716d4ee02fc2eeae5b4692a6606924 100644 (file)
--- a/osl.c
+++ b/osl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2008 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -156,54 +156,6 @@ out:
        return ret;
 }
 
-/**
- * Map a file into memory.
- *
- * \param path Name of the regular file to map.
- * \param open_mode Either \p O_RDONLY or \p O_RDWR.
- * \param obj On success, the mapping is returned here.
- *
- * \return Positive on success, negative on errors. Possible errors include: \p
- * E_FSTAT, any errors returned by para_open(), \p E_EMPTY, \p E_MMAP.
- *
- * \sa para_open(), mmap(2).
- */
-int mmap_full_file(const char *path, int open_mode, struct osl_object *obj)
-{
-       int fd, ret, mmap_prot, mmap_flags;
-       struct stat file_status;
-
-       if (open_mode == O_RDONLY) {
-               mmap_prot = PROT_READ;
-               mmap_flags = MAP_PRIVATE;
-       } else {
-               mmap_prot = PROT_READ | PROT_WRITE;
-               mmap_flags = MAP_SHARED;
-       }
-       ret = para_open(path, open_mode, 0);
-       if (ret < 0)
-               return ret;
-       fd = ret;
-       ret = -E_FSTAT;
-       if (fstat(fd, &file_status) < 0)
-               goto out;
-       obj->size = file_status.st_size;
-       ret = -E_EMPTY;
-       PARA_DEBUG_LOG("%s: size %zu\n", path, obj->size);
-       if (!obj->size)
-               goto out;
-       obj->data = mmap(NULL, obj->size, mmap_prot, mmap_flags, fd, 0);
-       if (obj->data == MAP_FAILED) {
-               obj->data = NULL;
-               ret = -E_MMAP;
-               goto out;
-       }
-       ret = 1;
-out:
-       close(fd);
-       return ret;
-}
-
 /**
  * Traverse the given directory recursively.
  *
@@ -211,9 +163,10 @@ out:
  * \param func The function to call for each entry.
  * \param private_data Pointer to an arbitrary data structure.
  *
- * For each regular file  in \a dirname, the supplied function \a func is
+ * For each regular file under \a dirname, the supplied function \a func is
  * called.  The full path of the regular file and the \a private_data pointer
- * are passed to \a func.
+ * are passed to \a func. Directories for which the calling process has no
+ * permissions to change to are silently ignored.
  *
  * \return On success, 1 is returned. Otherwise, this function returns a
  * negative value which indicates the kind of the error.
@@ -226,7 +179,7 @@ int for_each_file_in_dir(const char *dirname,
        int cwd_fd, ret2, ret = para_opendir(dirname, &dir, &cwd_fd);
 
        if (ret < 0)
-               return ret;
+               return ret == -ERRNO_TO_PARA_ERROR(EACCES)? 1 : ret;
        /* scan cwd recursively */
        while ((entry = readdir(dir))) {
                mode_t m;
@@ -365,7 +318,7 @@ static int init_column_descriptions(struct osl_table *t)
        if (ret < 0)
                goto err;
        ret = -E_BAD_DB_DIR;
-       if (!t->desc->dir)
+       if (!t->desc->dir && (t->num_disk_storage_columns || t->num_mapped_columns))
                goto err;
        /* the size of the index header without column descriptions */
        t->index_header_size = IDX_COLUMN_DESCRIPTIONS;
@@ -658,10 +611,7 @@ static int create_table_index(struct osl_table *t)
  *
  * \param desc Pointer to the table description.
  *
- * \return Positive on success, negative on errors. Possible errors include: \p
- * E_BAD_TABLE_DESC, \p E_BAD_DB_DIR, \p E_BAD_NAME, \p E_NO_COMPARE_FUNC, \p
- * E_NO_COLUMN_NAME, \p E_DUPLICATE_COL_NAME, \p E_MKDIR, any errors returned
- * by para_open().
+ * \return Standard.
  */
 int osl_create_table(const struct osl_table_description *desc)
 {
@@ -678,7 +628,7 @@ int osl_create_table(const struct osl_table_description *desc)
                        continue;
                if (!table_dir) {
                        ret = para_mkdir(desc->dir, 0777);
-                       if (ret < 0 && ret != -E_EXIST)
+                       if (ret < 0 && !is_errno(-ret, EEXIST))
                                goto out;
                        table_dir = make_message("%s/%s", desc->dir,
                                desc->name);
@@ -794,7 +744,9 @@ static int map_column(struct osl_table *t, unsigned col_num)
                return ret;
        }
        ret = mmap_full_file(filename, O_RDWR,
-               &t->columns[col_num].data_map);
+               &t->columns[col_num].data_map.data,
+               &t->columns[col_num].data_map.size,
+               NULL);
        free(filename);
        return ret;
 }
@@ -823,7 +775,7 @@ int map_table(struct osl_table *t, enum map_table_flags flags)
        filename = index_filename(t->desc);
        PARA_DEBUG_LOG("mapping table '%s' (index: %s)\n", t->desc->name, filename);
        ret = mmap_full_file(filename, flags & MAP_TBL_FL_MAP_RDONLY?
-               O_RDONLY : O_RDWR, &t->index_map);
+               O_RDONLY : O_RDWR, &t->index_map.data, &t->index_map.size, NULL);
        free(filename);
        if (ret < 0)
                return ret;
@@ -1042,8 +994,14 @@ static void free_volatile_objects(const struct osl_table *t,
        for (n = rb_first(&rb_col->rbtree); n; n = rb_next(n)) {
                struct osl_row *r = get_row_pointer(n, rb_col->rbtree_num);
                if (flags & OSL_FREE_VOLATILE)
-                       for (j = 0; j < t->num_volatile_columns; j++)
-                               free(r->volatile_objects[j].data);
+                       FOR_EACH_VOLATILE_COLUMN(j, t, cd) {
+                               if (cd->storage_flags & OSL_DONT_FREE)
+                                       continue;
+                               free(r->volatile_objects[
+                                       t->columns[j].volatile_num].data);
+                       }
+//                     for (j = 0; j < t->num_volatile_columns; j++)
+//                             free(r->volatile_objects[j].data);
                free(r->volatile_objects);
        }
 }
@@ -1202,10 +1160,7 @@ int init_rbtrees(struct osl_table *t)
  * The table description given by \a desc should coincide with the
  * description used at creation time.
  *
- * \return Positive on success, negative on errors. Possible errors include:
- * errors returned by init_table_structure(), \p E_NOENT, \p E_STAT, \p \p
- * E_NOTDIR, \p E_BAD_TABLE_DESC, \p E_BAD_DB_DIR, \p E_NO_COMPARE_FUNC, \p
- * E_NO_COLUMN_NAME, errors returned by init_rbtrees().
+ * \return Standard.
  */
 int osl_open_table(const struct osl_table_description *table_desc,
                struct osl_table **result)
@@ -1225,13 +1180,10 @@ int osl_open_table(const struct osl_table_description *table_desc,
                ret = stat(dirname, &statbuf);
                free(dirname);
                if (ret < 0) {
-                       if (errno == ENOENT)
-                               ret = -E_NOENT;
-                       else
-                               ret = -E_STAT;
+                       ret = -ERRNO_TO_PARA_ERROR(errno);
                        goto err;
                }
-               ret = -E_NOTDIR;
+               ret = -ERRNO_TO_PARA_ERROR(ENOTDIR);
                if (!S_ISDIR(statbuf.st_mode))
                        goto err;
        }
@@ -1264,7 +1216,7 @@ static int create_disk_storage_object_dir(const struct osl_table *t,
        dirname = disk_storage_dirname(t, col_num, ds_name);
        ret = para_mkdir(dirname, 0777);
        free(dirname);
-       if (ret < 0 && ret != -E_EXIST)
+       if (ret < 0 && !is_errno(-ret, EEXIST))
                return ret;
        return 1;
 }
@@ -1357,15 +1309,11 @@ static int delete_disk_storage_file(const struct osl_table *t, unsigned col_num,
                const char *ds_name)
 {
        char *dirname, *filename = disk_storage_path(t, col_num, ds_name);
-       int ret = unlink(filename);
+       int ret = unlink(filename), err = errno;
 
-       PARA_DEBUG_LOG("deleted %s\n", filename);
        free(filename);
-       if (ret < 0) {
-               if (errno == ENOENT)
-                       return -E_NOENT;
-               return -E_UNLINK;
-       }
+       if (ret < 0)
+               return -ERRNO_TO_PARA_ERROR(err);
        if (!(t->desc->flags & OSL_LARGE_TABLE))
                return 1;
        dirname = disk_storage_dirname(t, col_num, ds_name);
@@ -1627,7 +1575,7 @@ int osl_del_row(struct osl_table *t, struct osl_row *row)
                        mark_mapped_object_invalid(t, r->num, i);
                        continue;
                }
-               if (st == OSL_NO_STORAGE)
+               if (st == OSL_NO_STORAGE && !(cd->storage_flags & OSL_DONT_FREE))
                        free(r->volatile_objects[col->volatile_num].data);
        }
        if (t->num_mapped_columns) {
@@ -1842,9 +1790,7 @@ out:
  * mapped columns of constant size (which may be updated directly if \p
  * OSL_RBTREE is not set).  Otherwise the rbtree might become corrupted.
  *
- * \return Positive on success, negative on errors. Possible errors include: \p
- * E_BAD_TABLE, \p E_RB_KEY_EXISTS, \p E_BAD_SIZE, \p E_NOENT, \p E_UNLINK,
- * errors returned by para_write_file(), \p E_MKDIR.
+ * \return Standard
  */
 int osl_update_object(struct osl_table *t, const struct osl_row *r,
                unsigned col_num, struct osl_object *obj)
@@ -1876,7 +1822,7 @@ int osl_update_object(struct osl_table *t, const struct osl_row *r,
                if (ret < 0)
                        return ret;
                ret = delete_disk_storage_file(t, col_num, ds_name);
-               if (ret < 0 && ret != -E_NOENT) {
+               if (ret < 0 && !is_errno(-ret, ENOENT)) {
                        free(ds_name);
                        return ret;
                }
@@ -1966,7 +1912,7 @@ int osl_open_disk_object(const struct osl_table *t, const struct osl_row *r,
        filename = disk_storage_path(t, col_num, ds_name);
        free(ds_name);
        PARA_DEBUG_LOG("filename: %s\n", filename);
-       ret = mmap_full_file(filename, O_RDONLY, obj);
+       ret = mmap_full_file(filename, O_RDONLY, &obj->data, &obj->size, NULL);
        free(filename);
        return ret;
 }
@@ -2013,7 +1959,7 @@ int osl_get_num_rows(const struct osl_table *t, unsigned *num_rows)
  * \param rank Result pointer.
  *
  * The rank is, by definition, the position of the row in the linear order
- * determined by an inorder tree walk of the rbtree associated with column
+ * determined by an in-order tree walk of the rbtree associated with column
  * number \a col_num of \a table.
  *
  * \return Positive on success, negative on errors.
@@ -2067,8 +2013,17 @@ int osl_get_nth_row(const struct osl_table *t, unsigned col_num,
 {
        struct osl_column *col;
        struct rb_node *node;
-       int ret = check_rbtree_col(t, col_num, &col);
+       unsigned num_rows;
+       int ret;
 
+       if (n == 0)
+               return -E_RB_KEY_NOT_FOUND;
+       ret = osl_get_num_rows(t, &num_rows);
+       if (ret < 0)
+               return ret;
+       if (n > num_rows)
+               return -E_RB_KEY_NOT_FOUND;
+       ret = check_rbtree_col(t, col_num, &col);
        if (ret < 0)
                return ret;
        node = rb_nth(col->rbtree.rb_node, n);