From 9b7d811ddad946e728d9348a78cb06dee159df96 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 9 Jul 2005 22:06:59 -0500 Subject: [PATCH] This patch adds a check to use fstat or fstat64 in getsize.c if the target is a regular file, instead of doing binary searching. It also fixes a couple of cases where a file descriptor is leaked in the ext2fs_getsize() routine on error. Signed-off-by: Andreas Dilger --- configure | 3 ++- configure.in | 2 +- lib/blkid/ChangeLog | 5 +++++ lib/blkid/getsize.c | 17 ++++++++++++++++- lib/ext2fs/ChangeLog | 6 ++++++ lib/ext2fs/getsize.c | 49 ++++++++++++++++++++++++++++++++----------------- 6 files changed, 62 insertions(+), 20 deletions(-) diff --git a/configure b/configure index 9b267e2..b22a201 100755 --- a/configure +++ b/configure @@ -13819,7 +13819,8 @@ fi -for ac_func in chflags getrusage llseek lseek64 open64 getmntinfo strtoull strcasecmp srandom fchown mallinfo fdatasync strnlen strptime sysconf pathconf posix_memalign memalign valloc __secure_getenv prctl + +for ac_func in chflags getrusage llseek lseek64 open64 fstat64 getmntinfo strtoull strcasecmp srandom fchown mallinfo fdatasync strnlen strptime sysconf pathconf posix_memalign memalign valloc __secure_getenv prctl do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/configure.in b/configure.in index c9600f0..1c1351a 100644 --- a/configure.in +++ b/configure.in @@ -628,7 +628,7 @@ AC_CHECK_MEMBER(struct sockaddr.sa_len, [#include #include ]) dnl -AC_CHECK_FUNCS(chflags getrusage llseek lseek64 open64 getmntinfo strtoull strcasecmp srandom fchown mallinfo fdatasync strnlen strptime sysconf pathconf posix_memalign memalign valloc __secure_getenv prctl) +AC_CHECK_FUNCS(chflags getrusage llseek lseek64 open64 fstat64 getmntinfo strtoull strcasecmp srandom fchown mallinfo fdatasync strnlen strptime sysconf pathconf posix_memalign memalign valloc __secure_getenv prctl) dnl dnl Check to see if -lsocket is required (solaris) to make something dnl that uses socket() to compile; this is needed for the UUID library diff --git a/lib/blkid/ChangeLog b/lib/blkid/ChangeLog index 5f77116..767f11e 100644 --- a/lib/blkid/ChangeLog +++ b/lib/blkid/ChangeLog @@ -1,3 +1,8 @@ +2005-07-09 Andreas Dilger + + * getsize.c (blkid_get_dev_size): Use fstat/fstat64 to get size of + regular files. + 2006-06-30 Theodore Ts'o * Release of E2fsprogs 1.38 diff --git a/lib/blkid/getsize.c b/lib/blkid/getsize.c index d45e1c2..75bec52 100644 --- a/lib/blkid/getsize.c +++ b/lib/blkid/getsize.c @@ -31,7 +31,6 @@ #endif #ifdef HAVE_SYS_DISKLABEL_H #include -#include #endif #ifdef HAVE_SYS_DISK_H #ifdef HAVE_SYS_QUEUE_H @@ -42,6 +41,10 @@ #ifdef __linux__ #include #endif +#if HAVE_SYS_STAT_H +#include +#endif + #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) #define BLKGETSIZE _IO(0x12,96) /* return device size */ @@ -139,6 +142,18 @@ blkid_loff_t blkid_get_dev_size(int fd) } #endif #endif /* HAVE_SYS_DISKLABEL_H */ + { +#ifdef HAVE_FSTAT64 + struct stat64 st; + if (fstat64(fd, &st) == 0) +#else + struct stat st; + if (fstat(fd, &st) == 0) +#endif + if (S_ISREG(st.st_mode)) + return st.st_size; + } + /* * OK, we couldn't figure it out by using a specialized ioctl, diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index aeb8dce..58e29a9 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,9 @@ +2005-07-09 Andreas Dilger + + * getsize.c (ext2fs_get_device_size): Use fstat/fstat64 to get + size of regular files. Fix file descriptor leaks in error + paths. + 2006-06-30 Theodore Ts'o * Release of E2fsprogs 1.38 diff --git a/lib/ext2fs/getsize.c b/lib/ext2fs/getsize.c index 0c7355f..d59a893 100644 --- a/lib/ext2fs/getsize.c +++ b/lib/ext2fs/getsize.c @@ -41,6 +41,9 @@ #ifdef __linux__ #include #endif +#if HAVE_SYS_STAT_H +#include +#endif #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) #define BLKGETSIZE _IO(0x12,96) /* return device size */ @@ -137,7 +140,7 @@ static int valid_offset (int fd, ext2_loff_t offset) errcode_t ext2fs_get_device_size(const char *file, int blocksize, blk_t *retblocks) { - int fd; + int fd, rc = 0; int valid_blkgetsize64 = 1; #ifdef __linux__ struct utsname ut; @@ -168,9 +171,8 @@ errcode_t ext2fs_get_device_size(const char *file, int blocksize, if ((sizeof(*retblocks) < sizeof(unsigned long long)) && ((size64 / (blocksize / 512)) > 0xFFFFFFFF)) return EFBIG; - close(fd); *retblocks = size64 / (blocksize / 512); - return 0; + goto out; } #endif @@ -183,28 +185,27 @@ errcode_t ext2fs_get_device_size(const char *file, int blocksize, #endif if (valid_blkgetsize64 && ioctl(fd, BLKGETSIZE64, &size64) >= 0) { - if ((sizeof(*retblocks) < sizeof(unsigned long long)) - && ((size64 / blocksize) > 0xFFFFFFFF)) - return EFBIG; - close(fd); + if ((sizeof(*retblocks) < sizeof(unsigned long long)) && + ((size64 / blocksize) > 0xFFFFFFFF)) { + rc = EFBIG; + goto out; + } *retblocks = size64 / blocksize; - return 0; + goto out; } #endif #ifdef BLKGETSIZE if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - close(fd); *retblocks = size / (blocksize / 512); - return 0; + goto out; } #endif #ifdef FDGETPRM if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) { - close(fd); *retblocks = this_floppy.size / (blocksize / 512); - return 0; + goto out; } #endif @@ -215,7 +216,7 @@ errcode_t ext2fs_get_device_size(const char *file, int blocksize, u_int bs; if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) { *retblocks = ms / blocksize; - return 0; + goto out; } } #elif defined(DIOCGDINFO) @@ -233,14 +234,27 @@ errcode_t ext2fs_get_device_size(const char *file, int blocksize, if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { pp = &lab.d_partitions[part]; if (pp->p_size) { - close(fd); *retblocks = pp->p_size / (blocksize / 512); - return 0; + goto out; } } #endif /* defined(DIOCG*) */ #endif /* HAVE_SYS_DISKLABEL_H */ + { +#ifdef HAVE_FSTAT64 + struct stat64 st; + if (fstat64(fd, &st) == 0) +#else + struct stat st; + if (fstat(fd, &st) == 0) +#endif + if (S_ISREG(st.st_mode)) { + *retblocks = st.st_size / blocksize; + goto out; + } + } + /* * OK, we couldn't figure it out by using a specialized ioctl, * which is generally the best way. So do binary search to @@ -259,13 +273,14 @@ errcode_t ext2fs_get_device_size(const char *file, int blocksize, high = mid; } valid_offset (fd, 0); - close(fd); size64 = low + 1; if ((sizeof(*retblocks) < sizeof(unsigned long long)) && ((size64 / blocksize) > 0xFFFFFFFF)) return EFBIG; *retblocks = size64 / blocksize; - return 0; +out: + close(fd); + return rc; } #endif /* WIN32 */ -- 1.8.3.1