Whamcloud - gitweb
Fix about remote acl operation:
[fs/lustre-release.git] / lustre / utils / l_facl.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2004-2006 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #include <stdlib.h>
24 #include <stdint.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <pwd.h>
31 #include <grp.h>
32 #include <stdarg.h>
33 #include <stddef.h>
34 #include <libgen.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37 #include <mntent.h>
38
39 #include <lustre/liblustreapi.h>
40 #include <lustre/lustre_user.h>
41
42 #include "obdctl.h"
43
44 static char *progname;
45
46 static void usage(void)
47 {
48         fprintf(stderr,
49                 "\nusage: %s {uid} {gid} {mdtname} {ino} {handle} {cmd}\n"
50                 "Normally invoked as an upcall from Lustre, set via:\n"
51                 "  /proc/fs/lustre/mdt/{mdtname}/rmtacl_upcall\n",
52                 progname);
53 }
54
55 static inline void show_result(struct rmtacl_downcall_data *data)
56 {
57         fprintf(stdout, "buflen %d\n\n%s\n", data->add_buflen, data->add_buf);
58 }
59
60 #define MDS_ERR "server processing error"
61
62 static void errlog(char *buf, const char *fmt, ...)
63 {
64         va_list args;
65
66         va_start(args, fmt);
67         vsprintf(buf, fmt, args);
68         va_end(args);
69 }
70
71 static char *get_lustre_mount(void)
72 {
73         FILE *fp;
74         struct mntent *mnt;
75         static char mntpath[PATH_MAX] = "";
76
77         fp = setmntent(MOUNTED, "r");
78         if (fp == NULL) {
79                 fprintf(stderr, "setmntent %s failed: %s\n",
80                         MOUNTED, strerror(errno));
81                 return NULL;
82         }
83
84         while (1) {
85                 mnt = getmntent(fp);
86                 if (!mnt)
87                         break;
88
89                 if (!llapi_is_lustre_mnttype(mnt))
90                         continue;
91
92                 if (strstr(mnt->mnt_fsname, ":/lustre")) {
93                         /* save the mountpoint dir part */
94                         strncpy(mntpath, mnt->mnt_dir, sizeof(mntpath));
95                         endmntent(fp);
96                         return mntpath;
97                 }
98         }
99         endmntent(fp);
100
101         return NULL;
102 }
103
104 int main(int argc, char **argv)
105 {
106         struct rmtacl_downcall_data *data;
107         char procname[1024], *buf, *mntpath;
108         int out_pipe[2], err_pipe[2], pid, size, buflen, fd, rc;
109
110         progname = basename(argv[0]);
111
112         if (argc != 7) {
113                 usage();
114                 return 1;
115         }
116
117         size = offsetof(struct rmtacl_downcall_data, add_buf[RMTACL_SIZE_MAX]);
118         data = malloc(size);
119         if (!data) {
120                 fprintf(stderr, "malloc %d failed\n", size);
121                 return 1;
122         }
123         memset(data, 0, size);
124         data->add_magic = RMTACL_DOWNCALL_MAGIC;
125         data->add_key = strtoll(argv[4], NULL, 10);
126         data->add_handle = strtoul(argv[5], NULL, 10);
127         buf = data->add_buf;
128
129         mntpath = get_lustre_mount();
130         if (!mntpath) {
131                 errlog(buf, MDS_ERR"(no lustre mounted on MDS)\n");
132                 goto downcall;
133         }
134
135         /* create pipe */
136         if (pipe(out_pipe) < 0 || pipe(err_pipe) < 0) {
137                 errlog(buf, MDS_ERR"(pipe failed): %s\n", strerror(errno));
138                 goto downcall;
139         }
140
141         if ((pid = fork()) < 0) {
142                 errlog(buf, MDS_ERR"(fork failed): %s\n", strerror(errno));
143                 goto downcall;
144         } else if (pid == 0) {
145                 uid_t uid;
146                 gid_t gid;
147
148                 close(out_pipe[0]);
149                 if (out_pipe[1] != STDOUT_FILENO) {
150                         dup2(out_pipe[1], STDOUT_FILENO);
151                         close(out_pipe[1]);
152                 }
153                 close(err_pipe[0]);
154                 if (err_pipe[1] != STDERR_FILENO) {
155                         dup2(err_pipe[1], STDERR_FILENO);
156                         close(err_pipe[1]);
157                 }
158                 close(STDIN_FILENO);
159
160                 if (chdir(mntpath) < 0) {
161                         fprintf(stderr, "chdir %s failed: %s\n",
162                                 mntpath, strerror(errno));
163                         return 1;
164                 }
165
166                 gid = (gid_t)atoi(argv[2]);
167                 if (gid) {
168                         if (setgid(gid) == -1) {
169                                 fprintf(stderr, "setgid %u failed: %s\n",
170                                         gid, strerror(errno));
171                                 return 1;
172                         }
173                 }
174
175                 uid = (uid_t)atoi(argv[1]);
176                 if (uid) {
177                         if (setuid(uid) == -1) {
178                                 fprintf(stderr, "setuid %u failed: %s\n",
179                                         uid, strerror(errno));
180                                 return 1;
181                         }
182                 }
183
184                 execl("/bin/sh", "sh", "-c", argv[6], NULL);
185                 fprintf(stderr, "execl %s failed: %s\n",
186                         argv[6], strerror(errno));
187
188                 return 1;
189         }
190
191         /* parent process handling */
192         close(out_pipe[1]);
193         close(err_pipe[1]);
194
195         buflen = 0;
196         while (1) {
197                 rc = read(out_pipe[0], buf + buflen, RMTACL_SIZE_MAX - buflen);
198                 if (rc < 0) {
199                         errlog(buf, MDS_ERR"(read failed): %s\n",
200                                strerror(errno));
201                         break;
202                 }
203                 if (rc == 0)
204                         break;
205                 buflen += rc;
206                 if (buflen >= RMTACL_SIZE_MAX)
207                         break;
208         }
209
210         if (buflen != 0) {
211                 wait(&rc);
212                 goto downcall;
213         }
214
215         while (1) {
216                 rc = read(err_pipe[0], buf + buflen, RMTACL_SIZE_MAX - buflen);
217                 if (rc < 0) {
218                         errlog(buf, MDS_ERR"(read failed): %s\n",
219                                strerror(errno));
220                         break;
221                 }
222                 if (rc == 0)
223                         break;
224                 buflen += rc;
225                 if (buflen >= RMTACL_SIZE_MAX)
226                         break;
227         }
228
229         wait(&rc);
230
231 downcall:
232         buf[RMTACL_SIZE_MAX - 1] = 0;
233         data->add_buflen = strlen(buf) + 1;
234         if (getenv("L_FACL_TEST")) {
235                 show_result(data);
236                 free(data);
237                 return 0;
238         }
239
240         snprintf(procname, sizeof(procname),
241                  "/proc/fs/lustre/mdt/%s/rmtacl_info", argv[3]);
242         fd = open(procname, O_WRONLY);
243         if (fd < 0) {
244                 fprintf(stderr, "open %s failed: %s\n",
245                         procname, strerror(errno));
246                 free(data);
247                 return 1;
248         }
249
250         buflen = offsetof(struct rmtacl_downcall_data,
251                           add_buf[data->add_buflen]);
252         rc = write(fd, data, buflen);
253         close(fd);
254         if (rc != buflen) {
255                 fprintf(stderr, "write %s len %d return %d: %s\n",
256                         procname, buflen, rc, strerror(errno));
257                 free(data);
258                 return 1;
259         }
260
261         free(data);
262         return 0;
263 }