diff --git a/minix/include/minix/vtreefs.h b/minix/include/minix/vtreefs.h index 00e6db0d3..7c1d6ed22 100644 --- a/minix/include/minix/vtreefs.h +++ b/minix/include/minix/vtreefs.h @@ -7,8 +7,9 @@ typedef void *cbdata_t; #define NO_INDEX ((index_t) -1) -/* Maximum file name length, excluding terminating null character. It is set - * to a low value to limit memory usage, but can be changed to any value. +/* Maximum file name length, excluding terminating null character, for which + * the name will be allocated statically. Longer names will be allocated + * dynamically, and should not be used for system-critical file systems. */ #define PNAME_MAX 24 diff --git a/minix/lib/libvtreefs/inode.c b/minix/lib/libvtreefs/inode.c index 3b40f8cb0..6ad4a4bee 100644 --- a/minix/lib/libvtreefs/inode.c +++ b/minix/lib/libvtreefs/inode.c @@ -70,6 +70,7 @@ init_inodes(unsigned int inodes, struct inode_stat * stat, for (i = 1; i < nr_inodes; i++) { node = &inode[i]; node->i_num = i; + node->i_name = NULL; node->i_parent = NULL; node->i_count = 0; TAILQ_INIT(&node->i_children); @@ -186,12 +187,13 @@ add_inode(struct inode * parent, const char * name, index_t index, cbdata_t cbdata) { struct inode *newnode; + char *newname; int slot; CHECK_INODE(parent); assert(S_ISDIR(parent->i_stat.mode)); assert(!(parent->i_flags & I_DELETED)); - assert(strlen(name) <= PNAME_MAX); + assert(strlen(name) <= NAME_MAX); assert(index >= 0 || index == NO_INDEX); assert(stat != NULL); assert(nr_indexed_entries >= 0); @@ -204,18 +206,28 @@ add_inode(struct inode * parent, const char * name, index_t index, assert(!TAILQ_EMPTY(&unused_inodes)); newnode = TAILQ_FIRST(&unused_inodes); + + /* Use the static name buffer if the name is short enough. Otherwise, + * allocate heap memory for the name. + */ + newname = newnode->i_namebuf; + if (strlen(name) > PNAME_MAX && + (newname = malloc(strlen(name) + 1)) == NULL) + return NULL; + TAILQ_REMOVE(&unused_inodes, newnode, i_unused); assert(newnode->i_count == 0); /* Copy the relevant data to the inode. */ newnode->i_parent = parent; + newnode->i_name = newname; newnode->i_flags = 0; newnode->i_index = index; newnode->i_stat = *stat; newnode->i_indexed = nr_indexed_entries; newnode->i_cbdata = cbdata; - strlcpy(newnode->i_name, name, sizeof(newnode->i_name)); + strcpy(newnode->i_name, name); /* Clear the extra data for this inode, if present. */ clear_inode_extra(newnode); @@ -255,6 +267,8 @@ get_inode_name(const struct inode * node) { CHECK_INODE(node); + assert(!(node->i_flags & I_DELETED)); + assert(node->i_name != NULL); return node->i_name; } @@ -394,7 +408,7 @@ get_inode_by_name(const struct inode * parent, const char * name) int slot; CHECK_INODE(parent); - assert(strlen(name) <= PNAME_MAX); + assert(strlen(name) <= NAME_MAX); assert(S_ISDIR(parent->i_stat.mode)); /* Get the hash value, and search for the inode. */ @@ -547,6 +561,12 @@ delete_inode(struct inode * node) if (node->i_index != NO_INDEX) LIST_REMOVE(node, i_hindex); + /* Free the name if allocated dynamically. */ + assert(node->i_name != NULL); + if (node->i_name != node->i_namebuf) + free(node->i_name); + node->i_name = NULL; + node->i_flags |= I_DELETED; /* diff --git a/minix/lib/libvtreefs/inode.h b/minix/lib/libvtreefs/inode.h index 01716edd8..3340cca32 100644 --- a/minix/lib/libvtreefs/inode.h +++ b/minix/lib/libvtreefs/inode.h @@ -22,7 +22,8 @@ struct inode { /* Inode metadata */ struct inode_stat i_stat; /* POSIX attributes */ - char i_name[PNAME_MAX + 1]; /* name of the inode in the parent */ + char i_namebuf[PNAME_MAX + 1]; /* buffer for static (short) names */ + char *i_name; /* name of the inode in the parent */ unsigned int i_count; /* reference count */ index_t i_index; /* index number in parent / NO_INDEX */ int i_indexed; /* number of indexed entries */ diff --git a/minix/lib/libvtreefs/path.c b/minix/lib/libvtreefs/path.c index 23b8d68c8..7d604306a 100644 --- a/minix/lib/libvtreefs/path.c +++ b/minix/lib/libvtreefs/path.c @@ -18,7 +18,7 @@ fs_lookup(ino_t dir_nr, char * name, struct fsdriver_node * node_details, if (!S_ISDIR(node->i_stat.mode)) return ENOTDIR; - if (strlen(name) > PNAME_MAX) + if (strlen(name) > NAME_MAX) return ENAMETOOLONG; if (!strcmp(name, ".")) { diff --git a/minix/lib/libvtreefs/stadir.c b/minix/lib/libvtreefs/stadir.c index 5a4a5e5c8..bb15049db 100644 --- a/minix/lib/libvtreefs/stadir.c +++ b/minix/lib/libvtreefs/stadir.c @@ -116,7 +116,7 @@ fs_statvfs(struct statvfs * buf) { buf->f_flag = ST_NOTRUNC; - buf->f_namemax = PNAME_MAX; + buf->f_namemax = NAME_MAX; return OK; }