Make resize2fs expand or truncate a file containing a filesystem.
(Addresses Debian Bug: #271607)
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
diff --git a/resize/ChangeLog b/resize/ChangeLog
index b88505e..8a3fde2 100644
--- a/resize/ChangeLog
+++ b/resize/ChangeLog
@@ -1,3 +1,9 @@
+2005-12-29 Theodore Ts'o <tytso@mit.edu>
+
+ * main.c (main): If the filesystem being resized is a regular
+ file, truncate or expand the file to match the new
+ filesystem size. (Addresses Debian Bug: #271607)
+
2005-08-08 Theodore Ts'o <tytso@mit.edu>
* resize2fs.c (move_itables): Fix fencepost error caught by valgrind.
diff --git a/resize/main.c b/resize/main.c
index f4abf3a..1142c9c 100644
--- a/resize/main.c
+++ b/resize/main.c
@@ -12,14 +12,19 @@
* %End-Header%
*/
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
extern char *optarg;
extern int optind;
#endif
-#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
#include <sys/stat.h>
+#include <fcntl.h>
#include "e2p/e2p.h"
@@ -117,13 +122,17 @@
int flags = 0;
int flush = 0;
int force = 0;
- int fd;
+ int fd, ret;
blk_t new_size = 0;
blk_t max_size = 0;
io_manager io_ptr;
- char *tmp;
char *new_size_str = 0;
+#ifdef HAVE_FSTAT64
+ struct stat64 st_buf;
+#else
struct stat st_buf;
+#endif
+ __s64 new_file_size;
unsigned int sys_page_size = 4096;
long sysval;
@@ -176,16 +185,31 @@
*io_options++ = 0;
check_mount(device_name);
+
+#ifdef HAVE_OPEN64
+ fd = open64(device_name, O_RDWR);
+#else
+ fd = open(device_name, O_RDWR);
+#endif
+ if (fd < 0) {
+ com_err("open", errno, _("while opening %s"),
+ device_name);
+ exit(1);
+ }
+
+#ifdef HAVE_FSTAT64
+ ret = fstat64(fd, &st_buf);
+#else
+ ret = fstat(fd, &st_buf);
+#endif
+ if (ret < 0) {
+ com_err("open", errno,
+ _("while getting stat information for %s"),
+ device_name);
+ exit(1);
+ }
if (flush) {
- fd = open(device_name, O_RDONLY, 0);
-
- if (fd < 0) {
- com_err("open", errno,
- _("while opening %s for flushing"),
- device_name);
- exit(1);
- }
retval = ext2fs_sync_device(fd, 1);
if (retval) {
com_err(argv[0], retval,
@@ -193,7 +217,11 @@
device_name);
exit(1);
}
+ }
+
+ if (!S_ISREG(st_buf.st_mode )) {
close(fd);
+ fd = -1;
}
if (flags & RESIZE_DEBUG_IO) {
@@ -234,7 +262,7 @@
/*
* Get the size of the containing partition, and use this for
- * defaults and for making sure the new filesystme doesn't
+ * defaults and for making sure the new filesystem doesn't
* exceed the partition size.
*/
retval = ext2fs_get_device_size(device_name, fs->blocksize,
@@ -264,15 +292,15 @@
* automatically extend it in a sparse fashion by writing the
* last requested block.
*/
- if ((new_size > max_size) &&
- (stat(device_name, &st_buf) == 0) &&
- S_ISREG(st_buf.st_mode) &&
- ((tmp = malloc(fs->blocksize)) != 0)) {
- memset(tmp, 0, fs->blocksize);
- retval = io_channel_write_blk(fs->io, new_size-1, 1, tmp);
- if (retval == 0)
+ new_file_size = ((__u64) new_size) * fs->blocksize;
+ if ((__u64) new_file_size >
+ (((__u64) 1) << (sizeof(st_buf.st_size)*8 - 1)) - 1)
+ fd = -1;
+ if ((new_file_size > st_buf.st_size) &&
+ (fd > 0)) {
+ if ((ext2fs_llseek(fd, new_file_size-1, SEEK_SET) >= 0) &&
+ (write(fd, "0", 1) == 1))
max_size = new_size;
- free(tmp);
}
if (!force && (new_size > max_size)) {
fprintf(stderr, _("The containing partition (or device)"
@@ -306,5 +334,16 @@
}
printf(_("The filesystem on %s is now %d blocks long.\n\n"),
device_name, new_size);
+
+ if ((st_buf.st_size > new_file_size) &&
+ (fd > 0)) {
+#ifdef HAVE_FSTAT64
+ ftruncate64(fd, new_file_size);
+#else
+ ftruncate(fd, (off_t) new_file_size);
+#endif
+ }
+ if (fd > 0)
+ close(fd);
return (0);
}