138494Sobrien/*
2310490Scy * Copyright (c) 1997-2014 Erez Zadok
338494Sobrien * Copyright (c) 1989 Jan-Simon Pendry
438494Sobrien * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
538494Sobrien * Copyright (c) 1989 The Regents of the University of California.
638494Sobrien * All rights reserved.
738494Sobrien *
838494Sobrien * This code is derived from software contributed to Berkeley by
938494Sobrien * Jan-Simon Pendry at Imperial College, London.
1038494Sobrien *
1138494Sobrien * Redistribution and use in source and binary forms, with or without
1238494Sobrien * modification, are permitted provided that the following conditions
1338494Sobrien * are met:
1438494Sobrien * 1. Redistributions of source code must retain the above copyright
1538494Sobrien *    notice, this list of conditions and the following disclaimer.
1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1738494Sobrien *    notice, this list of conditions and the following disclaimer in the
1838494Sobrien *    documentation and/or other materials provided with the distribution.
19310490Scy * 3. Neither the name of the University nor the names of its contributors
2038494Sobrien *    may be used to endorse or promote products derived from this software
2138494Sobrien *    without specific prior written permission.
2238494Sobrien *
2338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2438494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2538494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2638494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2738494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2838494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2938494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3038494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3138494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3238494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3338494Sobrien * SUCH DAMAGE.
3438494Sobrien *
3538494Sobrien *
36174294Sobrien * File: am-utils/hlfsd/stubs.c
3738494Sobrien *
3838494Sobrien * HLFSD was written at Columbia University Computer Science Department, by
3938494Sobrien * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
4038494Sobrien * It is being distributed under the same terms and conditions as amd does.
4138494Sobrien */
4238494Sobrien
4338494Sobrien#ifdef HAVE_CONFIG_H
4438494Sobrien# include <config.h>
4538494Sobrien#endif /* HAVE_CONFIG_H */
4638494Sobrien#include <am_defs.h>
4738494Sobrien#include <hlfsd.h>
4838494Sobrien
4938494Sobrien/*
5038494Sobrien * STATIC VARIABLES:
5138494Sobrien */
5238494Sobrienstatic nfsfattr rootfattr = {NFDIR, 0040555, 2, 0, 0, 512, 512, 0,
5338494Sobrien			     1, 0, ROOTID};
5438494Sobrienstatic nfsfattr slinkfattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
5538494Sobrien			      (NFS_MAXPATHLEN + 1) / 512, 0, SLINKID};
5638494Sobrien				/* user name file attributes */
5738494Sobrienstatic nfsfattr un_fattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
5838494Sobrien			    (NFS_MAXPATHLEN + 1) / 512, 0, INVALIDID};
5938494Sobrienstatic int started;
6038494Sobrienstatic am_nfs_fh slink;
6138494Sobrienstatic am_nfs_fh un_fhandle;
6238494Sobrien
6338494Sobrien/*
6438494Sobrien * GLOBALS:
6538494Sobrien */
6638494Sobrienam_nfs_fh root;
6738494Sobrienam_nfs_fh *root_fhp =		&root;
6838494Sobrien
6938494Sobrien
7038494Sobrien/* initialize NFS file handles for hlfsd */
7138494Sobrienvoid
7238494Sobrienhlfsd_init_filehandles(void)
7338494Sobrien{
7438494Sobrien  u_int ui;
7538494Sobrien
7638494Sobrien  ui = ROOTID;
7738494Sobrien  memcpy(root.fh_data, &ui, sizeof(ui));
7838494Sobrien
7938494Sobrien  ui = SLINKID;
8038494Sobrien  memcpy(slink.fh_data, &ui, sizeof(ui));
8138494Sobrien
8238494Sobrien  ui = INVALIDID;
8338494Sobrien  memcpy(un_fhandle.fh_data, &ui, sizeof(ui));
8438494Sobrien}
8538494Sobrien
8638494Sobrien
8738494Sobrienvoidp
8838494Sobriennfsproc_null_2_svc(voidp argp, struct svc_req *rqstp)
8938494Sobrien{
9038494Sobrien  static char res;
9138494Sobrien
9238494Sobrien  return (voidp) &res;
9338494Sobrien}
9438494Sobrien
9538494Sobrien
9638494Sobrien/* compare if two filehandles are equal */
9738494Sobrienstatic int
9838494Sobrieneq_fh(const am_nfs_fh *fh1, const am_nfs_fh *fh2)
9938494Sobrien{
10038494Sobrien  return (!memcmp((char *) fh1, (char *) fh2, sizeof(am_nfs_fh)));
10138494Sobrien}
10238494Sobrien
10338494Sobrien
10438494Sobriennfsattrstat *
10538494Sobriennfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
10638494Sobrien{
10738494Sobrien  static nfsattrstat res;
10838494Sobrien  uid_t uid = (uid_t) INVALIDID;
10938494Sobrien  gid_t gid = (gid_t) INVALIDID;
11038494Sobrien
11138494Sobrien  if (!started) {
11238494Sobrien    started++;
11338494Sobrien    rootfattr.na_ctime = startup;
11438494Sobrien    rootfattr.na_mtime = startup;
11538494Sobrien    slinkfattr.na_ctime = startup;
11638494Sobrien    slinkfattr.na_mtime = startup;
11738494Sobrien    un_fattr.na_ctime = startup;
11838494Sobrien    un_fattr.na_mtime = startup;
11938494Sobrien  }
12038494Sobrien
121119679Smbr  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
122119679Smbr    res.ns_status = NFSERR_STALE;
123119679Smbr    return &res;
124119679Smbr  }
12538494Sobrien  if (eq_fh(argp, &root)) {
126174294Sobrien#if 0
127174294Sobrien    /*
128174294Sobrien     * XXX: increment mtime of parent directory, causes NFS clients to
129174294Sobrien     * invalidate their cache for that directory.
130174294Sobrien     * Some NFS clients may need this code.
131174294Sobrien     */
132174294Sobrien    if (uid != rootfattr.na_uid) {
133174294Sobrien      clocktime(&rootfattr.na_mtime);
134174294Sobrien      rootfattr.na_uid = uid;
135174294Sobrien    }
136310490Scy#endif /* 0 */
13738494Sobrien    res.ns_status = NFS_OK;
13838494Sobrien    res.ns_u.ns_attr_u = rootfattr;
13938494Sobrien  } else if (eq_fh(argp, &slink)) {
14038494Sobrien
14138494Sobrien#ifndef MNT2_NFS_OPT_SYMTTL
14238494Sobrien    /*
14338494Sobrien     * This code is needed to defeat Solaris 2.4's (and newer) symlink
14442629Sobrien     * values cache.  It forces the last-modified time of the symlink to be
14538494Sobrien     * current.  It is not needed if the O/S has an nfs flag to turn off the
14638494Sobrien     * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
147119679Smbr     *
148119679Smbr     * Additionally, Linux currently ignores the nt_useconds field,
149119679Smbr     * so we must update the nt_seconds field every time.
15038494Sobrien     */
151119679Smbr    if (uid != slinkfattr.na_uid) {
152174294Sobrien      clocktime(&slinkfattr.na_mtime);
153119679Smbr      slinkfattr.na_uid = uid;
154119679Smbr    }
15538494Sobrien#endif /* not MNT2_NFS_OPT_SYMTTL */
15638494Sobrien
15738494Sobrien    res.ns_status = NFS_OK;
15838494Sobrien    res.ns_u.ns_attr_u = slinkfattr;
15938494Sobrien  } else {
16038494Sobrien    if (gid != hlfs_gid) {
16138494Sobrien      res.ns_status = NFSERR_STALE;
16238494Sobrien    } else {
163277879Spfg      (void)memcpy(&uid, argp->fh_data, sizeof(uid));
16438494Sobrien      if (plt_search(uid) != (uid2home_t *) NULL) {
16538494Sobrien	res.ns_status = NFS_OK;
16638494Sobrien	un_fattr.na_fileid = uid;
16738494Sobrien	res.ns_u.ns_attr_u = un_fattr;
16851292Sobrien	dlog("nfs_getattr: successful search for uid=%ld, gid=%ld",
16951292Sobrien	     (long) uid, (long) gid);
17038494Sobrien      } else {			/* not found */
17138494Sobrien	res.ns_status = NFSERR_STALE;
17238494Sobrien      }
17338494Sobrien    }
17438494Sobrien  }
17538494Sobrien  return &res;
17638494Sobrien}
17738494Sobrien
17838494Sobrien
17938494Sobriennfsattrstat *
18038494Sobriennfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp)
18138494Sobrien{
18238494Sobrien  static nfsattrstat res = {NFSERR_ROFS};
18338494Sobrien
18438494Sobrien  return &res;
18538494Sobrien}
18638494Sobrien
18738494Sobrien
18838494Sobrienvoidp
18938494Sobriennfsproc_root_2_svc(voidp argp, struct svc_req *rqstp)
19038494Sobrien{
19138494Sobrien  static char res;
19238494Sobrien
19338494Sobrien  return (voidp) &res;
19438494Sobrien}
19538494Sobrien
19638494Sobrien
19738494Sobriennfsdiropres *
19838494Sobriennfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
19938494Sobrien{
20038494Sobrien  static nfsdiropres res;
20138494Sobrien  int idx;
20238494Sobrien  uid_t uid = (uid_t) INVALIDID;
20338494Sobrien  gid_t gid = (gid_t) INVALIDID;
20438494Sobrien
20538494Sobrien  if (!started) {
20638494Sobrien    started++;
20738494Sobrien    rootfattr.na_ctime = startup;
20838494Sobrien    rootfattr.na_mtime = startup;
20938494Sobrien    slinkfattr.na_ctime = startup;
21038494Sobrien    slinkfattr.na_mtime = startup;
21138494Sobrien    un_fattr.na_ctime = startup;
21238494Sobrien    un_fattr.na_mtime = startup;
21338494Sobrien  }
21438494Sobrien
21538494Sobrien  if (eq_fh(&argp->da_fhandle, &slink)) {
21638494Sobrien    res.dr_status = NFSERR_NOTDIR;
21738494Sobrien    return &res;
21838494Sobrien  }
21938494Sobrien
220119679Smbr  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
221119679Smbr    res.dr_status = NFSERR_NOENT;
222119679Smbr    return &res;
223119679Smbr  }
22438494Sobrien  if (eq_fh(&argp->da_fhandle, &root)) {
22538494Sobrien    if (argp->da_name[0] == '.' &&
22638494Sobrien	(argp->da_name[1] == '\0' ||
22738494Sobrien	 (argp->da_name[1] == '.' &&
22838494Sobrien	  argp->da_name[2] == '\0'))) {
229174294Sobrien#if 0
230174294Sobrien    /*
231174294Sobrien     * XXX: increment mtime of parent directory, causes NFS clients to
232174294Sobrien     * invalidate their cache for that directory.
233174294Sobrien     * Some NFS clients may need this code.
234174294Sobrien     */
235174294Sobrien      if (uid != rootfattr.na_uid) {
236174294Sobrien	clocktime(&rootfattr.na_mtime);
237174294Sobrien	rootfattr.na_uid = uid;
238174294Sobrien      }
239310490Scy#endif /* 0 */
24038494Sobrien      res.dr_u.dr_drok_u.drok_fhandle = root;
24138494Sobrien      res.dr_u.dr_drok_u.drok_attributes = rootfattr;
24238494Sobrien      res.dr_status = NFS_OK;
24338494Sobrien      return &res;
24438494Sobrien    }
24538494Sobrien
24638494Sobrien    if (STREQ(argp->da_name, slinkname)) {
24782794Sobrien#ifndef MNT2_NFS_OPT_SYMTTL
24882794Sobrien      /*
24982794Sobrien       * This code is needed to defeat Solaris 2.4's (and newer) symlink
25082794Sobrien       * values cache.  It forces the last-modified time of the symlink to be
25182794Sobrien       * current.  It is not needed if the O/S has an nfs flag to turn off the
25282794Sobrien       * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
253119679Smbr       *
254119679Smbr       * Additionally, Linux currently ignores the nt_useconds field,
255119679Smbr       * so we must update the nt_seconds field every time.
25682794Sobrien       */
257119679Smbr      if (uid != slinkfattr.na_uid) {
258174294Sobrien	clocktime(&slinkfattr.na_mtime);
259119679Smbr	slinkfattr.na_uid = uid;
260119679Smbr      }
26182794Sobrien#endif /* not MNT2_NFS_OPT_SYMTTL */
26238494Sobrien      res.dr_u.dr_drok_u.drok_fhandle = slink;
26338494Sobrien      res.dr_u.dr_drok_u.drok_attributes = slinkfattr;
26438494Sobrien      res.dr_status = NFS_OK;
26538494Sobrien      return &res;
26638494Sobrien    }
26738494Sobrien
268119679Smbr    if (gid != hlfs_gid) {
26938494Sobrien      res.dr_status = NFSERR_NOENT;
27038494Sobrien      return &res;
27138494Sobrien    }
27238494Sobrien
27342629Sobrien    /* if gets here, gid == hlfs_gid */
27438494Sobrien    if ((idx = untab_index(argp->da_name)) < 0) {
27538494Sobrien      res.dr_status = NFSERR_NOENT;
27638494Sobrien      return &res;
27738494Sobrien    } else {			/* entry found and gid is permitted */
27838494Sobrien      un_fattr.na_fileid = untab[idx].uid;
27938494Sobrien      res.dr_u.dr_drok_u.drok_attributes = un_fattr;
280277879Spfg      memset(&un_fhandle, 0, sizeof(un_fhandle));
281277879Spfg      memcpy(un_fhandle.fh_data, &untab[idx].uid, sizeof(untab[idx].uid));
282174294Sobrien      xstrlcpy((char *) &un_fhandle.fh_data[sizeof(int)],
283174294Sobrien	       untab[idx].username,
284174294Sobrien	       sizeof(am_nfs_fh) - sizeof(int));
28538494Sobrien      res.dr_u.dr_drok_u.drok_fhandle = un_fhandle;
28638494Sobrien      res.dr_status = NFS_OK;
28751292Sobrien      dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s",
28851292Sobrien	   (long) uid, (long) gid, untab[idx].username);
28938494Sobrien      return &res;
29038494Sobrien    }
29138494Sobrien  } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */
29238494Sobrien
29338494Sobrien  res.dr_status = NFSERR_STALE;
29438494Sobrien  return &res;
29538494Sobrien}
29638494Sobrien
29738494Sobrien
29838494Sobriennfsreadlinkres *
29938494Sobriennfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
30038494Sobrien{
30138494Sobrien  static nfsreadlinkres res;
30238494Sobrien  uid_t userid = (uid_t) INVALIDID;
30338494Sobrien  gid_t groupid = hlfs_gid + 1;	/* anything not hlfs_gid */
30438494Sobrien  int retval = 0;
305310490Scy  char *path_val = NULL;
30638494Sobrien  char *username;
30738494Sobrien  static uid_t last_uid = (uid_t) INVALIDID;
30838494Sobrien
30938494Sobrien  if (eq_fh(argp, &root)) {
31038494Sobrien    res.rlr_status = NFSERR_ISDIR;
31138494Sobrien  } else if (eq_fh(argp, &slink)) {
31282794Sobrien    if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0)
31338494Sobrien      return (nfsreadlinkres *) NULL;
31438494Sobrien
315174294Sobrien    clocktime(&slinkfattr.na_atime);
31638494Sobrien
31738494Sobrien    res.rlr_status = NFS_OK;
31838494Sobrien    if (groupid == hlfs_gid) {
31938494Sobrien      res.rlr_u.rlr_data_u = DOTSTRING;
320119679Smbr    } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid, groupid))) {
32138494Sobrien      /*
32238494Sobrien       * parent process (fork in homedir()) continues
32338494Sobrien       * processing, by getting a NULL returned as a
32438494Sobrien       * "special".  Child returns result.
32538494Sobrien       */
326310490Scy      return NULL;
32738494Sobrien    }
32838494Sobrien
32938494Sobrien  } else {			/* check if asked for user mailbox */
33038494Sobrien
33182794Sobrien    if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0) {
33238494Sobrien      return (nfsreadlinkres *) NULL;
33338494Sobrien    }
33438494Sobrien
33538494Sobrien    if (groupid == hlfs_gid) {
336277879Spfg      memcpy(&userid, argp->fh_data, sizeof(userid));
33738494Sobrien      username = (char *) &argp->fh_data[sizeof(int)];
33838494Sobrien      if (!(res.rlr_u.rlr_data_u = mailbox(userid, username)))
33938494Sobrien	return (nfsreadlinkres *) NULL;
34038494Sobrien    } else {
34138494Sobrien      res.rlr_status = NFSERR_STALE;
34238494Sobrien    }
34338494Sobrien  }
34438494Sobrien
34538494Sobrien  /* print info, but try to avoid repetitions */
34638494Sobrien  if (userid != last_uid) {
34751292Sobrien    plog(XLOG_USER, "mailbox for uid=%ld, gid=%ld is %s",
34851292Sobrien	 (long) userid, (long) groupid, (char *) res.rlr_u.rlr_data_u);
34938494Sobrien    last_uid = userid;
35038494Sobrien  }
35138494Sobrien
352174294Sobrien  /* I don't think it will pass this if -D fork */
35338494Sobrien  if (serverpid == getpid())
35438494Sobrien    return &res;
35538494Sobrien
35638494Sobrien  if (!svc_sendreply(nfsxprt, (XDRPROC_T_TYPE) xdr_readlinkres, (SVC_IN_ARG_TYPE) &res))
35738494Sobrien    svcerr_systemerr(nfsxprt);
35838494Sobrien
35938494Sobrien  /*
36038494Sobrien   * Child exists here.   We need to determine which
36138494Sobrien   * exist status to return.  The exit status
36238494Sobrien   * is gathered using wait() and determines
36338494Sobrien   * if we returned $HOME/.hlfsspool or $ALTDIR.  The parent
36438494Sobrien   * needs this info so it can update the lookup table.
36538494Sobrien   */
36638494Sobrien  if (path_val && alt_spooldir && STREQ(path_val, alt_spooldir))
36738494Sobrien    retval = 1;		/* could not get real home dir (or uid 0 user) */
36838494Sobrien  else
36938494Sobrien    retval = 0;
37038494Sobrien
37138494Sobrien  /*
372310490Scy   * If asked for -D nofork, then must return the value,
37338494Sobrien   * NOT exit, or else the main hlfsd server exits.
374310490Scy   * If -D fork (default), then we do want to exit from the process.
375174294Sobrien   * Bug: where is that status information being collected?
37638494Sobrien   */
377174294Sobrien  if (amuDebug(D_FORK))
378310490Scy    exit(retval);
379310490Scy  else
38038494Sobrien    return &res;
38138494Sobrien}
38238494Sobrien
38338494Sobrien
38438494Sobriennfsreadres *
38538494Sobriennfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp)
38638494Sobrien{
38738494Sobrien  static nfsreadres res = {NFSERR_ACCES};
38838494Sobrien
38938494Sobrien  return &res;
39038494Sobrien}
39138494Sobrien
39238494Sobrien
39338494Sobrienvoidp
39438494Sobriennfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp)
39538494Sobrien{
39638494Sobrien  static char res;
39738494Sobrien
39838494Sobrien  return (voidp) &res;
39938494Sobrien}
40038494Sobrien
40138494Sobrien
40238494Sobriennfsattrstat *
40338494Sobriennfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp)
40438494Sobrien{
40538494Sobrien  static nfsattrstat res = {NFSERR_ROFS};
40638494Sobrien
40738494Sobrien  return &res;
40838494Sobrien}
40938494Sobrien
41038494Sobrien
41138494Sobriennfsdiropres *
41238494Sobriennfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
41338494Sobrien{
41438494Sobrien  static nfsdiropres res = {NFSERR_ROFS};
41538494Sobrien
41638494Sobrien  return &res;
41738494Sobrien}
41838494Sobrien
41938494Sobrien
42038494Sobriennfsstat *
42138494Sobriennfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
42238494Sobrien{
42338494Sobrien  static nfsstat res = {NFSERR_ROFS};
42438494Sobrien
42538494Sobrien  return &res;
42638494Sobrien}
42738494Sobrien
42838494Sobrien
42938494Sobriennfsstat *
43038494Sobriennfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp)
43138494Sobrien{
43238494Sobrien  static nfsstat res = {NFSERR_ROFS};
43338494Sobrien
43438494Sobrien  return &res;
43538494Sobrien}
43638494Sobrien
43738494Sobrien
43838494Sobriennfsstat *
43938494Sobriennfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp)
44038494Sobrien{
44138494Sobrien  static nfsstat res = {NFSERR_ROFS};
44238494Sobrien
44338494Sobrien  return &res;
44438494Sobrien}
44538494Sobrien
44638494Sobrien
44738494Sobriennfsstat *
44838494Sobriennfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp)
44938494Sobrien{
45038494Sobrien  static nfsstat res = {NFSERR_ROFS};
45138494Sobrien
45238494Sobrien  return &res;
45338494Sobrien}
45438494Sobrien
45538494Sobrien
45638494Sobriennfsdiropres *
45738494Sobriennfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
45838494Sobrien{
45938494Sobrien  static nfsdiropres res = {NFSERR_ROFS};
46038494Sobrien
46138494Sobrien  return &res;
46238494Sobrien}
46338494Sobrien
46438494Sobrien
46538494Sobriennfsstat *
46638494Sobriennfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
46738494Sobrien{
46838494Sobrien  static nfsstat res = {NFSERR_ROFS};
46938494Sobrien
47038494Sobrien  return &res;
47138494Sobrien}
47238494Sobrien
47338494Sobrien
47438494Sobriennfsreaddirres *
47538494Sobriennfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
47638494Sobrien{
47738494Sobrien  static nfsreaddirres res;
478310490Scy  static nfsentry slinkent = {SLINKID, NULL, {SLINKCOOKIE}};
47938494Sobrien  static nfsentry dotdotent = {ROOTID, "..", {DOTDOTCOOKIE}, &slinkent};
48038494Sobrien  static nfsentry dotent = {ROOTID, ".", {DOTCOOKIE}, &dotdotent};
48138494Sobrien
48238494Sobrien  slinkent.ne_name = slinkname;
48338494Sobrien
48438494Sobrien  if (eq_fh(&argp->rda_fhandle, &slink)) {
48538494Sobrien    res.rdr_status = NFSERR_NOTDIR;
48638494Sobrien  } else if (eq_fh(&argp->rda_fhandle, &root)) {
487174294Sobrien    clocktime(&rootfattr.na_atime);
48838494Sobrien
48938494Sobrien    res.rdr_status = NFS_OK;
49038494Sobrien    switch (argp->rda_cookie[0]) {
49138494Sobrien    case 0:
49238494Sobrien      res.rdr_u.rdr_reply_u.dl_entries = &dotent;
49338494Sobrien      break;
49438494Sobrien    case DOTCOOKIE:
49538494Sobrien      res.rdr_u.rdr_reply_u.dl_entries = &dotdotent;
49638494Sobrien      break;
49738494Sobrien    case DOTDOTCOOKIE:
49838494Sobrien      res.rdr_u.rdr_reply_u.dl_entries = &slinkent;
49938494Sobrien      break;
50038494Sobrien    case SLINKCOOKIE:
501310490Scy      res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) NULL;
50238494Sobrien      break;
50338494Sobrien    }
50438494Sobrien    res.rdr_u.rdr_reply_u.dl_eof = TRUE;
50538494Sobrien  } else {
50638494Sobrien    res.rdr_status = NFSERR_STALE;
50738494Sobrien  }
50838494Sobrien  return &res;
50938494Sobrien}
51038494Sobrien
51138494Sobrien
51238494Sobriennfsstatfsres *
51338494Sobriennfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
51438494Sobrien{
51538494Sobrien  static nfsstatfsres res = {NFS_OK};
51638494Sobrien
51738494Sobrien  res.sfr_u.sfr_reply_u.sfrok_tsize = 1024;
51838494Sobrien  res.sfr_u.sfr_reply_u.sfrok_bsize = 1024;
51938494Sobrien
52038494Sobrien  /*
52138494Sobrien   * Some "df" programs automatically assume that file systems
52238494Sobrien   * with zero blocks are meta-filesystems served by automounters.
52338494Sobrien   */
52438494Sobrien  res.sfr_u.sfr_reply_u.sfrok_blocks = 0;
52538494Sobrien  res.sfr_u.sfr_reply_u.sfrok_bfree = 0;
52638494Sobrien  res.sfr_u.sfr_reply_u.sfrok_bavail = 0;
52738494Sobrien
52838494Sobrien  return &res;
52938494Sobrien}
530