From 84a5f846c952785afc96a6f75b4db418e4511cff Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 21 Nov 2015 11:24:55 -0600 Subject: [PATCH] open() has been extended. You can now open block drivers and access them just as you can character drivers. For example, you can hexdump a block device. --- ChangeLog | 7 ++++++- fs/driver/driver.h | 35 +++++++++++++++++++++++++++++++++++ fs/driver/fs_blockproxy.c | 14 +++++++------- fs/vfs/fs_open.c | 39 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 84 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 59ba77c5ca..cd40ad5570 100755 --- a/ChangeLog +++ b/ChangeLog @@ -11132,4 +11132,9 @@ * drivers/timers/pcf85263.c and include/nuttx/times/pcf85263.h: Add a driver for the NXP PCF85263 I2C RTC. Untested on initial commit (2015-11-20). - + * fs/driver/fs_blockproxy.c: Add logic to create a temporary char driver + using drivers/bch to mediate character oriented accessed to a block + driver (2015-11-21). + * fs/vfs/open.c: If the use attempts to open a block driver, use + block_proxy() to insert a character driver conversion layer in front + of the block driver (2015-11-21). diff --git a/fs/driver/driver.h b/fs/driver/driver.h index 066d3ebd64..72ba7318a0 100644 --- a/fs/driver/driver.h +++ b/fs/driver/driver.h @@ -91,8 +91,43 @@ extern "C" * ****************************************************************************/ +#ifndef CONFIG_DISABLE_MOUNTPOINT int find_blockdriver(FAR const char *pathname, int mountflags, FAR struct inode **ppinode); +#endif + +/* fs/drivers/fs_blockproxy.c ***********************************************/ +/**************************************************************************** + * Name: block_proxy + * + * Description: + * Create a temporary char driver using drivers/bch to mediate character + * oriented accessed to the block driver. + * + * Input parameters: + * blkdev - The path to the block driver + * oflags - Character driver open flags + * + * Returned Value: + * If positive, non-zero file descriptor is returned on success. This + * is the file descriptor of the nameless character driver that mediates + * accesses to the block driver. + * + * Errors that may be returned: + * + * ENOMEM - Failed to create a temporay path name. + * + * Plus: + * + * - Errors reported from bchdev_register() + * - Errors reported from open() or unlink() + * + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && \ + !defined(CONFIG_DISABLE_MOUNTPOINT) +int block_proxy(FAR const char *blkdev, int oflags); +#endif #undef EXTERN #if defined(__cplusplus) diff --git a/fs/driver/fs_blockproxy.c b/fs/driver/fs_blockproxy.c index 73e7285795..afabd1880f 100644 --- a/fs/driver/fs_blockproxy.c +++ b/fs/driver/fs_blockproxy.c @@ -148,12 +148,12 @@ static FAR char *unique_chardev(void) * Name: block_proxy * * Description: - * Create a temporary char driver using drivers/bch that mediate character + * Create a temporary char driver using drivers/bch to mediate character * oriented accessed to the block driver. * * Input parameters: * blkdev - The path to the block driver - * mode - Character driver access priviledges + * oflags - Character driver open flags * * Returned Value: * If positive, non-zero file descriptor is returned on success. This @@ -171,7 +171,7 @@ static FAR char *unique_chardev(void) * ****************************************************************************/ -int block_proxy(FAR const char *blkdev, mode_t mode) +int block_proxy(FAR const char *blkdev, int oflags) { FAR char *chardev; bool readonly; @@ -179,7 +179,7 @@ int block_proxy(FAR const char *blkdev, mode_t mode) int fd; DEBUGASSERT(blkdev); - DEBUGASSERT((mode & (O_CREAT | O_EXCL | O_APPEND | O_TRUNC)) == 0); + DEBUGASSERT((oflags & (O_CREAT | O_EXCL | O_APPEND | O_TRUNC)) == 0); /* Create a unique temporary file name for the character device */ @@ -192,7 +192,7 @@ int block_proxy(FAR const char *blkdev, mode_t mode) /* Should this character driver be read-only? */ - readonly = ((mode & O_WROK) == 0); + readonly = ((oflags & O_WROK) == 0); /* Wrap the block driver with an instance of the BCH driver */ @@ -207,8 +207,8 @@ int block_proxy(FAR const char *blkdev, mode_t mode) /* Open the newly created character driver */ - mode &= ~(O_CREAT | O_EXCL | O_APPEND | O_TRUNC); - fd = open(chardev, mode); + oflags &= ~(O_CREAT | O_EXCL | O_APPEND | O_TRUNC); + fd = open(chardev, oflags); if (fd < 0) { ret = -errno; diff --git a/fs/vfs/fs_open.c b/fs/vfs/fs_open.c index ae903970fe..b0a5ca2c50 100644 --- a/fs/vfs/fs_open.c +++ b/fs/vfs/fs_open.c @@ -130,9 +130,42 @@ int open(const char *path, int oflags, ...) goto errout; } - /* Verify that the inode is valid and either a "normal" character driver or a - * mountpoint. We specifically exclude block drivers and and "special" - * inodes (semaphores, message queues, shared memory). +#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && \ + !defined(CONFIG_DISABLE_MOUNTPOINT) + /* If the inode is block driver, then we may return a character driver + * proxy for the block driver. block_proxy() will instantiate a BCH + * character driver wrapper around the block driver, open(), then + * unlink() the character driver. On success, block_proxy() will + * return the file descriptor of the opened character driver. + * + * NOTE: This will recurse to open the character driver proxy. + */ + + if (INODE_IS_BLOCK(inode)) + { + /* Release the inode reference */ + + inode_release(inode); + + /* Get the file descriptor of the opened character driver proxy */ + + fd = block_proxy(path, oflags); + if (fd < 0) + { + ret = fd; + goto errout; + } + + /* Return the file descriptor */ + + return fd; + } + else +#endif + + /* Verify that the inode is either a "normal" character driver or a + * mountpoint. We specifically "special" inodes (semaphores, message + * queues, shared memory). */ #ifndef CONFIG_DISABLE_MOUNTPOINT