From cbe7492ee0e5a9bced8267d9c7ab2fd997299fda Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 2 Mar 2012 15:30:04 +0100 Subject: Update due to API changes --- rtems/rtems_yaffs.c | 976 +++++++++++++++++++++++----------------------------- 1 file changed, 426 insertions(+), 550 deletions(-) diff --git a/rtems/rtems_yaffs.c b/rtems/rtems_yaffs.c index 4dcf002..a573ae7 100644 --- a/rtems/rtems_yaffs.c +++ b/rtems/rtems_yaffs.c @@ -3,7 +3,7 @@ * * Copyright (C) 2010, 2011 Sebastien Bourdeauducq * Copyright (C) 2011 Stephan Hoffmann - * Copyright (C) 2011 embedded brains GmbH + * Copyright (C) 2011-2012 embedded brains GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,12 @@ #define MAX_SIZE 0x7fffffff +/* RTEMS interface */ + +static const rtems_filesystem_file_handlers_r yaffs_directory_handlers; +static const rtems_filesystem_file_handlers_r yaffs_file_handlers; +static const rtems_filesystem_operations_table yaffs_ops; + /* locking */ static void ylock(struct yaffs_dev *dev) @@ -58,454 +65,295 @@ static void rtems_yaffs_os_unmount(struct yaffs_dev *dev) (*os_context->unmount)(dev, os_context); } -/* Helper functions */ - -static int is_valid_offset(rtems_off64_t offset) +static struct yaffs_obj *ryfs_get_object_by_location( + const rtems_filesystem_location_info_t *loc +) { - return (0 <= offset && offset <= MAX_SIZE); + return loc->node_access; } -static int is_path_divider(YCHAR ch) +static struct yaffs_obj *ryfs_get_object_by_iop( + const rtems_libio_t *iop +) { - const YCHAR *str = YAFFS_PATH_DIVIDERS; - - while(*str){ - if(*str == ch) - return 1; - str++; - } - - return 0; + return iop->pathinfo.node_access; } -static struct yaffs_obj *h_find_object(struct yaffs_dev *dev, struct yaffs_obj *dir, const char *pathname, const char **out_of_fs); - -static struct yaffs_obj *h_follow_link(struct yaffs_obj *obj, const char **out_of_fs) +static struct yaffs_dev *ryfs_get_device_by_mt_entry( + const rtems_filesystem_mount_table_entry_t *mt_entry +) { - if(obj) - obj = yaffs_get_equivalent_obj(obj); + return mt_entry->fs_info; +} - while(obj && obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) { - YCHAR *alias = obj->variant.symlink_variant.alias; +static void ryfs_set_location(rtems_filesystem_location_info_t *loc, struct yaffs_obj *obj) +{ + loc->node_access = obj; - if(is_path_divider(*alias)) - /* Starts with a /, need to scan from root up */ - obj = h_find_object(obj->my_dev, NULL, alias, out_of_fs); - else - /* Relative to here, so use the parent of the symlink as a start */ - obj = h_find_object(obj->my_dev, obj->parent, alias, out_of_fs); - } - return obj; + switch (obj->variant_type) { + case YAFFS_OBJECT_TYPE_FILE: + loc->handlers = &yaffs_file_handlers; + break; + case YAFFS_OBJECT_TYPE_DIRECTORY: + loc->handlers = &yaffs_directory_handlers; + break; + default: + loc->handlers = &rtems_filesystem_handlers_default; + break; + }; } - -static struct yaffs_obj *h_find_object(struct yaffs_dev *dev, struct yaffs_obj *dir, const char *pathname, const char **out_of_fs) +static bool ryfs_eval_is_directory( + rtems_filesystem_eval_path_context_t *ctx, + void *arg +) { - YCHAR str[YAFFS_MAX_NAME_LENGTH+1]; - int i; - char sux[NAME_MAX]; - - /* RTEMS sometimes calls eval_path with pathloc already pointing to the file to look for - * and name being the name of the file. Deal with this case. - * And no, I have no idea either. - */ - if(strchr(pathname, '/') == NULL) { - yaffs_get_obj_name(dir, sux, NAME_MAX); - if(strcmp(sux, pathname) == 0) - return dir; - } - - *out_of_fs = NULL; - - if(!dev->is_mounted) - return NULL; - - if(dir == NULL) - dir = dev->root_dir; - - while(dir) { - /* - * parse off /. - * curve ball: also throw away surplus '/' - * eg. "/ram/x////ff" gets treated the same as "/ram/x/ff" - */ - while(is_path_divider(*pathname)) - pathname++; /* get rid of '/' */ - - i = 0; - str[0] = 0; - - while(*pathname && !is_path_divider(*pathname)) { - if (i < YAFFS_MAX_NAME_LENGTH) { - str[i] = *pathname; - str[i+1] = '\0'; - i++; - } - pathname++; - } + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc(ctx); + struct yaffs_obj *obj = ryfs_get_object_by_location(currentloc); - if(strcmp(str, _Y(".")) == 0) { - /* Do nothing */ - } else if(strcmp(str, _Y("..")) == 0) { - if(dir->parent != NULL) - dir = dir->parent; - else { - while(is_path_divider(*pathname)) - pathname++; /* get rid of '/' */ - *out_of_fs = pathname; - return NULL; - } - } - else { - if(str[0] != 0) { - if(dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) - return NULL; - dir = yaffs_find_by_name(dir, str); - } - dir = h_follow_link(dir, out_of_fs); - } + obj = yaffs_get_equivalent_obj(obj); - if(!*pathname) - /* got to the end of the string */ - return dir; - } - - return NULL; + return obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY; } -/* RTEMS interface */ - -static const rtems_filesystem_file_handlers_r yaffs_directory_handlers; -static const rtems_filesystem_file_handlers_r yaffs_file_handlers; -static const rtems_filesystem_operations_table yaffs_ops; +static const char *ryfs_make_string(char *buf, const char *src, size_t len) +{ + buf [len] = '\0'; -//#define VERBOSE_DEBUG + return memcpy(buf, src, len); +} -static int ycb_eval_path(const char *pathname, size_t pathnamelen, int flags, rtems_filesystem_location_info_t *pathloc) +static struct yaffs_obj *ryfs_search_in_directory( + struct yaffs_obj *dir, + const char *token, + size_t tokenlen +) { - const char *out_of_fs; - struct yaffs_dev *dev; - struct yaffs_obj *obj; + if (rtems_filesystem_is_parent_directory(token, tokenlen)) { + dir = dir->parent; + } else if (!rtems_filesystem_is_current_directory(token, tokenlen)) { + if (tokenlen < YAFFS_MAX_NAME_LENGTH) { + char buf [YAFFS_MAX_NAME_LENGTH + 1]; - dev = pathloc->mt_entry->fs_info; - - /* The RTEMS eval path system is not a good idea. */ - ylock(dev); - obj = h_find_object(dev, pathloc->node_access, pathname, &out_of_fs); - yunlock(dev); - if(obj == NULL) { - /* Really. It is not. */ - int extra; - - if(out_of_fs == NULL) { -#ifdef VERBOSE_DEBUG - printf("newnode: ENOENT (%s)\n", pathname); -#endif - rtems_set_errno_and_return_minus_one(ENOENT); - } -#ifdef VERBOSE_DEBUG - printf("newnode: out of fs (%s -> %s) we@%p callback@%p\n", pathname, out_of_fs, ycb_eval_path, pathloc->mt_entry->mt_point_node.ops->evalpath_h); -#endif - *pathloc = pathloc->mt_entry->mt_point_node; - extra = 0; - while(is_path_divider(*(out_of_fs-1))) { - out_of_fs--; - extra++; + dir = yaffs_find_by_name( + dir, + ryfs_make_string(buf, token, tokenlen) + ); + } else { + dir = NULL; } - return pathloc->ops->evalpath_h(out_of_fs-2, pathnamelen - (out_of_fs - pathname) + 2 + extra, flags, pathloc); - } - pathloc->node_access = obj; - pathloc->ops = &yaffs_ops; - if(obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) - pathloc->handlers = &yaffs_directory_handlers; - else if(obj->variant_type == YAFFS_OBJECT_TYPE_FILE) - pathloc->handlers = &yaffs_file_handlers; - else { - errno = ENOSYS; - return -1; } -#ifdef VERBOSE_DEBUG - printf("newnode: %p (path: %s, flags: %x)\n", pathloc->node_access, pathname, flags); -#endif - return 0; + + return dir; } -static int ycb_eval_path_for_make(const char *path, rtems_filesystem_location_info_t *pathloc, const char **name) +static rtems_filesystem_eval_path_generic_status ryfs_eval_token( + rtems_filesystem_eval_path_context_t *ctx, + void *arg, + const char *token, + size_t tokenlen +) { - char *s; - char *path1, *path2; - int r, i; + rtems_filesystem_eval_path_generic_status status = + RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; + rtems_filesystem_location_info_t *currentloc = + rtems_filesystem_eval_path_get_currentloc(ctx); + struct yaffs_obj *dir = ryfs_get_object_by_location(currentloc); + bool access_ok = rtems_filesystem_eval_path_check_access( + ctx, + RTEMS_FS_PERMS_EXEC, + dir->yst_mode, + (uid_t) dir->yst_uid, + (gid_t) dir->yst_gid + ); - path1 = strdup(path); - if(path1 == NULL) { - errno = ENOMEM; - return -1; - } - i = strlen(path1) - 1; - while((i >= 0) && (path1[i] == '/')) { - path1[i] = '\0'; - i--; - } + if (access_ok) { + struct yaffs_obj *entry = ryfs_search_in_directory(dir, token, tokenlen); - s = strrchr(path1, '/'); - if(s == NULL) { - *name = path; - free(path1); - return ycb_eval_path(".", strlen(path), 0, pathloc); - } + if (entry != NULL) { + bool terminal = !rtems_filesystem_eval_path_has_path(ctx); + int eval_flags = rtems_filesystem_eval_path_get_flags(ctx); + bool follow_hard_link = (eval_flags & RTEMS_FS_FOLLOW_HARD_LINK) != 0; + bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0; + enum yaffs_obj_type type = entry->variant_type; - *name = path + (s - path1) + 1; + rtems_filesystem_eval_path_clear_token(ctx); - path2 = strdup(path); - if(path2 == NULL) { - errno = ENOMEM; - free(path1); - return -1; - } - s = path2 + (s - path1); - *s = 0; - r = ycb_eval_path(path2, strlen(path2), 0, pathloc); - free(path1); - free(path2); - - if(r == 0) { - if(pathloc->handlers != &yaffs_directory_handlers) { - pathloc->ops->freenod_h(pathloc); - errno = EINVAL; - return -1; + if (type == YAFFS_OBJECT_TYPE_HARDLINK && (follow_hard_link || !terminal)) { + entry = yaffs_get_equivalent_obj(entry); + } + + if (type == YAFFS_OBJECT_TYPE_SYMLINK && (follow_sym_link || !terminal)) { + const char *target = entry->variant.symlink_variant.alias; + + rtems_filesystem_eval_path_recursive(ctx, target, strlen(target)); + } else { + ryfs_set_location(currentloc, entry); + + if (!terminal) { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; + } + } + } else { + status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; } } - - return r; + + return status; } -static int ycb_link(rtems_filesystem_location_info_t *to_loc, rtems_filesystem_location_info_t *parent_loc, const char *name) +static const rtems_filesystem_eval_path_generic_config ryfs_eval_config = { + .is_directory = ryfs_eval_is_directory, + .eval_token = ryfs_eval_token +}; + +static void ryfs_eval_path(rtems_filesystem_eval_path_context_t *ctx) { - /* TODO */ - errno = ENOSYS; - return -1; + rtems_filesystem_eval_path_generic(ctx, NULL, &ryfs_eval_config); } -static int ycb_dir_rmnod(rtems_filesystem_location_info_t *parent_loc, rtems_filesystem_location_info_t *pathloc); +/* Helper functions */ -static int ycb_unlink(rtems_filesystem_location_info_t *parent_pathloc, rtems_filesystem_location_info_t *pathloc) +static int is_valid_offset(off_t offset) { - return ycb_dir_rmnod(parent_pathloc, pathloc); + return (0 <= offset && offset <= MAX_SIZE); } -static rtems_filesystem_node_types_t ycb_node_type(rtems_filesystem_location_info_t *pathloc) +static rtems_filesystem_node_types_t ryfs_node_type( + const rtems_filesystem_location_info_t *loc +) { - struct yaffs_obj *obj; - - obj = pathloc->node_access; - switch(obj->variant_type) { + struct yaffs_obj *obj = ryfs_get_object_by_location(loc); + rtems_filesystem_node_types_t type; + + switch (obj->variant_type) { case YAFFS_OBJECT_TYPE_FILE: - return RTEMS_FILESYSTEM_MEMORY_FILE; - case YAFFS_OBJECT_TYPE_SYMLINK: - return RTEMS_FILESYSTEM_SYM_LINK; + type = RTEMS_FILESYSTEM_MEMORY_FILE; + break; case YAFFS_OBJECT_TYPE_DIRECTORY: - return RTEMS_FILESYSTEM_DIRECTORY; + type = RTEMS_FILESYSTEM_DIRECTORY; + break; + case YAFFS_OBJECT_TYPE_SYMLINK: + type = RTEMS_FILESYSTEM_SYM_LINK; + break; case YAFFS_OBJECT_TYPE_HARDLINK: - return RTEMS_FILESYSTEM_HARD_LINK; + type = RTEMS_FILESYSTEM_HARD_LINK; + break; case YAFFS_OBJECT_TYPE_SPECIAL: - return RTEMS_FILESYSTEM_DEVICE; - default: /* YAFFS_OBJECT_TYPE_UNKNOWN */ + type = RTEMS_FILESYSTEM_DEVICE; + break; + default: + type = RTEMS_FILESYSTEM_INVALID_NODE_TYPE; + break; + } + + return type; +} + +static int ryfs_mknod( + const rtems_filesystem_location_info_t *parentloc, + const char *name, + size_t namelen, + mode_t mode, + dev_t dev +) +{ + int rv = 0; + struct yaffs_obj *parent = ryfs_get_object_by_location(parentloc); + struct yaffs_obj *(*create)( + struct yaffs_obj *parent, + const YCHAR *name, + u32 mode, + u32 uid, + u32 gid + ); + + switch (mode & S_IFMT) { + case S_IFREG: + create = yaffs_create_file; + break; + case S_IFDIR: + create = yaffs_create_dir; + break; + default: errno = EINVAL; - return -1; + rv = -1; + break; } -} - -static int ycb_mknod(const char *path, mode_t mode, dev_t the_dev, rtems_filesystem_location_info_t *pathloc) -{ - char *name, *s; - int ret = 0; - - struct yaffs_obj *parent = pathloc->node_access; - struct yaffs_dev *dev = parent->my_dev; - name = strdup(path); - if(name == NULL) { - errno = ENOMEM; - return -1; - } - s = strchr(name, '/'); - if(s != NULL) - *s = '\0'; + if (rv == 0) { + char buf [YAFFS_MAX_NAME_LENGTH + 1]; + struct yaffs_obj *entry = (*create)( + parent, + ryfs_make_string(buf, name, namelen), + mode, + geteuid(), + getegid() + ); - if(parent->my_dev->read_only) { - errno = EROFS; - free(name); - return -1; - } - - ylock(dev); - - if(yaffs_find_by_name(parent, name)) { - errno = EEXIST; - ret = -1; - goto free; - } - - if(S_ISDIR(mode)) { - struct yaffs_obj *dir; - - dir = yaffs_create_dir(parent, name, mode, 0, 0); - if(dir == NULL) { - errno = ENOSPC; /* just assume no space */ - ret = -1; - goto free; - } - } else if(S_ISREG(mode)) { - struct yaffs_obj *file; - - file = yaffs_create_file(parent, name, mode, 0, 0); - if(file == NULL) { - errno = ENOSPC; /* just assume no space */ - ret = -1; - goto free; + if (entry == NULL) { + errno = ENOSPC; + rv = -1; } - } else { - printf("mknod of unsupported type\n"); - errno = ENOSYS; - ret = -1; - goto free; } -free: - yunlock(dev); - free(name); - return ret; -} - -static int ycb_chown(rtems_filesystem_location_info_t *pathloc, uid_t owner, gid_t group) -{ - /* not implemented */ - errno = 0; - return 0; -} -static int ycb_freenod(rtems_filesystem_location_info_t *pathloc) -{ -#ifdef VERBOSE_DEBUG - printf("freenode: %p\n", pathloc->node_access); -#endif - return 0; -} - -static int ycb_mount(rtems_filesystem_mount_table_entry_t *mt_entry) -{ - /* not implemented */ - errno = ENOSYS; - return -1; -} - -static int ycb_unmount(rtems_filesystem_mount_table_entry_t *mt_entry) -{ - /* not implemented */ - errno = ENOSYS; - return -1; -} - -static int ycb_fsunmount(rtems_filesystem_mount_table_entry_t *mt_entry) -{ - struct yaffs_dev *dev = mt_entry->fs_info; - - ylock(dev); - yaffs_flush_whole_cache(dev); - yaffs_deinitialise(dev); - yunlock(dev); - rtems_yaffs_os_unmount(dev); - - return 0; + return rv; } -static int ycb_utime(rtems_filesystem_location_info_t *pathloc, time_t actime, time_t modtime) +static int ryfs_utime( + const rtems_filesystem_location_info_t *loc, + time_t actime, + time_t modtime +) { - struct yaffs_obj *obj; - struct yaffs_dev *dev; + int rv = 0; + struct yaffs_obj *obj = ryfs_get_object_by_location(loc); - obj = pathloc->node_access; - dev = obj->my_dev; - - ylock(dev); obj = yaffs_get_equivalent_obj(obj); - if(obj != NULL) { + if (obj != NULL) { obj->dirty = 1; - obj->yst_atime = obj->yst_ctime = (u32)actime; - obj->yst_mtime = (u32)modtime; + obj->yst_atime = (u32) actime; + obj->yst_mtime = (u32) modtime; + obj->yst_ctime = (u32) time(NULL); + } else { + errno = EIO; + rv = -1; } - yunlock(dev); - return 0; -} -static int ycb_evaluate_link(rtems_filesystem_location_info_t *pathloc, int flags) -{ - /* TODO */ - errno = ENOSYS; - return -1; -} - -static int ycb_symlink(rtems_filesystem_location_info_t *loc, const char *link_name, const char *node_name) -{ - /* TODO */ - errno = ENOSYS; - return -1; -} - -static ssize_t ycb_readlink(rtems_filesystem_location_info_t *loc, char *buf, size_t bufsize) -{ - /* TODO */ - errno = ENOSYS; - return -1; + return rv; } -static int ycb_rename(rtems_filesystem_location_info_t *old_parent_loc, rtems_filesystem_location_info_t *old_loc, rtems_filesystem_location_info_t *new_parent_loc, const char *name) -{ - struct yaffs_obj *obj; - struct yaffs_dev *dev; - int r; - char oldname[NAME_MAX]; - - obj = old_loc->node_access; - dev = obj->my_dev; - - if(obj->my_dev->read_only) { - errno = EROFS; - return -1; - } - - ylock(dev); - yaffs_get_obj_name(obj, oldname, NAME_MAX); - r = yaffs_rename_obj(obj->parent, oldname, new_parent_loc->node_access, name); - if(r == YAFFS_FAIL) { - yunlock(dev); +static int ryfs_rename( + const rtems_filesystem_location_info_t *old_parent_loc, + const rtems_filesystem_location_info_t *old_loc, + const rtems_filesystem_location_info_t *new_parent_loc, + const char *name, + size_t namelen +) +{ + int rv = 0; + struct yaffs_obj *obj = ryfs_get_object_by_location(old_loc); + char old_name_buf [YAFFS_MAX_NAME_LENGTH + 1]; + char new_name_buf [YAFFS_MAX_NAME_LENGTH + 1]; + int yc; + + yaffs_get_obj_name(obj, old_name_buf, sizeof(old_name_buf)); + yc = yaffs_rename_obj( + obj->parent, + old_name_buf, + ryfs_get_object_by_location(new_parent_loc), + ryfs_make_string(new_name_buf, name, namelen) + ); + if (yc != YAFFS_OK) { errno = EIO; - return -1; + rv = -1; } - yunlock(dev); - return 0; -} - -static int ycb_statvfs(rtems_filesystem_location_info_t *loc, struct statvfs *buf) -{ - /* TODO */ - printf("%s\n", __func__); - errno = ENOSYS; - return -1; -} - -static int ycb_dir_open(rtems_libio_t *iop, const char *pathname, uint32_t flag, uint32_t mode) -{ - /* nothing to do */ - return 0; -} -static int ycb_dir_close(rtems_libio_t *iop) -{ - /* nothing to do */ - return 0; + return rv; } -static ssize_t ycb_dir_read(rtems_libio_t *iop, void *buffer, size_t count) +static ssize_t ryfs_dir_read(rtems_libio_t *iop, void *buffer, size_t count) { struct yaffs_obj *obj; struct yaffs_dev *dev; @@ -514,20 +362,20 @@ static ssize_t ycb_dir_read(rtems_libio_t *iop, void *buffer, size_t count) size_t maxcount; struct list_head *next; ssize_t readlen; - + obj = (struct yaffs_obj *)iop->pathinfo.node_access; dev = obj->my_dev; maxcount = count / sizeof(struct dirent); ylock(dev); - + if(iop->offset == 0) { if(list_empty(&obj->variant.dir_variant.children)) iop->data1 = NULL; else iop->data1 = list_entry(obj->variant.dir_variant.children.next, struct yaffs_obj, siblings); } - + i = 0; while((i < maxcount) && (iop->data1 != NULL)) { de[i].d_ino = (long)yaffs_get_equivalent_obj((struct yaffs_obj *)iop->data1)->obj_id; @@ -535,7 +383,7 @@ static ssize_t ycb_dir_read(rtems_libio_t *iop, void *buffer, size_t count) yaffs_get_obj_name((struct yaffs_obj *)iop->data1, de[i].d_name, NAME_MAX); de[i].d_reclen = sizeof(struct dirent); de[i].d_namlen = (unsigned short)strnlen(de[i].d_name, NAME_MAX); - + i++; next = ((struct yaffs_obj *)iop->data1)->siblings.next; if(next == &obj->variant.dir_variant.children) @@ -543,16 +391,16 @@ static ssize_t ycb_dir_read(rtems_libio_t *iop, void *buffer, size_t count) else iop->data1 = list_entry(next, struct yaffs_obj, siblings); } - + readlen = (ssize_t)(i * sizeof(struct dirent)); iop->offset = iop->offset + readlen; yunlock(dev); - + return readlen; } -static rtems_off64_t ycb_dir_lseek(rtems_libio_t *iop, rtems_off64_t length, int whence) +static off_t ryfs_dir_lseek(rtems_libio_t *iop, off_t length, int whence) { /* We support only rewinding */ if (whence == SEEK_SET && length == 0) { @@ -562,130 +410,139 @@ static rtems_off64_t ycb_dir_lseek(rtems_libio_t *iop, rtems_off64_t length, int } } -static int ycb_fstat(rtems_filesystem_location_info_t *loc, struct stat *buf) +static int ryfs_fstat(const rtems_filesystem_location_info_t *loc, struct stat *buf) { - struct yaffs_obj *obj; - struct yaffs_dev *dev; - - obj = (struct yaffs_obj *)loc->node_access; - dev = (struct yaffs_dev *)obj->my_dev; + int rv = 0; + struct yaffs_obj *obj = ryfs_get_object_by_location(loc); + struct yaffs_dev *dev = obj->my_dev; ylock(dev); - - obj = yaffs_get_equivalent_obj(obj); - buf->st_ino = obj->obj_id; - buf->st_mode = obj->yst_mode & ~(unsigned)S_IFMT; /* clear out file type bits */ - - if(obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) - buf->st_mode |= S_IFDIR; - else if(obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) - buf->st_mode |= S_IFLNK; - else if(obj->variant_type == YAFFS_OBJECT_TYPE_FILE) - buf->st_mode |= S_IFREG; - - buf->st_rdev = 0ll; - buf->st_nlink = (nlink_t)yaffs_get_obj_link_count(obj); - buf->st_uid = 0; - buf->st_gid = 0; - buf->st_rdev = obj->yst_rdev; - buf->st_size = yaffs_get_obj_length(obj); - buf->st_blksize = obj->my_dev->data_bytes_per_chunk; - buf->st_blocks = (blkcnt_t)((buf->st_size + buf->st_blksize -1)/buf->st_blksize); - buf->st_atime = (time_t)obj->yst_atime; - buf->st_ctime = (time_t)obj->yst_ctime; - buf->st_mtime = (time_t)obj->yst_mtime; + obj = yaffs_get_equivalent_obj(obj); + if (obj != NULL) { + buf->st_ino = obj->obj_id; + buf->st_mode = obj->yst_mode; + buf->st_nlink = (nlink_t) yaffs_get_obj_link_count(obj); + buf->st_rdev = obj->yst_rdev; + buf->st_size = yaffs_get_obj_length(obj); + buf->st_blksize = obj->my_dev->data_bytes_per_chunk; + buf->st_blocks = (blkcnt_t) + ((buf->st_size + buf->st_blksize - 1) / buf->st_blksize); + buf->st_uid = (uid_t) obj->yst_uid; + buf->st_gid = (gid_t) obj->yst_gid; + buf->st_atime = (time_t) obj->yst_atime; + buf->st_ctime = (time_t) obj->yst_ctime; + buf->st_mtime = (time_t) obj->yst_mtime; + } else { + errno = EIO; + rv = -1; + } yunlock(dev); - - return 0; + + return rv; } -static int ycb_fchmod(rtems_filesystem_location_info_t *loc, mode_t mode) +static int ryfs_fchmod(const rtems_filesystem_location_info_t *loc, mode_t mode) { - struct yaffs_obj *obj; - struct yaffs_dev *dev; - int result; + int rv = 0; + mode_t mode_mask = S_IRWXU | S_IRWXG | S_IRWXO; + + if ((mode & ~mode_mask) == 0) { + struct yaffs_obj *obj = ryfs_get_object_by_location(loc); + int yc; - if(mode & ~(0777u)){ + obj = yaffs_get_equivalent_obj(obj); + if (obj != NULL) { + obj->yst_mode = (obj->yst_mode & ~mode_mask) | mode; + obj->dirty = 1; + yc = yaffs_flush_file(obj, 0, 0); + } else { + yc = YAFFS_FAIL; + } + + if (yc != YAFFS_OK) { + errno = EIO; + rv = -1; + } + } else { errno = EINVAL; - return -1; - } - - obj = loc->node_access; - if(obj->my_dev->read_only) { - errno = EROFS; - return -1; + rv = -1; } - dev = obj->my_dev; + return rv; +} - ylock(dev); +static int ryfs_chown( + const rtems_filesystem_location_info_t *loc, + uid_t owner, + gid_t group +) +{ + int rv = 0; + struct yaffs_obj *obj = ryfs_get_object_by_location(loc); + int yc; obj = yaffs_get_equivalent_obj(obj); - - result = YAFFS_FAIL; - if(obj) { - obj->yst_mode = (obj->yst_mode & ~0777u) | mode; + if (obj != NULL) { + obj->yst_uid = owner; + obj->yst_gid = group; obj->dirty = 1; - result = yaffs_flush_file(obj, 0, 0); + yc = yaffs_flush_file(obj, 0, 0); + } else { + yc = YAFFS_FAIL; } - if(result != YAFFS_OK) { - yunlock(dev); + + if (yc != YAFFS_OK) { errno = EIO; - return -1; + rv = -1; } - yunlock(dev); - return 0; + + return rv; } -static int ycb_fdatasync(rtems_libio_t *iop) +static int ryfs_fsync_or_fdatasync(rtems_libio_t *iop) { - const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo; - struct yaffs_obj *obj = pathinfo->node_access; + int rv = 0; + struct yaffs_obj *obj = ryfs_get_object_by_iop(iop); struct yaffs_dev *dev = obj->my_dev; - int yc = YAFFS_OK; + int yc; ylock(dev); yc = yaffs_flush_file(obj, 0, 1); - if (rtems_filesystem_is_root_location(pathinfo)) { + if (rtems_filesystem_location_is_root(&iop->pathinfo)) { yaffs_flush_whole_cache(dev); } yunlock(dev); - if (yc == YAFFS_OK) { - return 0; - } else { - rtems_set_errno_and_return_minus_one(EIO); + if (yc != YAFFS_OK) { + errno = EIO; + rv = -1; } + + return rv; } -static int ycb_dir_rmnod(rtems_filesystem_location_info_t *parent_loc, rtems_filesystem_location_info_t *pathloc) +static int ryfs_rmnod( + const rtems_filesystem_location_info_t *parentloc, + const rtems_filesystem_location_info_t *loc +) { - struct yaffs_obj *obj; - struct yaffs_dev *dev; - int r; + int rv = 0; + struct yaffs_obj *obj = ryfs_get_object_by_location(loc); + int yc = yaffs_del_obj(obj); - obj = pathloc->node_access; - if(obj->my_dev->read_only) { - errno = EROFS; - return -1; - } - dev = obj->my_dev; - ylock(dev); - r = yaffs_del_obj(obj); - yunlock(dev); - if(r == YAFFS_FAIL) { + if (yc != YAFFS_OK) { errno = ENOTEMPTY; - return -1; + rv = -1; } - return 0; + + return rv; } -static int ycb_file_open(rtems_libio_t *iop, const char *pathname, uint32_t flag, uint32_t mode) +static int ryfs_file_open(rtems_libio_t *iop, const char *pathname, int oflag, mode_t mode) { - const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo; - struct yaffs_obj *obj = pathinfo->node_access; + struct yaffs_obj *obj = ryfs_get_object_by_iop(iop); struct yaffs_dev *dev = obj->my_dev; int length = 0; @@ -700,10 +557,9 @@ static int ycb_file_open(rtems_libio_t *iop, const char *pathname, uint32_t flag return 0; } -static int ycb_file_close(rtems_libio_t *iop) +static int ryfs_file_close(rtems_libio_t *iop) { - const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo; - struct yaffs_obj *obj = pathinfo->node_access; + struct yaffs_obj *obj = ryfs_get_object_by_iop(iop); struct yaffs_dev *dev = obj->my_dev; ylock(dev); @@ -713,19 +569,16 @@ static int ycb_file_close(rtems_libio_t *iop) return 0; } -static ssize_t ycb_file_read(rtems_libio_t *iop, void *buffer, size_t count) +static ssize_t ryfs_file_read(rtems_libio_t *iop, void *buffer, size_t count) { - struct yaffs_obj *obj; - struct yaffs_dev *dev; + struct yaffs_obj *obj = ryfs_get_object_by_iop(iop); + struct yaffs_dev *dev = obj->my_dev; ssize_t nr; int ol; size_t maxread; - obj = iop->pathinfo.node_access; - dev = obj->my_dev; - ylock(dev); - + ol = yaffs_get_obj_length(obj); if(iop->offset >= ol) maxread = 0; @@ -733,11 +586,11 @@ static ssize_t ycb_file_read(rtems_libio_t *iop, void *buffer, size_t count) maxread = (size_t)(ol - (int)iop->offset); if(count > maxread) count = maxread; - + nr = yaffs_file_rd(obj, buffer, iop->offset, (int)count); yunlock(dev); - + if(nr < 0) { errno = ENOSPC; return -1; @@ -745,13 +598,12 @@ static ssize_t ycb_file_read(rtems_libio_t *iop, void *buffer, size_t count) return nr; } -static ssize_t ycb_file_write(rtems_libio_t *iop, const void *buffer, size_t count) +static ssize_t ryfs_file_write(rtems_libio_t *iop, const void *buffer, size_t count) { - const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo; - struct yaffs_obj *obj = pathinfo->node_access; + struct yaffs_obj *obj = ryfs_get_object_by_iop(iop); struct yaffs_dev *dev = obj->my_dev; - rtems_off64_t offset = 0; - rtems_off64_t new_offset = 0; + off_t offset = 0; + off_t new_offset = 0; ssize_t rv = -1; if (count == 0) { @@ -776,7 +628,7 @@ static ssize_t ycb_file_write(rtems_libio_t *iop, const void *buffer, size_t cou return rv; } -static rtems_off64_t ycb_file_lseek(rtems_libio_t *iop, rtems_off64_t offset, int whence) +static off_t ryfs_file_lseek(rtems_libio_t *iop, off_t offset, int whence) { if (is_valid_offset(iop->offset)) { return iop->offset; @@ -785,23 +637,25 @@ static rtems_off64_t ycb_file_lseek(rtems_libio_t *iop, rtems_off64_t offset, in } } -int ycb_file_ftruncate(rtems_libio_t *iop, rtems_off64_t length) +static int ryfs_file_ftruncate(rtems_libio_t *iop, off_t length) { - struct yaffs_obj *obj; - struct yaffs_dev *dev; - int r; + int rv = 0; + struct yaffs_obj *obj = ryfs_get_object_by_iop(iop); + struct yaffs_dev *dev = obj->my_dev; + int yc; - obj = iop->pathinfo.node_access; - dev = obj->my_dev; ylock(dev); - r = yaffs_resize_file(obj, length); + yc = yaffs_resize_file(obj, length); yunlock(dev); - if(r == YAFFS_FAIL) { + + if (yc == YAFFS_OK) { + iop->size = length; + } else { errno = EIO; - return -1; + rv = -1; } - iop->size = length; - return 0; + + return rv; } int rtems_yaffs_mount_handler(rtems_filesystem_mount_table_entry_t *mt_entry, const void *data) @@ -809,7 +663,7 @@ int rtems_yaffs_mount_handler(rtems_filesystem_mount_table_entry_t *mt_entry, co const rtems_yaffs_mount_data *mount_data = data; struct yaffs_dev *dev = mount_data->dev; - if (dev->read_only && (mt_entry->options & RTEMS_FILESYSTEM_READ_WRITE) != 0) { + if (dev->read_only && mt_entry->writeable) { errno = EACCES; return -1; } @@ -821,9 +675,9 @@ int rtems_yaffs_mount_handler(rtems_filesystem_mount_table_entry_t *mt_entry, co return -1; } - mt_entry->mt_fs_root.node_access = dev->root_dir; - mt_entry->mt_fs_root.handlers = &yaffs_directory_handlers; - mt_entry->mt_fs_root.ops = &yaffs_ops; + mt_entry->mt_fs_root->location.node_access = dev->root_dir; + mt_entry->mt_fs_root->location.handlers = &yaffs_directory_handlers; + mt_entry->mt_fs_root->location.ops = &yaffs_ops; mt_entry->fs_info = dev; yaffs_flush_whole_cache(dev); @@ -832,57 +686,79 @@ int rtems_yaffs_mount_handler(rtems_filesystem_mount_table_entry_t *mt_entry, co return 0; } +static void ryfs_fsunmount(rtems_filesystem_mount_table_entry_t *mt_entry) +{ + struct yaffs_dev *dev = ryfs_get_device_by_mt_entry(mt_entry); + + ylock(dev); + yaffs_flush_whole_cache(dev); + yaffs_deinitialise(dev); + yunlock(dev); + rtems_yaffs_os_unmount(dev); +} + +static void ryfs_lock(rtems_filesystem_mount_table_entry_t *mt_entry) +{ + struct yaffs_dev *dev = ryfs_get_device_by_mt_entry(mt_entry); + + ylock(dev); +} + +static void ryfs_unlock(rtems_filesystem_mount_table_entry_t *mt_entry) +{ + struct yaffs_dev *dev = ryfs_get_device_by_mt_entry(mt_entry); + + yunlock(dev); +} + static const rtems_filesystem_file_handlers_r yaffs_directory_handlers = { - .open_h = ycb_dir_open, - .close_h = ycb_dir_close, - .read_h = ycb_dir_read, - .write_h = rtems_filesystem_default_write, /* write */ - .ioctl_h = rtems_filesystem_default_ioctl, /* ioctl */ - .lseek_h = ycb_dir_lseek, - .fstat_h = ycb_fstat, - .fchmod_h = ycb_fchmod, - .ftruncate_h = rtems_filesystem_default_ftruncate, /* ftruncate */ - .fsync_h = ycb_fdatasync, /* fsync */ - .fdatasync_h = ycb_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, /* fcntl */ - .rmnod_h = ycb_dir_rmnod + .open_h = rtems_filesystem_default_open, + .close_h = rtems_filesystem_default_close, + .read_h = ryfs_dir_read, + .write_h = rtems_filesystem_default_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = ryfs_dir_lseek, + .fstat_h = ryfs_fstat, + .ftruncate_h = rtems_filesystem_default_ftruncate_directory, + .fsync_h = ryfs_fsync_or_fdatasync, + .fdatasync_h = ryfs_fsync_or_fdatasync, + .fcntl_h = rtems_filesystem_default_fcntl }; static const rtems_filesystem_file_handlers_r yaffs_file_handlers = { - .open_h = ycb_file_open, - .close_h = ycb_file_close, - .read_h = ycb_file_read, - .write_h = ycb_file_write, - .ioctl_h = rtems_filesystem_default_ioctl, /* ioctl */ - .lseek_h = ycb_file_lseek, - .fstat_h = ycb_fstat, - .fchmod_h = rtems_filesystem_default_fchmod, /* fchmod */ - .ftruncate_h = ycb_file_ftruncate, - .fsync_h = ycb_fdatasync, /* fsync */ - .fdatasync_h = ycb_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, /* fcntl */ - .rmnod_h = rtems_filesystem_default_rmnod /* rmnod */ + .open_h = ryfs_file_open, + .close_h = ryfs_file_close, + .read_h = ryfs_file_read, + .write_h = ryfs_file_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = ryfs_file_lseek, + .fstat_h = ryfs_fstat, + .ftruncate_h = ryfs_file_ftruncate, + .fsync_h = ryfs_fsync_or_fdatasync, + .fdatasync_h = ryfs_fsync_or_fdatasync, + .fcntl_h = rtems_filesystem_default_fcntl }; static const rtems_filesystem_operations_table yaffs_ops = { - .evalpath_h = ycb_eval_path, - .evalformake_h = ycb_eval_path_for_make, - .link_h = ycb_link, - .unlink_h = ycb_unlink, - .node_type_h = ycb_node_type, - .mknod_h = ycb_mknod, - .chown_h = ycb_chown, - .freenod_h = ycb_freenod, - .mount_h = ycb_mount, + .lock_h = ryfs_lock, + .unlock_h = ryfs_unlock, + .eval_path_h = ryfs_eval_path, + .link_h = rtems_filesystem_default_link, + .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal, + .node_type_h = ryfs_node_type, + .mknod_h = ryfs_mknod, + .rmnod_h = ryfs_rmnod, + .fchmod_h = ryfs_fchmod, + .chown_h = ryfs_chown, + .clonenod_h = rtems_filesystem_default_clonenode, + .freenod_h = rtems_filesystem_default_freenode, + .mount_h = rtems_filesystem_default_mount, .fsmount_me_h = rtems_yaffs_mount_handler, - .unmount_h = ycb_unmount, - .fsunmount_me_h = ycb_fsunmount, - .utime_h = ycb_utime, - .eval_link_h = ycb_evaluate_link, - .symlink_h = ycb_symlink, - .readlink_h = ycb_readlink, - .rename_h = ycb_rename, - .statvfs_h = ycb_statvfs + .unmount_h = rtems_filesystem_default_unmount, + .fsunmount_me_h = ryfs_fsunmount, + .utime_h = ryfs_utime, + .symlink_h = rtems_filesystem_default_symlink, + .readlink_h = rtems_filesystem_default_readlink, + .rename_h = ryfs_rename, + .statvfs_h = rtems_filesystem_default_statvfs }; - -/* Yeah, who thought writing filesystem glue code could ever be so complicated? */ -- cgit v1.2.3