loff_t yaffs_get_file_size(struct yaffs_obj *obj) { YCHAR *alias = NULL; obj = yaffs_get_equivalent_obj(obj); switch (obj->variant_type) { case YAFFS_OBJECT_TYPE_FILE: return obj->variant.file_variant.file_size; case YAFFS_OBJECT_TYPE_SYMLINK: alias = obj->variant.symlink_variant.alias; if (!alias) return 0; return yaffs_strnlen(alias, YAFFS_MAX_ALIAS_LENGTH); default: return 0; } }
static struct yaffs_obj *h_follow_link(struct yaffs_obj *obj, const char **out_of_fs) { if(obj) obj = yaffs_get_equivalent_obj(obj); while(obj && obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) { YCHAR *alias = obj->variant.symlink_variant.alias; 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; }
static ssize_t ycb_dir_read(rtems_libio_t *iop, void *buffer, size_t count) { struct yaffs_obj *obj; struct yaffs_dev *dev; struct dirent *de = (struct dirent *)buffer; size_t i; 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; de[i].d_off = 0; 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) iop->data1 = NULL; /* end of list */ 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 int ycb_utime(rtems_filesystem_location_info_t *pathloc, time_t actime, time_t modtime) { struct yaffs_obj *obj; struct yaffs_dev *dev; obj = pathloc->node_access; dev = obj->my_dev; ylock(dev); obj = yaffs_get_equivalent_obj(obj); if(obj != NULL) { obj->dirty = 1; obj->yst_atime = obj->yst_ctime = (u32)actime; obj->yst_mtime = (u32)modtime; } yunlock(dev); return 0; }
static int ycb_fstat(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; 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; yunlock(dev); return 0; }
static int ycb_fchmod(rtems_filesystem_location_info_t *loc, mode_t mode) { struct yaffs_obj *obj; struct yaffs_dev *dev; int result; if(mode & ~(0777u)){ errno = EINVAL; return -1; } obj = loc->node_access; if(obj->my_dev->read_only) { errno = EROFS; return -1; } dev = obj->my_dev; ylock(dev); obj = yaffs_get_equivalent_obj(obj); result = YAFFS_FAIL; if(obj) { obj->yst_mode = (obj->yst_mode & ~0777u) | mode; obj->dirty = 1; result = yaffs_flush_file(obj, 0, 0); } if(result != YAFFS_OK) { yunlock(dev); errno = EIO; return -1; } yunlock(dev); return 0; }