diff --git a/fs/tmpfs/fs_tmpfs.c b/fs/tmpfs/fs_tmpfs.c index 46a5bf1001..e4f5e6b257 100644 --- a/fs/tmpfs/fs_tmpfs.c +++ b/fs/tmpfs/fs_tmpfs.c @@ -37,6 +37,7 @@ #include #include +#include "inode/inode.h" #include "fs_tmpfs.h" #ifndef CONFIG_DISABLE_MOUNTPOINT @@ -100,10 +101,12 @@ static int tmpfs_remove_dirent(FAR struct tmpfs_directory_s *tdo, FAR const char *name); static int tmpfs_add_dirent(FAR struct tmpfs_directory_s *tdo, FAR struct tmpfs_object_s *to, FAR const char *name); -static FAR struct tmpfs_file_s *tmpfs_alloc_file(void); +static FAR struct tmpfs_file_s * +tmpfs_alloc_file(FAR struct tmpfs_directory_s *parent); static int tmpfs_create_file(FAR struct tmpfs_s *fs, FAR const char *relpath, FAR struct tmpfs_file_s **tfo); -static FAR struct tmpfs_directory_s *tmpfs_alloc_directory(void); +static FAR struct tmpfs_directory_s * +tmpfs_alloc_directory(FAR struct tmpfs_directory_s *parent); static int tmpfs_create_directory(FAR struct tmpfs_s *fs, FAR const char *relpath, FAR struct tmpfs_directory_s **tdo); static int tmpfs_find_object(FAR struct tmpfs_s *fs, @@ -135,6 +138,7 @@ static ssize_t tmpfs_read(FAR struct file *filep, FAR char *buffer, static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); static off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence); +static int tmpfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); static int tmpfs_sync(FAR struct file *filep); static int tmpfs_dup(FAR const struct file *oldp, FAR struct file *newp); static int tmpfs_fstat(FAR const struct file *filep, FAR struct stat *buf); @@ -178,7 +182,7 @@ const struct mountpt_operations g_tmpfs_operations = tmpfs_read, /* read */ tmpfs_write, /* write */ tmpfs_seek, /* seek */ - NULL, /* ioctl */ + tmpfs_ioctl, /* ioctl */ tmpfs_mmap, /* mmap */ tmpfs_truncate, /* truncate */ NULL, /* poll */ @@ -523,6 +527,7 @@ static int tmpfs_add_dirent(FAR struct tmpfs_directory_s *tdo, /* Save the new object info in the new directory entry */ + to->to_parent = tdo; tde = &tdo->tdo_entry[index]; tde->tde_object = to; tde->tde_name = newname; @@ -534,7 +539,8 @@ static int tmpfs_add_dirent(FAR struct tmpfs_directory_s *tdo, * Name: tmpfs_alloc_file ****************************************************************************/ -static FAR struct tmpfs_file_s *tmpfs_alloc_file(void) +static FAR struct tmpfs_file_s * +tmpfs_alloc_file(FAR struct tmpfs_directory_s *parent) { FAR struct tmpfs_file_s *tfo; @@ -550,12 +556,13 @@ static FAR struct tmpfs_file_s *tmpfs_alloc_file(void) * locked with one reference count. */ - tfo->tfo_alloc = 0; - tfo->tfo_type = TMPFS_REGULAR; - tfo->tfo_refs = 1; - tfo->tfo_flags = 0; - tfo->tfo_size = 0; - tfo->tfo_data = NULL; + tfo->tfo_alloc = 0; + tfo->tfo_type = TMPFS_REGULAR; + tfo->tfo_refs = 1; + tfo->tfo_parent = parent; + tfo->tfo_flags = 0; + tfo->tfo_size = 0; + tfo->tfo_data = NULL; nxrmutex_init(&tfo->tfo_lock); tmpfs_lock_file(tfo); @@ -643,7 +650,7 @@ static int tmpfs_create_file(FAR struct tmpfs_s *fs, * one reference count. */ - newtfo = tmpfs_alloc_file(); + newtfo = tmpfs_alloc_file(parent); if (newtfo == NULL) { ret = -ENOMEM; @@ -684,7 +691,8 @@ errout_with_parent: * Name: tmpfs_alloc_directory ****************************************************************************/ -static FAR struct tmpfs_directory_s *tmpfs_alloc_directory(void) +static FAR struct tmpfs_directory_s * +tmpfs_alloc_directory(FAR struct tmpfs_directory_s *parent) { FAR struct tmpfs_directory_s *tdo; @@ -701,6 +709,7 @@ static FAR struct tmpfs_directory_s *tmpfs_alloc_directory(void) tdo->tdo_alloc = 0; tdo->tdo_type = TMPFS_DIRECTORY; tdo->tdo_refs = 0; + tdo->tdo_parent = parent; tdo->tdo_nentries = 0; tdo->tdo_entry = NULL; @@ -788,7 +797,7 @@ static int tmpfs_create_directory(FAR struct tmpfs_s *fs, * the new directory and the object is not locked. */ - newtdo = tmpfs_alloc_directory(); + newtdo = tmpfs_alloc_directory(parent); if (newtdo == NULL) { ret = -ENOMEM; @@ -1070,6 +1079,52 @@ static int tmpfs_find_directory(FAR struct tmpfs_s *fs, return ret; } +/**************************************************************************** + * Name: tmpfs_getpath + ****************************************************************************/ + +static int tmpfs_getpath(FAR struct tmpfs_object_s *to, + FAR char *path, size_t len) +{ + FAR struct tmpfs_dirent_s *tde = NULL; + FAR struct tmpfs_directory_s *tdo; + uint16_t i; + + if (to->to_parent != NULL) + { + int ret = tmpfs_getpath((FAR struct tmpfs_object_s *)to->to_parent, + path, len); + if (ret < 0) + { + return ret; + } + + tdo = to->to_parent; + + for (i = 0; i < tdo->tdo_nentries; i++) + { + tde = &tdo->tdo_entry[i]; + if (to == tde->tde_object) + { + break; + } + } + + if (i == tdo->tdo_nentries) + { + return -ENOENT; + } + + strlcat(path, tde->tde_name, len); + if (to->to_type == TMPFS_DIRECTORY) + { + strlcat(path, "/", len); + } + } + + return OK; +} + /**************************************************************************** * Name: tmpfs_statfs_callout ****************************************************************************/ @@ -1712,6 +1767,44 @@ static int tmpfs_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map) return ret; } +/**************************************************************************** + * Name: tmpfs_ioctl + ****************************************************************************/ + +static int tmpfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct tmpfs_file_s *tfo; + int ret = -ENOTTY; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL); + + /* Recover our private data from the struct file instance */ + + tfo = filep->f_priv; + + /* Only one ioctl command is supported */ + + if (cmd == FIOC_FILEPATH) + { + FAR char *ptr = (FAR char *)((uintptr_t)arg); + ret = inode_getpath(filep->f_inode, ptr, PATH_MAX); + if (ret < 0) + { + return ret; + } + + ret = tmpfs_getpath((FAR struct tmpfs_object_s *)tfo, ptr, PATH_MAX); + if (ret < 0) + { + return ret; + } + } + + return ret; +} + /**************************************************************************** * Name: tmpfs_sync ****************************************************************************/ @@ -2071,7 +2164,7 @@ static int tmpfs_bind(FAR struct inode *blkdriver, FAR const void *data, * the file system structure. */ - tdo = tmpfs_alloc_directory(); + tdo = tmpfs_alloc_directory(NULL); if (tdo == NULL) { kmm_free(fs); diff --git a/fs/tmpfs/fs_tmpfs.h b/fs/tmpfs/fs_tmpfs.h index 49a640fff9..0a352dd51c 100644 --- a/fs/tmpfs/fs_tmpfs.h +++ b/fs/tmpfs/fs_tmpfs.h @@ -79,6 +79,7 @@ struct tmpfs_object_s size_t to_alloc; /* Allocated size of the memory object */ uint8_t to_type; /* See enum tmpfs_objtype_e */ uint8_t to_refs; /* Reference count */ + FAR struct tmpfs_directory_s *to_parent; }; /* The form of a directory memory object */ @@ -92,6 +93,7 @@ struct tmpfs_directory_s size_t tdo_alloc; /* Allocated size of the directory object */ uint8_t tdo_type; /* See enum tmpfs_objtype_e */ uint8_t tdo_refs; /* Reference count */ + FAR struct tmpfs_directory_s *tdo_parent; /* Remaining fields are unique to a directory object */ @@ -118,6 +120,7 @@ struct tmpfs_file_s size_t tfo_alloc; /* Allocated size of the file object */ uint8_t tfo_type; /* See enum tmpfs_objtype_e */ uint8_t tfo_refs; /* Reference count */ + FAR struct tmpfs_directory_s *tfo_parent; /* Remaining fields are unique to a directory object */