mirror of
https://github.com/apache/nuttx.git
synced 2026-06-02 17:48:54 +08:00
Various fixes to the recent, big procfs checkin
This commit is contained in:
+115
-99
@@ -540,10 +540,12 @@ static ssize_t part_procfs_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct part_procfs_file_s *attr;
|
||||
ssize_t ret, total = 0, blkpererase;
|
||||
FAR struct mtd_geometry_s geo;
|
||||
ssize_t total = 0;
|
||||
ssize_t blkpererase;
|
||||
ssize_t ret;
|
||||
#ifdef CONFIG_MTD_PARTITION_NAMES
|
||||
char partname[11];
|
||||
char partname[11];
|
||||
FAR const char *ptr;
|
||||
uint8_t x;
|
||||
#endif
|
||||
@@ -555,114 +557,128 @@ static ssize_t part_procfs_read(FAR struct file *filep, FAR char *buffer,
|
||||
attr = (FAR struct part_procfs_file_s *)filep->f_priv;
|
||||
DEBUGASSERT(attr);
|
||||
|
||||
/* Provide the requested data */
|
||||
/* If we are at the end of the list, then return 0 signifying the
|
||||
* end-of-file. This also handles the special case when there are
|
||||
* no registered MTD partitions.
|
||||
*/
|
||||
|
||||
if (attr->nextpart == g_pfirstpartition)
|
||||
if (attr->nextpart)
|
||||
{
|
||||
/* Output a header before the first entry */
|
||||
|
||||
if (attr->nextpart == g_pfirstpartition)
|
||||
{
|
||||
#ifdef CONFIG_MTD_PARTITION_NAMES
|
||||
total = snprintf(buffer, buflen, "Name Start Size");
|
||||
total = snprintf(buffer, buflen, "Name Start Size");
|
||||
#else
|
||||
total = snprintf(buffer, buflen, " Start Size");
|
||||
total = snprintf(buffer, buflen, " Start Size");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FS_PROCFS_EXCLUDE_MTD
|
||||
total += snprintf(&buffer[total], buflen - total, " MTD\n");
|
||||
total += snprintf(&buffer[total], buflen - total, " MTD\n");
|
||||
#else
|
||||
total += snprintf(&buffer[total], buflen - total, "\n");
|
||||
total += snprintf(&buffer[total], buflen - total, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Provide the requested data */
|
||||
|
||||
do
|
||||
{
|
||||
/* Get the geometry of the FLASH device */
|
||||
|
||||
ret = attr->nextpart->parent->ioctl(attr->nextpart->parent,
|
||||
MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("ERROR: mtd->ioctl failed: %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the number of blocks per erase. There must be an even number
|
||||
* of blocks in one erase blocks.
|
||||
*/
|
||||
|
||||
blkpererase = geo.erasesize / geo.blocksize;
|
||||
|
||||
/* Copy data from the next known partition */
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITION_NAMES
|
||||
if (attr->nextpart->name == NULL)
|
||||
{
|
||||
strcpy(partname, "(noname) ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = attr->nextpart->name;
|
||||
for (x = 0; x < sizeof(partname) - 1; x++)
|
||||
{
|
||||
/* Test for end of partition name */
|
||||
|
||||
if (*ptr == ',' || *ptr == '\0')
|
||||
{
|
||||
/* Perform space fill for alignment */
|
||||
|
||||
partname[x] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy next byte of partition name */
|
||||
|
||||
partname[x] = *ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
partname[x] = '\0';
|
||||
}
|
||||
|
||||
/* Terminate the partition name and add to output buffer */
|
||||
|
||||
ret = snprintf(&buffer[total], buflen - total, "%s%7d %7d",
|
||||
partname, attr->nextpart->firstblock / blkpererase,
|
||||
attr->nextpart->neraseblocks);
|
||||
#else
|
||||
ret = snprintf(&buffer[total], buflen - total, "%7d %7d",
|
||||
attr->nextpart->firstblock / blkpererase,
|
||||
attr->nextpart->neraseblocks);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FS_PROCFS_EXCLUDE_MTD
|
||||
if (ret + total < buflen)
|
||||
{
|
||||
ret += snprintf(&buffer[total + ret], buflen - (total + ret),
|
||||
" %s\n", attr->nextpart->parent->name);
|
||||
}
|
||||
#else
|
||||
if (ret + total < buflen)
|
||||
{
|
||||
ret += snprintf(&buffer[total + ret], buflen - (total + ret),
|
||||
"\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret + total < buflen)
|
||||
{
|
||||
/* It fit in the buffer totally. Advance total and move to
|
||||
* next partition.
|
||||
*/
|
||||
|
||||
total += ret;
|
||||
attr->nextpart = attr->nextpart->pnext;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This one didn't fit completely. Truncate the partial
|
||||
* entry and break the loop.
|
||||
*/
|
||||
|
||||
buffer[total] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (attr->nextpart);
|
||||
}
|
||||
|
||||
while (attr->nextpart)
|
||||
{
|
||||
/* Get the geometry of the FLASH device */
|
||||
|
||||
ret = attr->nextpart->parent->ioctl(attr->nextpart->parent, MTDIOC_GEOMETRY,
|
||||
(unsigned long)((uintptr_t)&geo));
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("ERROR: mtd->ioctl failed: %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the number of blocks per erase. There must be an even number of
|
||||
* blocks in one erase blocks.
|
||||
*/
|
||||
|
||||
blkpererase = geo.erasesize / geo.blocksize;
|
||||
|
||||
/* Copy data from the next known partition */
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITION_NAMES
|
||||
if (attr->nextpart->name == NULL)
|
||||
{
|
||||
strcpy(partname, "(noname) ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = attr->nextpart->name;
|
||||
for (x = 0; x < sizeof(partname) - 1; x++)
|
||||
{
|
||||
/* Test for end of partition name */
|
||||
|
||||
if (*ptr == ',' || *ptr == '\0')
|
||||
{
|
||||
/* Perform space fill for alignment */
|
||||
|
||||
partname[x] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy next byte of partition name */
|
||||
|
||||
partname[x] = *ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
partname[x] = '\0';
|
||||
}
|
||||
|
||||
/* Terminate the partition name and add to output buffer */
|
||||
|
||||
ret = snprintf(&buffer[total], buflen - total, "%s%7d %7d",
|
||||
partname, attr->nextpart->firstblock / blkpererase,
|
||||
attr->nextpart->neraseblocks);
|
||||
#else
|
||||
ret = snprintf(&buffer[total], buflen - total, "%7d %7d",
|
||||
attr->nextpart->firstblock / blkpererase,
|
||||
attr->nextpart->neraseblocks);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FS_PROCFS_EXCLUDE_MTD
|
||||
if (ret + total < buflen)
|
||||
{
|
||||
ret += snprintf(&buffer[total + ret], buflen - (total + ret),
|
||||
" %s\n", attr->nextpart->parent->name);
|
||||
}
|
||||
#else
|
||||
if (ret + total < buflen)
|
||||
{
|
||||
ret += snprintf(&buffer[total + ret], buflen - (total + ret), "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret + total < buflen)
|
||||
{
|
||||
/* It fit in the buffer totally. Advance total and move to
|
||||
* next partition.
|
||||
*/
|
||||
total += ret;
|
||||
attr->nextpart = attr->nextpart->pnext;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This one didn't fit completely. Truncate the partial
|
||||
* entry and break the loop.
|
||||
*/
|
||||
buffer[total] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the file offset */
|
||||
|
||||
if (total > 0)
|
||||
|
||||
+29
-17
@@ -199,7 +199,8 @@ static ssize_t mtd_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct mtd_file_s *priv;
|
||||
ssize_t total = 0, ret;
|
||||
ssize_t total = 0;
|
||||
ssize_t ret;
|
||||
|
||||
fvdbg("buffer=%p buflen=%d\n", buffer, (int)buflen);
|
||||
|
||||
@@ -208,28 +209,39 @@ static ssize_t mtd_read(FAR struct file *filep, FAR char *buffer,
|
||||
priv = (FAR struct mtd_file_s *)filep->f_priv;
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Provide the requested data */
|
||||
/* If we are at the end of the list, then return 0 signifying the
|
||||
* end-of-file. This also handles the special case when there are
|
||||
* no registered MTD devices.
|
||||
*/
|
||||
|
||||
if (priv->pnextmtd == g_pfirstmtd)
|
||||
if (priv->pnextmtd)
|
||||
{
|
||||
total = snprintf(buffer, buflen, "Num Device\n");
|
||||
}
|
||||
/* Output a header before the first entry */
|
||||
|
||||
while (priv->pnextmtd)
|
||||
{
|
||||
ret = snprintf(&buffer[total], buflen - total, "%-5d%s\n",
|
||||
priv->pnextmtd->mtdno, priv->pnextmtd->name);
|
||||
if (priv->pnextmtd == g_pfirstmtd)
|
||||
{
|
||||
total = snprintf(buffer, buflen, "Num Device\n");
|
||||
}
|
||||
|
||||
if (ret + total < buflen)
|
||||
/* The provide the requested data */
|
||||
|
||||
do
|
||||
{
|
||||
total += ret;
|
||||
priv->pnextmtd = priv->pnextmtd->pnext;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[total] = '\0';
|
||||
break;
|
||||
ret = snprintf(&buffer[total], buflen - total, "%-5d%s\n",
|
||||
priv->pnextmtd->mtdno, priv->pnextmtd->name);
|
||||
|
||||
if (ret + total < buflen)
|
||||
{
|
||||
total += ret;
|
||||
priv->pnextmtd = priv->pnextmtd->pnext;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[total] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (priv->pnextmtd);
|
||||
}
|
||||
|
||||
/* Update the file offset */
|
||||
|
||||
@@ -384,6 +384,7 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
FAR struct procfs_level0_s *level0;
|
||||
FAR struct procfs_dir_priv_s *dirpriv;
|
||||
FAR void *priv = NULL;
|
||||
irqstate_t flags;
|
||||
|
||||
@@ -448,7 +449,10 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
|
||||
if (match(g_procfsentries[x].pathpattern, relpath))
|
||||
{
|
||||
/* Match found! Call the handler's opendir routine */
|
||||
/* 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);
|
||||
@@ -459,8 +463,8 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
|
||||
/* Set the procfs_entry handler */
|
||||
|
||||
level0 = (FAR struct procfs_level0_s *) dir->u.procfs;
|
||||
level0->procfsentry = &g_procfsentries[x];
|
||||
dirpriv = (FAR struct procfs_dir_priv_s *)dir->u.procfs;
|
||||
dirpriv->procfsentry = &g_procfsentries[x];
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -684,7 +688,7 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||
#endif /* CONFIG_FS_PROCFS_EXCLUDE_PROCESS */
|
||||
}
|
||||
|
||||
/* Are we reading in intermediate subdirectory? */
|
||||
/* Are we reading an intermediate subdirectory? */
|
||||
|
||||
else if (priv->level == 1 && priv->procfsentry == NULL)
|
||||
{
|
||||
|
||||
@@ -708,7 +708,6 @@ static int process_dup(FAR const struct file *oldp, FAR struct file *newp)
|
||||
static int process_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
FAR struct tcb_s *tcb;
|
||||
FAR void *priv = NULL;
|
||||
irqstate_t flags;
|
||||
|
||||
fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL");
|
||||
@@ -784,14 +783,15 @@ static int process_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
level1->base.level = 1;
|
||||
level1->base.nentries = PROCFS_NATTRS;
|
||||
level1->base.index = 0;
|
||||
level1->pid = pid;
|
||||
/* Note that the index and procentry pointer were implicitly nullified
|
||||
* by kzalloc(). Only the remaining, non-zero entries need be initialized.
|
||||
*/
|
||||
|
||||
priv = (FAR void *)level1;
|
||||
level1->base.level = 1;
|
||||
level1->base.nentries = PROCFS_NATTRS;
|
||||
level1->pid = pid;
|
||||
|
||||
dir->u.procfs = priv;
|
||||
dir->u.procfs = (FAR void *)level1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -969,12 +969,28 @@ static int process_stat(const char *relpath, struct stat *buf)
|
||||
|
||||
buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR;
|
||||
}
|
||||
|
||||
/* Verify that the process ID is followed by valid path segment delimiter */
|
||||
|
||||
else if (*ptr != '/')
|
||||
{
|
||||
/* We are required to return -ENOENT all all invalid paths */
|
||||
|
||||
fdbg("ERROR: Bad delimiter '%c' in relpath '%s'\n", *ptr, relpath);
|
||||
return -ENOENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, the second segment of the relpath should be a well
|
||||
* known attribute of the task/thread.
|
||||
*/
|
||||
|
||||
/* Skip over the path segment delimiter */
|
||||
|
||||
ptr++;
|
||||
|
||||
/* Lookup the well-known attribute string. */
|
||||
|
||||
ret = process_findattr(ptr);
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -982,7 +998,7 @@ static int process_stat(const char *relpath, struct stat *buf)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* It's a read-only file name */
|
||||
/* If the attribute exists, it is the name for a read-only file. */
|
||||
|
||||
buf->st_mode = S_IFREG|S_IROTH|S_IRGRP|S_IRUSR;
|
||||
}
|
||||
|
||||
+11
-11
@@ -52,9 +52,9 @@
|
||||
|
||||
struct procfs_operations
|
||||
{
|
||||
/* The mountpoint open method differs from the driver open method
|
||||
* because it receives (1) the inode that contains the mountpoint
|
||||
* private data, (2) the relative path into the mountpoint, and (3)
|
||||
/* The procfs open method differs from the driver open method
|
||||
* because it receives (1) the inode that contains the procfs
|
||||
* private data, (2) the relative path into the procfs, and (3)
|
||||
* information to manage privileges.
|
||||
*/
|
||||
|
||||
@@ -74,7 +74,7 @@ struct procfs_operations
|
||||
* are extended methods needed to deal with the unique needs of mounted
|
||||
* file systems.
|
||||
*
|
||||
* Additional open-file-specific mountpoint operations:
|
||||
* Additional open-file-specific procfs operations:
|
||||
*/
|
||||
|
||||
int (*dup)(FAR const struct file *oldp, FAR struct file *newp);
|
||||
@@ -99,8 +99,8 @@ struct procfs_operations
|
||||
|
||||
struct procfs_entry_s
|
||||
{
|
||||
FAR const char *pathpattern;
|
||||
const struct procfs_operations *ops;
|
||||
FAR const char *pathpattern;
|
||||
FAR const struct procfs_operations *ops;
|
||||
};
|
||||
|
||||
/* Specifies the common elements for an open file in the procfs
|
||||
@@ -110,17 +110,17 @@ struct procfs_entry_s
|
||||
|
||||
struct procfs_file_s
|
||||
{
|
||||
const struct procfs_entry_s *pProcfsEntry;
|
||||
FAR const struct procfs_entry_s *procfsentry;
|
||||
};
|
||||
|
||||
/* The generic proc/ pseudo directory structure */
|
||||
|
||||
struct procfs_dir_priv_s
|
||||
{
|
||||
uint8_t level; /* Directory level. Currently 0 or 1 */
|
||||
uint16_t index; /* Index to the next directory entry */
|
||||
uint16_t nentries; /* Number of directory entries */
|
||||
struct procfs_entry_s *pProcfsEntry; /* Pointer to procfs handler entry */
|
||||
uint8_t level; /* Directory level. Currently 0 or 1 */
|
||||
uint16_t index; /* Index to the next directory entry */
|
||||
uint16_t nentries; /* Number of directory entries */
|
||||
FAR const struct procfs_entry_s *procfsentry; /* Pointer to procfs handler entry */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user