138494Sobrien/*
2174294Sobrien * Copyright (c) 1997-2006 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.
1938494Sobrien * 3. All advertising materials mentioning features or use of this software
2042629Sobrien *    must display the following acknowledgment:
2138494Sobrien *      This product includes software developed by the University of
2238494Sobrien *      California, Berkeley and its contributors.
2338494Sobrien * 4. Neither the name of the University nor the names of its contributors
2438494Sobrien *    may be used to endorse or promote products derived from this software
2538494Sobrien *    without specific prior written permission.
2638494Sobrien *
2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738494Sobrien * SUCH DAMAGE.
3838494Sobrien *
3938494Sobrien *
40174294Sobrien * File: am-utils/hlfsd/stubs.c
4138494Sobrien *
4238494Sobrien * HLFSD was written at Columbia University Computer Science Department, by
4338494Sobrien * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
4438494Sobrien * It is being distributed under the same terms and conditions as amd does.
4538494Sobrien */
4638494Sobrien
4738494Sobrien#ifdef HAVE_CONFIG_H
4838494Sobrien# include <config.h>
4938494Sobrien#endif /* HAVE_CONFIG_H */
5038494Sobrien#include <am_defs.h>
5138494Sobrien#include <hlfsd.h>
5238494Sobrien
5338494Sobrien/*
5438494Sobrien * STATIC VARIABLES:
5538494Sobrien */
5638494Sobrienstatic nfsfattr rootfattr = {NFDIR, 0040555, 2, 0, 0, 512, 512, 0,
5738494Sobrien			     1, 0, ROOTID};
5838494Sobrienstatic nfsfattr slinkfattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
5938494Sobrien			      (NFS_MAXPATHLEN + 1) / 512, 0, SLINKID};
6038494Sobrien				/* user name file attributes */
6138494Sobrienstatic nfsfattr un_fattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
6238494Sobrien			    (NFS_MAXPATHLEN + 1) / 512, 0, INVALIDID};
6338494Sobrienstatic int started;
6438494Sobrienstatic am_nfs_fh slink;
6538494Sobrienstatic am_nfs_fh un_fhandle;
6638494Sobrien
6738494Sobrien/*
6838494Sobrien * GLOBALS:
6938494Sobrien */
7038494Sobrienam_nfs_fh root;
7138494Sobrienam_nfs_fh *root_fhp =		&root;
7238494Sobrien
7338494Sobrien
7438494Sobrien/* initialize NFS file handles for hlfsd */
7538494Sobrienvoid
7638494Sobrienhlfsd_init_filehandles(void)
7738494Sobrien{
7838494Sobrien  u_int ui;
7938494Sobrien
8038494Sobrien  ui = ROOTID;
8138494Sobrien  memcpy(root.fh_data, &ui, sizeof(ui));
8238494Sobrien
8338494Sobrien  ui = SLINKID;
8438494Sobrien  memcpy(slink.fh_data, &ui, sizeof(ui));
8538494Sobrien
8638494Sobrien  ui = INVALIDID;
8738494Sobrien  memcpy(un_fhandle.fh_data, &ui, sizeof(ui));
8838494Sobrien}
8938494Sobrien
9038494Sobrien
9138494Sobrienvoidp
9238494Sobriennfsproc_null_2_svc(voidp argp, struct svc_req *rqstp)
9338494Sobrien{
9438494Sobrien  static char res;
9538494Sobrien
9638494Sobrien  return (voidp) &res;
9738494Sobrien}
9838494Sobrien
9938494Sobrien
10038494Sobrien/* compare if two filehandles are equal */
10138494Sobrienstatic int
10238494Sobrieneq_fh(const am_nfs_fh *fh1, const am_nfs_fh *fh2)
10338494Sobrien{
10438494Sobrien  return (!memcmp((char *) fh1, (char *) fh2, sizeof(am_nfs_fh)));
10538494Sobrien}
10638494Sobrien
10738494Sobrien
10838494Sobriennfsattrstat *
10938494Sobriennfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
11038494Sobrien{
11138494Sobrien  static nfsattrstat res;
11238494Sobrien  uid_t uid = (uid_t) INVALIDID;
11338494Sobrien  gid_t gid = (gid_t) INVALIDID;
11438494Sobrien
11538494Sobrien  if (!started) {
11638494Sobrien    started++;
11738494Sobrien    rootfattr.na_ctime = startup;
11838494Sobrien    rootfattr.na_mtime = startup;
11938494Sobrien    slinkfattr.na_ctime = startup;
12038494Sobrien    slinkfattr.na_mtime = startup;
12138494Sobrien    un_fattr.na_ctime = startup;
12238494Sobrien    un_fattr.na_mtime = startup;
12338494Sobrien  }
12438494Sobrien
125119679Smbr  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
126119679Smbr    res.ns_status = NFSERR_STALE;
127119679Smbr    return &res;
128119679Smbr  }
12938494Sobrien  if (eq_fh(argp, &root)) {
130174294Sobrien#if 0
131174294Sobrien    /*
132174294Sobrien     * XXX: increment mtime of parent directory, causes NFS clients to
133174294Sobrien     * invalidate their cache for that directory.
134174294Sobrien     * Some NFS clients may need this code.
135174294Sobrien     */
136174294Sobrien    if (uid != rootfattr.na_uid) {
137174294Sobrien      clocktime(&rootfattr.na_mtime);
138174294Sobrien      rootfattr.na_uid = uid;
139174294Sobrien    }
140174294Sobrien#endif
14138494Sobrien    res.ns_status = NFS_OK;
14238494Sobrien    res.ns_u.ns_attr_u = rootfattr;
14338494Sobrien  } else if (eq_fh(argp, &slink)) {
14438494Sobrien
14538494Sobrien#ifndef MNT2_NFS_OPT_SYMTTL
14638494Sobrien    /*
14738494Sobrien     * This code is needed to defeat Solaris 2.4's (and newer) symlink
14842629Sobrien     * values cache.  It forces the last-modified time of the symlink to be
14938494Sobrien     * current.  It is not needed if the O/S has an nfs flag to turn off the
15038494Sobrien     * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
151119679Smbr     *
152119679Smbr     * Additionally, Linux currently ignores the nt_useconds field,
153119679Smbr     * so we must update the nt_seconds field every time.
15438494Sobrien     */
155119679Smbr    if (uid != slinkfattr.na_uid) {
156174294Sobrien      clocktime(&slinkfattr.na_mtime);
157119679Smbr      slinkfattr.na_uid = uid;
158119679Smbr    }
15938494Sobrien#endif /* not MNT2_NFS_OPT_SYMTTL */
16038494Sobrien
16138494Sobrien    res.ns_status = NFS_OK;
16238494Sobrien    res.ns_u.ns_attr_u = slinkfattr;
16338494Sobrien  } else {
16438494Sobrien    if (gid != hlfs_gid) {
16538494Sobrien      res.ns_status = NFSERR_STALE;
16638494Sobrien    } else {
16738494Sobrien      memset((char *) &uid, 0, sizeof(int));
16838494Sobrien      uid = *(u_int *) argp->fh_data;
16938494Sobrien      if (plt_search(uid) != (uid2home_t *) NULL) {
17038494Sobrien	res.ns_status = NFS_OK;
17138494Sobrien	un_fattr.na_fileid = uid;
17238494Sobrien	res.ns_u.ns_attr_u = un_fattr;
17351292Sobrien	dlog("nfs_getattr: successful search for uid=%ld, gid=%ld",
17451292Sobrien	     (long) uid, (long) gid);
17538494Sobrien      } else {			/* not found */
17638494Sobrien	res.ns_status = NFSERR_STALE;
17738494Sobrien      }
17838494Sobrien    }
17938494Sobrien  }
18038494Sobrien  return &res;
18138494Sobrien}
18238494Sobrien
18338494Sobrien
18438494Sobriennfsattrstat *
18538494Sobriennfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp)
18638494Sobrien{
18738494Sobrien  static nfsattrstat res = {NFSERR_ROFS};
18838494Sobrien
18938494Sobrien  return &res;
19038494Sobrien}
19138494Sobrien
19238494Sobrien
19338494Sobrienvoidp
19438494Sobriennfsproc_root_2_svc(voidp argp, struct svc_req *rqstp)
19538494Sobrien{
19638494Sobrien  static char res;
19738494Sobrien
19838494Sobrien  return (voidp) &res;
19938494Sobrien}
20038494Sobrien
20138494Sobrien
20238494Sobriennfsdiropres *
20338494Sobriennfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
20438494Sobrien{
20538494Sobrien  static nfsdiropres res;
20638494Sobrien  int idx;
20738494Sobrien  uid_t uid = (uid_t) INVALIDID;
20838494Sobrien  gid_t gid = (gid_t) INVALIDID;
20938494Sobrien
21038494Sobrien  if (!started) {
21138494Sobrien    started++;
21238494Sobrien    rootfattr.na_ctime = startup;
21338494Sobrien    rootfattr.na_mtime = startup;
21438494Sobrien    slinkfattr.na_ctime = startup;
21538494Sobrien    slinkfattr.na_mtime = startup;
21638494Sobrien    un_fattr.na_ctime = startup;
21738494Sobrien    un_fattr.na_mtime = startup;
21838494Sobrien  }
21938494Sobrien
22038494Sobrien  if (eq_fh(&argp->da_fhandle, &slink)) {
22138494Sobrien    res.dr_status = NFSERR_NOTDIR;
22238494Sobrien    return &res;
22338494Sobrien  }
22438494Sobrien
225119679Smbr  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
226119679Smbr    res.dr_status = NFSERR_NOENT;
227119679Smbr    return &res;
228119679Smbr  }
22938494Sobrien  if (eq_fh(&argp->da_fhandle, &root)) {
23038494Sobrien    if (argp->da_name[0] == '.' &&
23138494Sobrien	(argp->da_name[1] == '\0' ||
23238494Sobrien	 (argp->da_name[1] == '.' &&
23338494Sobrien	  argp->da_name[2] == '\0'))) {
234174294Sobrien#if 0
235174294Sobrien    /*
236174294Sobrien     * XXX: increment mtime of parent directory, causes NFS clients to
237174294Sobrien     * invalidate their cache for that directory.
238174294Sobrien     * Some NFS clients may need this code.
239174294Sobrien     */
240174294Sobrien      if (uid != rootfattr.na_uid) {
241174294Sobrien	clocktime(&rootfattr.na_mtime);
242174294Sobrien	rootfattr.na_uid = uid;
243174294Sobrien      }
244174294Sobrien#endif
24538494Sobrien      res.dr_u.dr_drok_u.drok_fhandle = root;
24638494Sobrien      res.dr_u.dr_drok_u.drok_attributes = rootfattr;
24738494Sobrien      res.dr_status = NFS_OK;
24838494Sobrien      return &res;
24938494Sobrien    }
25038494Sobrien
25138494Sobrien    if (STREQ(argp->da_name, slinkname)) {
25282794Sobrien#ifndef MNT2_NFS_OPT_SYMTTL
25382794Sobrien      /*
25482794Sobrien       * This code is needed to defeat Solaris 2.4's (and newer) symlink
25582794Sobrien       * values cache.  It forces the last-modified time of the symlink to be
25682794Sobrien       * current.  It is not needed if the O/S has an nfs flag to turn off the
25782794Sobrien       * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
258119679Smbr       *
259119679Smbr       * Additionally, Linux currently ignores the nt_useconds field,
260119679Smbr       * so we must update the nt_seconds field every time.
26182794Sobrien       */
262119679Smbr      if (uid != slinkfattr.na_uid) {
263174294Sobrien	clocktime(&slinkfattr.na_mtime);
264119679Smbr	slinkfattr.na_uid = uid;
265119679Smbr      }
26682794Sobrien#endif /* not MNT2_NFS_OPT_SYMTTL */
26738494Sobrien      res.dr_u.dr_drok_u.drok_fhandle = slink;
26838494Sobrien      res.dr_u.dr_drok_u.drok_attributes = slinkfattr;
26938494Sobrien      res.dr_status = NFS_OK;
27038494Sobrien      return &res;
27138494Sobrien    }
27238494Sobrien
273119679Smbr    if (gid != hlfs_gid) {
27438494Sobrien      res.dr_status = NFSERR_NOENT;
27538494Sobrien      return &res;
27638494Sobrien    }
27738494Sobrien
27842629Sobrien    /* if gets here, gid == hlfs_gid */
27938494Sobrien    if ((idx = untab_index(argp->da_name)) < 0) {
28038494Sobrien      res.dr_status = NFSERR_NOENT;
28138494Sobrien      return &res;
28238494Sobrien    } else {			/* entry found and gid is permitted */
28338494Sobrien      un_fattr.na_fileid = untab[idx].uid;
28438494Sobrien      res.dr_u.dr_drok_u.drok_attributes = un_fattr;
28538494Sobrien      memset((char *) &un_fhandle, 0, sizeof(am_nfs_fh));
28638494Sobrien      *(u_int *) un_fhandle.fh_data = (u_int) untab[idx].uid;
287174294Sobrien      xstrlcpy((char *) &un_fhandle.fh_data[sizeof(int)],
288174294Sobrien	       untab[idx].username,
289174294Sobrien	       sizeof(am_nfs_fh) - sizeof(int));
29038494Sobrien      res.dr_u.dr_drok_u.drok_fhandle = un_fhandle;
29138494Sobrien      res.dr_status = NFS_OK;
29251292Sobrien      dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s",
29351292Sobrien	   (long) uid, (long) gid, untab[idx].username);
29438494Sobrien      return &res;
29538494Sobrien    }
29638494Sobrien  } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */
29738494Sobrien
29838494Sobrien  res.dr_status = NFSERR_STALE;
29938494Sobrien  return &res;
30038494Sobrien}
30138494Sobrien
30238494Sobrien
30338494Sobriennfsreadlinkres *
30438494Sobriennfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
30538494Sobrien{
30638494Sobrien  static nfsreadlinkres res;
30738494Sobrien  uid_t userid = (uid_t) INVALIDID;
30838494Sobrien  gid_t groupid = hlfs_gid + 1;	/* anything not hlfs_gid */
30938494Sobrien  int retval = 0;
31038494Sobrien  char *path_val = (char *) NULL;
31138494Sobrien  char *username;
31238494Sobrien  static uid_t last_uid = (uid_t) INVALIDID;
31338494Sobrien
31438494Sobrien  if (eq_fh(argp, &root)) {
31538494Sobrien    res.rlr_status = NFSERR_ISDIR;
31638494Sobrien  } else if (eq_fh(argp, &slink)) {
31782794Sobrien    if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0)
31838494Sobrien      return (nfsreadlinkres *) NULL;
31938494Sobrien
320174294Sobrien    clocktime(&slinkfattr.na_atime);
32138494Sobrien
32238494Sobrien    res.rlr_status = NFS_OK;
32338494Sobrien    if (groupid == hlfs_gid) {
32438494Sobrien      res.rlr_u.rlr_data_u = DOTSTRING;
325119679Smbr    } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid, groupid))) {
32638494Sobrien      /*
32738494Sobrien       * parent process (fork in homedir()) continues
32838494Sobrien       * processing, by getting a NULL returned as a
32938494Sobrien       * "special".  Child returns result.
33038494Sobrien       */
33138494Sobrien      return (nfsreadlinkres *) NULL;
33238494Sobrien    }
33338494Sobrien
33438494Sobrien  } else {			/* check if asked for user mailbox */
33538494Sobrien
33682794Sobrien    if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0) {
33738494Sobrien      return (nfsreadlinkres *) NULL;
33838494Sobrien    }
33938494Sobrien
34038494Sobrien    if (groupid == hlfs_gid) {
34138494Sobrien      memset((char *) &userid, 0, sizeof(int));
34238494Sobrien      userid = *(u_int *) argp->fh_data;
34338494Sobrien      username = (char *) &argp->fh_data[sizeof(int)];
34438494Sobrien      if (!(res.rlr_u.rlr_data_u = mailbox(userid, username)))
34538494Sobrien	return (nfsreadlinkres *) NULL;
34638494Sobrien    } else {
34738494Sobrien      res.rlr_status = NFSERR_STALE;
34838494Sobrien    }
34938494Sobrien  }
35038494Sobrien
35138494Sobrien  /* print info, but try to avoid repetitions */
35238494Sobrien  if (userid != last_uid) {
35351292Sobrien    plog(XLOG_USER, "mailbox for uid=%ld, gid=%ld is %s",
35451292Sobrien	 (long) userid, (long) groupid, (char *) res.rlr_u.rlr_data_u);
35538494Sobrien    last_uid = userid;
35638494Sobrien  }
35738494Sobrien
358174294Sobrien  /* I don't think it will pass this if -D fork */
35938494Sobrien  if (serverpid == getpid())
36038494Sobrien    return &res;
36138494Sobrien
36238494Sobrien  if (!svc_sendreply(nfsxprt, (XDRPROC_T_TYPE) xdr_readlinkres, (SVC_IN_ARG_TYPE) &res))
36338494Sobrien    svcerr_systemerr(nfsxprt);
36438494Sobrien
36538494Sobrien  /*
36638494Sobrien   * Child exists here.   We need to determine which
36738494Sobrien   * exist status to return.  The exit status
36838494Sobrien   * is gathered using wait() and determines
36938494Sobrien   * if we returned $HOME/.hlfsspool or $ALTDIR.  The parent
37038494Sobrien   * needs this info so it can update the lookup table.
37138494Sobrien   */
37238494Sobrien  if (path_val && alt_spooldir && STREQ(path_val, alt_spooldir))
37338494Sobrien    retval = 1;		/* could not get real home dir (or uid 0 user) */
37438494Sobrien  else
37538494Sobrien    retval = 0;
37638494Sobrien
37738494Sobrien  /*
378174294Sobrien   * If asked for -D fork, then must return the value,
37938494Sobrien   * NOT exit, or else the main hlfsd server exits.
380174294Sobrien   * Bug: where is that status information being collected?
38138494Sobrien   */
382174294Sobrien  if (amuDebug(D_FORK))
38338494Sobrien    return &res;
38438494Sobrien
38538494Sobrien  exit(retval);
38638494Sobrien}
38738494Sobrien
38838494Sobrien
38938494Sobriennfsreadres *
39038494Sobriennfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp)
39138494Sobrien{
39238494Sobrien  static nfsreadres res = {NFSERR_ACCES};
39338494Sobrien
39438494Sobrien  return &res;
39538494Sobrien}
39638494Sobrien
39738494Sobrien
39838494Sobrienvoidp
39938494Sobriennfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp)
40038494Sobrien{
40138494Sobrien  static char res;
40238494Sobrien
40338494Sobrien  return (voidp) &res;
40438494Sobrien}
40538494Sobrien
40638494Sobrien
40738494Sobriennfsattrstat *
40838494Sobriennfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp)
40938494Sobrien{
41038494Sobrien  static nfsattrstat res = {NFSERR_ROFS};
41138494Sobrien
41238494Sobrien  return &res;
41338494Sobrien}
41438494Sobrien
41538494Sobrien
41638494Sobriennfsdiropres *
41738494Sobriennfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
41838494Sobrien{
41938494Sobrien  static nfsdiropres res = {NFSERR_ROFS};
42038494Sobrien
42138494Sobrien  return &res;
42238494Sobrien}
42338494Sobrien
42438494Sobrien
42538494Sobriennfsstat *
42638494Sobriennfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
42738494Sobrien{
42838494Sobrien  static nfsstat res = {NFSERR_ROFS};
42938494Sobrien
43038494Sobrien  return &res;
43138494Sobrien}
43238494Sobrien
43338494Sobrien
43438494Sobriennfsstat *
43538494Sobriennfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp)
43638494Sobrien{
43738494Sobrien  static nfsstat res = {NFSERR_ROFS};
43838494Sobrien
43938494Sobrien  return &res;
44038494Sobrien}
44138494Sobrien
44238494Sobrien
44338494Sobriennfsstat *
44438494Sobriennfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp)
44538494Sobrien{
44638494Sobrien  static nfsstat res = {NFSERR_ROFS};
44738494Sobrien
44838494Sobrien  return &res;
44938494Sobrien}
45038494Sobrien
45138494Sobrien
45238494Sobriennfsstat *
45338494Sobriennfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp)
45438494Sobrien{
45538494Sobrien  static nfsstat res = {NFSERR_ROFS};
45638494Sobrien
45738494Sobrien  return &res;
45838494Sobrien}
45938494Sobrien
46038494Sobrien
46138494Sobriennfsdiropres *
46238494Sobriennfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
46338494Sobrien{
46438494Sobrien  static nfsdiropres res = {NFSERR_ROFS};
46538494Sobrien
46638494Sobrien  return &res;
46738494Sobrien}
46838494Sobrien
46938494Sobrien
47038494Sobriennfsstat *
47138494Sobriennfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
47238494Sobrien{
47338494Sobrien  static nfsstat res = {NFSERR_ROFS};
47438494Sobrien
47538494Sobrien  return &res;
47638494Sobrien}
47738494Sobrien
47838494Sobrien
47938494Sobriennfsreaddirres *
48038494Sobriennfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
48138494Sobrien{
48238494Sobrien  static nfsreaddirres res;
48338494Sobrien  static nfsentry slinkent = {SLINKID, 0, {SLINKCOOKIE}};
48438494Sobrien  static nfsentry dotdotent = {ROOTID, "..", {DOTDOTCOOKIE}, &slinkent};
48538494Sobrien  static nfsentry dotent = {ROOTID, ".", {DOTCOOKIE}, &dotdotent};
48638494Sobrien
48738494Sobrien  slinkent.ne_name = slinkname;
48838494Sobrien
48938494Sobrien  if (eq_fh(&argp->rda_fhandle, &slink)) {
49038494Sobrien    res.rdr_status = NFSERR_NOTDIR;
49138494Sobrien  } else if (eq_fh(&argp->rda_fhandle, &root)) {
492174294Sobrien    clocktime(&rootfattr.na_atime);
49338494Sobrien
49438494Sobrien    res.rdr_status = NFS_OK;
49538494Sobrien    switch (argp->rda_cookie[0]) {
49638494Sobrien    case 0:
49738494Sobrien      res.rdr_u.rdr_reply_u.dl_entries = &dotent;
49838494Sobrien      break;
49938494Sobrien    case DOTCOOKIE:
50038494Sobrien      res.rdr_u.rdr_reply_u.dl_entries = &dotdotent;
50138494Sobrien      break;
50238494Sobrien    case DOTDOTCOOKIE:
50338494Sobrien      res.rdr_u.rdr_reply_u.dl_entries = &slinkent;
50438494Sobrien      break;
50538494Sobrien    case SLINKCOOKIE:
50638494Sobrien      res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) 0;
50738494Sobrien      break;
50838494Sobrien    }
50938494Sobrien    res.rdr_u.rdr_reply_u.dl_eof = TRUE;
51038494Sobrien  } else {
51138494Sobrien    res.rdr_status = NFSERR_STALE;
51238494Sobrien  }
51338494Sobrien  return &res;
51438494Sobrien}
51538494Sobrien
51638494Sobrien
51738494Sobriennfsstatfsres *
51838494Sobriennfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
51938494Sobrien{
52038494Sobrien  static nfsstatfsres res = {NFS_OK};
52138494Sobrien
52238494Sobrien  res.sfr_u.sfr_reply_u.sfrok_tsize = 1024;
52338494Sobrien  res.sfr_u.sfr_reply_u.sfrok_bsize = 1024;
52438494Sobrien
52538494Sobrien  /*
52638494Sobrien   * Some "df" programs automatically assume that file systems
52738494Sobrien   * with zero blocks are meta-filesystems served by automounters.
52838494Sobrien   */
52938494Sobrien  res.sfr_u.sfr_reply_u.sfrok_blocks = 0;
53038494Sobrien  res.sfr_u.sfr_reply_u.sfrok_bfree = 0;
53138494Sobrien  res.sfr_u.sfr_reply_u.sfrok_bavail = 0;
53238494Sobrien
53338494Sobrien  return &res;
53438494Sobrien}
535