nfsdiropres * nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) { static nfsdiropres res; am_node *mp; int retry; uid_t uid; gid_t gid; if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "lookup:"); /* finally, find the effective uid/gid from RPC request */ if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) plog(XLOG_ERROR, "cannot get uid/gid from RPC credentials"); xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) uid); xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid); mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE); if (mp == NULL) { if (retry < 0) { amd_stats.d_drops++; return 0; } res.dr_status = nfs_error(retry); } else { int error; am_node *ap; if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, argp->da_name); ap = mp->am_al->al_mnt->mf_ops->lookup_child(mp, argp->da_name, &error, VLOOK_CREATE); if (ap && error < 0) ap = mp->am_al->al_mnt->mf_ops->mount_child(ap, &error); if (ap == 0) { if (error < 0) { amd_stats.d_drops++; return 0; } res.dr_status = nfs_error(error); } else { /* * XXX: EXPERIMENTAL! Delay unmount of what was looked up. This * should reduce the chance for race condition between unmounting an * entry synchronously, and re-mounting it asynchronously. */ if (ap->am_ttl < mp->am_ttl) ap->am_ttl = mp->am_ttl; mp_to_fh(ap, &res.dr_u.dr_drok_u.drok_fhandle); res.dr_u.dr_drok_u.drok_attributes = ap->am_fattr; res.dr_status = NFS_OK; } mp->am_stats.s_lookup++; /* reschedule_timeout_mp(); */ } return &res; }
nfsdiropres * nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) { static nfsdiropres res; int idx; uid_t uid = (uid_t) INVALIDID; gid_t gid = (gid_t) INVALIDID; if (!started) { started++; rootfattr.na_ctime = startup; rootfattr.na_mtime = startup; slinkfattr.na_ctime = startup; slinkfattr.na_mtime = startup; un_fattr.na_ctime = startup; un_fattr.na_mtime = startup; } if (eq_fh(&argp->da_fhandle, &slink)) { res.dr_status = NFSERR_NOTDIR; return &res; } if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) { res.dr_status = NFSERR_NOENT; return &res; } if (eq_fh(&argp->da_fhandle, &root)) { if (argp->da_name[0] == '.' && (argp->da_name[1] == '\0' || (argp->da_name[1] == '.' && argp->da_name[2] == '\0'))) { #if 0 /* * XXX: increment mtime of parent directory, causes NFS clients to * invalidate their cache for that directory. * Some NFS clients may need this code. */ if (uid != rootfattr.na_uid) { clocktime(&rootfattr.na_mtime); rootfattr.na_uid = uid; } #endif /* 0 */ res.dr_u.dr_drok_u.drok_fhandle = root; res.dr_u.dr_drok_u.drok_attributes = rootfattr; res.dr_status = NFS_OK; return &res; } if (STREQ(argp->da_name, slinkname)) { #ifndef MNT2_NFS_OPT_SYMTTL /* * This code is needed to defeat Solaris 2.4's (and newer) symlink * values cache. It forces the last-modified time of the symlink to be * current. It is not needed if the O/S has an nfs flag to turn off the * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez. * * Additionally, Linux currently ignores the nt_useconds field, * so we must update the nt_seconds field every time. */ if (uid != slinkfattr.na_uid) { clocktime(&slinkfattr.na_mtime); slinkfattr.na_uid = uid; } #endif /* not MNT2_NFS_OPT_SYMTTL */ res.dr_u.dr_drok_u.drok_fhandle = slink; res.dr_u.dr_drok_u.drok_attributes = slinkfattr; res.dr_status = NFS_OK; return &res; } if (gid != hlfs_gid) { res.dr_status = NFSERR_NOENT; return &res; } /* if gets here, gid == hlfs_gid */ if ((idx = untab_index(argp->da_name)) < 0) { res.dr_status = NFSERR_NOENT; return &res; } else { /* entry found and gid is permitted */ u_int xuid; un_fattr.na_fileid = untab[idx].uid; res.dr_u.dr_drok_u.drok_attributes = un_fattr; memset(&un_fhandle, 0, sizeof(am_nfs_fh)); xuid = (u_int) untab[idx].uid; memcpy(un_fhandle.fh_data, &xuid, sizeof(xuid)); xstrlcpy((char *) &un_fhandle.fh_data[sizeof(xuid)], untab[idx].username, sizeof(am_nfs_fh) - sizeof(xuid)); res.dr_u.dr_drok_u.drok_fhandle = un_fhandle; res.dr_status = NFS_OK; dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s", (long) uid, (long) gid, untab[idx].username); return &res; } } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */ res.dr_status = NFSERR_STALE; return &res; }
nfsreadlinkres * nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) { static nfsreadlinkres res; uid_t userid = (uid_t) INVALIDID; gid_t groupid = hlfs_gid + 1; /* anything not hlfs_gid */ int retval = 0; char *path_val = NULL; char *username; static uid_t last_uid = (uid_t) INVALIDID; if (eq_fh(argp, &root)) { res.rlr_status = NFSERR_ISDIR; } else if (eq_fh(argp, &slink)) { if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0) return (nfsreadlinkres *) NULL; clocktime(&slinkfattr.na_atime); res.rlr_status = NFS_OK; if (groupid == hlfs_gid) { res.rlr_u.rlr_data_u = DOTSTRING; } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid, groupid))) { /* * parent process (fork in homedir()) continues * processing, by getting a NULL returned as a * "special". Child returns result. */ return NULL; } } else { /* check if asked for user mailbox */ if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0) { return (nfsreadlinkres *) NULL; } if (groupid == hlfs_gid) { u_int xuserid; memcpy(&xuserid, argp->fh_data, sizeof(xuserid)); userid = xuserid; username = (char *) &argp->fh_data[sizeof(xuserid)]; if (!(res.rlr_u.rlr_data_u = mailbox(userid, username))) return (nfsreadlinkres *) NULL; } else { res.rlr_status = NFSERR_STALE; } } /* print info, but try to avoid repetitions */ if (userid != last_uid) { plog(XLOG_USER, "mailbox for uid=%ld, gid=%ld is %s", (long) userid, (long) groupid, (char *) res.rlr_u.rlr_data_u); last_uid = userid; } /* I don't think it will pass this if -D fork */ if (serverpid == getpid()) return &res; if (!svc_sendreply(nfsxprt, (XDRPROC_T_TYPE) xdr_readlinkres, (SVC_IN_ARG_TYPE) &res)) svcerr_systemerr(nfsxprt); /* * Child exists here. We need to determine which * exist status to return. The exit status * is gathered using wait() and determines * if we returned $HOME/.hlfsspool or $ALTDIR. The parent * needs this info so it can update the lookup table. */ if (path_val && alt_spooldir && STREQ(path_val, alt_spooldir)) retval = 1; /* could not get real home dir (or uid 0 user) */ else retval = 0; /* * If asked for -D nofork, then must return the value, * NOT exit, or else the main hlfsd server exits. * If -D fork (default), then we do want to exit from the process. * Bug: where is that status information being collected? */ if (amuDebug(D_FORK)) exit(retval); else return &res; }
nfsattrstat * nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) { static nfsattrstat res; uid_t uid = (uid_t) INVALIDID; gid_t gid = (gid_t) INVALIDID; if (!started) { started++; rootfattr.na_ctime = startup; rootfattr.na_mtime = startup; slinkfattr.na_ctime = startup; slinkfattr.na_mtime = startup; un_fattr.na_ctime = startup; un_fattr.na_mtime = startup; } if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) { res.ns_status = NFSERR_STALE; return &res; } if (eq_fh(argp, &root)) { #if 0 /* * XXX: increment mtime of parent directory, causes NFS clients to * invalidate their cache for that directory. * Some NFS clients may need this code. */ if (uid != rootfattr.na_uid) { clocktime(&rootfattr.na_mtime); rootfattr.na_uid = uid; } #endif /* 0 */ res.ns_status = NFS_OK; res.ns_u.ns_attr_u = rootfattr; } else if (eq_fh(argp, &slink)) { #ifndef MNT2_NFS_OPT_SYMTTL /* * This code is needed to defeat Solaris 2.4's (and newer) symlink * values cache. It forces the last-modified time of the symlink to be * current. It is not needed if the O/S has an nfs flag to turn off the * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez. * * Additionally, Linux currently ignores the nt_useconds field, * so we must update the nt_seconds field every time. */ if (uid != slinkfattr.na_uid) { clocktime(&slinkfattr.na_mtime); slinkfattr.na_uid = uid; } #endif /* not MNT2_NFS_OPT_SYMTTL */ res.ns_status = NFS_OK; res.ns_u.ns_attr_u = slinkfattr; } else { if (gid != hlfs_gid) { res.ns_status = NFSERR_STALE; } else { u_int xuid; memcpy(&xuid, argp->fh_data, sizeof(xuid)); uid = xuid; if (plt_search(uid) != (uid2home_t *) NULL) { res.ns_status = NFS_OK; un_fattr.na_fileid = uid; res.ns_u.ns_attr_u = un_fattr; dlog("nfs_getattr: successful search for uid=%ld, gid=%ld", (long) uid, (long) gid); } else { /* not found */ res.ns_status = NFSERR_STALE; } } } return &res; }