summaryrefslogtreecommitdiff
path: root/nuttx/fs/fs_fat32.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/fs/fs_fat32.c')
-rw-r--r--nuttx/fs/fs_fat32.c143
1 files changed, 135 insertions, 8 deletions
diff --git a/nuttx/fs/fs_fat32.c b/nuttx/fs/fs_fat32.c
index 633695fd1..e8677e1be 100644
--- a/nuttx/fs/fs_fat32.c
+++ b/nuttx/fs/fs_fat32.c
@@ -98,6 +98,7 @@ static int fat_mkdir(struct inode *mountpt, const char *relpath,
static int fat_rmdir(struct inode *mountpt, const char *relpath);
static int fat_rename(struct inode *mountpt, const char *oldrelpath,
const char *newrelpath);
+static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf);
/****************************************************************************
* Private Variables
@@ -132,7 +133,8 @@ const struct mountpt_operations fat_operations =
fat_unlink,
fat_mkdir,
fat_rmdir,
- fat_rename
+ fat_rename,
+ fat_stat
};
/****************************************************************************
@@ -1189,7 +1191,7 @@ static int fat_sync(FAR struct file *filp)
DIR_PUTFSTCLUSTLO(direntry, ff->ff_startcluster);
DIR_PUTFSTCLUSTHI(direntry, ff->ff_startcluster >> 16);
- wrttime = fat_gettime();
+ wrttime = fat_systime2fattime();
DIR_PUTWRTTIME(direntry, wrttime & 0xffff);
DIR_PUTWRTDATE(direntry, wrttime >> 16);
@@ -1482,10 +1484,13 @@ static int fat_bind(FAR struct inode *blkdriver, const void *data,
return -ENOMEM;
}
- /* Initialize the allocated mountpt state structure */
+ /* Initialize the allocated mountpt state structure. The filesystem is
+ * responsible for one reference ont the blkdriver inode and does not
+ * have to addref() here (but does have to release in ubind().
+ */
- fs->fs_blkdriver = blkdriver;
- sem_init(&fs->fs_sem, 0, 0);
+ fs->fs_blkdriver = blkdriver; /* Save the block driver reference */
+ sem_init(&fs->fs_sem, 0, 0); /* Initialize the semaphore that controls access */
/* Then get information about the FAT32 filesystem on the devices managed
* by this block driver.
@@ -1539,9 +1544,16 @@ static int fat_unbind(void *handle)
if (fs->fs_blkdriver)
{
struct inode *inode = fs->fs_blkdriver;
- if (inode && inode->u.i_bops && inode->u.i_bops->close)
+ if (inode)
{
- (void)inode->u.i_bops->close(inode);
+ if (inode->u.i_bops && inode->u.i_bops->close)
+ {
+ (void)inode->u.i_bops->close(inode);
+ }
+
+ /* Release our reference to the block driver */
+
+ inode_release(inode);
}
}
@@ -1731,7 +1743,7 @@ static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
direntry[DIR_NAME] = '.';
DIR_PUTATTRIBUTES(direntry, FATATTR_DIRECTORY);
- crtime = fat_gettime();
+ crtime = fat_systime2fattime();
DIR_PUTCRTIME(direntry, crtime & 0xffff);
DIR_PUTWRTTIME(direntry, crtime & 0xffff);
DIR_PUTCRDATE(direntry, crtime >> 16);
@@ -1992,6 +2004,121 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
}
/****************************************************************************
+ * Name: fat_stat
+ *
+ * Description: Return information about a file or directory
+ *
+ ****************************************************************************/
+
+static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf)
+{
+ struct fat_mountpt_s *fs;
+ struct fat_dirinfo_s dirinfo;
+ uint16 date;
+ uint16 date2;
+ uint16 time;
+ ubyte attribute;
+ int ret;
+
+ /* Sanity checks */
+
+ DEBUGASSERT(mountpt && mountpt->i_private);
+
+ /* Get the mountpoint private data from the inode structure */
+
+ fs = mountpt->i_private;
+
+ /* Check if the mount is still healthy */
+
+ fat_semtake(fs);
+ ret = fat_checkmount(fs);
+ if (ret != OK)
+ {
+ goto errout_with_semaphore;
+ }
+
+ /* Find the directory entry corresponding to relpath. */
+
+ ret = fat_finddirentry(fs, &dirinfo, relpath);
+
+ /* If nothing was found, then we fail with EEXIST */
+
+ if (ret < 0)
+ {
+ goto errout_with_semaphore;
+ }
+
+ if (! dirinfo.fd_entry)
+ {
+ ret = -ENOENT;
+ goto errout_with_semaphore;
+ }
+
+ /* Get the FAT attribute and map it so some meaningful mode_t values */
+
+ attribute = DIR_GETATTRIBUTES(dirinfo.fd_entry);
+ if ((attribute & FATATTR_VOLUMEID) != 0)
+ {
+ ret = -ENOENT;
+ goto errout_with_semaphore;
+ }
+
+ /* Set the access permissions. The file/directory is always readable
+ * by everyone but may be writeable by no-one.
+ */
+
+ memset(buf, 0, sizeof(struct stat));
+ buf->st_mode = S_IROTH|S_IRGRP|S_IRUSR;
+ if ((attribute & FATATTR_READONLY) == 0)
+ {
+ buf->st_mode |= S_IWOTH|S_IWGRP|S_IWUSR;
+ }
+
+ /* We will report only types file or directory */
+
+ if ((attribute & FATATTR_DIRECTORY) != 0)
+ {
+ buf->st_mode |= S_IFDIR;
+ }
+ else
+ {
+ buf->st_mode |= S_IFREG;
+ }
+
+ /* File/directory size, access block size */
+
+ buf->st_size = DIR_GETFILESIZE(dirinfo.fd_entry);
+ buf->st_blksize = fs->fs_hwsectorsize;
+ buf->st_blocks = SEC_NSECTORS(fs, buf->st_size + SEC_NDXMASK(fs));
+
+ /* Times */
+
+ date = DIR_GETWRTDATE(dirinfo.fd_entry);
+ time = DIR_GETWRTTIME(dirinfo.fd_entry);
+ buf->st_mtime = fat_fattime2systime(time, date);
+
+ date2 = DIR_GETLASTACCDATE(dirinfo.fd_entry);
+ if (date == date2)
+ {
+ buf->st_atime = buf->st_mtime;
+ }
+ else
+ {
+ buf->st_atime = fat_fattime2systime(0, date2);
+ }
+
+ date = DIR_GETCRDATE(dirinfo.fd_entry);
+ time = DIR_GETCRTIME(dirinfo.fd_entry);
+ buf->st_ctime = fat_fattime2systime(time, date);
+
+ ret = OK;
+
+ errout_with_semaphore:
+ fat_semgive(fs);
+ return ret;
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/