X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=osl.c;h=0b14447b296c736ecaed7d831e0801a45c99296f;hp=fa37dea95ce42faec7131e0b371c837790361c3d;hb=32facbd1b7948f146515e53194cfd4f33c54353f;hpb=340eefa8e83c72319de0feda257d49e668b33f22 diff --git a/osl.c b/osl.c index fa37dea9..0b14447b 100644 --- a/osl.c +++ b/osl.c @@ -5,17 +5,19 @@ */ /** \file osl.c Object storage layer functions. */ +#include /* readdir() */ +#include + + #include "para.h" #include "error.h" +#include "fd.h" #include "list.h" #include "osl_core.h" -#include /* readdir() */ -#include - /** * A wrapper for lseek(2). * - * \param fd The filedescriptor whose offset is to be to repositioned. + * \param fd The file descriptor whose offset is to be to repositioned. * \param offset A value-result parameter. * \param whence Usual repositioning directive. * @@ -44,8 +46,8 @@ int para_lseek(int fd, off_t *offset, int whence) * \param buf The buffer to write. * \param size The length of \a buf in bytes. * - * This function writes out the given bufffer and retries if an interrupt - * occured during the write. + * This function writes out the given buffer and retries if an interrupt + * occurred during the write. * * \return On success, the number of bytes written is returned, otherwise, the * function returns \p -E_WRITE. @@ -93,46 +95,6 @@ ssize_t para_write_all(int fd, const void *buf, size_t size) } return 1; } -/** - * Wrapper for the open(2) system call. - * - * \param path The filename. - * \param flags The usual open(2) flags. - * \param mode Specifies the permissions to use. - * - * The mode parameter must be specified when O_CREAT is in the flags, and is ignored - * otherwise. - * - * \return Positive on success, negative on errors. Possible errors: \p - * E_EXIST, \p E_ISDIR, \p E_NOENT, \p E_OSL_PERM. - * - * \sa open(2). - */ -int para_open(const char *path, int flags, mode_t mode) -{ - PARA_DEBUG_LOG("opening %s\n", path); - int ret = open(path, flags, mode); - - if (ret >= 0) - return ret; - switch (errno) { - case EEXIST: - ret = -E_EXIST; - break; - case EISDIR: - ret = -E_ISDIR; - break; - case ENOENT: - ret = -E_NOENT; - break; - case EPERM: - ret = -E_OSL_PERM; - break; - }; - PARA_ERROR_LOG("failed to open %s: %s\n", path, strerror(errno)); - return ret; -} - /** * Open a file, write the given buffer and close the file. * @@ -249,9 +211,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. @@ -259,26 +222,12 @@ out: int for_each_file_in_dir(const char *dirname, int (*func)(const char *, const void *), const void *private_data) { - DIR *dir = NULL; + DIR *dir; struct dirent *entry; - /* - * Opening the current directory (".") and calling fchdir() to return - * is usually faster and more reliable than saving cwd in some buffer - * and calling chdir() afterwards (see man 3 getcwd). - */ - int cwd_fd = open(".", O_RDONLY); - int ret = -1; - -// PARA_DEBUG_LOG("dirname: %s\n", dirname); - if (cwd_fd < 0) - return -E_OSL_GETCWD; - ret = -E_OSL_CHDIR; - if (chdir(dirname) < 0) - goto out; - ret = -E_OSL_OPENDIR; - dir = opendir("."); - if (!dir) - goto out; + int cwd_fd, ret2, ret = para_opendir(dirname, &dir, &cwd_fd); + + if (ret < 0) + return ret == -E_CHDIR_PERM? 1 : ret; /* scan cwd recursively */ while ((entry = readdir(dir))) { mode_t m; @@ -310,29 +259,14 @@ int for_each_file_in_dir(const char *dirname, } ret = 1; out: - if (dir) - closedir(dir); - if (fchdir(cwd_fd) < 0 && ret >= 0) - ret = -E_OSL_CHDIR; + closedir(dir); + ret2 = para_fchdir(cwd_fd); + if (ret2 < 0 && ret >= 0) + ret = ret2; close(cwd_fd); return ret; } -int para_mkdir(const char *path, mode_t mode) -{ - if (!mkdir(path, mode)) - return 1; - if (errno == EEXIST) - return -E_EXIST; - if (errno == ENOSPC) - return -E_NOSPC; - if (errno == ENOTDIR) - return -E_NOTDIR; - if (errno == EPERM) - return E_OSL_PERM; - return -E_MKDIR; -} - static int verify_name(const char *name) { if (!name) @@ -651,7 +585,7 @@ static int compare_table_descriptions(struct osl_table *t) ret = -E_BAD_TABLE_FLAGS; if (desc.flags != t->desc->flags) goto out; - ret = E_BAD_COLUMN_NUM; + ret = -E_BAD_COLUMN_NUM; if (desc.num_columns != t->desc->num_columns) goto out; FOR_EACH_COLUMN(i, t->desc, cd1) { @@ -819,8 +753,7 @@ static void unmap_column(struct osl_table *t, unsigned col_num) * \param t Pointer to a mapped table. * \param flags Options for unmapping. * - * \return Positive on success, negative on errors. Possible errors include: - * E_NOT_MAPPED, E_MUNMAP. + * \return Positive on success, negative on errors. * * \sa map_table(), enum osl_close_flags, para_munmap(). */ @@ -1153,7 +1086,7 @@ void clear_rbtrees(struct osl_table *t) * \param flags Options for what should be cleaned up. * * If osl_open_table() succeeds, the resulting table pointer must later be - * passed to this function in order to flush all changes to the filesystem and + * passed to this function in order to flush all changes to the file system and * to free the resources that were allocated by osl_open_table(). * * \return Positive on success, negative on errors. Possible errors: \p E_BAD_TABLE, @@ -1735,7 +1668,7 @@ static int check_rbtree_col(const struct osl_table *t, unsigned col_num, * Lookup \a obj in \a t and return the row containing \a obj. The column * specified by \a col_num must have an associated rbtree. * - * \return Positive on success, negative on errors. If an error occured, \a + * \return Positive on success, negative on errors. If an error occurred, \a * result is set to \p NULL. Possible errors include: \p E_BAD_TABLE, \p * E_BAD_STORAGE_FLAGS, errors returned by get_mapped_object(), \p * E_RB_KEY_NOT_FOUND. @@ -1765,9 +1698,12 @@ int osl_get_row(const struct osl_table *t, unsigned col_num, static int rbtree_loop(struct osl_column *col, void *private_data, osl_rbtree_loop_func *func) { - struct rb_node *n; + struct rb_node *n, *tmp; - for (n = rb_first(&col->rbtree); n; n = rb_next(n)) { + /* this for-loop is safe against removal of an entry */ + for (n = rb_first(&col->rbtree), tmp = n? rb_next(n) : NULL; + n; + n = tmp, tmp = tmp? rb_next(tmp) : NULL) { struct osl_row *r = get_row_pointer(n, col->rbtree_num); int ret = func(r, private_data); if (ret < 0) @@ -1779,9 +1715,12 @@ static int rbtree_loop(struct osl_column *col, void *private_data, static int rbtree_loop_reverse(struct osl_column *col, void *private_data, osl_rbtree_loop_func *func) { - struct rb_node *n; + struct rb_node *n, *tmp; - for (n = rb_last(&col->rbtree); n; n = rb_prev(n)) { + /* safe against removal of an entry */ + for (n = rb_last(&col->rbtree), tmp = n? rb_prev(n) : NULL; + n; + n = tmp, tmp = tmp? rb_prev(tmp) : NULL) { struct osl_row *r = get_row_pointer(n, col->rbtree_num); int ret = func(r, private_data); if (ret < 0) @@ -1801,9 +1740,9 @@ static int rbtree_loop_reverse(struct osl_column *col, void *private_data, * This function does an in-order walk of the rbtree associated with \a * col_num. It is an error if the \p OSL_RBTREE flag is not set for this * column. For each node in the rbtree, the given function \a func is called - * with two \p void* pointers as arguments: The first argument points to the + * with two pointers as arguments: The first osl_row* argument points to the * row that contains the object corresponding to the rbtree node currently - * traversed, and the \a private_data pointer is passed to \a func as the + * traversed, and the \a private_data pointer is passed verbatim to \a func as the * second argument. The loop terminates either if \a func returns a negative * value, or if all nodes of the tree have been visited. * @@ -1897,7 +1836,7 @@ out: * * This function gets rid of all references to the old object. This includes * removal of the rbtree node in case there is an rbtree associated with \a - * col_num. It then inserts \a obj into the table and the rbtree if neccessary. + * col_num. It then inserts \a obj into the table and the rbtree if necessary. * * If the \p OSL_RBTREE flag is set for \a col_num, you \b MUST call this * function in order to change the contents of an object, even for volatile or