summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-27 18:08:18 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-27 18:08:18 +0000
commit9f53bc85a64da31a21ede71a112f2f6c0486417b (patch)
tree5a9efc0762dca5d39b1f748bb516e19d38fb178a
parent9f5af96aa10a6bca769370503e19b4651b81c0a9 (diff)
downloadnuttx-9f53bc85a64da31a21ede71a112f2f6c0486417b.tar.gz
nuttx-9f53bc85a64da31a21ede71a112f2f6c0486417b.tar.bz2
nuttx-9f53bc85a64da31a21ede71a112f2f6c0486417b.zip
Add stat()
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@257 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/Documentation/NuttX.html4
-rw-r--r--nuttx/TODO2
-rw-r--r--nuttx/arch/sim/src/up_exit.c1
-rw-r--r--nuttx/examples/mount/mount_main.c111
-rw-r--r--nuttx/fs/Makefile2
-rw-r--r--nuttx/fs/fs_closedir.c32
-rw-r--r--nuttx/fs/fs_fat32.c143
-rw-r--r--nuttx/fs/fs_fat32.h14
-rw-r--r--nuttx/fs/fs_fat32util.c33
-rw-r--r--nuttx/fs/fs_mount.c9
-rw-r--r--nuttx/fs/fs_stat.c208
-rw-r--r--nuttx/include/fcntl.h32
-rw-r--r--nuttx/include/nuttx/fs.h1
-rw-r--r--nuttx/include/stdio.h25
-rw-r--r--nuttx/include/sys/stat.h71
-rw-r--r--nuttx/include/sys/types.h35
17 files changed, 612 insertions, 113 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 4eefb2b56..4725a971f 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -150,5 +150,7 @@
0.2.7 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Added stat() to fs layer
+ * Added stat() supported to FAT
* Started m68322
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index 31fca173a..7f2d686b4 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -296,6 +296,8 @@
This port is complete but not stable with timer interrupts enabled.
There seems to be some issue when the stack pointer enters into the indirect IRAM
address space during interrupt handling.
+ This architecture has not been built in some time will likely have some compilation
+ problems because of SDCC compiler differences.
</p>
</td>
</tr>
@@ -582,6 +584,8 @@ Other memory:
0.2.7 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Added stat() to fs layer
+ * Added stat() supported to FAT
* Started m68322
</pre></ul>
diff --git a/nuttx/TODO b/nuttx/TODO
index fec57450f..4b459930a 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -38,7 +38,7 @@ o Libraries
- sscanf() and lib_vsprintf() do not support floating point values.
o File system
-- Add disk usage stats, stat(), chmod(), truncate().
+- Add statfs(), chmod(), truncate().
- FAT32: long file names
o Console Output
diff --git a/nuttx/arch/sim/src/up_exit.c b/nuttx/arch/sim/src/up_exit.c
index 0f9c4cc56..650403b7e 100644
--- a/nuttx/arch/sim/src/up_exit.c
+++ b/nuttx/arch/sim/src/up_exit.c
@@ -73,7 +73,6 @@
void _exit(int status)
{
_TCB* tcb = (_TCB*)g_readytorun.head;
- irqstate_t flags;
dbg("TCB=%p exitting\n", tcb);
diff --git a/nuttx/examples/mount/mount_main.c b/nuttx/examples/mount/mount_main.c
index a3c75d2ae..184c1fcc0 100644
--- a/nuttx/examples/mount/mount_main.c
+++ b/nuttx/examples/mount/mount_main.c
@@ -83,11 +83,44 @@ static char g_namebuffer[256];
* Private Functions
****************************************************************************/
+static void show_stat(const char *path, struct stat *ps)
+{
+ printf("%s stat:\n", path);
+ printf("\tmode : %08x\n", ps->st_mode);
+ if (S_ISREG(ps->st_mode))
+ {
+ printf("\ttype : File\n");
+ }
+ else if (S_ISDIR(ps->st_mode))
+ {
+ printf("\ttype : Directory\n");
+ }
+ else if (S_ISCHR(ps->st_mode))
+ {
+ printf("\ttype : Character driver\n");
+ }
+ else if (S_ISBLK(ps->st_mode))
+ {
+ printf("\ttype : Block driver\n");
+ }
+ else
+ {
+ printf("\ttype : Unknown\n");
+ }
+
+ printf("\tsize : %d (bytes)\n", ps->st_size);
+ printf("\tblock size : %d (bytes)\n", ps->st_blksize);
+ printf("\tsize : %d (blocks)\n", ps->st_blocks);
+ printf("\taccess time : %d (blocks)\n", ps->st_atime);
+ printf("\tmodify time : %d (blocks)\n", ps->st_mtime);
+ printf("\tchange time : %d (blocks)\n", ps->st_ctime);
+}
+
/****************************************************************************
- * Name: fail_read_open
+ * Name: show_directories
****************************************************************************/
-static void show_directories( const char *path, int indent )
+static void show_directories(const char *path, int indent)
{
DIR *dirp;
struct dirent *direntry;
@@ -410,6 +443,59 @@ static void succeed_rename(const char *oldpath, const char *newpath)
}
/****************************************************************************
+ * Name: fail_stat
+ ****************************************************************************/
+
+static void fail_stat(const char *path, int expectederror)
+{
+ struct stat buf;
+ int ret;
+
+ /* Try stat() against a file or directory. It should fail with expectederror */
+
+ printf("fail_stat: Try stat(%s)\n", path);
+
+ ret = stat(path, &buf);
+ if (ret == 0)
+ {
+ printf("fail_stat: ERROR stat(%s) succeeded\n", path);
+ show_stat(path, &buf);
+ g_nerrors++;
+ }
+ else if (*get_errno_ptr() != expectederror)
+ {
+ printf("fail_stat: ERROR stat(%s) failed with errno=%d (expected %d)\n",
+ path, *get_errno_ptr(), expectederror);
+ g_nerrors++;
+ }
+}
+
+/****************************************************************************
+ * Name: succeed_stat
+ ****************************************************************************/
+
+static void succeed_stat(const char *path)
+{
+ struct stat buf;
+ int ret;
+
+ printf("succeed_stat: Try stat(%s)\n", path);
+
+ ret = stat(path, &buf);
+ if (ret != 0)
+ {
+ printf("succeed_stat: ERROR stat(%s) failed with errno=%d\n",
+ path, *get_errno_ptr());
+ g_nerrors++;
+ }
+ else
+ {
+ printf("succeed_stat: stat(%s) succeeded\n", path);
+ show_stat(path, &buf);
+ }
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -442,12 +528,15 @@ int user_start(int argc, char *argv[])
/* Read a test file that is already on the test file system image */
show_directories("", 0);
+ succeed_stat(g_testfile1);
read_test_file(g_testfile1);
/* Write a test file into a pre-existing directory on the test file system */
+ fail_stat(g_testfile2, ENOENT);
write_test_file(g_testfile2);
show_directories("", 0);
+ succeed_stat(g_testfile2);
/* Read the file that we just wrote */
@@ -468,6 +557,7 @@ int user_start(int argc, char *argv[])
/* Try unlink() against the test file1. It should succeed. */
succeed_unlink(g_testfile1);
+ fail_stat(g_testfile1, ENOENT);
show_directories("", 0);
/* Attempt to open testfile1 should fail with ENOENT */
@@ -486,20 +576,23 @@ int user_start(int argc, char *argv[])
succeed_unlink(g_testfile2);
show_directories("", 0);
+ fail_stat(g_testfile2, ENOENT);
/* Try mkdir() against the test dir1. It should fail with EEXIST. */
fail_mkdir(g_testdir1, EEXIST);
- /* Try rmdir() against the test directory. It should now succeed. */
+ /* Try rmdir() against the test directory. mkdir should now succeed. */
succeed_rmdir(g_testdir1);
show_directories("", 0);
+ fail_stat(g_testdir1, ENOENT);
/* Try mkdir() against the test dir2. It should succeed */
succeed_mkdir(g_testdir2);
show_directories("", 0);
+ succeed_stat(g_testdir2);
/* Try mkdir() against the test dir2. It should fail with EXIST */
@@ -507,8 +600,10 @@ int user_start(int argc, char *argv[])
/* Write a test file into a new directory on the test file system */
+ fail_stat(g_testfile3, ENOENT);
write_test_file(g_testfile3);
show_directories("", 0);
+ succeed_stat(g_testfile3);
/* Read the file that we just wrote */
@@ -516,8 +611,10 @@ int user_start(int argc, char *argv[])
/* Use mkdir() to create test dir3. It should succeed */
+ fail_stat(g_testdir3, ENOENT);
succeed_mkdir(g_testdir3);
show_directories("", 0);
+ succeed_stat(g_testdir3);
/* Try rename() on the root directory. Should fail with EXDEV*/
@@ -529,13 +626,19 @@ int user_start(int argc, char *argv[])
/* Try rename() to a non-existing directory. Should succeed */
+ fail_stat(g_testdir4, ENOENT);
succeed_rename(g_testdir3, g_testdir4);
show_directories("", 0);
+ fail_stat(g_testdir3, ENOENT);
+ succeed_stat(g_testdir4);
/* Try rename() of file. Should work. */
+ fail_stat(g_testfile4, ENOENT);
succeed_rename(g_testfile3, g_testfile4);
show_directories("", 0);
+ fail_stat(g_testfile3, ENOENT);
+ succeed_stat(g_testfile4);
/* Make sure that we can still read the renamed file */
@@ -554,7 +657,7 @@ int user_start(int argc, char *argv[])
printf("user_start: %d errors reported\n", g_nerrors);
}
-
+
fflush(stdout);
return 0;
}
diff --git a/nuttx/fs/Makefile b/nuttx/fs/Makefile
index 4ba32383d..a61d811d8 100644
--- a/nuttx/fs/Makefile
+++ b/nuttx/fs/Makefile
@@ -41,7 +41,7 @@ ASRCS =
AOBJS = $(ASRCS:.S=$(OBJEXT))
CSRCS = fs_open.c fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_dup.c \
- fs_opendir.c fs_closedir.c fs_readdir.c fs_readdirr.c \
+ fs_opendir.c fs_closedir.c fs_stat.c fs_readdir.c fs_readdirr.c \
fs_seekdir.c fs_telldir.c fs_rewinddir.c fs_fsync.c fs_files.c \
fs_inode.c fs_inodefind.c fs_inodereserve.c \
fs_inoderemove.c fs_registerdriver.c fs_unregisterdriver.c \
diff --git a/nuttx/fs/fs_closedir.c b/nuttx/fs/fs_closedir.c
index 6c81ace6d..c99853110 100644
--- a/nuttx/fs/fs_closedir.c
+++ b/nuttx/fs/fs_closedir.c
@@ -76,24 +76,27 @@
int closedir(FAR DIR *dirp)
{
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
-#ifndef CONFIG_DISABLE_MOUNTPOUNT
struct inode *inode;
-#endif
int ret;
if (!idir || !idir->fd_root)
{
- *get_errno_ptr() = EBADF;
- return ERROR;
+ ret = EBADF;
+ goto errout;
}
+ /* This is the 'root' inode of the directory. This means different
+ * things wih different filesystems.
+ */
+
+ inode = idir->fd_root;
+
/* The way that we handle the close operation depends on what kind of root
* inode we have open.
*/
#ifndef CONFIG_DISABLE_MOUNTPOUNT
- inode = idir->fd_root;
- if (INODE_IS_MOUNTPT(inode))
+ if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSUEDONODE(idir->fd_flags))
{
/* The node is a file system mointpoint. Verify that the mountpoint
* supports the closedir() method (not an error if it does not)
@@ -106,8 +109,8 @@ int closedir(FAR DIR *dirp)
ret = inode->u.i_mops->closedir(inode, idir);
if (ret < 0)
{
- *get_errno_ptr() = -ret;
- return ERROR;
+ ret = -ret;
+ goto errout_with_inode;
}
}
}
@@ -126,15 +129,20 @@ int closedir(FAR DIR *dirp)
/* Release our references on the contained 'root' inode */
- if (idir->fd_root)
- {
- inode_release(idir->fd_root);
- }
+ inode_release(idir->fd_root);
/* Then release the container */
free(idir);
return OK;
+
+errout_with_inode:
+ inode_release(inode);
+ free(idir);
+
+errout:
+ *get_errno_ptr() = ret;
+ return ERROR;
}
#endif /* CONFIG_NFILE_DESCRIPTORS */
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
****************************************************************************/
diff --git a/nuttx/fs/fs_fat32.h b/nuttx/fs/fs_fat32.h
index 4bf1edde7..b654e0006 100644
--- a/nuttx/fs/fs_fat32.h
+++ b/nuttx/fs/fs_fat32.h
@@ -43,6 +43,7 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <semaphore.h>
+#include <time.h>
/****************************************************************************
* Definitions
@@ -282,7 +283,7 @@
# define DIR_GETCRTIME(p) fat_getuint16(UBYTE_PTR(p,DIR_CRTIME))
# define DIR_GETCRDATE(p) fat_getuint16(UBYTE_PTR(p,DIR_CRDATE))
-# define DIR_GETLASTACCDATE(p) fat_getuint16(UBYTE_PTR(p,DIR_LASTACCDTE))
+# define DIR_GETLASTACCDATE(p) fat_getuint16(UBYTE_PTR(p,DIR_LASTACCDATE))
# define DIR_GETFSTCLUSTHI(p) fat_getuint16(UBYTE_PTR(p,DIR_FSTCLUSTHI))
# define DIR_GETWRTTIME(p) fat_getuint16(UBYTE_PTR(p,DIR_WRTTIME))
# define DIR_GETWRTDATE(p) fat_getuint16(UBYTE_PTR(p,DIR_WRTDATE))
@@ -320,7 +321,7 @@
# define DIR_PUTCRTIME(p,v) fat_putuint16(UBYTE_PTR(p,DIR_CRTIME),v)
# define DIR_PUTCRDATE(p,v) fat_putuint16(UBYTE_PTR(p,DIR_CRDATE),v)
-# define DIR_PUTLASTACCDATE(p,v) fat_putuint16(UBYTE_PTR(p,DIR_LASTACCDTE),v)
+# define DIR_PUTLASTACCDATE(p,v) fat_putuint16(UBYTE_PTR(p,DIR_LASTACCDATE),v)
# define DIR_PUTFSTCLUSTHI(p,v) fat_putuint16(UBYTE_PTR(p,DIR_FSTCLUSTHI),v)
# define DIR_PUTWRTTIME(p,v) fat_putuint16(UBYTE_PTR(p,DIR_WRTTIME),v)
# define DIR_PUTWRTDATE(p,v) fat_putuint16(UBYTE_PTR(p,DIR_WRTDATE),v)
@@ -366,7 +367,7 @@
# define DIR_GETCRTIME(p) UINT16_VAL(p,DIR_CRTIME)
# define DIR_GETCRDATE(p) UINT16_VAL(p,DIR_CRDATE)
-# define DIR_GETLASTACCDATE(p) UINT16_VAL(p,DIR_LASTACCDTE)
+# define DIR_GETLASTACCDATE(p) UINT16_VAL(p,DIR_LASTACCDATE)
# define DIR_GETFSTCLUSTHI(p) UINT16_VAL(p,DIR_FSTCLUSTHI)
# define DIR_GETWRTTIME(p) UINT16_VAL(p,DIR_WRTTIME)
# define DIR_GETWRTDATE(p) UINT16_VAL(p,DIR_WRTDATE)
@@ -404,7 +405,7 @@
# define DIR_PUTCRTIME(p,v) UINT16_PUT(p,DIR_CRTIME,v)
# define DIR_PUTCRDATE(p,v) UINT16_PUT(p,DIR_CRDATE,v)
-# define DIR_PUTLASTACCDATE(p,v) UINT16_PUT(p,DIR_LASTACCDTE,v)
+# define DIR_PUTLASTACCDATE(p,v) UINT16_PUT(p,DIR_LASTACCDATE,v)
# define DIR_PUTFSTCLUSTHI(p,v) UINT16_PUT(p,DIR_FSTCLUSTHI,v)
# define DIR_PUTWRTTIME(p,v) UINT16_PUT(p,DIR_WRTTIME,v)
# define DIR_PUTWRTDATE(p,v) UINT16_PUT(p,DIR_WRTDATE,v)
@@ -526,7 +527,8 @@ EXTERN void fat_semgive(struct fat_mountpt_s *fs);
/* Get the current time for FAT creation and write times */
-EXTERN uint32 fat_gettime(void);
+EXTERN uint32 fat_systime2fattime(void);
+EXTERN time_t fat_fattime2systime(uint16 time, uint16 date);
/* Handle hardware interactions for mounting */
@@ -551,7 +553,7 @@ EXTERN sint32 fat_extendchain(struct fat_mountpt_s *fs, uint32 cluster);
#define fat_createchain(fs) fat_extendchain(fs, 0)
-/* Help for traverseing directory trees */
+/* Help for traversing directory trees */
EXTERN int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir);
EXTERN int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
diff --git a/nuttx/fs/fs_fat32util.c b/nuttx/fs/fs_fat32util.c
index c44e2c6bd..be36d6f75 100644
--- a/nuttx/fs/fs_fat32util.c
+++ b/nuttx/fs/fs_fat32util.c
@@ -530,9 +530,11 @@ void fat_semgive(struct fat_mountpt_s *fs)
}
/****************************************************************************
- * Name: fat_gettime
+ * Name: fat_systime2fattime
+ *
+ * Desciption: Get the system time convertto a time and and date suitble
+ * for writing into the FAT FS.
*
- * Desciption: Get the time and date suitble for writing into the FAT FS.
* TIME in LS 16-bits:
* Bits 0:4 = 2 second count (0-29 representing 0-58 seconds)
* Bits 5-10 = minutes (0-59)
@@ -542,10 +544,31 @@ void fat_semgive(struct fat_mountpt_s *fs)
* Bits 5:8 = Month of year (1-12)
* Bits 9:15 = Year from 1980 (0-127 representing 1980-2107)
*
+ ****************************************************************************/
+
+uint32 fat_systime2fattime(void)
+{
+#warning "Time not implemented"
+ return 0;
+}
+
+/****************************************************************************
+ * Name: fat_fattime2systime
+ *
+ * Desciption: Convert FAT data and time to a system time_t
+ *
+ * 16-bit FAT time:
+ * Bits 0:4 = 2 second count (0-29 representing 0-58 seconds)
+ * Bits 5-10 = minutes (0-59)
+ * Bits 11-15 = hours (0-23)
+ * 16-bit FAT date:
+ * Bits 0:4 = Day of month (0-31)
+ * Bits 5:8 = Month of year (1-12)
+ * Bits 9:15 = Year from 1980 (0-127 representing 1980-2107)
*
****************************************************************************/
-uint32 fat_gettime(void)
+time_t fat_fattime2systime(uint16 fattime, uint16 fatdate)
{
#warning "Time not implemented"
return 0;
@@ -1812,7 +1835,7 @@ int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
DIR_PUTATTRIBUTES(dirinfo->fd_entry, FATATTR_ARCHIVE);
- writetime = fat_gettime();
+ writetime = fat_systime2fattime();
DIR_PUTWRTTIME(dirinfo->fd_entry, writetime & 0xffff);
DIR_PUTWRTDATE(dirinfo->fd_entry, writetime > 16);
@@ -1877,7 +1900,7 @@ int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
/* ARCHIVE attribute, write time, creation time */
DIR_PUTATTRIBUTES(dirinfo->fd_entry, FATATTR_ARCHIVE);
- time = fat_gettime();
+ time = fat_systime2fattime();
DIR_PUTWRTTIME(dirinfo->fd_entry, time & 0xffff);
DIR_PUTCRTIME(dirinfo->fd_entry, time & 0xffff);
DIR_PUTWRTDATE(dirinfo->fd_entry, time >> 16);
diff --git a/nuttx/fs/fs_mount.c b/nuttx/fs/fs_mount.c
index 1f64b1eb2..00b80a574 100644
--- a/nuttx/fs/fs_mount.c
+++ b/nuttx/fs/fs_mount.c
@@ -225,6 +225,10 @@ int mount(const char *source, const char *target,
goto errout_with_mountpt;
}
+ /* Increment reference count for the reference we pass to the file system */
+
+ blkdrvr_inode->i_crefs++;
+
/* On failure, the bind method returns -errorcode */
status = mops->bind(blkdrvr_inode, data, &fshandle);
@@ -233,7 +237,7 @@ int mount(const char *source, const char *target,
/* The inode is unhappy with the blkdrvr for some reason */
errcode = -status;
- goto errout_with_mountpt;
+ goto errout_with_blkdrvr2;
}
/* We have it, now populate it with driver specific information. */
@@ -258,6 +262,9 @@ int mount(const char *source, const char *target,
/* A lot of goto's! But they make the error handling much simpler */
+ errout_with_blkdrvr2:
+ inode_release(blkdrvr_inode);
+
errout_with_mountpt:
inode_release(mountpt_inode);
diff --git a/nuttx/fs/fs_stat.c b/nuttx/fs/fs_stat.c
new file mode 100644
index 000000000..ac72658ba
--- /dev/null
+++ b/nuttx/fs/fs_stat.c
@@ -0,0 +1,208 @@
+/****************************************************************************
+ * fs_stat.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Compilation Switches
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <sched.h>
+#include <errno.h>
+#include "fs_internal.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+
+/****************************************************************************
+ * Name: statpsuedo
+ ****************************************************************************/
+
+static inline int statpsuedo(FAR struct inode *inode, FAR struct stat *buf)
+{
+ /* Most of the stat entries just do not apply */
+
+ memset(buf, 0, sizeof(struct stat) );
+ if (inode->u.i_ops)
+ {
+ if (inode->u.i_ops->read)
+ {
+ buf->st_mode = S_IROTH|S_IRGRP|S_IRUSR;
+ }
+
+ if (inode->u.i_ops->write)
+ {
+ buf->st_mode |= S_IWOTH|S_IWGRP|S_IWUSR;
+ }
+
+ if (INODE_IS_MOUNTPT(inode))
+ {
+ buf->st_mode |= S_IFDIR;
+ }
+ else if (INODE_IS_BLOCK(inode))
+ {
+ /* What is it also has child inodes? */
+
+ buf->st_mode |= S_IFBLK;
+ }
+ else
+ {
+ /* What is it also has child inodes? */
+
+ buf->st_mode |= S_IFCHR;
+ }
+ }
+ else
+ {
+ /* If it has no operations, then it must just be a intermeidate
+ * node in the inode tree. It is something like a directory.
+ */
+
+ buf->st_mode |= S_IFDIR;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stat
+ *
+ * Return: Zero on success; -1 on failure with errno set:
+ *
+ * EACCES Search permission is denied for one of the directories in the
+ * path prefix of path.
+ * EFAULT Bad address.
+ * ENOENT A component of the path path does not exist, or the path is an
+ * empty string.
+ * ENOMEM Out of memory
+ * ENOTDIR A component of the path is not a directory.
+ *
+ ****************************************************************************/
+
+int stat(const char *path, FAR struct stat *buf)
+{
+ FAR struct inode *inode;
+ const char *relpath = NULL;
+ int ret;
+
+ /* Sanity checks */
+
+ if (!path || !buf)
+ {
+ ret = EFAULT;
+ goto errout;
+ }
+
+ if (!path[0])
+ {
+ ret = ENOENT;
+ goto errout;
+ }
+
+ /* Get an inode for this file */
+
+ inode = inode_find(path, &relpath);
+ if (!inode)
+ {
+ /* This name does not refer to a psudeo-inode and there is no
+ * mountpoint that includes in this path.
+ */
+
+ ret = ENOENT;
+ goto errout;
+ }
+
+ /* The way we handle the stat depends on the type of inode that we
+ * are dealing with.
+ */
+
+#ifndef CONFIG_DISABLE_MOUNTPOUNT
+ if (INODE_IS_MOUNTPT(inode))
+ {
+ /* The node is a file system mointpoint. Verify that the mountpoint
+ * supports the stat() method
+ */
+
+ if (inode->u.i_mops && inode->u.i_mops->stat)
+ {
+ /* Perform the rewinddir() operation */
+
+ ret = inode->u.i_mops->stat(inode, relpath, buf);
+ }
+ }
+ else
+#endif
+ {
+ /* The node is part of the root psuedo file system */
+
+ ret = statpsuedo(inode, buf);
+ }
+
+ /* Check if the stat operation was successful */
+
+ if (ret < 0)
+ {
+ ret = -ret;
+ goto errout_with_inode;
+ }
+
+ /* Successfully stat'ed the file */
+
+ inode_release(inode);
+ return OK;
+
+/* Failure conditions always set the errno appropriately */
+
+ errout_with_inode:
+ inode_release(inode);
+ errout:
+ *get_errno_ptr() = ret;
+ return ERROR;
+}
+
+#endif /* CONFIG_NFILE_DESCRIPTORS */
diff --git a/nuttx/include/fcntl.h b/nuttx/include/fcntl.h
index 1949be42a..10780da2c 100644
--- a/nuttx/include/fcntl.h
+++ b/nuttx/include/fcntl.h
@@ -104,38 +104,6 @@
#define DN_RENAME 4 /* A file was renamed */
#define DN_ATTRIB 5 /* Attributes of a file were changed */
-#define S_IFMT 0170000
-#define S_IFSOCK 0140000
-#define S_IFLNK 0120000
-#define S_IFREG 0100000
-#define S_IFBLK 0060000
-#define S_IFCHR 0020000
-#define S_IFDIR 0040000
-#define S_IFIFO 0010000
-#define S_ISUID 0004000
-#define S_ISGID 0002000
-#define S_ISVTX 0001000
-#define S_IRWXU 0000700
-#define S_IRUSR 0000400
-#define S_IWUSR 0000200
-#define S_IXUSR 0000100
-#define S_IRWXG 0000070
-#define S_IRGRP 0000040
-#define S_IWGRP 0000020
-#define S_IXGRP 0000010
-#define S_IRWXO 0000007
-#define S_IROTH 0000004
-#define S_IWOTH 0000002
-#define S_IXOTH 0000001
-
-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
-#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
-#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
-#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
-
/********************************************************************************
* Public Type Definitions
********************************************************************************/
diff --git a/nuttx/include/nuttx/fs.h b/nuttx/include/nuttx/fs.h
index c703bcf36..efb3251f2 100644
--- a/nuttx/include/nuttx/fs.h
+++ b/nuttx/include/nuttx/fs.h
@@ -163,6 +163,7 @@ struct mountpt_operations
int (*mkdir)(struct inode *mountpt, const char *relpath, mode_t mode);
int (*rmdir)(struct inode *mountpt, const char *relpath);
int (*rename)(struct inode *mountpt, const char *oldrelpath, const char *newrelpath);
+ int (*stat)(struct inode *mountpt, const char *relpath, struct stat *buf);
/* NOTE: More operations will be needed here to support: disk usage stats
* file stat(), file attributes, file truncation, etc.
diff --git a/nuttx/include/stdio.h b/nuttx/include/stdio.h
index bdad75eb6..592ded26a 100644
--- a/nuttx/include/stdio.h
+++ b/nuttx/include/stdio.h
@@ -80,29 +80,6 @@
* Public Type Definitions
************************************************************/
-struct stat
-{
- dev_t st_dev; /* ID of device containing a */
- /* directory entry for this file */
- ino_t st_ino; /* Inode number */
- unsigned short st_mode; /* File type, attributes, and */
- /* access control summary */
- unsigned short st_nlink; /* Number of links */
- uid_t st_uid; /* User ID of file owner */
- gid_t st_gid; /* Group ID of file group */
- dev_t st_rdev; /* Device ID; this entry defined */
- /* only for char or blk spec files */
- off_t st_size; /* File size (bytes) */
- time_t st_atime; /* Time of last access */
- time_t st_mtime; /* Last modification time */
- time_t st_ctime; /* Last file status change time */
- /* Measured in secs since */
- /* 00:00:00 GMT, Jan 1, 1970 */
- long st_blksize; /* Non-standard, Wind-River field */
- unsigned long st_blocks; /* Non-standard, Wind-River field */
- long st_gen; /* file generation value: Non-standard, Wind-River field */
-};
-
struct statfs
{
long f_bavail; /* free blocks available to non-superuser */
@@ -166,9 +143,7 @@ EXTERN int vsprintf(char *buf, const char *s, va_list ap);
EXTERN int chdir(const char *path);
EXTERN FILE *fdopen(int fd, const char *type);
-EXTERN int fstat(int fd, FAR struct stat *buf);
EXTERN char *getcwd(FAR char *buf, size_t size);
-EXTERN int stat(const char *path, FAR struct stat *buf);
EXTERN int statfs(const char *path, FAR struct statfs *buf);
#undef EXTERN
diff --git a/nuttx/include/sys/stat.h b/nuttx/include/sys/stat.h
index 0d686e10f..20fbc3a59 100644
--- a/nuttx/include/sys/stat.h
+++ b/nuttx/include/sys/stat.h
@@ -1,5 +1,5 @@
/************************************************************
- * stat.h
+ * sys/stat.h
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
@@ -41,11 +41,76 @@
************************************************************/
#include <sys/types.h>
+#include <time.h>
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/* mode_t bit settings (most of these do not apply to Nuttx).
+ * This assumes that the full size of a mode_t is 16-bits.
+ * (However, mode_t must be size 'int' because it is promoted
+ * to size int when passed in varargs).
+ */
+
+#define S_IXOTH 0000001 /* Permissions for others: RWX */
+#define S_IWOTH 0000002
+#define S_IROTH 0000004
+#define S_IRWXO 0000007
+
+#define S_IXGRP 0000010 /* Group permissions: RWX */
+#define S_IWGRP 0000020
+#define S_IRGRP 0000040
+#define S_IRWXG 0000070
+
+#define S_IXUSR 0000100 /* Owner permissions: RWX */
+#define S_IWUSR 0000200
+#define S_IRUSR 0000400
+#define S_IRWXU 0000700
+
+#define S_ISVTX 0001000 /* "sticky" bit */
+#define S_ISGID 0002000 /* Set group ID bit */
+#define S_ISUID 0004000 /* Set UID bit */
+
+#define S_IFIFO 0010000 /* File type bites */
+#define S_IFCHR 0020000
+#define S_IFDIR 0040000
+#define S_IFBLK 0060000
+#define S_IFREG 0100000
+#define S_IFLNK 0120000
+#define S_IFSOCK 0140000
+#define S_IFMT 0170000
+
+/* File type macros that operate on an instance of mode_t */
+
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
/************************************************************
* Type Definitions
************************************************************/
+/* This is the simplified struct stat as returned by fstat().
+ * This structure provides information about a specific file
+ * or directory in the file system.
+ */
+
+struct stat
+{
+ mode_t st_mode; /* File type, atributes, and access mode bits */
+ off_t st_size; /* Size of file/directory, in bytes */
+ blksize_t st_blksize; /* Blocksize used for filesystem I/O */
+ blkcnt_t st_blocks; /* Number of blocks allocated*/
+ time_t st_atime; /* Time of last access */
+ time_t st_mtime; /* Time of last modification */
+ time_t st_ctime; /* Time of last status change */
+};
+
/************************************************************
* Global Function Prototypes
************************************************************/
@@ -58,7 +123,9 @@ extern "C" {
#define EXTERN extern
#endif
-EXTERN int mkdir(const char *pathname, mode_t mode);
+EXTERN int mkdir(FAR const char *pathname, mode_t mode);
+EXTERN int stat(const char *path, FAR struct stat *buf);
+EXTERN int fstat(int fd, FAR struct stat *buf);
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/include/sys/types.h b/nuttx/include/sys/types.h
index 916681c39..97b2d7eed 100644
--- a/nuttx/include/sys/types.h
+++ b/nuttx/include/sys/types.h
@@ -99,24 +99,29 @@ typedef double double_t;
/* Misc. scalar types */
-typedef unsigned int mode_t;
+typedef unsigned int mode_t; /* Needs at least 16-bits but must be */
+ /* sizeof(int) because it is passed */
+ /* via varargs. */
#ifdef CONFIG_SMALL_MEMORY
-typedef uint16 size_t;
-typedef sint16 ssize_t;
-typedef sint16 off_t;
+typedef uint16 size_t;
+typedef sint16 ssize_t;
+typedef sint16 off_t;
+typedef uint16 blksize_t;
+typedef uint16 blkcnt_t;
#else
-typedef uint32 size_t;
-typedef sint32 ssize_t;
-typedef sint32 off_t;
+typedef uint32 size_t;
+typedef sint32 ssize_t;
+typedef sint32 off_t;
+typedef uint16 blksize_t;
+typedef uint32 blkcnt_t;
#endif
-//typedef sint32 time_t;
-typedef sint16 uid_t;
-typedef sint16 gid_t;
-typedef uint16 dev_t;
-typedef uint16 ino_t;
-typedef unsigned int sig_atomic_t;
-typedef int pid_t;
-typedef int STATUS;
+typedef sint16 uid_t;
+typedef sint16 gid_t;
+typedef uint16 dev_t;
+typedef uint16 ino_t;
+typedef unsigned int sig_atomic_t;
+typedef int pid_t;
+typedef int STATUS;
/* Process entry point */