rtname = a->rtname;
a->dfd = a->logfd = a->rtfd = -1;
a->ddev = a->logdev = a->rtdev = 0;
- a->dbsize = a->lbsize = a->rtbsize = 0;
- a->dsize = a->logBBsize = a->logBBstart = a->rtsize = 0;
+ a->dsize = a->lbsize = a->rtbsize = 0;
+ a->dbsize = a->logBBsize = a->logBBstart = a->rtsize = 0;
(void)getcwd(curdir,MAXPATHLEN);
needcd = 0;
a->ddev= libxfs_device_open(dname, a->dcreat, flags,
a->setblksize);
a->dfd = libxfs_device_to_fd(a->ddev);
+ platform_findsizes(dname, a->dfd, &a->dsize,
+ &a->dbsize);
} else {
if (!check_open(dname, flags, &rawfile, &blockfile))
goto done;
a->dcreat, flags, a->setblksize);
a->dfd = libxfs_device_to_fd(a->ddev);
platform_findsizes(rawfile, a->dfd,
- &a->dsize, &a->dbsize);
+ &a->dsize, &a->dbsize);
}
needcd = 1;
} else
a->logdev = libxfs_device_open(logname,
a->lcreat, flags, a->setblksize);
a->logfd = libxfs_device_to_fd(a->logdev);
+ platform_findsizes(dname, a->logfd, &a->logBBsize,
+ &a->lbsize);
} else {
if (!check_open(logname, flags, &rawfile, &blockfile))
goto done;
a->lcreat, flags, a->setblksize);
a->logfd = libxfs_device_to_fd(a->logdev);
platform_findsizes(rawfile, a->logfd,
- &a->logBBsize, &a->lbsize);
+ &a->logBBsize, &a->lbsize);
}
needcd = 1;
} else
a->rtdev = libxfs_device_open(rtname,
a->rcreat, flags, a->setblksize);
a->rtfd = libxfs_device_to_fd(a->rtdev);
+ platform_findsizes(dname, a->rtfd, &a->rtsize,
+ &a->rtbsize);
} else {
if (!check_open(rtname, flags, &rawfile, &blockfile))
goto done;
a->rcreat, flags, a->setblksize);
a->rtfd = libxfs_device_to_fd(a->rtdev);
platform_findsizes(rawfile, a->rtfd,
- &a->rtsize, &a->rtbsize);
+ &a->rtsize, &a->rtbsize);
}
needcd = 1;
} else
#ifdef ENABLE_BLKID
static int
check_overwrite(
- char *device)
+ const char *device)
{
const char *type;
blkid_probe pr = NULL;
fd = open(device, O_RDONLY);
if (fd < 0)
goto out;
- platform_findsizes(device, fd, &size, &bsz);
+ platform_findsizes((char *)device, fd, &size, &bsz);
close(fd);
/* nothing to overwrite on a 0-length device */
"according to blkid\n"), progname, device);
}
ret = 1;
-
out:
if (pr)
blkid_free_probe(pr);
struct stat statbuf;
/* can't get topology info from a file */
- if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode))
+ if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) {
+ fprintf(stderr,
+ _("%s: Warning: trying to probe topology of a file %s!\n"),
+ progname, device);
return;
+ }
pr = blkid_new_probe_from_filename(device);
if (!pr)
access are not working!
static int
check_overwrite(
- char *device)
+ const char *device)
{
return 1;
}
}
}
+static void
+check_device_type(
+ const char *name,
+ int *isfile,
+ bool no_size,
+ bool no_name,
+ int *create,
+ bool force_overwrite,
+ const char *optname)
+{
+ struct stat64 statbuf;
+
+ if (*isfile && (no_size || no_name)) {
+ fprintf(stderr,
+ _("if -%s file then -%s name and -%s size are required\n"),
+ optname, optname, optname);
+ usage();
+ }
+
+ if (!name) {
+ fprintf(stderr, _("No device name specified\n"));
+ usage();
+ }
+
+ if (stat64(name, &statbuf)) {
+ if (errno == ENOENT && *isfile) {
+ if (create)
+ *create = 1;
+ return;
+ }
+
+ fprintf(stderr,
+ _("Error accessing specified device %s: %s\n"),
+ name, strerror(errno));
+ usage();
+ return;
+ }
+
+ if (!force_overwrite && check_overwrite(name)) {
+ fprintf(stderr,
+ _("%s: Use the -f option to force overwrite.\n"),
+ progname);
+ exit(1);
+ }
+
+ /*
+ * We only want to completely truncate and recreate an existing file if
+ * we were specifically told it was a file. Set the create flag only in
+ * this case to trigger that behaviour.
+ */
+ if (S_ISREG(statbuf.st_mode)) {
+ if (!*isfile)
+ *isfile = 1;
+ else if (create)
+ *create = 1;
+ return;
+ }
+
+ if (S_ISBLK(statbuf.st_mode)) {
+ if (*isfile) {
+ fprintf(stderr,
+ _("specified \"-%s file\" on a block device %s\n"),
+ optname, name);
+ usage();
+ }
+ return;
+ }
+
+ fprintf(stderr,
+ _("specified device %s not a file or block device\n"),
+ name);
+ usage();
+}
+
static void
fixup_log_stripe_unit(
int lsflag,
__uint32_t bsize;
int i;
xfs_off_t off;
- int tmp;
/*
* We open regular files with O_TRUNC|O_CREAT. Nothing to do here...
}
memset(buf, 0, new_sb->sb_sectsize);
- tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
- if (tmp < 0) {
- fprintf(stderr, _("existing superblock read failed: %s\n"),
- strerror(errno));
- goto done;
- }
- if (tmp != new_sb->sb_sectsize) {
- fprintf(stderr,
- _("warning: could not read existing superblock, skip zeroing\n"));
+ /*
+ * If we are creating an image file, it might be of zero length at this
+ * point in time. Hence reading the existing superblock is going to
+ * return zero bytes. It's not a failure we need to warn about in this
+ * case.
+ */
+ off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
+ if (off != new_sb->sb_sectsize) {
+ if (!xi->disfile)
+ fprintf(stderr,
+ _("error reading existing superblock: %s\n"),
+ strerror(errno));
goto done;
}
libxfs_sb_from_disk(&sb, buf);
case D_FILE:
xi.disfile = getnum(value, &dopts,
D_FILE);
- if (xi.disfile && !Nflag)
- xi.dcreat = 1;
break;
case D_NAME:
xi.dname = getstr(value, &dopts, D_NAME);
case L_FILE:
xi.lisfile = getnum(value, &lopts,
L_FILE);
- if (xi.lisfile)
- xi.lcreat = 1;
break;
case L_INTERNAL:
loginternal = getnum(value, &lopts,
case R_FILE:
xi.risfile = getnum(value, &ropts,
R_FILE);
- if (xi.risfile)
- xi.rcreat = 1;
break;
case R_NAME:
case R_DEV:
lsectorsize = sectorsize;
}
+ /*
+ * Before anything else, verify that we are correctly operating on
+ * files or block devices and set the control parameters correctly.
+ * Explicitly disable direct IO for image files so we don't error out on
+ * sector size mismatches between the new filesystem and the underlying
+ * host filesystem.
+ */
+ check_device_type(dfile, &xi.disfile, !dsize, !dfile,
+ Nflag ? NULL : &xi.dcreat, force_overwrite, "d");
+ if (!loginternal)
+ check_device_type(xi.logname, &xi.lisfile, !logsize, !xi.logname,
+ Nflag ? NULL : &xi.lcreat,
+ force_overwrite, "l");
+ if (xi.rtname)
+ check_device_type(xi.rtname, &xi.risfile, !rtsize, !xi.rtname,
+ Nflag ? NULL : &xi.rcreat,
+ force_overwrite, "r");
+ if (xi.disfile || xi.lisfile || xi.risfile)
+ xi.isdirect = 0;
+
memset(&ft, 0, sizeof(ft));
get_topology(&xi, &ft, force_overwrite);
}
- if (xi.disfile && (!dsize || !xi.dname)) {
- fprintf(stderr,
- _("if -d file then -d name and -d size are required\n"));
- usage();
- }
if (dsize) {
__uint64_t dbytes;
usage();
}
- if (xi.lisfile && (!logsize || !xi.logname)) {
- fprintf(stderr,
- _("if -l file then -l name and -l size are required\n"));
- usage();
- }
if (logsize) {
__uint64_t logbytes;
(long long)logbytes, blocksize,
(long long)(logblocks << blocklog));
}
- if (xi.risfile && (!rtsize || !xi.rtname)) {
- fprintf(stderr,
- _("if -r file then -r name and -r size are required\n"));
- usage();
- }
if (rtsize) {
__uint64_t rtbytes;
xi.rtsize &= sector_mask;
xi.logBBsize &= (__uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT);
- if (!force_overwrite) {
- if (check_overwrite(dfile) ||
- check_overwrite(logfile) ||
- check_overwrite(xi.rtname)) {
- fprintf(stderr,
- _("%s: Use the -f option to force overwrite.\n"),
- progname);
- exit(1);
- }
- }
+ /* don't do discards on print-only runs or on files */
if (discard && !Nflag) {
- discard_blocks(xi.ddev, xi.dsize);
- if (xi.rtdev)
+ if (!xi.disfile)
+ discard_blocks(xi.ddev, xi.dsize);
+ if (xi.rtdev && !xi.risfile)
discard_blocks(xi.rtdev, xi.rtsize);
- if (xi.logdev && xi.logdev != xi.ddev)
+ if (xi.logdev && xi.logdev != xi.ddev && !xi.lisfile)
discard_blocks(xi.logdev, xi.logBBsize);
}
/*
* If the data area is a file, then grow it out to its final size
- * so that the reads for the end of the device in the mount code
- * will succeed.
+ * if needed so that the reads for the end of the device in the mount
+ * code will succeed.
*/
- if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
- fprintf(stderr, _("%s: Growing the data section failed\n"),
- progname);
- exit(1);
+ if (xi.disfile && xi.dsize * xi.dbsize < dblocks * blocksize) {
+ if (ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
+ fprintf(stderr,
+ _("%s: Growing the data section failed\n"),
+ progname);
+ exit(1);
+ }
}
/*