fs: open: Add Truncate flag to zfs open
This commit has added new flag FS_O_TRUNC to support truncation during file open. Modified fs_open to handle truncation based on provided flags. Included unit tests for flag behavior with common filesystems. Signed-off-by: RAJAGOPALAN GANGADHARAN <g.raju2000@gmail.com>
This commit is contained in:
parent
c36d9ec3a8
commit
65c4ca1f05
3 changed files with 121 additions and 1 deletions
|
@ -160,8 +160,11 @@ struct fs_statvfs {
|
||||||
#define FS_O_CREATE 0x10
|
#define FS_O_CREATE 0x10
|
||||||
/** Open/create file for append */
|
/** Open/create file for append */
|
||||||
#define FS_O_APPEND 0x20
|
#define FS_O_APPEND 0x20
|
||||||
|
/** Truncate the file while opening */
|
||||||
|
#define FS_O_TRUNC 0x40
|
||||||
/** Bitmask for open/create flags */
|
/** Bitmask for open/create flags */
|
||||||
#define FS_O_FLAGS_MASK 0x30
|
#define FS_O_FLAGS_MASK 0x70
|
||||||
|
|
||||||
|
|
||||||
/** Bitmask for open flags */
|
/** Bitmask for open flags */
|
||||||
#define FS_O_MASK (FS_O_MODE_MASK | FS_O_FLAGS_MASK)
|
#define FS_O_MASK (FS_O_MODE_MASK | FS_O_FLAGS_MASK)
|
||||||
|
@ -268,6 +271,7 @@ static inline void fs_dir_t_init(struct fs_dir_t *zdp)
|
||||||
* - @c FS_O_RDWR open for read/write (<tt>FS_O_READ | FS_O_WRITE</tt>)
|
* - @c FS_O_RDWR open for read/write (<tt>FS_O_READ | FS_O_WRITE</tt>)
|
||||||
* - @c FS_O_CREATE create file if it does not exist
|
* - @c FS_O_CREATE create file if it does not exist
|
||||||
* - @c FS_O_APPEND move to end of file before each write
|
* - @c FS_O_APPEND move to end of file before each write
|
||||||
|
* - @c FS_O_TRUNC truncate the file
|
||||||
*
|
*
|
||||||
* @warning If @p flags are set to 0 the function will open file, if it exists
|
* @warning If @p flags are set to 0 the function will open file, if it exists
|
||||||
* and is accessible, but you will have no read/write access to it.
|
* and is accessible, but you will have no read/write access to it.
|
||||||
|
@ -284,6 +288,7 @@ static inline void fs_dir_t_init(struct fs_dir_t *zdp)
|
||||||
* FS_MOUNT_FLAG_READ_ONLY flag;
|
* FS_MOUNT_FLAG_READ_ONLY flag;
|
||||||
* @retval -ENOENT when the file does not exist at the path;
|
* @retval -ENOENT when the file does not exist at the path;
|
||||||
* @retval -ENOTSUP when not implemented by underlying file system driver;
|
* @retval -ENOTSUP when not implemented by underlying file system driver;
|
||||||
|
* @retval -EACCES when trying to truncate a file without opening it for write.
|
||||||
* @retval <0 an other negative errno code, depending on a file system back-end.
|
* @retval <0 an other negative errno code, depending on a file system back-end.
|
||||||
*/
|
*/
|
||||||
int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags);
|
int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags);
|
||||||
|
|
|
@ -134,6 +134,7 @@ int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags)
|
||||||
{
|
{
|
||||||
struct fs_mount_t *mp;
|
struct fs_mount_t *mp;
|
||||||
int rc = -EINVAL;
|
int rc = -EINVAL;
|
||||||
|
bool truncate_file = false;
|
||||||
|
|
||||||
if ((file_name == NULL) ||
|
if ((file_name == NULL) ||
|
||||||
(strlen(file_name) <= 1) || (file_name[0] != '/')) {
|
(strlen(file_name) <= 1) || (file_name[0] != '/')) {
|
||||||
|
@ -160,6 +161,19 @@ int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((flags & FS_O_TRUNC) != 0) {
|
||||||
|
if ((flags & FS_O_WRITE) == 0) {
|
||||||
|
/** Truncate not allowed when file is not opened for write */
|
||||||
|
LOG_ERR("file should be opened for write to truncate!!");
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
CHECKIF(mp->fs->truncate == NULL) {
|
||||||
|
LOG_ERR("file truncation not supported!!");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
truncate_file = true;
|
||||||
|
}
|
||||||
|
|
||||||
zfp->mp = mp;
|
zfp->mp = mp;
|
||||||
rc = mp->fs->open(zfp, file_name, flags);
|
rc = mp->fs->open(zfp, file_name, flags);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
@ -168,6 +182,16 @@ int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (truncate_file) {
|
||||||
|
/* Truncate the opened file to 0 length */
|
||||||
|
rc = mp->fs->truncate(zfp, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("file truncation failed (%d)", rc);
|
||||||
|
zfp->mp = NULL;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy flags to zfp for use with other fs_ API calls */
|
/* Copy flags to zfp for use with other fs_ API calls */
|
||||||
zfp->flags = flags;
|
zfp->flags = flags;
|
||||||
|
|
||||||
|
|
|
@ -149,9 +149,13 @@ void test_fs_open_flags(void)
|
||||||
ZOPEN(&ts, FS_O_READ, -ENOENT);
|
ZOPEN(&ts, FS_O_READ, -ENOENT);
|
||||||
ZOPEN(&ts, FS_O_RDWR, -ENOENT);
|
ZOPEN(&ts, FS_O_RDWR, -ENOENT);
|
||||||
ZOPEN(&ts, FS_O_APPEND, -ENOENT);
|
ZOPEN(&ts, FS_O_APPEND, -ENOENT);
|
||||||
|
ZOPEN(&ts, FS_O_TRUNC, -EACCES);
|
||||||
ZOPEN(&ts, FS_O_APPEND | FS_O_READ, -ENOENT);
|
ZOPEN(&ts, FS_O_APPEND | FS_O_READ, -ENOENT);
|
||||||
ZOPEN(&ts, FS_O_APPEND | FS_O_WRITE, -ENOENT);
|
ZOPEN(&ts, FS_O_APPEND | FS_O_WRITE, -ENOENT);
|
||||||
ZOPEN(&ts, FS_O_APPEND | FS_O_RDWR, -ENOENT);
|
ZOPEN(&ts, FS_O_APPEND | FS_O_RDWR, -ENOENT);
|
||||||
|
ZOPEN(&ts, FS_O_TRUNC | FS_O_RDWR, -ENOENT);
|
||||||
|
ZOPEN(&ts, FS_O_TRUNC | FS_O_APPEND, -EACCES);
|
||||||
|
ZOPEN(&ts, FS_O_TRUNC | FS_O_RDWR | FS_O_APPEND, -ENOENT);
|
||||||
ZEND();
|
ZEND();
|
||||||
|
|
||||||
|
|
||||||
|
@ -319,6 +323,73 @@ void test_fs_open_flags(void)
|
||||||
ZUNLINK(&ts);
|
ZUNLINK(&ts);
|
||||||
ZEND();
|
ZEND();
|
||||||
|
|
||||||
|
/** FS_O_TRUNC tests */
|
||||||
|
ZBEGIN("Attempt truncate a new file without write access");
|
||||||
|
ZOPEN(&ts, FS_O_CREATE | FS_O_TRUNC, -EACCES);
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZEND();
|
||||||
|
|
||||||
|
ZBEGIN("Attempt truncate a new file with write access");
|
||||||
|
ZOPEN(&ts, FS_O_CREATE | FS_O_WRITE | FS_O_TRUNC, 0);
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZEND();
|
||||||
|
|
||||||
|
ZBEGIN("Attempt truncate existing with no write access");
|
||||||
|
ZMKEMPTY(&ts);
|
||||||
|
ZOPEN(&ts, FS_O_TRUNC, -EACCES);
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZEND();
|
||||||
|
|
||||||
|
ZBEGIN("Attempt truncate existing with write access");
|
||||||
|
ZMKEMPTY(&ts);
|
||||||
|
ZOPEN(&ts, FS_O_TRUNC | FS_O_WRITE, 0);
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZEND();
|
||||||
|
|
||||||
|
ZBEGIN("Attempt truncate existing with read access");
|
||||||
|
ZMKEMPTY(&ts);
|
||||||
|
ZOPEN(&ts, FS_O_READ | FS_O_TRUNC, -EACCES);
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZEND();
|
||||||
|
|
||||||
|
ZBEGIN("Attempt truncate existing with R/W access");
|
||||||
|
ZMKEMPTY(&ts);
|
||||||
|
ZOPEN(&ts, FS_O_RDWR | FS_O_TRUNC, 0);
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZEND();
|
||||||
|
|
||||||
|
ZBEGIN("Attempt read on truncated file but no read access");
|
||||||
|
ZMKEMPTY(&ts);
|
||||||
|
ZOPEN(&ts, FS_O_WRITE | FS_O_TRUNC, 0);
|
||||||
|
#ifndef BYPASS_FS_OPEN_FLAGS_LFS_ASSERT_CRASH
|
||||||
|
ZREAD(&ts, -EACCES);
|
||||||
|
#else
|
||||||
|
TC_PRINT("Read bypassed\n");
|
||||||
|
#endif
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZEND();
|
||||||
|
|
||||||
|
ZBEGIN("Attempt append existing with WRITE access truncated file");
|
||||||
|
ZMKEMPTY(&ts);
|
||||||
|
ZOPEN(&ts, FS_O_APPEND | FS_O_WRITE | FS_O_TRUNC, 0);
|
||||||
|
ZCHKPOS(&ts, 0);
|
||||||
|
ZWRITE(&ts, ts.write_size);
|
||||||
|
#ifndef BYPASS_FS_OPEN_FLAGS_LFS_ASSERT_CRASH
|
||||||
|
ZREAD(&ts, -EACCES);
|
||||||
|
#else
|
||||||
|
TC_PRINT("Read bypassed\n");
|
||||||
|
#endif
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZEND();
|
||||||
|
|
||||||
|
|
||||||
/* This is simple check by file position, not contents. Since writing
|
/* This is simple check by file position, not contents. Since writing
|
||||||
* same pattern twice, the position of file should be twice the
|
* same pattern twice, the position of file should be twice the
|
||||||
|
@ -355,4 +426,24 @@ void test_fs_open_flags(void)
|
||||||
ZCLOSE(&ts);
|
ZCLOSE(&ts);
|
||||||
ZUNLINK(&ts);
|
ZUNLINK(&ts);
|
||||||
ZEND();
|
ZEND();
|
||||||
|
|
||||||
|
|
||||||
|
ZBEGIN("Check if file is truncated with data");
|
||||||
|
/* Prepare file */
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZOPEN(&ts, FS_O_CREATE | FS_O_WRITE, 0);
|
||||||
|
ZWRITE(&ts, ts.write_size);
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
|
||||||
|
/* Make sure file has the content */
|
||||||
|
ZOPEN(&ts, FS_O_CREATE | FS_O_READ, 0);
|
||||||
|
ZREAD(&ts, ts.write_size);
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
|
||||||
|
ZOPEN(&ts, FS_O_TRUNC | FS_O_RDWR, 0);
|
||||||
|
ZCHKPOS(&ts, 0);
|
||||||
|
ZREAD(&ts, 0);
|
||||||
|
ZCLOSE(&ts);
|
||||||
|
ZUNLINK(&ts);
|
||||||
|
ZEND();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue