2 * Copyright (c) 1997-2006 Erez Zadok
3 * Copyright (c) 1989 Jan-Simon Pendry
4 * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1989 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * File: am-utils/hlfsd/stubs.c
42 * HLFSD was written at Columbia University Computer Science Department, by
43 * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
44 * It is being distributed under the same terms and conditions as amd does.
49 #endif /* HAVE_CONFIG_H */
56 static nfsfattr rootfattr = {NFDIR, 0040555, 2, 0, 0, 512, 512, 0,
58 static nfsfattr slinkfattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
59 (NFS_MAXPATHLEN + 1) / 512, 0, SLINKID};
60 /* user name file attributes */
61 static nfsfattr un_fattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
62 (NFS_MAXPATHLEN + 1) / 512, 0, INVALIDID};
64 static am_nfs_fh slink;
65 static am_nfs_fh un_fhandle;
71 am_nfs_fh *root_fhp = &root;
74 /* initialize NFS file handles for hlfsd */
76 hlfsd_init_filehandles(void)
81 memcpy(root.fh_data, &ui, sizeof(ui));
84 memcpy(slink.fh_data, &ui, sizeof(ui));
87 memcpy(un_fhandle.fh_data, &ui, sizeof(ui));
92 nfsproc_null_2_svc(voidp argp, struct svc_req *rqstp)
100 /* compare if two filehandles are equal */
102 eq_fh(const am_nfs_fh *fh1, const am_nfs_fh *fh2)
104 return (!memcmp((char *) fh1, (char *) fh2, sizeof(am_nfs_fh)));
109 nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
111 static nfsattrstat res;
112 uid_t uid = (uid_t) INVALIDID;
113 gid_t gid = (gid_t) INVALIDID;
117 rootfattr.na_ctime = startup;
118 rootfattr.na_mtime = startup;
119 slinkfattr.na_ctime = startup;
120 slinkfattr.na_mtime = startup;
121 un_fattr.na_ctime = startup;
122 un_fattr.na_mtime = startup;
125 if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
126 res.ns_status = NFSERR_STALE;
129 if (eq_fh(argp, &root)) {
132 * XXX: increment mtime of parent directory, causes NFS clients to
133 * invalidate their cache for that directory.
134 * Some NFS clients may need this code.
136 if (uid != rootfattr.na_uid) {
137 clocktime(&rootfattr.na_mtime);
138 rootfattr.na_uid = uid;
141 res.ns_status = NFS_OK;
142 res.ns_u.ns_attr_u = rootfattr;
143 } else if (eq_fh(argp, &slink)) {
145 #ifndef MNT2_NFS_OPT_SYMTTL
147 * This code is needed to defeat Solaris 2.4's (and newer) symlink
148 * values cache. It forces the last-modified time of the symlink to be
149 * current. It is not needed if the O/S has an nfs flag to turn off the
150 * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
152 * Additionally, Linux currently ignores the nt_useconds field,
153 * so we must update the nt_seconds field every time.
155 if (uid != slinkfattr.na_uid) {
156 clocktime(&slinkfattr.na_mtime);
157 slinkfattr.na_uid = uid;
159 #endif /* not MNT2_NFS_OPT_SYMTTL */
161 res.ns_status = NFS_OK;
162 res.ns_u.ns_attr_u = slinkfattr;
164 if (gid != hlfs_gid) {
165 res.ns_status = NFSERR_STALE;
167 (void)memcpy(&uid, argp->fh_data, sizeof(uid));
168 if (plt_search(uid) != (uid2home_t *) NULL) {
169 res.ns_status = NFS_OK;
170 un_fattr.na_fileid = uid;
171 res.ns_u.ns_attr_u = un_fattr;
172 dlog("nfs_getattr: successful search for uid=%ld, gid=%ld",
173 (long) uid, (long) gid);
174 } else { /* not found */
175 res.ns_status = NFSERR_STALE;
184 nfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp)
186 static nfsattrstat res = {NFSERR_ROFS};
193 nfsproc_root_2_svc(voidp argp, struct svc_req *rqstp)
202 nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
204 static nfsdiropres res;
206 uid_t uid = (uid_t) INVALIDID;
207 gid_t gid = (gid_t) INVALIDID;
211 rootfattr.na_ctime = startup;
212 rootfattr.na_mtime = startup;
213 slinkfattr.na_ctime = startup;
214 slinkfattr.na_mtime = startup;
215 un_fattr.na_ctime = startup;
216 un_fattr.na_mtime = startup;
219 if (eq_fh(&argp->da_fhandle, &slink)) {
220 res.dr_status = NFSERR_NOTDIR;
224 if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
225 res.dr_status = NFSERR_NOENT;
228 if (eq_fh(&argp->da_fhandle, &root)) {
229 if (argp->da_name[0] == '.' &&
230 (argp->da_name[1] == '\0' ||
231 (argp->da_name[1] == '.' &&
232 argp->da_name[2] == '\0'))) {
235 * XXX: increment mtime of parent directory, causes NFS clients to
236 * invalidate their cache for that directory.
237 * Some NFS clients may need this code.
239 if (uid != rootfattr.na_uid) {
240 clocktime(&rootfattr.na_mtime);
241 rootfattr.na_uid = uid;
244 res.dr_u.dr_drok_u.drok_fhandle = root;
245 res.dr_u.dr_drok_u.drok_attributes = rootfattr;
246 res.dr_status = NFS_OK;
250 if (STREQ(argp->da_name, slinkname)) {
251 #ifndef MNT2_NFS_OPT_SYMTTL
253 * This code is needed to defeat Solaris 2.4's (and newer) symlink
254 * values cache. It forces the last-modified time of the symlink to be
255 * current. It is not needed if the O/S has an nfs flag to turn off the
256 * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
258 * Additionally, Linux currently ignores the nt_useconds field,
259 * so we must update the nt_seconds field every time.
261 if (uid != slinkfattr.na_uid) {
262 clocktime(&slinkfattr.na_mtime);
263 slinkfattr.na_uid = uid;
265 #endif /* not MNT2_NFS_OPT_SYMTTL */
266 res.dr_u.dr_drok_u.drok_fhandle = slink;
267 res.dr_u.dr_drok_u.drok_attributes = slinkfattr;
268 res.dr_status = NFS_OK;
272 if (gid != hlfs_gid) {
273 res.dr_status = NFSERR_NOENT;
277 /* if gets here, gid == hlfs_gid */
278 if ((idx = untab_index(argp->da_name)) < 0) {
279 res.dr_status = NFSERR_NOENT;
281 } else { /* entry found and gid is permitted */
282 un_fattr.na_fileid = untab[idx].uid;
283 res.dr_u.dr_drok_u.drok_attributes = un_fattr;
284 memset(&un_fhandle, 0, sizeof(un_fhandle));
285 memcpy(un_fhandle.fh_data, &untab[idx].uid, sizeof(untab[idx].uid));
286 xstrlcpy((char *) &un_fhandle.fh_data[sizeof(int)],
288 sizeof(am_nfs_fh) - sizeof(int));
289 res.dr_u.dr_drok_u.drok_fhandle = un_fhandle;
290 res.dr_status = NFS_OK;
291 dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s",
292 (long) uid, (long) gid, untab[idx].username);
295 } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */
297 res.dr_status = NFSERR_STALE;
303 nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
305 static nfsreadlinkres res;
306 uid_t userid = (uid_t) INVALIDID;
307 gid_t groupid = hlfs_gid + 1; /* anything not hlfs_gid */
309 char *path_val = (char *) NULL;
311 static uid_t last_uid = (uid_t) INVALIDID;
313 if (eq_fh(argp, &root)) {
314 res.rlr_status = NFSERR_ISDIR;
315 } else if (eq_fh(argp, &slink)) {
316 if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0)
317 return (nfsreadlinkres *) NULL;
319 clocktime(&slinkfattr.na_atime);
321 res.rlr_status = NFS_OK;
322 if (groupid == hlfs_gid) {
323 res.rlr_u.rlr_data_u = DOTSTRING;
324 } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid, groupid))) {
326 * parent process (fork in homedir()) continues
327 * processing, by getting a NULL returned as a
328 * "special". Child returns result.
330 return (nfsreadlinkres *) NULL;
333 } else { /* check if asked for user mailbox */
335 if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0) {
336 return (nfsreadlinkres *) NULL;
339 if (groupid == hlfs_gid) {
340 memcpy(&userid, argp->fh_data, sizeof(userid));
341 username = (char *) &argp->fh_data[sizeof(int)];
342 if (!(res.rlr_u.rlr_data_u = mailbox(userid, username)))
343 return (nfsreadlinkres *) NULL;
345 res.rlr_status = NFSERR_STALE;
349 /* print info, but try to avoid repetitions */
350 if (userid != last_uid) {
351 plog(XLOG_USER, "mailbox for uid=%ld, gid=%ld is %s",
352 (long) userid, (long) groupid, (char *) res.rlr_u.rlr_data_u);
356 /* I don't think it will pass this if -D fork */
357 if (serverpid == getpid())
360 if (!svc_sendreply(nfsxprt, (XDRPROC_T_TYPE) xdr_readlinkres, (SVC_IN_ARG_TYPE) &res))
361 svcerr_systemerr(nfsxprt);
364 * Child exists here. We need to determine which
365 * exist status to return. The exit status
366 * is gathered using wait() and determines
367 * if we returned $HOME/.hlfsspool or $ALTDIR. The parent
368 * needs this info so it can update the lookup table.
370 if (path_val && alt_spooldir && STREQ(path_val, alt_spooldir))
371 retval = 1; /* could not get real home dir (or uid 0 user) */
376 * If asked for -D fork, then must return the value,
377 * NOT exit, or else the main hlfsd server exits.
378 * Bug: where is that status information being collected?
380 if (amuDebug(D_FORK))
388 nfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp)
390 static nfsreadres res = {NFSERR_ACCES};
397 nfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp)
406 nfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp)
408 static nfsattrstat res = {NFSERR_ROFS};
415 nfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
417 static nfsdiropres res = {NFSERR_ROFS};
424 nfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
426 static nfsstat res = {NFSERR_ROFS};
433 nfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp)
435 static nfsstat res = {NFSERR_ROFS};
442 nfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp)
444 static nfsstat res = {NFSERR_ROFS};
451 nfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp)
453 static nfsstat res = {NFSERR_ROFS};
460 nfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
462 static nfsdiropres res = {NFSERR_ROFS};
469 nfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
471 static nfsstat res = {NFSERR_ROFS};
478 nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
480 static nfsreaddirres res;
481 static nfsentry slinkent = {SLINKID, 0, {SLINKCOOKIE}};
482 static nfsentry dotdotent = {ROOTID, "..", {DOTDOTCOOKIE}, &slinkent};
483 static nfsentry dotent = {ROOTID, ".", {DOTCOOKIE}, &dotdotent};
485 slinkent.ne_name = slinkname;
487 if (eq_fh(&argp->rda_fhandle, &slink)) {
488 res.rdr_status = NFSERR_NOTDIR;
489 } else if (eq_fh(&argp->rda_fhandle, &root)) {
490 clocktime(&rootfattr.na_atime);
492 res.rdr_status = NFS_OK;
493 switch (argp->rda_cookie[0]) {
495 res.rdr_u.rdr_reply_u.dl_entries = &dotent;
498 res.rdr_u.rdr_reply_u.dl_entries = &dotdotent;
501 res.rdr_u.rdr_reply_u.dl_entries = &slinkent;
504 res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) 0;
507 res.rdr_u.rdr_reply_u.dl_eof = TRUE;
509 res.rdr_status = NFSERR_STALE;
516 nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
518 static nfsstatfsres res = {NFS_OK};
520 res.sfr_u.sfr_reply_u.sfrok_tsize = 1024;
521 res.sfr_u.sfr_reply_u.sfrok_bsize = 1024;
524 * Some "df" programs automatically assume that file systems
525 * with zero blocks are meta-filesystems served by automounters.
527 res.sfr_u.sfr_reply_u.sfrok_blocks = 0;
528 res.sfr_u.sfr_reply_u.sfrok_bfree = 0;
529 res.sfr_u.sfr_reply_u.sfrok_bavail = 0;