'lafs' will need this, so make it a separate file.
Not in liblafs as it isn't really that generic.
Signed-off-by: NeilBrown <neilb@suse.de>
CPPFLAGS = -I../include
CFLAGS = -Wall -Werror -g
LDFLAGS = -L../lib
-LDLIBS = -llafs -ltalloc -lreadline -luuid
+LDLIBS = libinternal.a -llafs -ltalloc -lreadline -luuid
-all : mkfs.lafs lafs
+# 'internal' library
+LIBSRC = open_device.c
+LIBOBJ = $(patsubst %.c,%.o,$(LIBSRC))
-mkfs.lafs : mkfs.lafs.o ../lib/liblafs.a
+all : mkfs.lafs lafs libinternal.a
-lafs : lafs.o ../lib/liblafs.a
+mkfs.lafs : mkfs.lafs.o ../lib/liblafs.a libinternal.a
+
+lafs : lafs.o ../lib/liblafs.a libinternal.a
+
+libinternal.a : $(LIBOBJ) internal.h
+ ar cr libinternal.a $(LIBOBJ)
+ ranlib libinternal.a
--- /dev/null
+
+int open_device(char *devname, long long *device_bytes, int regular_file,
+ char **error);
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/mount.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
#include <lafs/lafs.h>
#include <talloc.h>
+#include "internal.h"
+
/*
* A new filesystem must contain:
* inode 0 - TypeInodeFile with all the files listed here
*valp = val;
}
-int open_device(char *devname, long long *device_bytes, int regular_file)
-{
- /* must be able to get an exclusive open on the device and its size
- * must be non-trivial
- * If 'regular_file', then expect a regular file to be used instead.
- */
- int fd;
- struct stat stb;
- unsigned long long size = 0;
-
- fd = open(devname, O_RDWR|O_EXCL);
- if (fd < 0 || fstat(fd, &stb) < 0) {
- fprintf(stderr, "mkfs.lafs: cannot open device %s: %s\n",
- devname, strerror(errno));
- exit(2);
- }
-
- if (regular_file) {
- if ((stb.st_mode & S_IFMT) != S_IFREG)
- fprintf(stderr, "mkfs.lafs: %s is not a regular file\n",
- devname);
- else
- size = stb.st_size;
- } else {
- if ((stb.st_mode & S_IFMT) != S_IFBLK)
- fprintf(stderr, "mkfs.lafs: %s is not a block device\n",
- devname);
- else if (ioctl(fd, BLKGETSIZE64, &size) != 0)
- fprintf(stderr, "mkfs.lafs: Cannot get size of %s\n",
- devname);
- else if (size == 0)
- size = 1;/*ensure we get an error */
- }
- if (size == 0)
- ;
- else if (size < 64*1024)
- fprintf(stderr, "mkfs.lafs: %s is too small for a LAFS filesystem\n",
- devname);
- else {
- *device_bytes = size;
- return fd;
- }
- exit(2);
-}
-
int main(int argc, char *argv[])
{
int verbose = 0;
}
/* Validate device */
- dev_fd = open_device(devname, &device_bytes, regular_file);
+ dev_fd = open_device(devname, &device_bytes, regular_file, &error);
+ if (dev_fd < 0) {
+ fprintf(stderr, "mkfs.lafs: %s\n", error);
+ free(error);
+ exit(2);
+ }
/* Validate parameters */
error = lafs_validate_geometry(&block_bytes, &segment_bytes,
--- /dev/null
+
+/* support routine to open device or file for lafs tools. */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "internal.h"
+
+int open_device(char *devname, long long *device_bytes, int regular_file,
+ char **error)
+{
+ /* must be able to get an exclusive open on the device and its size
+ * must be non-trivial
+ * If 'regular_file', then expect a regular file to be used instead.
+ * If device_bytes is already non-zero then it is OK to create
+ * a regular file.
+ */
+ int fd;
+ struct stat stb;
+ unsigned long long size = 0;
+
+ *error = NULL;
+
+ if (!regular_file)
+ fd = open(devname, O_RDWR|O_EXCL);
+ else if (*device_bytes)
+ fd = open(devname, O_RDWR|O_CREAT, 0666);
+ else
+ fd = open(devname, O_RDWR);
+ if (fd < 0 || fstat(fd, &stb) < 0) {
+ asprintf(error, "cannot open %s %s:%s",
+ regular_file? "file" : "device",
+ devname, strerror(errno));
+ return -1;
+ }
+
+ if (regular_file) {
+ if ((stb.st_mode & S_IFMT) != S_IFREG)
+ asprintf(error, "%s is not a regular file",
+ devname);
+ else {
+ if (*device_bytes) {
+ char zero = 0;
+ lseek64(fd, *device_bytes-1, 0);
+ write(fd, &zero, 1);
+ fstat(fd, &stb);
+ }
+ size = stb.st_size;
+ }
+ } else {
+ if ((stb.st_mode & S_IFMT) != S_IFBLK)
+ asprintf(error, "%s is not a block device",
+ devname);
+ else if (ioctl(fd, BLKGETSIZE64, &size) != 0)
+ asprintf(error, "Cannot get size of %s",
+ devname);
+ }
+
+ if (!error && size < 64*1024)
+ asprintf(error, "%s is too small for a LAFS filesystem",
+ devname);
+
+ if (*error) {
+ close(fd);
+ return -1;
+ }
+ *device_bytes = size;
+ lseek64(fd, 0, 0);
+ return fd;
+}