Whamcloud - gitweb
- make HEAD from b_post_cmd3
[fs/lustre-release.git] / lustre / utils / l_facl.c
diff --git a/lustre/utils/l_facl.c b/lustre/utils/l_facl.c
new file mode 100644 (file)
index 0000000..3d12ec0
--- /dev/null
@@ -0,0 +1,268 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (C) 2004-2006 Cluster File Systems, Inc.
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <libgen.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <mntent.h>
+
+#include <lustre/liblustreapi.h>
+#include <lustre/lustre_user.h>
+
+#include "obdctl.h"
+
+static char *progname;
+
+static void usage(void)
+{
+        fprintf(stderr,
+                "\nusage: %s {uid} {gid} {mdtname} {key} {handle} {cmd}\n"
+                "Normally invoked as an upcall from Lustre, set via:\n"
+                "  /proc/fs/lustre/mdt/{mdtname}/rmtacl_upcall\n",
+                progname);
+}
+
+static inline void show_result(struct rmtacl_downcall_data *data)
+{
+        fprintf(stdout, "buflen %d\n\n%s\n", data->add_buflen, data->add_buf);
+}
+
+#define MDS_ERR "server processing error"
+
+static void errlog(char *buf, const char *fmt, ...)
+{
+        va_list args;
+
+        va_start(args, fmt);
+        vsprintf(buf, fmt, args);
+        va_end(args);
+}
+
+static char *get_lustre_mount(void)
+{
+        FILE *fp;
+        struct mntent *mnt;
+        static char mntpath[PATH_MAX] = "";
+
+        fp = setmntent(MOUNTED, "r");
+        if (fp == NULL) {
+                fprintf(stderr, "setmntent %s failed: %s\n",
+                        MOUNTED, strerror(errno));
+                return NULL;
+        }
+
+        while (1) {
+                mnt = getmntent(fp);
+                if (!mnt)
+                        break;
+
+                if (!llapi_is_lustre_mnttype(mnt))
+                        continue;
+
+                /*
+                 * XXX: The fsname can be configed by user, it should pass into as a parameter.
+                 *      Since we only need one client on mdt node for remote set{get}facl, it is
+                 *      unnecessary to do the accurate match for fsname, but match ":/" temporary.
+                 */
+                //if (strstr(mnt->mnt_fsname, ":/lustre")) {
+                        /* save the mountpoint dir part */
+                        strncpy(mntpath, mnt->mnt_dir, sizeof(mntpath));
+                        endmntent(fp);
+                        return mntpath;
+                //}
+        }
+        endmntent(fp);
+
+        return NULL;
+}
+
+int main(int argc, char **argv)
+{
+        struct rmtacl_downcall_data *data;
+        char procname[1024], *buf, *mntpath;
+        int out_pipe[2], err_pipe[2], pid, size, buflen, fd, rc;
+
+        progname = basename(argv[0]);
+
+        if (argc != 7) {
+                usage();
+                return 1;
+        }
+
+        size = offsetof(struct rmtacl_downcall_data, add_buf[RMTACL_SIZE_MAX]);
+        data = malloc(size);
+        if (!data) {
+                fprintf(stderr, "malloc %d failed\n", size);
+                return 1;
+        }
+        memset(data, 0, size);
+        data->add_magic = RMTACL_DOWNCALL_MAGIC;
+        data->add_key = strtoll(argv[4], NULL, 10);
+        data->add_handle = strtoul(argv[5], NULL, 10);
+        buf = data->add_buf;
+
+        mntpath = get_lustre_mount();
+        if (!mntpath) {
+                errlog(buf, MDS_ERR"(no lustre mounted on MDS)\n");
+                goto downcall;
+        }
+
+        /* create pipe */
+        if (pipe(out_pipe) < 0 || pipe(err_pipe) < 0) {
+                errlog(buf, MDS_ERR"(pipe failed): %s\n", strerror(errno));
+                goto downcall;
+        }
+
+        if ((pid = fork()) < 0) {
+                errlog(buf, MDS_ERR"(fork failed): %s\n", strerror(errno));
+                goto downcall;
+        } else if (pid == 0) {
+                uid_t uid;
+                gid_t gid;
+
+                close(out_pipe[0]);
+                if (out_pipe[1] != STDOUT_FILENO) {
+                        dup2(out_pipe[1], STDOUT_FILENO);
+                        close(out_pipe[1]);
+                }
+                close(err_pipe[0]);
+                if (err_pipe[1] != STDERR_FILENO) {
+                        dup2(err_pipe[1], STDERR_FILENO);
+                        close(err_pipe[1]);
+                }
+                close(STDIN_FILENO);
+
+                if (chdir(mntpath) < 0) {
+                        fprintf(stderr, "chdir %s failed: %s\n",
+                                mntpath, strerror(errno));
+                        return 1;
+                }
+
+                gid = (gid_t)atoi(argv[2]);
+                if (gid) {
+                        if (setgid(gid) == -1) {
+                                fprintf(stderr, "setgid %u failed: %s\n",
+                                        gid, strerror(errno));
+                                return 1;
+                        }
+                }
+
+                uid = (uid_t)atoi(argv[1]);
+                if (uid) {
+                        if (setuid(uid) == -1) {
+                                fprintf(stderr, "setuid %u failed: %s\n",
+                                        uid, strerror(errno));
+                                return 1;
+                        }
+                }
+
+                execl("/bin/sh", "sh", "-c", argv[6], NULL);
+                fprintf(stderr, "execl %s failed: %s\n",
+                        argv[6], strerror(errno));
+
+                return 1;
+        }
+
+        /* parent process handling */
+        close(out_pipe[1]);
+        close(err_pipe[1]);
+
+        buflen = 0;
+        while (1) {
+                rc = read(out_pipe[0], buf + buflen, RMTACL_SIZE_MAX - buflen);
+                if (rc < 0) {
+                        errlog(buf, MDS_ERR"(read failed): %s\n",
+                               strerror(errno));
+                        break;
+                }
+                if (rc == 0)
+                        break;
+                buflen += rc;
+                if (buflen >= RMTACL_SIZE_MAX)
+                        break;
+        }
+
+        if (buflen != 0) {
+                wait(&rc);
+                goto downcall;
+        }
+
+        while (1) {
+                rc = read(err_pipe[0], buf + buflen, RMTACL_SIZE_MAX - buflen);
+                if (rc < 0) {
+                        errlog(buf, MDS_ERR"(read failed): %s\n",
+                               strerror(errno));
+                        break;
+                }
+                if (rc == 0)
+                        break;
+                buflen += rc;
+                if (buflen >= RMTACL_SIZE_MAX)
+                        break;
+        }
+
+        wait(&rc);
+
+downcall:
+        buf[RMTACL_SIZE_MAX - 1] = 0;
+        data->add_buflen = strlen(buf) + 1;
+        if (getenv("L_FACL_TEST")) {
+                show_result(data);
+                free(data);
+                return 0;
+        }
+
+        snprintf(procname, sizeof(procname),
+                 "/proc/fs/lustre/mdt/%s/rmtacl_info", argv[3]);
+        fd = open(procname, O_WRONLY);
+        if (fd < 0) {
+                fprintf(stderr, "open %s failed: %s\n",
+                        procname, strerror(errno));
+                free(data);
+                return 1;
+        }
+
+        buflen = offsetof(struct rmtacl_downcall_data,
+                          add_buf[data->add_buflen]);
+        rc = write(fd, data, buflen);
+        close(fd);
+        if (rc != buflen) {
+                fprintf(stderr, "write %s len %d return %d: %s\n",
+                        procname, buflen, rc, strerror(errno));
+                free(data);
+                return 1;
+        }
+
+        free(data);
+        return 0;
+}