Whamcloud - gitweb
Eliminate compile warning.
[fs/lustre-release.git] / lustre / utils / l_getgroups.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2004 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 <syslog.h>
35
36 #include <lustre/lustre_user.h>
37
38 static char *progname;
39
40 void usage(FILE *out)
41 {
42         fprintf(out, "\nusage: %s {-d | mdsname} {uid}\n"
43                      "Normally invoked as an upcall from Lustre, set via:\n"
44                      "  /proc/fs/lustre/mds/{mdsname}/group_upcall\n"
45                      "\t-d: debug, print values to stdout instead of Lustre\n",
46                      progname);
47 }
48
49 static int compare_u32(const void *v1, const void *v2)
50 {
51         return (*(__u32 *)v1 - *(__u32 *)v2);
52 }
53
54 static void errlog(const char *fmt, ...)
55 {
56         va_list arg;
57
58         openlog(progname, LOG_PERROR, LOG_AUTHPRIV);
59
60         va_start(arg, fmt);
61         vsyslog(LOG_NOTICE, fmt, arg);
62         va_end(arg);
63
64         closelog();
65 }
66
67 int get_groups_local(struct mds_grp_downcall_data **grp)
68 {
69         struct mds_grp_downcall_data *param;
70         int i, maxgroups, size;
71         struct passwd *pw;
72         struct group  *gr;
73
74         pw = getpwuid((*grp)->mgd_uid);
75         if (!pw) {
76                 errlog("no such user %u\n", (*grp)->mgd_uid);
77                 (*grp)->mgd_err = errno ? errno : EIDRM;
78                 return sizeof(*param);
79         }
80         (*grp)->mgd_gid = pw->pw_gid;
81
82         maxgroups = sysconf(_SC_NGROUPS_MAX);
83         size = offsetof(struct mds_grp_downcall_data, mgd_groups[maxgroups]);
84         param = malloc(size);
85         if (param == NULL) {
86                 errlog("fail to alloc %d bytes for uid %u with %d groups\n",
87                        size, (*grp)->mgd_uid, maxgroups);
88                 return sizeof(*param);
89         }
90
91         memcpy(param, *grp, sizeof(*param));
92         param->mgd_groups[param->mgd_ngroups++] = pw->pw_gid;
93         *grp = param;
94         while ((gr = getgrent())) {
95                 if (gr->gr_gid == pw->pw_gid)
96                         continue;
97                 if (!gr->gr_mem)
98                         continue;
99                 for (i = 0; gr->gr_mem[i]; i++) {
100                         if (strcmp(gr->gr_mem[i], pw->pw_name) == 0) {
101                                 param->mgd_groups[param->mgd_ngroups++] =
102                                         gr->gr_gid;
103                                 break;
104                         }
105                 }
106                 if (param->mgd_ngroups == maxgroups)
107                         break;
108         }
109         endgrent();
110         qsort(param->mgd_groups, param->mgd_ngroups,
111               sizeof(param->mgd_groups[0]), compare_u32);
112
113         return size;
114 }
115
116 /* Note that we need to make the downcall regardless of error, so that the
117  * MDS doesn't continue to wait on the upcall. */
118 int main(int argc, char **argv)
119 {
120         int fd, rc, size, debug = 0;
121         struct mds_grp_downcall_data sparam = { MDS_GRP_DOWNCALL_MAGIC };
122         struct mds_grp_downcall_data *param = &sparam;
123         char pathname[1024], *end;
124
125         progname = strrchr(argv[0], '/');
126         if (progname == NULL)
127                 progname = argv[0];
128         else
129                 progname++;
130
131         if (argc != 3) {
132                 fprintf(stderr, "%s: bad parameter count\n", progname);
133                 usage(stderr);
134                 return EINVAL;
135         }
136
137         if (strcmp(argv[1], "-d") == 0)
138                 debug = 1;
139
140         param->mgd_uid = strtoul(argv[2], &end, 0);
141         if (*end) {
142                 fprintf(stderr, "%s: invalid uid '%s'\n", progname, argv[2]);
143                 usage(stderr);
144                 return EINVAL;
145         }
146
147         size = get_groups_local(&param);
148         if (debug) {
149                 int i;
150                 if (param->mgd_err) {
151                         if (param->mgd_err != ENXIO)
152                                 fprintf(stderr,
153                                         "%s: error getting uid %d groups: %s\n",
154                                         progname, param->mgd_uid,
155                                         strerror(param->mgd_err));
156                         rc = param->mgd_err;
157                 } else {
158                         printf("uid=%d gid=", param->mgd_uid);
159                         for (i = 0; i < param->mgd_ngroups; i++)
160                                 printf("%s%d", i > 0 ? "," : "",
161                                        param->mgd_groups[i]);
162                         printf("\n");
163                         rc = 0;
164                 }
165         } else {
166                 snprintf(pathname, 1024, "/proc/fs/lustre/mds/%s/group_info",
167                          argv[1]);
168                 fd = open(pathname, O_WRONLY);
169                 if (fd < 0) {
170                         fprintf(stderr, "%s: can't open device %s: %s\n",
171                                 progname, pathname, strerror(errno));
172                         rc = errno;
173                 } else {
174                         rc = write(fd, param, size);
175                         if (rc > 0)
176                                 rc = 0;
177
178                         close(fd);
179                 }
180         }
181         return rc;
182 }