diff --git a/ChangeLog b/ChangeLog index 08adf37518..8921efdc04 100755 --- a/ChangeLog +++ b/ChangeLog @@ -11189,3 +11189,9 @@ * net/: Remove CONFIG_NET_PINGADDRCONF. This was a uIP way of assigning IP addresses, but is not standard and not a appropriate feature in general (2015-12-01). + * fs/procfs: The procfs file system can now be configured so that it + supports a runtime registration of procfs entries with + CONFIG_FS_PROCFS_REGISTER=y (2015-12-01). + * arch/arm/src/stm32/stm32_ccm_procfs.c: Is no longer a part of the + 'base' procfs entries and can now only be supported via run time + registration with CONFIG_FS_PROCFS_REGISTER=y (2015-12-01). diff --git a/arch b/arch index 350314f22d..0dc110a8fa 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 350314f22d2357cf4f67b384c89eaa92715758c3 +Subproject commit 0dc110a8fa020ed7c301fe0cdcb836ee8ea939e9 diff --git a/fs/procfs/Kconfig b/fs/procfs/Kconfig index 2b4fe81af2..39d5011842 100644 --- a/fs/procfs/Kconfig +++ b/fs/procfs/Kconfig @@ -15,6 +15,13 @@ config FS_PROCFS if FS_PROCFS +config FS_PROCFS_REGISTER + bool "Run-time registration" + default n + ---help--- + Support run-time registration of the new entries in the procfs file + system. + menu "Exclude individual procfs entries" config FS_PROCFS_EXCLUDE_PROCESS @@ -59,10 +66,5 @@ config FS_PROCFS_EXCLUDE_SMARTFS depends on FS_SMARTFS default n -config FS_PROCFS_EXCLUDE_CCM - bool "Exclude CCM memory usage" - depends on STM32_CCM_PROCFS - default n - endmenu # endif # FS_PROCFS diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c index 951f3caa5d..d96fabca9a 100644 --- a/fs/procfs/fs_procfs.c +++ b/fs/procfs/fs_procfs.c @@ -104,7 +104,11 @@ extern const struct procfs_operations ccm_procfsoperations; ****************************************************************************/ /* Table of all known / pre-registered procfs handlers / participants. */ -static const struct procfs_entry_s g_procfsentries[] = +#ifdef CONFIG_FS_PROCFS_REGISTER +static const struct procfs_entry_s g_base_entries[] = +#else +static const struct procfs_entry_s g_procfs_entries[] = +#endif { #ifndef CONFIG_FS_PROCFS_EXCLUDE_PROCESS { "[0-9]*/**", &proc_operations }, @@ -136,14 +140,18 @@ static const struct procfs_entry_s g_procfsentries[] = #if !defined(CONFIG_FS_PROCFS_EXCLUDE_UPTIME) { "uptime", &uptime_operations }, #endif - -#if defined(CONFIG_STM32_CCM_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_CCM) - { "ccm", &ccm_procfsoperations }, -#endif }; -static const uint8_t g_procfsentrycount = sizeof(g_procfsentries) / +#ifdef CONFIG_FS_PROCFS_REGISTER +static const uint8_t g_base_entrycount = sizeof(g_base_entries) / + sizeof(struct procfs_entry_s); + +static FAR struct procfs_entry_s *g_procfs_entries; +static uint8_t g_procfs_entrycount; +#else +static const uint8_t g_procfs_entrycount = sizeof(g_procfs_entries) / sizeof(struct procfs_entry_s); +#endif /**************************************************************************** * Private Function Prototypes @@ -186,6 +194,14 @@ static int procfs_statfs(FAR struct inode *mountpt, static int procfs_stat(FAR struct inode *mountpt, FAR const char *relpath, FAR struct stat *buf); +/* Initialization */ + +#ifdef CONFIG_FS_PROCFS_REGISTER +int procfs_initialize(void); +#else +# define procfs_initialize() +#endif + /**************************************************************************** * Private Variables ****************************************************************************/ @@ -301,25 +317,25 @@ static int procfs_open(FAR struct file *filep, FAR const char *relpath, /* Perform the stat based on the procfs_entry operations */ - for (x = 0; x < g_procfsentrycount; x++) + for (x = 0; x < g_procfs_entrycount; x++) { /* Test if the path matches this entry's specification */ - if (match(g_procfsentries[x].pathpattern, relpath)) + if (match(g_procfs_entries[x].pathpattern, relpath)) { /* Match found! Stat using this procfs entry */ - DEBUGASSERT(g_procfsentries[x].ops && - g_procfsentries[x].ops->open); + DEBUGASSERT(g_procfs_entries[x].ops && + g_procfs_entries[x].ops->open); - ret = g_procfsentries[x].ops->open(filep, relpath, oflags, mode); + ret = g_procfs_entries[x].ops->open(filep, relpath, oflags, mode); if (ret == OK) { DEBUGASSERT(filep->f_priv); ((struct procfs_file_s *) filep->f_priv)->procfsentry = - &g_procfsentries[x]; + &g_procfs_entries[x]; } } } @@ -506,19 +522,19 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, /* Search the static array of procfs_entries */ - for (x = 0; x < g_procfsentrycount; x++) + for (x = 0; x < g_procfs_entrycount; x++) { /* Test if the path matches this entry's specification */ - if (match(g_procfsentries[x].pathpattern, relpath)) + if (match(g_procfs_entries[x].pathpattern, relpath)) { /* Match found! Call the handler's opendir routine. If successful, * this opendir routine will create an entry derived from struct * procfs_dir_priv_s as dir->u.procfs. */ - DEBUGASSERT(g_procfsentries[x].ops && g_procfsentries[x].ops->opendir); - ret = g_procfsentries[x].ops->opendir(relpath, dir); + DEBUGASSERT(g_procfs_entries[x].ops && g_procfs_entries[x].ops->opendir); + ret = g_procfs_entries[x].ops->opendir(relpath, dir); if (ret == OK) { @@ -527,7 +543,7 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, /* Set the procfs_entry handler */ dirpriv = (FAR struct procfs_dir_priv_s *)dir->u.procfs; - dirpriv->procfsentry = &g_procfsentries[x]; + dirpriv->procfsentry = &g_procfs_entries[x]; } return ret; @@ -535,7 +551,7 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, /* Test for a sub-string match (e.g. "ls /proc/fs") */ - else if (strncmp(g_procfsentries[x].pathpattern, relpath, len) == 0) + else if (strncmp(g_procfs_entries[x].pathpattern, relpath, len) == 0) { FAR struct procfs_level1_s *level1; @@ -635,9 +651,9 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) * directory name. */ - while (index < priv->nentries + g_procfsentrycount) + while (index < priv->nentries + g_procfs_entrycount) { - name = g_procfsentries[index - priv->nentries].pathpattern; + name = g_procfs_entries[index - priv->nentries].pathpattern; while (*name != '/' && *name != '\0') { if (*name == '*' || *name == '[' || *name == '?') @@ -665,7 +681,7 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) * fs/nxffs */ - name = g_procfsentries[index - priv->nentries].pathpattern; + name = g_procfs_entries[index - priv->nentries].pathpattern; if (!level0->lastlen || (strncmp(name, level0->lastread, level0->lastlen) != 0)) { @@ -686,7 +702,7 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) /* Test if we are at the end of the directory */ - if (index >= priv->nentries + g_procfsentrycount) + if (index >= priv->nentries + g_procfs_entrycount) { /* We signal the end of the directory by returning the special * error -ENOENT @@ -763,13 +779,13 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) * subdirectory are listed in order in the procfs_entry array. */ - if (strncmp(g_procfsentries[level1->base.index].pathpattern, - g_procfsentries[level1->firstindex].pathpattern, + if (strncmp(g_procfs_entries[level1->base.index].pathpattern, + g_procfs_entries[level1->firstindex].pathpattern, level1->subdirlen) == 0) { /* This entry matches. Report the subdir entry */ - name = &g_procfsentries[level1->base.index].pathpattern[ + name = &g_procfs_entries[level1->base.index].pathpattern[ level1->subdirlen + 1]; level1->lastlen = strcspn(name, "/"); level1->lastread = name; @@ -859,6 +875,9 @@ static int procfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir) static int procfs_bind(FAR struct inode *blkdriver, const void *data, void **handle) { + /* Make sure that we are properly initialized */ + + procfs_initialize(); return OK; } @@ -933,23 +952,23 @@ static int procfs_stat(struct inode *mountpt, const char *relpath, /* Perform the stat based on the procfs_entry operations */ - for (x = 0; x < g_procfsentrycount; x++) + for (x = 0; x < g_procfs_entrycount; x++) { /* Test if the path matches this entry's specification */ - if (match(g_procfsentries[x].pathpattern, relpath)) + if (match(g_procfs_entries[x].pathpattern, relpath)) { /* Match found! Stat using this procfs entry */ - DEBUGASSERT(g_procfsentries[x].ops && - g_procfsentries[x].ops->stat); + DEBUGASSERT(g_procfs_entries[x].ops && + g_procfs_entries[x].ops->stat); - return g_procfsentries[x].ops->stat(relpath, buf); + return g_procfs_entries[x].ops->stat(relpath, buf); } /* Test for an internal subdirectory stat */ - else if (strncmp(g_procfsentries[x].pathpattern, relpath, len) == 0) + else if (strncmp(g_procfs_entries[x].pathpattern, relpath, len) == 0) { /* It's an internal subdirectory */ @@ -968,8 +987,98 @@ static int procfs_stat(struct inode *mountpt, const char *relpath, return ret; } +/**************************************************************************** + * Name: procfs_initialize + * + * Description: + * Configure the initial set of entries in the procfs file system. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure + * + ****************************************************************************/ + +#ifdef CONFIG_FS_PROCFS_REGISTER +int procfs_initialize(void) +{ + /* Are we already initialized? */ + + if (g_procfs_entries == NULL) + { + /* No.. allocate a modifyable list of entries */ + + g_procfs_entries = (FAR struct procfs_entry_s *) + kmm_malloc(sizeof(g_base_entries)); + + if (g_procfs_entries == NULL) + { + return -ENOMEM; + } + + /* And copy the fixed entries into the allocated array */ + + memcpy(g_procfs_entries, g_base_entries, sizeof(g_base_entries)); + g_procfs_entrycount = g_base_entrycount; + } + + return OK; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: procfs_register + * + * Description: + * Add a new entry to the procfs file system. + * + * Input Parameters: + * entry - Describes the entry to be registered. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure + * + ****************************************************************************/ + +#ifdef CONFIG_FS_PROCFS_REGISTER +int procfs_register(FAR const struct procfs_file_s *entry) +{ + FAR struct procfs_entry_s *newtable; + unsigned int newcount; + size_t newsize; + int ret; + + /* Make sure that we are properly initialized */ + + procfs_initialize(); + + /* realloc the procfs entries */ + + newcount = g_procfs_entrycount + 1; + newsize = newcount * sizeof(struct procfs_entry_s); + + sched_lock(); + newtable = (FAR struct procfs_entry_s *)realloc(g_procfs_entries, newsize); + if (newtable == NULL) + { + ret = -ENOMEM; + } + else + { + memcpy(&newtable[g_procfs_entrycount], entry, sizeof(struct procfs_entry_s)); + g_procfs_entrycount = newcount; + ret = OK; + } + + sched_unlock(); + return ret; +} +#endif + #endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */ diff --git a/include/nuttx/fs/procfs.h b/include/nuttx/fs/procfs.h index 7dfb6da123..3188f6159a 100644 --- a/include/nuttx/fs/procfs.h +++ b/include/nuttx/fs/procfs.h @@ -180,6 +180,24 @@ size_t procfs_memcpy(FAR const char *src, size_t srclen, FAR char *dest, size_t destlen, off_t *offset); +/**************************************************************************** + * Name: procfs_register + * + * Description: + * Add a new entry to the procfs file system. + * + * Input Parameters: + * entry - Describes the entry to be registered. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure + * + ****************************************************************************/ + +#ifdef CONFIG_FS_PROCFS_REGISTER +int procfs_register(FAR const struct procfs_file_s *entry); +#endif + #undef EXTERN #ifdef __cplusplus }