Whamcloud - gitweb
b=15316
[fs/lustre-release.git] / lustre / utils / liblustreapi.c
index 8efe2db..b9328e5 100644 (file)
@@ -292,7 +292,7 @@ int llapi_file_create(const char *name, unsigned long stripe_size,
 }
 
 typedef int (semantic_func_t)(char *path, DIR *parent, DIR *d,
-                              void *data, struct dirent64 *de);
+                              void *data, cfs_dirent_t *de);
 
 #define MAX_LOV_UUID_COUNT      max(LOV_MAX_STRIPE_COUNT, 1000)
 #define OBD_NOT_FOUND           (-1)
@@ -518,8 +518,12 @@ void lov_dump_user_lmm_v1(struct lov_user_md_v1 *lum, char *path, int is_dir,
         /* if it's a directory */
         if (is_dir) {
                 if (obdstripe == 1) {
+                        if (lum->lmm_object_gr == LOV_OBJECT_GROUP_DEFAULT) {
+                                llapi_printf(LLAPI_MSG_NORMAL, "(Default) ");
+                                lum->lmm_object_gr = LOV_OBJECT_GROUP_CLEAR;
+                        }
                         llapi_printf(LLAPI_MSG_NORMAL, 
-                                     "default stripe_count: %d stripe_size: %u "
+                                     "stripe_count: %d stripe_size: %u "
                                      "stripe_offset: %d\n",
                                      lum->lmm_stripe_count == (__u16)-1 ? -1 :
                                      lum->lmm_stripe_count,
@@ -789,9 +793,9 @@ static DIR *opendir_parent(char *path)
 static int llapi_semantic_traverse(char *path, int size, DIR *parent,
                                    semantic_func_t sem_init,
                                    semantic_func_t sem_fini, void *data,
-                                   struct dirent64 *de)
+                                   cfs_dirent_t *de)
 {
-        struct dirent64 *dent;
+        cfs_dirent_t *dent;
         int len, ret;
         DIR *d, *p = NULL;
 
@@ -976,7 +980,7 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds)
 }
 
 static int cb_find_init(char *path, DIR *parent, DIR *dir,
-                        void *data, struct dirent64 *de)
+                        void *data, cfs_dirent_t *de)
 {
         struct find_param *param = (struct find_param *)data;
         int decision = 1; /* 1 is accepted; -1 is rejected. */
@@ -1215,7 +1219,7 @@ decided:
 }
 
 static int cb_common_fini(char *path, DIR *parent, DIR *d, void *data,
-                          struct dirent64 *de)
+                          cfs_dirent_t *de)
 {
         struct find_param *param = (struct find_param *)data;
         param->depth--;
@@ -1255,7 +1259,7 @@ int llapi_find(char *path, struct find_param *param)
 }
 
 static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data,
-                        struct dirent64 *de)
+                        cfs_dirent_t *de)
 {
         struct find_param *param = (struct find_param *)data;
         int ret = 0;
@@ -1601,7 +1605,7 @@ int llapi_quotactl(char *mnt, struct if_quotactl *qctl)
 }
 
 static int cb_quotachown(char *path, DIR *parent, DIR *d, void *data,
-                         struct dirent64 *de)
+                         cfs_dirent_t *de)
 {
         struct find_param *param = (struct find_param *)data;
         lstat_t *st;
@@ -1693,67 +1697,293 @@ out:
         return ret;
 }
 
-int llapi_getfacl(char *fname, char *cmd)
+#include <pwd.h>
+#include <grp.h>
+#include <mntent.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <ctype.h>
+
+static int rmtacl_notify(int ops)
 {
-        struct rmtacl_ioctl_data data;
-        char out[RMTACL_SIZE_MAX] = "";
-        int fd, rc;
-
-        data.cmd = cmd;
-        data.cmd_len = strlen(cmd) + 1;
-        data.res = out;
-        data.res_len = sizeof(out);
-
-        fd = open(fname, 0);
-        if (fd == -1) {
-                llapi_err(LLAPI_MSG_ERROR,"open %s failed", fname);
+        FILE *fp;
+        struct mntent *mnt;
+        int found = 0, fd, rc;
+
+        fp = setmntent(MOUNTED, "r");
+        if (fp == NULL) {
+                perror("setmntent");
                 return -1;
         }
 
-        rc = ioctl(fd, LL_IOC_GETFACL, &data);
-        close(fd);
-        if (errno == EBADE) {
-                llapi_err(LLAPI_MSG_ERROR, "Please use getfacl directly!");
-                rc = 1;
-        } else if (rc) {
-                llapi_err(LLAPI_MSG_ERROR,"getfacl %s failed", fname);
+        while (1) {
+                mnt = getmntent(fp);
+                if (!mnt)
+                        break;
+
+                if (!llapi_is_lustre_mnt(mnt))
+                        continue;
+
+                fd = open(mnt->mnt_dir, O_RDONLY | O_DIRECTORY);
+                if (fd < 0) {
+                        perror("open");
+                        return -1;
+                }
+
+                rc = ioctl(fd, LL_IOC_RMTACL, ops);
+                if (rc < 0) {
+                        perror("ioctl");
+                return -1;
+        }
+
+                found++;
+        }
+        endmntent(fp);
+        return found;
+}
+
+static char *next_token(char *p, int div)
+{
+        if (p == NULL)
+                return NULL;
+
+        if (div)
+                while (*p && *p != ':' && !isspace(*p))
+                        p++;
+        else
+                while (*p == ':' || isspace(*p))
+                        p++;
+
+        return *p ? p : NULL;
+}
+
+static int rmtacl_name2id(char *name, int is_user)
+{
+        if (is_user) {
+                struct passwd *pw;
+
+                if ((pw = getpwnam(name)) == NULL)
+                        return INVALID_ID;
+                else
+                        return (int)(pw->pw_uid);
         } else {
-                llapi_printf(LLAPI_MSG_NORMAL, "%s", out);
+                struct group *gr;
+
+                if ((gr = getgrnam(name)) == NULL)
+                        return INVALID_ID;
+                else
+                        return (int)(gr->gr_gid);
         }
+}
 
-        return rc;
+static int isodigit(int c)
+{
+        return (c >= '0' && c <= '7') ? 1 : 0;
+}
+
+/*
+ * Whether the name is just digits string (uid/gid) already or not.
+ * Return value:
+ * 1: str is id
+ * 0: str is not id
+ */
+static int str_is_id(char *str)
+{
+        if (str == NULL)
+                return 0;
+
+        if (*str == '0') {
+                str++;
+                if (*str == 'x' || *str == 'X') { /* for Hex. */
+                        if (!isxdigit(*(++str)))
+                                return 0;
+
+                        while (isxdigit(*(++str)));
+                } else if (isodigit(*str)) { /* for Oct. */
+                        while (isodigit(*(++str)));
+                }
+        } else if (isdigit(*str)) { /* for Dec. */
+                while (isdigit(*(++str)));
+        }
+
+        return (*str == 0) ? 1 : 0;
 }
 
-int llapi_setfacl(char *fname, char *cmd)
+typedef struct {
+        char *name;
+        int   length;
+        int   is_user;
+        int   next_token;
+} rmtacl_name_t;
+
+#define RMTACL_OPTNAME(name) name, sizeof(name) - 1
+
+static rmtacl_name_t rmtacl_namelist[] = {
+        { RMTACL_OPTNAME("user:"),            1,      0 },
+        { RMTACL_OPTNAME("group:"),           0,      0 },
+        { RMTACL_OPTNAME("default:user:"),    1,      0 },
+        { RMTACL_OPTNAME("default:group:"),   0,      0 },
+        /* for --tabular option */
+        { RMTACL_OPTNAME("user"),             1,      1 },
+        { RMTACL_OPTNAME("group"),            0,      1 },
+        { 0 }
+};
+
+static int rgetfacl_output(char *str)
 {
-        struct rmtacl_ioctl_data data;
-        char out[RMTACL_SIZE_MAX] = "";
-        int fd, rc;
-
-        data.cmd = cmd;
-        data.cmd_len = strlen(cmd) + 1;
-        data.res = out;
-        data.res_len = sizeof(out);
-
-        fd = open(fname, 0);
-        if (fd == -1) {
-                llapi_err(LLAPI_MSG_ERROR,"open %s failed", fname);
+        char *start = NULL, *end = NULL;
+        int is_user = 0, n, id;
+        char c;
+        rmtacl_name_t *rn;
+
+        if (str == NULL)
                 return -1;
+
+        for (rn = rmtacl_namelist; rn->name; rn++) {
+                if(strncmp(str, rn->name, rn->length) == 0) {
+                        if (!rn->next_token)
+                                start = str + rn->length;
+                        else
+                                start = next_token(str + rn->length, 0);
+                        is_user = rn->is_user;
+                        break;
+                }
         }
 
-        rc = ioctl(fd, LL_IOC_SETFACL, &data);
-        close(fd);
-        if (errno == EBADE) {
-                llapi_err(LLAPI_MSG_ERROR, "Please use setfacl directly!");
-                rc = 1;
-        } else if (errno == EOPNOTSUPP) {
-                llapi_err(LLAPI_MSG_ERROR, "setfacl: %s: %s", fname);
-                rc = 1;
-        } else if (rc) {
-                llapi_err(LLAPI_MSG_ERROR,"setfacl %s failed", fname);
+        end = next_token(start, 1);
+        if (end == NULL || start == end) {
+                n = printf("%s", str);
+                return n;
+        }
+
+        c = *end;
+        *end = 0;
+        id = rmtacl_name2id(start, is_user);
+        if (id == INVALID_ID) {
+                if (str_is_id(start)) {
+                        *end = c;
+                        n = printf("%s", str);
+                } else
+                        return -1;
+        } else if ((id == NOBODY_UID && is_user) ||
+                   (id == NOBODY_GID && !is_user)) {
+                *end = c;
+                n = printf("%s", str);
         } else {
-                llapi_printf(LLAPI_MSG_NORMAL, "%s", out);
+                *end = c;
+                *start = 0;
+                n = printf("%s%d%s", str, id, end);
         }
+        return n;
+}
 
-        return rc;
+static int child_status(int status)
+{
+        return WIFEXITED(status) ? WEXITSTATUS(status) : -1;
+}
+
+static int do_rmtacl(int argc, char *argv[], int ops, int (output_func)(char *))
+{
+        pid_t pid = 0;
+        int fd[2], status;
+        FILE *fp;
+        char buf[PIPE_BUF];
+
+        if (output_func) {
+                if (pipe(fd) < 0) {
+                        perror("pipe");
+                        return -1;
+                }
+
+                if ((pid = fork()) < 0) {
+                        perror("fork");
+                        close(fd[0]);
+                        close(fd[1]);
+                        return -1;
+                } else if (!pid) {
+                        /* child process redirects its output. */
+                        close(fd[0]);
+                        close(1);
+                        if (dup2(fd[1], 1) < 0) {
+                                perror("dup2");
+                                close(fd[1]);
+                                return -1;
+                        }
+                } else {
+                        close(fd[1]);
+                }
+        }
+
+        if (!pid) {
+                status = rmtacl_notify(ops);
+                if (status < 0)
+                        return -1;
+
+                exit(execvp(argv[0], argv));
+        }
+
+        /* the following is parent process */
+        if ((fp = fdopen(fd[0], "r")) == NULL) {
+                perror("fdopen");
+                kill(pid, SIGKILL);
+                close(fd[0]);
+                return -1;
+        }
+
+        while (fgets(buf, PIPE_BUF, fp) != NULL) {
+                if (output_func(buf) < 0)
+                        fprintf(stderr, "WARNING: unexpected error!\n[%s]\n",
+                                buf);
+        }
+        fclose(fp);
+        close(fd[0]);
+
+        if (waitpid(pid, &status, 0) < 0) {
+                perror("waitpid");
+                return -1;
+        }
+
+        return child_status(status);
+}
+
+int llapi_lsetfacl(int argc, char *argv[])
+{
+        return do_rmtacl(argc, argv, RMT_LSETFACL, NULL);
+}
+
+int llapi_lgetfacl(int argc, char *argv[])
+{
+        return do_rmtacl(argc, argv, RMT_LGETFACL, NULL);
+}
+
+int llapi_rsetfacl(int argc, char *argv[])
+{
+        return do_rmtacl(argc, argv, RMT_RSETFACL, NULL);
+}
+
+int llapi_rgetfacl(int argc, char *argv[])
+{
+        return do_rmtacl(argc, argv, RMT_RGETFACL, rgetfacl_output);
+}
+
+int llapi_cp(int argc, char *argv[])
+{
+        int rc;
+
+        rc = rmtacl_notify(RMT_RSETFACL);
+        if (rc < 0)
+                return -1;
+
+        exit(execvp(argv[0], argv));
+}
+
+int llapi_ls(int argc, char *argv[])
+{
+        int rc;
+
+        rc = rmtacl_notify(RMT_LGETFACL);
+        if (rc < 0)
+                return -1;
+
+        exit(execvp(argv[0], argv));
 }