[PATCH] libnilfs: set errno when device doesn't contain valid NILFS data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Fix the bug that no error number is set to errno variable if the
specified device doesn't contain a valid nilfs file system, which
causes caller programs to output successful message wrongly.  Three
functions, nilfs_open(), nilfs_sb_read() and nilfs_sb_write() have
this flaw.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@xxxxxxxxxxxxx>
---
 lib/sb.c |   55 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/lib/sb.c b/lib/sb.c
index 94bccaf..44453bb 100644
--- a/lib/sb.c
+++ b/lib/sb.c
@@ -97,10 +97,20 @@ static int nilfs_sb_is_valid(struct nilfs_super_block *sbp, int check_crc)
 	return crc == le32_to_cpu(sbp->s_sum);
 }
 
+static int nilfs_sb2_offset_is_too_small(struct nilfs_super_block *sbp,
+					 __u64 sb2_offset)
+{
+	return sb2_offset < ((le64_to_cpu(sbp->s_nsegments) *
+			      le32_to_cpu(sbp->s_blocks_per_segment)) <<
+			     (le32_to_cpu(sbp->s_log_block_size) +
+			      NILFS_SB_BLOCK_SIZE_SHIFT));
+}
+
 static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,
 			   __u64 *offsets)
 {
 	__u64 devsize, sb2_offset;
+	int invalid_fs = 0;
 
 	sbp[0] = malloc(NILFS_MAX_SB_SIZE);
 	sbp[1] = malloc(NILFS_MAX_SB_SIZE);
@@ -110,34 +120,40 @@ static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,
 	if (ioctl(devfd, BLKGETSIZE64, &devsize) != 0)
 		goto failed;
 
-	if (lseek(devfd, NILFS_SB_OFFSET_BYTES, SEEK_SET) < 0 ||
-	    read(devfd, sbp[0], NILFS_MAX_SB_SIZE) < 0 ||
-	    !nilfs_sb_is_valid(sbp[0], 0)) {
-		free(sbp[0]);
-		sbp[0] = NULL;
+	if (lseek(devfd, NILFS_SB_OFFSET_BYTES, SEEK_SET) >= 0 &&
+	    read(devfd, sbp[0], NILFS_MAX_SB_SIZE) >= 0) {
+		if (nilfs_sb_is_valid(sbp[0], 0))
+			goto sb1_ok;
+		invalid_fs = 1;
 	}
 
+	free(sbp[0]);
+	sbp[0] = NULL;
+sb1_ok:
+
 	sb2_offset = NILFS_SB2_OFFSET_BYTES(devsize);
 	if (offsets) {
 		offsets[0] = NILFS_SB_OFFSET_BYTES;
 		offsets[1] = sb2_offset;
 	}
 
-	if (lseek(devfd, sb2_offset, SEEK_SET) < 0 ||
-	    read(devfd, sbp[1], NILFS_MAX_SB_SIZE) < 0 ||
-	    !nilfs_sb_is_valid(sbp[1], 0))
-		goto sb2_failed;
+	if (lseek(devfd, sb2_offset, SEEK_SET) >= 0 &&
+	    read(devfd, sbp[1], NILFS_MAX_SB_SIZE) >= 0) {
+		if (nilfs_sb_is_valid(sbp[1], 0) &&
+		    !nilfs_sb2_offset_is_too_small(sbp[1], sb2_offset))
+			goto sb2_ok;
+		invalid_fs = 1;
+	}
 
-	if (sb2_offset <
-	    (le64_to_cpu(sbp[1]->s_nsegments) *
-	     le32_to_cpu(sbp[1]->s_blocks_per_segment)) <<
-	    (le32_to_cpu(sbp[1]->s_log_block_size) +
-	     NILFS_SB_BLOCK_SIZE_SHIFT))
-		goto sb2_failed;
+	free(sbp[1]);
+	sbp[1] = NULL;
+sb2_ok:
 
- sb2_done:
-	if (!sbp[0] && !sbp[1])
+	if (!sbp[0] && !sbp[1]) {
+		if (invalid_fs)
+			errno = EINVAL;
 		goto failed;
+	}
 
 	return 0;
 
@@ -145,11 +161,6 @@ static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,
 	free(sbp[0]);  /* free(NULL) is just ignored */
 	free(sbp[1]);
 	return -1;
-
- sb2_failed:
-	free(sbp[1]);
-	sbp[1] = NULL;
-	goto sb2_done;
 }
 
 struct nilfs_super_block *nilfs_sb_read(int devfd)
-- 
1.7.9.4

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Filesystem Development]     [Linux BTRFS]     [Linux CIFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux