Whamcloud - gitweb
LU-1347 build: remove the vim/emacs modelines
[fs/lustre-release.git] / lustre / utils / mkfs_lustre.c
index 4e0e57c..eadca90 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
  * GPL HEADER START
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -28,6 +26,8 @@
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2011, Whamcloud, Inc.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -303,21 +303,79 @@ int loop_cleanup(struct mkfs_opts *mop)
         return ret;
 }
 
+/* return canonicalized absolute pathname, even if the target file does not
+ * exist, unlike realpath */
+static char *absolute_path(char *devname)
+{
+        char  buf[PATH_MAX + 1];
+        char *path;
+        char *ptr;
+
+        path = malloc(PATH_MAX + 1);
+        if (path == NULL)
+                return NULL;
+
+        if (devname[0] != '/') {
+                if (getcwd(buf, sizeof(buf) - 1) == NULL)
+                        return NULL;
+                strcat(buf, "/");
+                strcat(buf, devname);
+        } else {
+                strcpy(buf, devname);
+        }
+        /* truncate filename before calling realpath */
+        ptr = strrchr(buf, '/');
+        if (ptr == NULL) {
+                free(path);
+                return NULL;
+        }
+        *ptr = '\0';
+        if (path != realpath(buf, path)) {
+                free(path);
+                return NULL;
+        }
+        /* add the filename back */
+        strcat(path, "/");
+        strcat(path, ptr + 1);
+        return path;
+}
+
 /* Determine if a device is a block device (as opposed to a file) */
 int is_block(char* devname)
 {
         struct stat st;
-        int ret = 0;
+        int         ret = 0;
+        char       *devpath;
+
+        devpath = absolute_path(devname);
+        if (devpath == NULL) {
+                fprintf(stderr, "%s: failed to resolve path to %s\n",
+                        progname, devname);
+                return -1;
+        }
 
         ret = access(devname, F_OK);
-        if (ret != 0)
-                return 0;
-        ret = stat(devname, &st);
         if (ret != 0) {
-                fprintf(stderr, "%s: cannot stat %s\n", progname, devname);
-                return -1;
+                if (strncmp(devpath, "/dev/", 5) == 0) {
+                    /* nobody sane wants to create a loopback file under
+                     * /dev. Let's just report the device doesn't exist */
+                    fprintf(stderr, "%s: %s apparently does not exist\n",
+                            progname, devpath);
+                    ret = -1;
+                    goto out;
+                }
+                ret = 0;
+                goto out;
         }
-        return S_ISBLK(st.st_mode);
+        ret = stat(devpath, &st);
+        if (ret != 0) {
+                fprintf(stderr, "%s: cannot stat %s\n", progname, devpath);
+                goto out;
+        }
+        ret = S_ISBLK(st.st_mode);
+out:
+        free(devpath);
+        return ret;
 }
 
 __u64 get_device_size(char* device)
@@ -357,7 +415,7 @@ __u64 get_device_size(char* device)
 
 int loop_format(struct mkfs_opts *mop)
 {
-        int ret = 0;
+        int fd;
 
         if (mop->mo_device_sz == 0) {
                 fatal();
@@ -366,23 +424,24 @@ int loop_format(struct mkfs_opts *mop)
                 return EINVAL;
         }
 
-        ret = creat(mop->mo_device, S_IRUSR|S_IWUSR);
-        if (ret < 0) {
-                ret = errno;
-                fprintf(stderr, "%s: Unable to create backing store: %d\n",
-                        progname, ret);
-        } else {
-                close(ret);
+        fd = creat(mop->mo_device, S_IRUSR|S_IWUSR);
+        if (fd < 0) {
+                fatal();
+                fprintf(stderr, "%s: Unable to create backing store: %s\n",
+                        progname, strerror(errno));
+                return errno;
         }
 
-        ret = truncate(mop->mo_device, mop->mo_device_sz * 1024);
-        if (ret != 0) {
-                ret = errno;
-                fprintf(stderr, "%s: Unable to truncate backing store: %d\n",
-                        progname, ret);
+        if (ftruncate(fd, mop->mo_device_sz * 1024) != 0) {
+                close(fd);
+                fatal();
+                fprintf(stderr, "%s: Unable to truncate backing store: %s\n",
+                        progname, strerror(errno));
+                return errno;
         }
 
-        return ret;
+        close(fd);
+        return 0;
 }
 
 /* Display the need for the latest e2fsprogs to be installed. make_backfs
@@ -404,7 +463,7 @@ static void disp_old_e2fsprogs_msg(const char *feature, int make_backfs)
                 E2FSPROGS, feature);
 #if !(HAVE_LDISKFSPROGS)
         fprintf(stderr, "Please install the latest version of e2fsprogs from\n"
-                "http://downloads.lustre.org/public/tools/e2fsprogs/\n"
+                "http://downloads.whamcloud.com/public/e2fsprogs/latest/\n"
                 "to enable this feature.\n");
 #endif
         if (make_backfs)
@@ -1720,8 +1779,10 @@ int main(int argc, char *const argv[])
 
         /* Are we using a loop device? */
         ret = is_block(mop.mo_device);
-        if (ret < 0)
+        if (ret < 0) {
+                ret = errno;
                 goto out;
+        }
         if (ret == 0)
                 mop.mo_flags |= MO_IS_LOOP;
 
@@ -1871,8 +1932,11 @@ int main(int argc, char *const argv[])
                         ret = errno;
 #ifndef TUNEFS /* mkfs.lustre */
                 /* Reformat the loopback file */
-                if (ret || (mop.mo_flags & MO_FORCEFORMAT))
+                if (ret || (mop.mo_flags & MO_FORCEFORMAT)) {
                         ret = loop_format(&mop);
+                        if (ret)
+                                goto out;
+                }
 #endif
                 if (ret == 0)
                         ret = loop_setup(&mop);