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; }
/** * 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_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; }
/** * 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 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_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; }
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; }
/** * 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; }
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; }
/** * 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 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 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; }
/** * 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; }
/** * 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_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; }