diff mbox series

[1/1] fs: fat: structure for name and extension

Message ID 20210120235506.36134-1-xypron.glpk@gmx.de
State Accepted, archived
Commit 041f0af3668e037f465d0e80ea5561fb3fbaa7d0
Delegated to: Heinrich Schuchardt
Headers show
Series [1/1] fs: fat: structure for name and extension | expand

Commit Message

Heinrich Schuchardt Jan. 20, 2021, 11:55 p.m. UTC
The short name and extension of FAT files are stored in adjacent fields of
the directory entry. For some operations like calculating a checksum or
copying both fields it is preferable to treat both as one structure.

Change the definition of the directory entry structure to include a
structure comprising the name and the extension field.

This resolves Coverity CID 316357, CID 316350, CID 316348.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 fs/fat/fat.c       | 32 ++++++++++++++++----------------
 fs/fat/fat_write.c | 20 +++++++++-----------
 include/fat.h      |  7 ++++++-
 3 files changed, 31 insertions(+), 28 deletions(-)

--
2.29.2
diff mbox series

Patch

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 157dad60a4..fb6ce094ac 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -123,16 +123,16 @@  static void get_name(dir_entry *dirent, char *s_name)
 {
 	char *ptr;

-	memcpy(s_name, dirent->name, 8);
+	memcpy(s_name, dirent->nameext.name, 8);
 	s_name[8] = '\0';
 	ptr = s_name;
 	while (*ptr && *ptr != ' ')
 		ptr++;
 	if (dirent->lcase & CASE_LOWER_BASE)
 		downcase(s_name, (unsigned)(ptr - s_name));
-	if (dirent->ext[0] && dirent->ext[0] != ' ') {
+	if (dirent->nameext.ext[0] && dirent->nameext.ext[0] != ' ') {
 		*ptr++ = '.';
-		memcpy(ptr, dirent->ext, 3);
+		memcpy(ptr, dirent->nameext.ext, 3);
 		if (dirent->lcase & CASE_LOWER_EXT)
 			downcase(ptr, 3);
 		ptr[3] = '\0';
@@ -472,16 +472,15 @@  static int slot2str(dir_slot *slotptr, char *l_name, int *idx)
 }

 /* Calculate short name checksum */
-static __u8 mkcksum(const char name[8], const char ext[3])
+static __u8 mkcksum(struct nameext *nameext)
 {
 	int i;
+	u8 *pos = (void *)nameext;

 	__u8 ret = 0;

-	for (i = 0; i < 8; i++)
-		ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + name[i];
-	for (i = 0; i < 3; i++)
-		ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + ext[i];
+	for (i = 0; i < 11; i++)
+		ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + pos[i];

 	return ret;
 }
@@ -896,7 +895,7 @@  static dir_entry *next_dent(fat_itr *itr)
 	}

 	/* have we reached the last valid entry? */
-	if (itr->dent->name[0] == 0)
+	if (itr->dent->nameext.name[0] == 0)
 		return NULL;

 	return itr->dent;
@@ -905,7 +904,7 @@  static dir_entry *next_dent(fat_itr *itr)
 static dir_entry *extract_vfat_name(fat_itr *itr)
 {
 	struct dir_entry *dent = itr->dent;
-	int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK;
+	int seqn = itr->dent->nameext.name[0] & ~LAST_LONG_ENTRY_MASK;
 	u8 chksum, alias_checksum = ((dir_slot *)dent)->alias_checksum;
 	int n = 0;

@@ -932,18 +931,19 @@  static dir_entry *extract_vfat_name(fat_itr *itr)
 	 * We are now at the short file name entry.
 	 * If it is marked as deleted, just skip it.
 	 */
-	if (dent->name[0] == DELETED_FLAG ||
-	    dent->name[0] == aRING)
+	if (dent->nameext.name[0] == DELETED_FLAG ||
+	    dent->nameext.name[0] == aRING)
 		return NULL;

 	itr->l_name[n] = '\0';

-	chksum = mkcksum(dent->name, dent->ext);
+	chksum = mkcksum(&dent->nameext);

 	/* checksum mismatch could mean deleted file, etc.. skip it: */
 	if (chksum != alias_checksum) {
 		debug("** chksum=%x, alias_checksum=%x, l_name=%s, s_name=%8s.%3s\n",
-		      chksum, alias_checksum, itr->l_name, dent->name, dent->ext);
+		      chksum, alias_checksum, itr->l_name, dent->nameext.name,
+		      dent->nameext.ext);
 		return NULL;
 	}

@@ -984,12 +984,12 @@  static int fat_itr_next(fat_itr *itr)
 		itr->dent_rem = itr->remaining;
 		itr->dent_start = itr->dent;
 		itr->dent_clust = itr->clust;
-		if (dent->name[0] == DELETED_FLAG)
+		if (dent->nameext.name[0] == DELETED_FLAG)
 			continue;

 		if (dent->attr & ATTR_VOLUME) {
 			if ((dent->attr & ATTR_VFAT) == ATTR_VFAT &&
-			    (dent->name[0] & LAST_LONG_ENTRY_MASK)) {
+			    (dent->nameext.name[0] & LAST_LONG_ENTRY_MASK)) {
 				/* long file name */
 				dent = extract_vfat_name(itr);
 				/*
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 2f4391e86f..a17e51750c 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -275,7 +275,7 @@  static int fat_find_empty_dentries(fat_itr *itr, int count)
 			log_debug("Not enough directory entries available\n");
 			return -ENOSPC;
 		}
-		switch (itr->dent->name[0]) {
+		switch (itr->dent->nameext.name[0]) {
 		case 0x00:
 		case DELETED_FLAG:
 			if (!n) {
@@ -399,7 +399,7 @@  fill_dir_slot(fat_itr *itr, const char *l_name, const char *shortname)
 	int idx = 0, ret;

 	/* Get short file name checksum value */
-	checksum = mkcksum(shortname, shortname + 8);
+	checksum = mkcksum((void *)shortname);

 	do {
 		memset(slotptr, 0x00, sizeof(dir_slot));
@@ -1169,7 +1169,7 @@  static void fill_dentry(fsdata *mydata, dir_entry *dentptr,

 	dentptr->attr = attr;

-	memcpy(dentptr->name, shortname, SHORT_NAME_SIZE);
+	memcpy(&dentptr->nameext, shortname, SHORT_NAME_SIZE);
 }

 /**
@@ -1194,7 +1194,7 @@  static dir_entry *find_directory_entry(fat_itr *itr, char *filename)
 		if (!match)
 			continue;

-		if (itr->dent->name[0] == '\0')
+		if (itr->dent->nameext.name[0] == '\0')
 			return NULL;
 		else
 			return itr->dent;
@@ -1470,7 +1470,7 @@  static int delete_single_dentry(fat_itr *itr)
 	struct dir_entry *dent = itr->dent;

 	memset(dent, 0, sizeof(*dent));
-	dent->name[0] = DELETED_FLAG;
+	dent->nameext.name[0] = DELETED_FLAG;

 	if (!itr->remaining)
 		return flush_dir(itr);
@@ -1486,7 +1486,7 @@  static int delete_single_dentry(fat_itr *itr)
 static int delete_long_name(fat_itr *itr)
 {
 	struct dir_entry *dent = itr->dent;
-	int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK;
+	int seqn = itr->dent->nameext.name[0] & ~LAST_LONG_ENTRY_MASK;

 	while (seqn--) {
 		int ret;
@@ -1531,7 +1531,7 @@  static int delete_dentry_long(fat_itr *itr)
 	dent = itr->dent_start;
 	/* Delete long name */
 	if ((dent->attr & ATTR_VFAT) == ATTR_VFAT &&
-	    (dent->name[0] & LAST_LONG_ENTRY_MASK)) {
+	    (dent->nameext.name[0] & LAST_LONG_ENTRY_MASK)) {
 		int ret;

 		ret = delete_long_name(itr);
@@ -1712,12 +1712,10 @@  int fat_mkdir(const char *new_dirname)
 	}
 	memset(dotdent, 0, bytesperclust);

-	memcpy(dotdent[0].name, ".       ", 8);
-	memcpy(dotdent[0].ext, "   ", 3);
+	memcpy(&dotdent[0].nameext, ".          ", 11);
 	dotdent[0].attr = ATTR_DIR | ATTR_ARCH;

-	memcpy(dotdent[1].name, "..      ", 8);
-	memcpy(dotdent[1].ext, "   ", 3);
+	memcpy(&dotdent[1].nameext, "..         ", 11);
 	dotdent[1].attr = ATTR_DIR | ATTR_ARCH;

 	if (itr->is_root)
diff --git a/include/fat.h b/include/fat.h
index b9f273f381..bd8e450b33 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -132,8 +132,13 @@  typedef struct volume_info
 #define CASE_LOWER_BASE	8	/* base (name) is lower case */
 #define CASE_LOWER_EXT	16	/* extension is lower case */

+struct nameext {
+	char name[8];
+	char ext[3];
+};
+
 typedef struct dir_entry {
-	char	name[8],ext[3];	/* Name and extension */
+	struct nameext nameext;	/* Name and extension */
 	__u8	attr;		/* Attribute bits */
 	__u8	lcase;		/* Case for name and ext (CASE_LOWER_x) */
 	__u8	ctime_ms;	/* Creation time, milliseconds */