static void rtems_rfs_rtems_eval_path (rtems_filesystem_eval_path_context_t *ctx) { rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_get_currentloc (ctx); rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (currentloc); rtems_rfs_inode_handle inode; int rc; rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc == 0) { rtems_filesystem_eval_path_generic ( ctx, &inode, &rtems_rfs_rtems_eval_config ); rc = rtems_rfs_inode_close (fs, &inode); if (rc != 0) { rtems_filesystem_eval_path_error ( ctx, rtems_rfs_rtems_error ("eval_path: closing inode", rc) ); } } else { rtems_filesystem_eval_path_error ( ctx, rtems_rfs_rtems_error ("eval_path: opening inode", rc) ); } }
static int rtems_rfs_rtems_dir_rmnod (rtems_filesystem_location_info_t* parent_pathloc, rtems_filesystem_location_info_t* pathloc) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (pathloc); int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_DIR_RMNOD)) printf ("rtems-rfs: dir-rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n", parent, doff, ino); if (ino == RTEMS_RFS_ROOT_INO) return rtems_rfs_rtems_error ("dir_rmnod: root inode", EBUSY); rtems_rfs_rtems_lock (fs); rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty); if (rc) { rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("dir_rmnod: unlinking", rc); } rtems_rfs_rtems_unlock (fs); return 0; }
static int rtems_rfs_rtems_utime(const rtems_filesystem_location_info_t* pathloc, time_t atime, time_t mtime) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_rfs_inode_handle inode; int rc; rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { return rtems_rfs_rtems_error ("utime: read inode", rc); } rtems_rfs_inode_set_atime (&inode, atime); rtems_rfs_inode_set_mtime (&inode, mtime); rc = rtems_rfs_inode_close (fs, &inode); if (rc) { return rtems_rfs_rtems_error ("utime: closing inode", rc); } return 0; }
static int rtems_rfs_rtems_fchmod (const rtems_filesystem_location_info_t* pathloc, mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_rfs_inode_handle inode; int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FCHMOD)) printf ("rtems-rfs-rtems: fchmod: in: ino:%" PRId32 " mode:%06" PRIomode_t "\n", ino, mode); rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { return rtems_rfs_rtems_error ("fchmod: opening inode", rc); } rtems_rfs_inode_set_mode (&inode, mode); rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { return rtems_rfs_rtems_error ("fchmod: closing inode", rc); } return 0; }
static rtems_filesystem_node_types_t rtems_rfs_rtems_node_type (const rtems_filesystem_location_info_t* pathloc) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_filesystem_node_types_t type; rtems_rfs_inode_handle inode; int rc; rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { return rtems_rfs_rtems_error ("node_type: opening inode", rc); } type = rtems_rfs_rtems_node_type_by_inode (&inode); rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { return rtems_rfs_rtems_error ("node_type: closing inode", rc); } return type; }
/** * This rountine will verify that the node being opened as a directory is in * fact a directory node. If it is then the offset into the directory will be * set to 0 to position to the first directory entry. */ static int rtems_rfs_rtems_dir_open (rtems_libio_t* iop, const char* pathname, int oflag, mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo); rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (iop); rtems_rfs_inode_handle inode; int rc; rtems_rfs_rtems_lock (fs); rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("dir_open: opening inode", rc); } if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode))) { rtems_rfs_inode_close (fs, &inode); rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("dir_open: not dir", ENOTDIR); } iop->offset = 0; rtems_rfs_inode_close (fs, &inode); rtems_rfs_rtems_unlock (fs); return 0; }
/** * This routine processes the read() system call. * * @param iop * @param buffer * @param count * @return int */ static ssize_t rtems_rfs_rtems_file_read (rtems_libio_t* iop, void* buffer, size_t count) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); rtems_rfs_pos pos; uint8_t* data = buffer; ssize_t read = 0; int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_READ)) printf("rtems-rfs: file-read: handle:%p count:%zd\n", file, count); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); pos = iop->offset; if (pos < rtems_rfs_file_size (file)) { while (count) { size_t size; rc = rtems_rfs_file_io_start (file, &size, true); if (rc > 0) { read = rtems_rfs_rtems_error ("file-read: read: io-start", rc); break; } if (size == 0) break; if (size > count) size = count; memcpy (data, rtems_rfs_file_data (file), size); data += size; count -= size; read += size; rc = rtems_rfs_file_io_end (file, size, true); if (rc > 0) { read = rtems_rfs_rtems_error ("file-read: read: io-end", rc); break; } } } if (read >= 0) iop->offset = pos + read; rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return read; }
static int rtems_rfs_rtems_mknod (const rtems_filesystem_location_info_t *parentloc, const char *name, size_t namelen, mode_t mode, dev_t dev) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parentloc); rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parentloc); rtems_rfs_ino ino; rtems_rfs_inode_handle inode; uid_t uid; gid_t gid; int rc; uid = geteuid (); gid = getegid (); rc = rtems_rfs_inode_create (fs, parent, name, namelen, rtems_rfs_rtems_imode (mode), 1, uid, gid, &ino); if (rc > 0) { return rtems_rfs_rtems_error ("mknod: inode create", rc); } rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { return rtems_rfs_rtems_error ("mknod: inode open", rc); } if (S_ISDIR(mode) || S_ISREG(mode)) { } else if (S_ISCHR (mode) || S_ISBLK (mode)) { int major; int minor; rtems_filesystem_split_dev_t (dev, major, minor); rtems_rfs_inode_set_block (&inode, 0, major); rtems_rfs_inode_set_block (&inode, 1, minor); } else { rtems_rfs_inode_close (fs, &inode); return rtems_rfs_rtems_error ("mknod: bad mode", EINVAL); } rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { return rtems_rfs_rtems_error ("mknod: closing inode", rc); } return 0; }
static int rtems_rfs_rtems_fchmod (const rtems_filesystem_location_info_t* pathloc, mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_rfs_inode_handle inode; uint16_t imode; #if defined (RTEMS_POSIX_API) uid_t uid; #endif int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FCHMOD)) printf ("rtems-rfs-rtems: fchmod: in: ino:%" PRId32 " mode:%06" PRIomode_t "\n", ino, mode); rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { return rtems_rfs_rtems_error ("fchmod: opening inode", rc); } imode = rtems_rfs_inode_get_mode (&inode); /* * Verify I am the owner of the node or the super user. */ #if defined (RTEMS_POSIX_API) uid = geteuid(); if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0)) { rtems_rfs_inode_close (fs, &inode); return rtems_rfs_rtems_error ("fchmod: checking uid", EPERM); } #endif imode &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX); imode |= mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX); rtems_rfs_inode_set_mode (&inode, imode); rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { return rtems_rfs_rtems_error ("fchmod: closing inode", rc); } return 0; }
/** * This routine will read the next directory entry based on the directory * offset. The offset should be equal to -n- time the size of an individual * dirent structure. If n is not an integer multiple of the sizeof a dirent * structure, an integer division will be performed to determine directory * entry that will be returned in the buffer. Count should reflect -m- times * the sizeof dirent bytes to be placed in the buffer. If there are not -m- * dirent elements from the current directory position to the end of the * exisiting file, the remaining entries will be placed in the buffer and the * returned value will be equal to -m actual- times the size of a directory * entry. */ static ssize_t rtems_rfs_rtems_dir_read (rtems_libio_t* iop, void* buffer, size_t count) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo); rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (iop); rtems_rfs_inode_handle inode; struct dirent* dirent; ssize_t bytes_transferred; int d; int rc; count = count / sizeof (struct dirent); dirent = buffer; rtems_rfs_rtems_lock (fs); rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("dir_read: read inode", rc); } bytes_transferred = 0; for (d = 0; d < count; d++, dirent++) { size_t size; rc = rtems_rfs_dir_read (fs, &inode, iop->offset, dirent, &size); if (rc == ENOENT) { rc = 0; break; } if (rc > 0) { bytes_transferred = rtems_rfs_rtems_error ("dir_read: dir read", rc); break; } iop->offset += size; bytes_transferred += sizeof (struct dirent); } rtems_rfs_inode_close (fs, &inode); rtems_rfs_rtems_unlock (fs); return bytes_transferred; }
/** * This handler maps an open() operation onto rtems_io_open(). * * @param iop * @param pathname * @param flag * @param mode * @return int */ static int rtems_rfs_rtems_device_open ( rtems_libio_t *iop, const char *pathname, uint32_t flag, uint32_t mode) { rtems_libio_open_close_args_t args; rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo); rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (iop); rtems_rfs_inode_handle inode; int major; int minor; rtems_status_code status; int rc; rtems_rfs_rtems_lock (fs); rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("device_open: opening inode", rc); } major = rtems_rfs_inode_get_block (&inode, 0); minor = rtems_rfs_inode_get_block (&inode, 1); rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("device_open: closing inode", rc); } rtems_rfs_rtems_unlock (fs); iop->data0 = major; iop->data1 = (void*)((intptr_t) minor); args.iop = iop; args.flags = iop->flags; args.mode = mode; status = rtems_io_open (major, minor, (void *) &args); if (status) return rtems_deviceio_errno(status); return 0; }
/** * This routine processes the lseek() system call. * * @param iop * @param offset * @param whence * @return off_t */ static off_t rtems_rfs_rtems_file_lseek (rtems_libio_t* iop, off_t offset, int whence) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); rtems_rfs_pos pos; int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK)) printf("rtems-rfs: file-lseek: handle:%p offset:%" PRIdoff_t "\n", file, offset); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); pos = iop->offset; rc = rtems_rfs_file_seek (file, pos, &pos); if (rc) { rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return rtems_rfs_rtems_error ("file_lseek: lseek", rc); } rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return iop->offset; }
/** * This routine processes the lseek() system call. * * @param iop * @param offset * @param whence * @return off_t */ static off_t rtems_rfs_rtems_file_lseek (rtems_libio_t* iop, off_t offset, int whence) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); off_t old_offset; off_t new_offset; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK)) printf("rtems-rfs: file-lseek: handle:%p offset:%" PRIdoff_t "\n", file, offset); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); old_offset = iop->offset; new_offset = rtems_filesystem_default_lseek_file (iop, offset, whence); if (new_offset != -1) { rtems_rfs_pos pos = iop->offset; int rc = rtems_rfs_file_seek (file, pos, &pos); if (rc) { rtems_rfs_rtems_error ("file_lseek: lseek", rc); iop->offset = old_offset; new_offset = -1; } } rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return new_offset; }
static int rtems_rfs_rtems_chown (const rtems_filesystem_location_info_t *pathloc, uid_t owner, gid_t group) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_rfs_inode_handle inode; #if defined (RTEMS_POSIX_API) uid_t uid; #endif int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_CHOWN)) printf ("rtems-rfs-rtems: chown: in: ino:%" PRId32 " uid:%d gid:%d\n", ino, owner, group); rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { return rtems_rfs_rtems_error ("chown: opening inode", rc); } /* * Verify I am the owner of the node or the super user. */ #if defined (RTEMS_POSIX_API) uid = geteuid(); if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0)) { rtems_rfs_inode_close (fs, &inode); return rtems_rfs_rtems_error ("chown: not able", EPERM); } #endif rtems_rfs_inode_set_uid_gid (&inode, owner, group); rc = rtems_rfs_inode_close (fs, &inode); if (rc) { return rtems_rfs_rtems_error ("chown: closing inode", rc); } return 0; }
/** * Rename the node. */ static int rtems_rfs_rtems_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* new_name, size_t new_name_len) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (old_loc); rtems_rfs_ino old_parent; rtems_rfs_ino new_parent; rtems_rfs_ino ino; uint32_t doff; int rc; old_parent = rtems_rfs_rtems_get_pathloc_ino (old_parent_loc); new_parent = rtems_rfs_rtems_get_pathloc_ino (new_parent_loc); ino = rtems_rfs_rtems_get_pathloc_ino (old_loc); doff = rtems_rfs_rtems_get_pathloc_doff (old_loc); if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RENAME)) printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 "\n", ino, doff, new_parent); /* * Link to the inode before unlinking so the inode is not erased when * unlinked. */ rc = rtems_rfs_link (fs, new_name, new_name_len, new_parent, ino, true); if (rc) { return rtems_rfs_rtems_error ("rename: linking", rc); } /* * Unlink all inodes even directories with the dir option as false because a * directory may not be empty. */ rc = rtems_rfs_unlink (fs, old_parent, ino, doff, rtems_rfs_unlink_dir_allowed); if (rc) { return rtems_rfs_rtems_error ("rename: unlinking", rc); } return 0; }
/** * The following routine does a sync on an inode node. Currently it flushes * everything related to this device. * * @param iop * @return int */ int rtems_rfs_rtems_fdatasync (rtems_libio_t* iop) { int rc; rc = rtems_rfs_buffer_sync (rtems_rfs_rtems_pathloc_dev (&iop->pathinfo)); if (rc) return rtems_rfs_rtems_error ("fdatasync: sync", rc); return 0; }
/** * This handler maps an open() operation onto rtems_io_open(). * * @param iop * @param pathname * @param flag * @param mode * @return int */ static int rtems_rfs_rtems_device_open ( rtems_libio_t *iop, const char *pathname, int oflag, mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo); rtems_rfs_ino ino = rtems_rfs_rtems_get_iop_ino (iop); rtems_rfs_inode_handle inode; rtems_device_major_number major; rtems_device_minor_number minor; int rc; rtems_rfs_rtems_lock (fs); rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc > 0) { rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("device_open: opening inode", rc); } major = rtems_rfs_inode_get_block (&inode, 0); minor = rtems_rfs_inode_get_block (&inode, 1); rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("device_open: closing inode", rc); } rtems_rfs_rtems_unlock (fs); iop->data0 = major; iop->data1 = (void *) (uintptr_t) minor; return rtems_deviceio_open (iop, pathname, oflag, mode, minor, major); }
/** * This routine processes the close() system call. Note that there is nothing * to flush at this point. * * @param iop * @return int */ static int rtems_rfs_rtems_file_close (rtems_libio_t* iop) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); rtems_rfs_file_system* fs = rtems_rfs_file_fs (file); int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_CLOSE)) printf("rtems-rfs: file-close: handle:%p\n", file); rtems_rfs_rtems_lock (fs); rc = rtems_rfs_file_close (fs, file); if (rc > 0) rc = rtems_rfs_rtems_error ("file-close: file close", rc); rtems_rfs_rtems_unlock (fs); return rc; }
/** * This routine will behave in one of three ways based on the state of argument * whence. Based on the state of its value the offset argument will be * interpreted using one of the following methods: * * SEEK_SET - offset is the absolute byte offset from the start of the * logical start of the dirent sequence that represents the * directory * SEEK_CUR - offset is used as the relative byte offset from the current * directory position index held in the iop structure * SEEK_END - N/A --> This will cause an assert. * * @param iop * @param offset * @param whence * return rtems_off64_t */ static rtems_off64_t rtems_rfs_rtems_dir_lseek (rtems_libio_t* iop, rtems_off64_t offset, int whence) { switch (whence) { case SEEK_SET: /* absolute move from the start of the file */ case SEEK_CUR: /* relative move */ break; case SEEK_END: /* Movement past the end of the directory via lseek */ /* is not a permitted operation */ default: return rtems_rfs_rtems_error ("dir_lseek: bad whence", EINVAL); break; } return 0; }
/** * This routine processes the ftruncate() system call. * * @param iop * @param length * @return int */ static int rtems_rfs_rtems_file_ftruncate (rtems_libio_t* iop, off_t length) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_FTRUNC)) printf("rtems-rfs: file-ftrunc: handle:%p length:%" PRIdoff_t "\n", file, length); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); rc = rtems_rfs_file_set_size (file, length); if (rc) rc = rtems_rfs_rtems_error ("file_ftruncate: set size", rc); rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return rc; }
static int rtems_rfs_rtems_symlink (const rtems_filesystem_location_info_t* parent_loc, const char* node_name, size_t node_name_len, const char* target) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc); rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc); int rc; rc = rtems_rfs_symlink (fs, node_name, node_name_len, target, strlen (target), geteuid(), getegid(), parent); if (rc) { return rtems_rfs_rtems_error ("symlink: linking", rc); } return 0; }
static ssize_t rtems_rfs_rtems_readlink (const rtems_filesystem_location_info_t* pathloc, char* buf, size_t bufsize) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); size_t length; int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_READLINK)) printf ("rtems-rfs-rtems: readlink: in: ino:%" PRId32 "\n", ino); rc = rtems_rfs_symlink_read (fs, ino, buf, bufsize, &length); if (rc) { return rtems_rfs_rtems_error ("readlink: reading link", rc); } return (ssize_t) length; }
/** * Routine to remove a node from the RFS file system. * * @param parent_pathloc * @param pathloc * @return int */ int rtems_rfs_rtems_rmnod (const rtems_filesystem_location_info_t* parent_pathloc, const rtems_filesystem_location_info_t* pathloc) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); uint32_t doff = rtems_rfs_rtems_get_pathloc_doff (pathloc); int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RMNOD)) printf ("rtems-rfs: rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n", parent, doff, ino); rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty); if (rc) { return rtems_rfs_rtems_error ("rmnod: unlinking", rc); } return 0; }
static int rtems_rfs_rtems_file_open (rtems_libio_t* iop, const char* pathname, int oflag, mode_t mode) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo); rtems_rfs_ino ino; rtems_rfs_file_handle* file; int flags; int rc; flags = 0; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN)) printf("rtems-rfs: file-open: path:%s ino:%" PRId32 " flags:%04i mode:%04" PRIu32 "\n", pathname, ino, flags, mode); rtems_rfs_rtems_lock (fs); ino = rtems_rfs_rtems_get_iop_ino (iop); rc = rtems_rfs_file_open (fs, ino, flags, &file); if (rc > 0) { rtems_rfs_rtems_unlock (fs); return rtems_rfs_rtems_error ("file-open: open", rc); } if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN)) printf("rtems-rfs: file-open: handle:%p\n", file); iop->size = rtems_rfs_file_size (file); rtems_rfs_rtems_set_iop_file_handle (iop, file); rtems_rfs_rtems_unlock (fs); return 0; }
/** * The following rouine creates a new link node under parent with the name * given in name. The link node is set to point to the node at targetloc. */ static int rtems_rfs_rtems_link (const rtems_filesystem_location_info_t *parentloc, const rtems_filesystem_location_info_t *targetloc, const char *name, size_t namelen) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (targetloc); rtems_rfs_ino target = rtems_rfs_rtems_get_pathloc_ino (targetloc); rtems_rfs_ino parent = rtems_rfs_rtems_get_pathloc_ino (parentloc); int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_LINK)) printf ("rtems-rfs-rtems: link: in: parent:%" PRId32 " target:%" PRId32 "\n", parent, target); rc = rtems_rfs_link (fs, name, namelen, parent, target, false); if (rc) { return rtems_rfs_rtems_error ("link: linking", rc); } return 0; }
static rtems_filesystem_eval_path_generic_status rtems_rfs_rtems_eval_token( rtems_filesystem_eval_path_context_t *ctx, void *arg, const char *token, size_t tokenlen ) { rtems_filesystem_eval_path_generic_status status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; rtems_rfs_inode_handle* inode = arg; bool access_ok = rtems_rfs_rtems_eval_perms (ctx, RTEMS_FS_PERMS_EXEC, inode); if (access_ok) { if (rtems_filesystem_is_current_directory (token, tokenlen)) { rtems_filesystem_eval_path_clear_token (ctx); } else { rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_get_currentloc( ctx ); rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc); rtems_rfs_ino entry_ino; uint32_t entry_doff; int rc = rtems_rfs_dir_lookup_ino ( fs, inode, token, tokenlen, &entry_ino, &entry_doff ); if (rc == 0) { rc = rtems_rfs_inode_close (fs, inode); if (rc == 0) { rc = rtems_rfs_inode_open (fs, entry_ino, inode, true); } if (rc != 0) { /* * This prevents the rtems_rfs_inode_close() from doing something in * rtems_rfs_rtems_eval_path(). */ memset (inode, 0, sizeof(*inode)); } } else { status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; rc = -1; } if (rc == 0) { bool is_sym_link = rtems_rfs_rtems_node_type_by_inode (inode) == RTEMS_FILESYSTEM_SYM_LINK; int eval_flags = rtems_filesystem_eval_path_get_flags (ctx); bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0; bool terminal = !rtems_filesystem_eval_path_has_path (ctx); rtems_filesystem_eval_path_clear_token (ctx); if (is_sym_link && (follow_sym_link || !terminal)) { rtems_rfs_rtems_follow_link (ctx, fs, entry_ino); } else { rc = rtems_rfs_rtems_set_handlers (currentloc, inode) ? 0 : EIO; if (rc == 0) { rtems_rfs_rtems_set_pathloc_ino (currentloc, entry_ino); rtems_rfs_rtems_set_pathloc_doff (currentloc, entry_doff); if (!terminal) { status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; } } else { rtems_filesystem_eval_path_error ( ctx, rtems_rfs_rtems_error ("eval_path: set handlers", rc) ); } } } } } return status; }
/** * This routine processes the write() system call. * * @param iop * @param buffer * @param count * @return ssize_t */ static ssize_t rtems_rfs_rtems_file_write (rtems_libio_t* iop, const void* buffer, size_t count) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); rtems_rfs_pos pos; rtems_rfs_pos file_size; const uint8_t* data = buffer; ssize_t write = 0; int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_WRITE)) printf("rtems-rfs: file-write: handle:%p count:%zd\n", file, count); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); pos = iop->offset; file_size = rtems_rfs_file_size (file); if (pos > file_size) { /* * If the iop position is past the physical end of the file we need to set * the file size to the new length before writing. The * rtems_rfs_file_io_end() will grow the file subsequently. */ rc = rtems_rfs_file_set_size (file, pos); if (rc) { rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return rtems_rfs_rtems_error ("file-write: write extend", rc); } rtems_rfs_file_set_bpos (file, pos); } else if (pos < file_size && rtems_libio_iop_is_append(iop)) { pos = file_size; rc = rtems_rfs_file_seek (file, pos, &pos); if (rc) { rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return rtems_rfs_rtems_error ("file-write: write append seek", rc); } } while (count) { size_t size = count; rc = rtems_rfs_file_io_start (file, &size, false); if (rc) { /* * If we have run out of space and have written some data return that * amount first as the inode will have accounted for it. This means * there was no error and the return code from can be ignored. */ if (!write) write = rtems_rfs_rtems_error ("file-write: write open", rc); break; } if (size > count) size = count; memcpy (rtems_rfs_file_data (file), data, size); data += size; count -= size; write += size; rc = rtems_rfs_file_io_end (file, size, false); if (rc) { write = rtems_rfs_rtems_error ("file-write: write close", rc); break; } } if (write >= 0) iop->offset = pos + write; rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return write; }
int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry, const void* data) { rtems_rfs_rtems_private* rtems; rtems_rfs_file_system* fs; uint32_t flags = 0; uint32_t max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS; const char* options = data; int rc; /* * Parse the options the user specifiies. */ while (options) { printf ("options=%s\n", options); if (strncmp (options, "hold-bitmaps", sizeof ("hold-bitmaps") - 1) == 0) flags |= RTEMS_RFS_FS_BITMAPS_HOLD; else if (strncmp (options, "no-local-cache", sizeof ("no-local-cache") - 1) == 0) flags |= RTEMS_RFS_FS_NO_LOCAL_CACHE; else if (strncmp (options, "max-held-bufs", sizeof ("max-held-bufs") - 1) == 0) { max_held_buffers = strtoul (options + sizeof ("max-held-bufs"), 0, 0); } else return rtems_rfs_rtems_error ("initialise: invalid option", EINVAL); options = strchr (options, ','); if (options) { ++options; if (*options == '\0') options = NULL; } } rtems = malloc (sizeof (rtems_rfs_rtems_private)); if (!rtems) return rtems_rfs_rtems_error ("initialise: local data", ENOMEM); memset (rtems, 0, sizeof (rtems_rfs_rtems_private)); rc = rtems_rfs_mutex_create (&rtems->access); if (rc > 0) { free (rtems); return rtems_rfs_rtems_error ("initialise: cannot create mutex", rc); } rc = rtems_rfs_mutex_lock (&rtems->access); if (rc > 0) { rtems_rfs_mutex_destroy (&rtems->access); free (rtems); return rtems_rfs_rtems_error ("initialise: cannot lock access mutex", rc); } rc = rtems_rfs_fs_open (mt_entry->dev, rtems, flags, max_held_buffers, &fs); if (rc) { free (rtems); return rtems_rfs_rtems_error ("initialise: open", rc); } mt_entry->fs_info = fs; mt_entry->ops = &rtems_rfs_ops; mt_entry->mt_fs_root->location.node_access = (void*) RTEMS_RFS_ROOT_INO; mt_entry->mt_fs_root->location.handlers = &rtems_rfs_rtems_dir_handlers; rtems_rfs_rtems_unlock (fs); return 0; }
int rtems_rfs_rtems_fstat (const rtems_filesystem_location_info_t* pathloc, struct stat* buf) { rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc); rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (pathloc); rtems_rfs_inode_handle inode; rtems_rfs_file_shared* shared; uint16_t mode; int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_STAT)) printf ("rtems-rfs-rtems: stat: in: ino:%" PRId32 "\n", ino); rc = rtems_rfs_inode_open (fs, ino, &inode, true); if (rc) { return rtems_rfs_rtems_error ("stat: opening inode", rc); } mode = rtems_rfs_inode_get_mode (&inode); if (RTEMS_RFS_S_ISCHR (mode) || RTEMS_RFS_S_ISBLK (mode)) { buf->st_rdev = rtems_filesystem_make_dev_t (rtems_rfs_inode_get_block (&inode, 0), rtems_rfs_inode_get_block (&inode, 1)); } buf->st_dev = rtems_rfs_fs_device (fs); buf->st_ino = rtems_rfs_inode_ino (&inode); buf->st_mode = rtems_rfs_rtems_mode (mode); buf->st_nlink = rtems_rfs_inode_get_links (&inode); buf->st_uid = rtems_rfs_inode_get_uid (&inode); buf->st_gid = rtems_rfs_inode_get_gid (&inode); /* * Need to check is the ino is an open file. If so we take the values from * the open file rather than the inode. */ shared = rtems_rfs_file_get_shared (fs, rtems_rfs_inode_ino (&inode)); if (shared) { buf->st_atime = rtems_rfs_file_shared_get_atime (shared); buf->st_mtime = rtems_rfs_file_shared_get_mtime (shared); buf->st_ctime = rtems_rfs_file_shared_get_ctime (shared); buf->st_blocks = rtems_rfs_file_shared_get_block_count (shared); if (S_ISLNK (buf->st_mode)) buf->st_size = rtems_rfs_file_shared_get_block_offset (shared); else buf->st_size = rtems_rfs_file_shared_get_size (fs, shared); } else { buf->st_atime = rtems_rfs_inode_get_atime (&inode); buf->st_mtime = rtems_rfs_inode_get_mtime (&inode); buf->st_ctime = rtems_rfs_inode_get_ctime (&inode); buf->st_blocks = rtems_rfs_inode_get_block_count (&inode); if (S_ISLNK (buf->st_mode)) buf->st_size = rtems_rfs_inode_get_block_offset (&inode); else buf->st_size = rtems_rfs_inode_get_size (fs, &inode); } buf->st_blksize = rtems_rfs_fs_block_size (fs); rc = rtems_rfs_inode_close (fs, &inode); if (rc > 0) { return rtems_rfs_rtems_error ("stat: closing inode", rc); } return 0; }
/** * This routine processes the write() system call. * * @param iop * @param buffer * @param count * @return ssize_t */ static ssize_t rtems_rfs_rtems_file_write (rtems_libio_t* iop, const void* buffer, size_t count) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); rtems_rfs_pos pos; const uint8_t* data = buffer; ssize_t write = 0; int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_WRITE)) printf("rtems-rfs: file-write: handle:%p count:%zd\n", file, count); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); pos = iop->offset; /* * If the iop position is past the physical end of the file we need to set * the file size to the new length before writing. If the position equals the * size of file we are still past the end of the file as positions number * from 0. For a specific position we need a file that has a length of one * more. */ if (pos >= rtems_rfs_file_size (file)) { rc = rtems_rfs_file_set_size (file, pos + 1); if (rc) { rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return rtems_rfs_rtems_error ("file-write: write extend", rc); } } rtems_rfs_file_set_bpos (file, pos); while (count) { size_t size = count; rc = rtems_rfs_file_io_start (file, &size, false); if (rc) { write = rtems_rfs_rtems_error ("file-write: write open", rc); break; } if (size > count) size = count; memcpy (rtems_rfs_file_data (file), data, size); data += size; count -= size; write += size; rc = rtems_rfs_file_io_end (file, size, false); if (rc) { write = rtems_rfs_rtems_error ("file-write: write close", rc); break; } } iop->size = rtems_rfs_file_size (file); rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return write; }