From cc3614dfe8f67033dca8c7c1f40c3367a0d3ca06 Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 14 Jan 2013 19:22:32 +0000 Subject: Finish dup logic for open files; fix bug in sigtimedwait(), would return wrong signo value if the signal was already pending git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5517 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/fs/fat/fs_fat32.c | 126 +++++++++++++++++++++++++++++++++++++- nuttx/fs/fat/fs_fat32.h | 1 - nuttx/fs/fat/fs_fat32util.c | 10 +-- nuttx/fs/nfs/nfs_node.h | 3 +- nuttx/fs/nfs/nfs_util.c | 9 +-- nuttx/fs/nfs/nfs_vfsops.c | 106 ++++++++++++++++++++++++++++---- nuttx/fs/nfs/rpc_clnt.c | 28 ++++----- nuttx/fs/nxffs/nxffs.h | 41 +++++++------ nuttx/fs/nxffs/nxffs_initialize.c | 4 +- nuttx/fs/nxffs/nxffs_open.c | 62 ++++++++++++++++++- nuttx/fs/romfs/fs_romfs.c | 2 +- 11 files changed, 317 insertions(+), 75 deletions(-) (limited to 'nuttx/fs') diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c index 788e6bebc..7164a9f8f 100644 --- a/nuttx/fs/fat/fs_fat32.c +++ b/nuttx/fs/fat/fs_fat32.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/fat/fs_fat32.c * - * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * References: @@ -86,7 +86,9 @@ static ssize_t fat_write(FAR struct file *filep, const char *buffer, size_t buflen); static off_t fat_seek(FAR struct file *filep, off_t offset, int whence); static int fat_ioctl(FAR struct file *filep, int cmd, unsigned long arg); + static int fat_sync(FAR struct file *filep); +static int fat_dup(FAR const struct file *oldp, FAR struct file *newp); static int fat_opendir(struct inode *mountpt, const char *relpath, struct fs_dirent_s *dir); @@ -129,7 +131,7 @@ const struct mountpt_operations fat_operations = fat_ioctl, /* ioctl */ fat_sync, /* sync */ - NULL, /* dup */ + fat_dup, /* dup */ fat_opendir, /* opendir */ NULL, /* closedir */ @@ -313,7 +315,6 @@ static int fat_open(FAR struct file *filep, const char *relpath, /* Initialize the file private data (only need to initialize non-zero elements) */ - ff->ff_open = true; ff->ff_oflags = oflags; /* Save information that can be used later to recover the directory entry */ @@ -898,6 +899,7 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence) DEBUGASSERT(fs != NULL); /* Map the offset according to the whence option */ + switch (whence) { case SEEK_SET: /* The offset is set to offset bytes. */ @@ -971,6 +973,7 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence) ret = cluster; goto errout_with_semaphore; } + ff->ff_startcluster = cluster; } @@ -1232,6 +1235,123 @@ errout_with_semaphore: return ret; } +/**************************************************************************** + * Name: fat_dup + * + * Description: Duplicate open file data in the new file structure. + * + ****************************************************************************/ + +static int fat_dup(FAR const struct file *oldp, FAR struct file *newp) +{ + FAR struct fat_mountpt_s *fs; + FAR struct fat_file_s *oldff; + FAR struct fat_file_s *newff; + int ret; + + fvdbg("Dup %p->%p\n", oldp, newp); + + /* Sanity checks */ + + DEBUGASSERT(oldp->f_priv != NULL && + newp->f_priv == NULL && + newp->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + fs = (struct fat_mountpt_s *)oldp->f_inode->i_private; + DEBUGASSERT(fs != NULL); + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + + /* Recover the old private data from the old struct file instance */ + + oldff = oldp->f_priv; + + /* Create a new instance of the file private date to describe the + * dup'ed file. + */ + + newff = (struct fat_file_s *)kmalloc(sizeof(struct fat_file_s)); + if (!newff) + { + ret = -ENOMEM; + goto errout_with_semaphore; + } + + /* Create a file buffer to support partial sector accesses */ + + newff->ff_buffer = (uint8_t*)fat_io_alloc(fs->fs_hwsectorsize); + if (!newff->ff_buffer) + { + ret = -ENOMEM; + goto errout_with_struct; + } + + /* Copy the rest of the open open file state from the old file structure. + * There are some assumptions and potential issues here: + * + * 1) We assume that the higher level logic has copied the elements of + * the file structure, in particular, the file position. + * 2) There is a problem with ff_size if there are multiple opened + * file structures, each believing they know the size of the file. + * If one instance modifies the file length, then the new size of + * the opened file will be unknown to the other. That is a lurking + * bug! + * + * One good solution to this might be to add a refernce count to the + * file structure. Then, instead of dup'ing the whole structure + * as is done here, just increment the reference count on the + * structure. The would have to be integrated with open logic as + * well, however, so that the same file structure is re-used if the + * file is re-opened. + */ + + newff->ff_bflags = 0; + newff->ff_oflags = oldff->ff_oflags; + newff->ff_sectorsincluster = oldff->ff_sectorsincluster; + newff->ff_dirindex = oldff->ff_dirindex; + newff->ff_currentcluster = oldff->ff_currentcluster; + newff->ff_dirsector = oldff->ff_dirsector; + newff->ff_size = oldff->ff_size; + newff->ff_currentsector = 0; + newff->ff_cachesector = 0; + + /* Attach the private date to the struct file instance */ + + newp->f_priv = newff; + + /* Then insert the new instance into the mountpoint structure. + * It needs to be there (1) to handle error conditions that effect + * all files, and (2) to inform the umount logic that we are busy + * (but a simple reference count could have done that). + */ + + newff->ff_next = fs->fs_head; + fs->fs_head = newff->ff_next; + + fat_semgive(fs); + return OK; + + /* Error exits -- goto's are nasty things, but they sure can make error + * handling a lot simpler. + */ + +errout_with_struct: + kfree(newff); + +errout_with_semaphore: + fat_semgive(fs); + return ret; +} + /**************************************************************************** * Name: fat_opendir * diff --git a/nuttx/fs/fat/fs_fat32.h b/nuttx/fs/fat/fs_fat32.h index 71a21333b..81f3f4675 100644 --- a/nuttx/fs/fat/fs_fat32.h +++ b/nuttx/fs/fat/fs_fat32.h @@ -752,7 +752,6 @@ struct fat_mountpt_s struct fat_file_s { struct fat_file_s *ff_next; /* Retained in a singly linked list */ - bool ff_open; /* true: The file is (still) open */ uint8_t ff_bflags; /* The file buffer flags */ uint8_t ff_oflags; /* Flags provided when file was opened */ uint8_t ff_sectorsincluster; /* Sectors remaining in cluster */ diff --git a/nuttx/fs/fat/fs_fat32util.c b/nuttx/fs/fat/fs_fat32util.c index 7231456d7..9aa1d3992 100644 --- a/nuttx/fs/fat/fs_fat32util.c +++ b/nuttx/fs/fat/fs_fat32util.c @@ -692,8 +692,6 @@ int fat_checkmount(struct fat_mountpt_s *fs) if (fs && fs->fs_mounted) { - struct fat_file_s *file; - /* We still think the mount is healthy. Check an see if this is * still the case */ @@ -715,14 +713,8 @@ int fat_checkmount(struct fat_mountpt_s *fs) /* If we get here, the mount is NOT healthy */ fs->fs_mounted = false; - - /* Make sure that this is flagged in every opened file */ - - for (file = fs->fs_head; file; file = file->ff_next) - { - file->ff_open = false; - } } + return -ENODEV; } diff --git a/nuttx/fs/nfs/nfs_node.h b/nuttx/fs/nfs/nfs_node.h index 4ae9e162c..408bd1993 100644 --- a/nuttx/fs/nfs/nfs_node.h +++ b/nuttx/fs/nfs/nfs_node.h @@ -1,7 +1,7 @@ /**************************************************************************** * fs/nfs/nfs_node.h * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Author: Jose Pablo Rojas Vargas * Gregory Nutt @@ -70,6 +70,7 @@ struct nfsnode { struct nfsnode *n_next; /* Retained in a singly linked list. */ + uint8_t n_crefs; /* Reference count (for nfs_dup) */ uint8_t n_type; /* File type */ uint8_t n_fhsize; /* Size in bytes of the file handle */ uint8_t n_flags; /* Node flags */ diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c index 73fda72a7..e7d28b3d7 100644 --- a/nuttx/fs/nfs/nfs_util.c +++ b/nuttx/fs/nfs/nfs_util.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/nfs/nfs_util.c * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -213,7 +213,6 @@ int nfs_request(struct nfsmount *nmp, int procnum, { struct rpcclnt *clnt = nmp->nm_rpcclnt; struct nfs_reply_header replyh; - int trylater_delay; int error; tryagain: @@ -250,12 +249,6 @@ tryagain: if (error == EAGAIN) { error = 0; - trylater_delay *= NFS_TIMEOUTMUL; - if (trylater_delay > NFS_MAXTIMEO) - { - trylater_delay = NFS_MAXTIMEO; - } - goto tryagain; } diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c index efb026c7f..01e999ac8 100644 --- a/nuttx/fs/nfs/nfs_vfsops.c +++ b/nuttx/fs/nfs/nfs_vfsops.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/nfs/nfs_vfsops.c * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Author: Jose Pablo Rojas Vargas * Gregory Nutt @@ -133,6 +133,7 @@ static int nfs_close(FAR struct file *filep); static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen); static ssize_t nfs_write(FAR struct file *filep, const char *buffer, size_t buflen); +static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp); static int nfs_opendir(struct inode *mountpt, const char *relpath, struct fs_dirent_s *dir); static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir); @@ -168,7 +169,7 @@ const struct mountpt_operations nfs_operations = NULL, /* ioctl */ NULL, /* sync */ - NULL, /* dup */ + nfs_dup, /* dup */ nfs_opendir, /* opendir */ NULL, /* closedir */ @@ -359,7 +360,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, /* Save the attributes in the file data structure */ - tmp = *ptr++; /* handle_follows */ + tmp = *ptr; /* handle_follows */ if (!tmp) { fdbg("WARNING: no file attributes\n"); @@ -369,7 +370,6 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, /* Initialize the file attributes */ nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr); - ptr += uint32_increment(sizeof(struct nfs_fattr)); } /* Any following dir_wcc data is ignored for now */ @@ -412,7 +412,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np) reqlen += (int)np->n_fhsize; ptr += uint32_increment(np->n_fhsize); - /* Copy the variable-length attribtes */ + /* Copy the variable-length attributes */ *ptr++ = nfs_false; /* Don't change mode */ *ptr++ = nfs_false; /* Don't change uid */ @@ -423,7 +423,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np) *ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ *ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ *ptr++ = nfs_false; /* No guard value */ - reqlen += 9*sizeof(uint32_t) + reqlen += 9 * sizeof(uint32_t); /* Perform the SETATTR RPC */ @@ -553,9 +553,9 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np, static int nfs_open(FAR struct file *filep, FAR const char *relpath, int oflags, mode_t mode) { - struct nfsmount *nmp; - struct nfsnode *np = NULL; - int error; + struct nfsmount *nmp; + struct nfsnode *np; + int error; /* Sanity checks */ @@ -634,6 +634,8 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath, * non-zero elements) */ + np->n_crefs = 1; + /* Attach the private data to the struct file instance */ filep->f_priv = np; @@ -656,6 +658,7 @@ errout_with_semaphore: { kfree(np); } + nfs_semgive(nmp); return -error; } @@ -693,8 +696,22 @@ static int nfs_close(FAR struct file *filep) nfs_semtake(nmp); - /* Find our file structure in the list of file structures containted in the - * mount structure. + /* Decrement the reference count. If the reference count would not + * decrement to zero, then that is all we have to do. + */ + + if (np->n_crefs > 1) + { + np->n_crefs--; + nfs_semgive(nmp); + return OK; + } + + /* There are no more references to the file structure. Now we need to + * free up all resources associated with the open file. + * + * First, find our file structure in the list of file structures + * containted in the mount structure. */ for (prev = NULL, curr = nmp->nm_head; curr; prev = curr, curr = curr->n_next) @@ -759,8 +776,8 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) /* Recover our private data from the struct file instance */ - nmp = (struct nfsmount*) filep->f_inode->i_private; - np = (struct nfsnode*) filep->f_priv; + nmp = (struct nfsmount*)filep->f_inode->i_private; + np = (struct nfsnode*)filep->f_priv; DEBUGASSERT(nmp != NULL); @@ -1093,6 +1110,66 @@ errout_with_semaphore: return -error; } +/**************************************************************************** + * Name: binfs_dup + * + * Description: + * Duplicate open file data in the new file structure. + * + ****************************************************************************/ + +static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp) +{ + struct nfsmount *nmp; + FAR struct nfsnode *np; + int error; + + fvdbg("Dup %p->%p\n", oldp, newp); + + /* Sanity checks */ + + DEBUGASSERT(oldp->f_priv != NULL && oldp->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + nmp = (struct nfsmount*)oldp->f_inode->i_private; + np = (struct nfsnode*)oldp->f_priv; + + DEBUGASSERT(nmp != NULL); + + /* Check if the mount is still healthy */ + + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + nfs_semgive(nmp); + return -error; + } + + /* Increment the reference count on the NFS node structure */ + + DEBUGASSERT(np->n_crefs < 0xff); + np->n_crefs++; + + /* And save this as the file data for the new node */ + + newp->f_priv = np; + + /* Then insert the new instance at the head of the list in the mountpoint + * tructure. It needs to be there (1) to handle error conditions that effect + * all files, and (2) to inform the umount logic that we are busy. We + * cannot unmount the file system if this list is not empty! + */ + + np->n_next = nmp->nm_head; + nmp->nm_head = np; + + nfs_semgive(nmp); + return OK; +} + /**************************************************************************** * Name: nfs_opendir * @@ -1756,12 +1833,15 @@ bad: { kfree(nmp->nm_so); } + if (nmp->nm_rpcclnt) { kfree(nmp->nm_rpcclnt); } + kfree(nmp); } + return error; } diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c index 0e2a394ba..9c2ada4f2 100644 --- a/nuttx/fs/nfs/rpc_clnt.c +++ b/nuttx/fs/nfs/rpc_clnt.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/nfs/rpc_clnt.c * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. * Author: Jose Pablo Rojas Vargas * Gregory Nutt @@ -224,8 +224,6 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname, static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, FAR void *reply, size_t resplen) { - FAR struct rpc_reply_header *replyheader; - uint32_t rxid; int error; /* Get the next RPC reply from the socket */ @@ -235,22 +233,22 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, { fdbg("ERROR: rpcclnt_receive returned: %d\n", error); - /* If we failed because of a timeout, then try sending the CALL - * message again. - */ + /* If we failed because of a timeout, then try sending the CALL + * message again. + */ - if (error == EAGAIN || error == ETIMEDOUT) - { - rpc->rc_timeout = true; - } - } + if (error == EAGAIN || error == ETIMEDOUT) + { + rpc->rc_timeout = true; + } + } /* Get the xid and check that it is an RPC replysvr */ else { - replyheader = (FAR struct rpc_reply_header *)reply; - rxid = replyheader->rp_xid; + FAR struct rpc_reply_header *replyheader = + (FAR struct rpc_reply_header *)reply; if (replyheader->rp_direction != rpc_reply) { @@ -260,7 +258,7 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, } } - return OK; + return error; } /**************************************************************************** @@ -275,7 +273,6 @@ static uint32_t rpcclnt_newxid(void) { static uint32_t rpcclnt_xid = 0; static uint32_t rpcclnt_xid_touched = 0; - int xidp = 0; srand(time(NULL)); if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0)) @@ -285,6 +282,7 @@ static uint32_t rpcclnt_newxid(void) } else { + int xidp = 0; do { xidp = rand(); diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h index 616dc7197..083e00fa7 100644 --- a/nuttx/fs/nxffs/nxffs.h +++ b/nuttx/fs/nxffs/nxffs.h @@ -1,7 +1,7 @@ /**************************************************************************** * fs/nxffs/nxffs.h * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * References: Linux/Documentation/filesystems/romfs.txt @@ -1044,6 +1044,7 @@ extern int nxffs_pack(FAR struct nxffs_volume_s *volume); * - nxffs_read() is defined in nxffs_read.c * - nxffs_write() is defined in nxffs_write.c * - nxffs_ioctl() is defined in nxffs_ioctl.c + * - nxffs_dup() is defined in nxffs_open.c * - nxffs_opendir(), nxffs_readdir(), and nxffs_rewindir() are defined in * nxffs_dirent.c * - nxffs_bind() and nxffs_unbind() are defined in nxffs_initialize.c @@ -1058,25 +1059,25 @@ struct fs_dirent_s; struct statfs; struct stat; -extern int nxffs_open(FAR struct file *filep, FAR const char *relpath, - int oflags, mode_t mode); -extern int nxffs_close(FAR struct file *filep); -extern ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, - size_t buflen); -extern ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, - size_t buflen); -extern int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); -extern int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath, - FAR struct fs_dirent_s *dir); -extern int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); -extern int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); -extern int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data, - FAR void **handle); -extern int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver); -extern int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf); -extern int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath, - FAR struct stat *buf); -extern int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath); +int nxffs_open(FAR struct file *filep, FAR const char *relpath, int oflags, + mode_t mode); +int nxffs_close(FAR struct file *filep); +ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen); +ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +int nxffs_dup(FAR const struct file *oldp, FAR struct file *newp); +int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct fs_dirent_s *dir); +int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); +int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); +int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data, + FAR void **handle); +int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver); +int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf); +int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct stat *buf); +int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath); #endif /* __FS_NXFFS_NXFFS_H */ diff --git a/nuttx/fs/nxffs/nxffs_initialize.c b/nuttx/fs/nxffs/nxffs_initialize.c index 0aa424869..4e7428c73 100644 --- a/nuttx/fs/nxffs/nxffs_initialize.c +++ b/nuttx/fs/nxffs/nxffs_initialize.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/nxffs/nxffs_initialize.c * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * References: Linux/Documentation/filesystems/romfs.txt @@ -84,7 +84,7 @@ const struct mountpt_operations nxffs_operations = nxffs_ioctl, /* ioctl */ NULL, /* sync -- No buffered data */ - NULL, /* dup -- not implemented */ + nxffs_dup, /* dup */ nxffs_opendir, /* opendir */ NULL, /* closedir */ diff --git a/nuttx/fs/nxffs/nxffs_open.c b/nuttx/fs/nxffs/nxffs_open.c index eb7817c57..b1e99267f 100644 --- a/nuttx/fs/nxffs/nxffs_open.c +++ b/nuttx/fs/nxffs/nxffs_open.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/nxffs/nxffs_open.c * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * References: Linux/Documentation/filesystems/romfs.txt @@ -1023,7 +1023,7 @@ int nxffs_open(FAR struct file *filep, FAR const char *relpath, #endif /* Limitation: A file must be opened for reading or writing, but not both. - * There is no general for extending the size of of a file. Extending the + * There is no general way of extending the size of a file. Extending the * file size of possible if the file to be extended is the last in the * sequence on FLASH, but since that case is not the general case, no file * extension is supported. @@ -1058,6 +1058,64 @@ int nxffs_open(FAR struct file *filep, FAR const char *relpath, return ret; } +/**************************************************************************** + * Name: binfs_dup + * + * Description: + * Duplicate open file data in the new file structure. + * + ****************************************************************************/ + +int nxffs_dup(FAR const struct file *oldp, FAR struct file *newp) +{ +#ifdef CONFIG_DEBUG + FAR struct nxffs_volume_s *volume; +#endif + FAR struct nxffs_ofile_s *ofile; + + fvdbg("Dup %p->%p\n", oldp, newp); + + /* Sanity checks */ + +#ifdef CONFIG_DEBUG + DEBUGASSERT(oldp->f_priv == NULL && oldp->f_inode != NULL); + + /* Get the mountpoint private data from the NuttX inode reference in the + * file structure + */ + + volume = (FAR struct nxffs_volume_s*)oldp->f_inode->i_private; + DEBUGASSERT(volume != NULL); +#endif + + /* Recover the open file state from the struct file instance */ + + ofile = (FAR struct nxffs_ofile_s *)oldp->f_priv; + + /* I do not think we need exclusive access to the volume to do this. + * The volume exclsem protects the open file list and, hence, would + * assure that the ofile is stable. However, it is assumed that the + * caller holds a value file descriptor associated with this ofile, + * so it should be stable throughout the life of this function. + */ + + /* Limitations: I do not think we have to be concerned about the + * usual NXFFS file limitations here: dup'ing cannot resulting + * in mixed reading and writing to the same file, or multiple + * writer to different file. + * + * I notice that nxffs_wropen will prohibit multiple opens for + * writing. But I do not thing that dup'ing a file already opened + * for writing suffers from any of these issues. + */ + + /* Just increment the reference count on the ofile */ + + ofile->crefs++; + newp->f_priv = (FAR void *)ofile; + return OK; +} + /**************************************************************************** * Name: nxffs_close * diff --git a/nuttx/fs/romfs/fs_romfs.c b/nuttx/fs/romfs/fs_romfs.c index de87c7fec..2814aa49d 100644 --- a/nuttx/fs/romfs/fs_romfs.c +++ b/nuttx/fs/romfs/fs_romfs.c @@ -636,7 +636,7 @@ static int romfs_dup(FAR const struct file *oldp, FAR struct file *newp) * dup'ed file. */ - newrf = (FAR struct romfs_file_s *)malloc(sizeof(struct romfs_file_s)); + newrf = (FAR struct romfs_file_s *)kmalloc(sizeof(struct romfs_file_s)); if (!newrf) { fdbg("Failed to allocate private data\n", ret); -- cgit v1.2.3