home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-01-17 | 88.7 KB | 3,833 lines |
- Newsgroups: comp.sources.misc
- From: youki-k@is.aist-nara.ac.jp (Youki Kadobayashi)
- Subject: v41i099: wwfs - WorldWide File System, Part14/22
- Message-ID: <1994Jan17.202407.20204@sparky.sterling.com>
- X-Md4-Signature: 2ca560d064717142f548dfb8b58e445f
- Sender: kent@sparky.sterling.com (Kent Landfield)
- Organization: Nara Institute of Science and Technology, Japan
- Date: Mon, 17 Jan 1994 20:24:07 GMT
- Approved: kent@sparky.sterling.com
-
- Submitted-by: youki-k@is.aist-nara.ac.jp (Youki Kadobayashi)
- Posting-number: Volume 41, Issue 99
- Archive-name: wwfs/part14
- Environment: UNIX, inet
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: config/mtab_file.c csd/cmfs.c csd/file.c csd/nfs_subr.c
- # csd/util.c csd/vol.c libww/libww.c wwalk/Makefile
- # wwmount/wwmount.c
- # Wrapped by kent@sparky on Sun Jan 16 17:48:36 1994
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 14 (of 22)."'
- if test -f 'config/mtab_file.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'config/mtab_file.c'\"
- else
- echo shar: Extracting \"'config/mtab_file.c'\" \(10879 characters\)
- sed "s/^X//" >'config/mtab_file.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Jan-Simon Pendry
- X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
- X * Copyright (c) 1990 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * This code is derived from software contributed to Berkeley by
- X * Jan-Simon Pendry at Imperial College, London.
- X *
- X * Redistribution and use in source and binary forms, with or without
- X * modification, are permitted provided that the following conditions
- X * are met:
- X * 1. Redistributions of source code must retain the above copyright
- X * notice, this list of conditions and the following disclaimer.
- X * 2. Redistributions in binary form must reproduce the above copyright
- X * notice, this list of conditions and the following disclaimer in the
- X * documentation and/or other materials provided with the distribution.
- X * 3. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the University of
- X * California, Berkeley and its contributors.
- X * 4. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- X * SUCH DAMAGE.
- X *
- X * %W% (Berkeley) %G%
- X *
- X * $Id: mtab_file.c,v 5.2.2.1 1992/02/09 15:10:42 jsp beta $
- X *
- X */
- X
- X#include "am.h"
- X
- X#ifdef READ_MTAB_FROM_FILE
- X
- X#ifdef USE_FCNTL
- X#include <fcntl.h>
- X#else
- X#include <sys/file.h>
- X#endif /* USE_FCNTL */
- X
- X#ifdef UPDATE_MTAB
- X
- X/*
- X * Do strict /etc/mtab locking
- X */
- X#define MTAB_LOCKING
- X
- X/*
- X * Firewall mtab entries
- X */
- X#define MTAB_STRIPNL
- X
- X#include <sys/stat.h>
- Xstatic FILE *mnt_file;
- X
- X/*
- X * If the system is being trashed by something, then
- X * opening mtab may fail with ENFILE. So, go to sleep
- X * for a second and try again. (Yes - this has happened to me.)
- X *
- X * Note that this *may* block the automounter, oh well.
- X * If we get to this state then things are badly wrong anyway...
- X *
- X * Give the system 10 seconds to recover but then give up.
- X * Hopefully something else will exit and free up some file
- X * table slots in that time.
- X */
- X#define NFILE_RETRIES 10 /* seconds */
- X
- X#ifdef MTAB_LOCKING
- X#ifdef LOCK_FCNTL
- Xstatic int lock(fd)
- X{
- X int rc;
- X struct flock lk;
- X
- X lk.l_type = F_WRLCK;
- X lk.l_whence = 0;
- X lk.l_start = 0;
- X lk.l_len = 0;
- X
- Xagain:
- X rc = fcntl(fd, F_SETLKW, (caddr_t) &lk);
- X if (rc < 0 && (errno == EACCES || errno == EAGAIN)) {
- X#ifdef DEBUG
- X dlog("Blocked, trying to obtain exclusive mtab lock");
- X#endif /* DEBUG */
- X sleep(1);
- X goto again;
- X }
- X return rc;
- X}
- X#else
- X#define lock(fd) (flock((fd), LOCK_EX))
- X#endif /* LOCK_FCNTL */
- X#endif /* MTAB_LOCKING */
- X
- Xstatic FILE *open_locked_mtab(mtab_file, mode, fs)
- Xchar *mtab_file;
- Xchar *mode;
- Xchar *fs;
- X{
- X FILE *mfp = 0;
- X
- X#ifdef UPDATE_MTAB
- X /*
- X * There is a possible race condition if two processes enter
- X * this routine at the same time. One will be blocked by the
- X * exclusive lock below (or by the shared lock in setmntent)
- X * and by the time the second process has the exclusive lock
- X * it will be on the wrong underlying object. To check for this
- X * the mtab file is stat'ed before and after all the locking
- X * sequence, and if it is a different file then we assume that
- X * it may be the wrong file (only "may", since there is another
- X * race between the initial stat and the setmntent).
- X *
- X * Simpler solutions to this problem are invited...
- X */
- X int racing = 2;
- X#ifdef MTAB_LOCKING
- X int rc;
- X int retries = 0;
- X struct stat st_before, st_after;
- X#endif /* MTAB_LOCKING */
- X
- X if (mnt_file) {
- X#ifdef DEBUG
- X dlog("Forced close on %s in read_mtab", mtab_file);
- X#endif /* DEBUG */
- X endmntent(mnt_file);
- X mnt_file = 0;
- X }
- X
- X#ifdef MTAB_LOCKING
- Xagain:
- X if (mfp) {
- X endmntent(mfp);
- X mfp = 0;
- X }
- X
- X clock_valid = 0;
- X if (stat(mtab_file, &st_before) < 0) {
- X plog(XLOG_ERROR, "%s: stat: %m", mtab_file);
- X if (errno == ESTALE) {
- X /* happens occasionally */
- X sleep(1);
- X goto again;
- X }
- X return 0;
- X }
- X#endif /* MTAB_LOCKING */
- X#endif /* UPDATE_MTAB */
- X
- Xeacces:
- X mfp = setmntent(mtab_file, mode);
- X if (!mfp) {
- X /*
- X * Since setmntent locks the descriptor, it
- X * is possible it can fail... so retry if
- X * needed.
- X */
- X if (errno == EACCES || errno == EAGAIN) {
- X#ifdef DEBUG
- X dlog("Blocked, trying to obtain exclusive mtab lock");
- X#endif /* DEBUG */
- X goto eacces;
- X } else if (errno == ENFILE && retries++ < NFILE_RETRIES) {
- X sleep(1);
- X goto eacces;
- X }
- X
- X plog(XLOG_ERROR, "setmntent(\"%s\", \"%s\"): %m", mtab_file, mode);
- X return 0;
- X }
- X
- X#ifdef MTAB_LOCKING
- X#ifdef UPDATE_MTAB
- X /*
- X * At this point we have an exclusive lock on the mount list,
- X * but it may be the wrong one so...
- X */
- X
- X /*
- X * Need to get an exclusive lock on the current
- X * mount table until we have a new copy written
- X * out, when the lock is released in free_mntlist.
- X * flock is good enough since the mount table is
- X * not shared between machines.
- X */
- X do
- X rc = lock(fileno(mfp));
- X while (rc < 0 && errno == EINTR);
- X if (rc < 0) {
- X plog(XLOG_ERROR, "Couldn't lock %s: %m", mtab_file);
- X endmntent(mfp);
- X return 0;
- X }
- X /*
- X * Now check whether the mtab file has changed under our feet
- X */
- X if (stat(mtab_file, &st_after) < 0) {
- X plog(XLOG_ERROR, "%s: stat", mtab_file);
- X goto again;
- X }
- X
- X if (st_before.st_dev != st_after.st_dev ||
- X st_before.st_ino != st_after.st_ino) {
- X struct timeval tv;
- X if (racing == 0) {
- X /* Sometimes print a warning */
- X plog(XLOG_WARNING,
- X "Possible mount table race - retrying %s", fs);
- X }
- X racing = (racing+1) & 3;
- X /*
- X * Take a nap. From: Doug Kingston <dpk@morgan.com>
- X */
- X tv.tv_sec = 0;
- X tv.tv_usec = (mypid & 0x07) << 17;
- X if (tv.tv_usec)
- X if (select(0, (voidp) 0, (voidp) 0, (voidp) 0, &tv) < 0)
- X plog(XLOG_WARNING, "mtab nap failed: %m");
- X
- X goto again;
- X }
- X#endif /* UPDATE_MTAB */
- X#endif /* MTAB_LOCKING */
- X
- X return mfp;
- X}
- X
- X/*
- X * Unlock the mount table
- X */
- Xvoid unlock_mntlist P((void));
- Xvoid unlock_mntlist()
- X{
- X /*
- X * Release file lock, by closing the file
- X */
- X if (mnt_file) {
- X endmntent(mnt_file);
- X mnt_file = 0;
- X }
- X}
- X
- X/*
- X * Write out a mount list
- X */
- Xvoid rewrite_mtab(mp)
- Xmntlist *mp;
- X{
- X FILE *mfp;
- X int error = 0;
- X
- X /*
- X * Concoct a temporary name in the same
- X * directory as the target mount table
- X * so that rename() will work.
- X */
- X char tmpname[64];
- X int retries;
- X int tmpfd;
- X char *cp;
- X char *mcp = mtab;
- X cp = strrchr(mcp, '/');
- X if (cp) {
- X bcopy(mcp, tmpname, cp - mcp);
- X tmpname[cp-mcp] = '\0';
- X } else {
- X plog(XLOG_WARNING, "No '/' in mtab (%s), using \".\" as tmp directory", mtab);
- X tmpname[0] = '.'; tmpname[1] = '\0';
- X }
- X strcat(tmpname, "/mtabXXXXXX");
- X mktemp(tmpname);
- X retries = 0;
- Xenfile1:
- X if ((tmpfd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
- X if (errno == ENFILE && retries++ < NFILE_RETRIES) {
- X sleep(1);
- X goto enfile1;
- X }
- X plog(XLOG_ERROR, "%s: open: %m", tmpname);
- X return;
- X }
- X if (close(tmpfd) < 0)
- X plog(XLOG_ERROR, "Couldn't close tmp file descriptor: %m");
- X
- X retries = 0;
- Xenfile2:
- X mfp = setmntent(tmpname, "w");
- X if (!mfp) {
- X if (errno == ENFILE && retries++ < NFILE_RETRIES) {
- X sleep(1);
- X goto enfile2;
- X }
- X plog(XLOG_ERROR, "setmntent(\"%s\", \"w\"): %m", tmpname);
- X error = 1;
- X goto out;
- X }
- X
- X while (mp) {
- X if (mp->mnt) {
- X if (addmntent(mfp, mp->mnt)) {
- X plog(XLOG_ERROR, "Can't write entry to %s", tmpname);
- X error = 1;
- X goto out;
- X }
- X }
- X mp = mp->mnext;
- X }
- X
- X /*
- X * SunOS 4.1 manuals say that the return code from entmntent()
- X * is always 1 and to treat as a void. That means we need to
- X * call fflush() to make sure the new mtab file got written.
- X */
- X if (fflush(mfp)) {
- X plog(XLOG_ERROR, "flush new mtab file: %m");
- X error = 1;
- X goto out;
- X }
- X
- X (void) endmntent(mfp);
- X
- X /*
- X * Rename temporary mtab to real mtab
- X */
- X if (rename(tmpname, mtab) < 0) {
- X plog(XLOG_ERROR, "rename %s to %s: %m", tmpname, mtab);
- X error = 1;
- X goto out;
- X }
- X
- Xout:
- X if (error)
- X (void) unlink(tmpname);
- X}
- X
- X#ifdef MTAB_STRIPNL
- Xstatic void mtab_stripnl(s)
- Xchar *s;
- X{
- X do {
- X s = strchr(s, '\n');
- X if (s)
- X *s++ = ' ';
- X } while (s);
- X}
- X#endif /* MTAB_STRIPNL */
- X
- X/*
- X * Append a mntent structure to the
- X * current mount table.
- X */
- Xvoid write_mntent(mp)
- Xstruct mntent *mp;
- X{
- X int retries = 0;
- X FILE *mfp;
- Xenfile:
- X mfp = open_locked_mtab(mtab, "a", mp->mnt_dir);
- X if (mfp) {
- X#ifdef MTAB_STRIPNL
- X mtab_stripnl(mp->mnt_opts);
- X#endif /* MTAB_STRIPNL */
- X if (addmntent(mfp, mp))
- X plog(XLOG_ERROR, "Couldn't write %s: %m", mtab);
- X if (fflush(mfp))
- X plog(XLOG_ERROR, "Couldn't flush %s: %m", mtab);
- X (void) endmntent(mfp);
- X } else {
- X if (errno == ENFILE && retries < NFILE_RETRIES) {
- X sleep(1);
- X goto enfile;
- X }
- X plog(XLOG_ERROR, "setmntent(\"%s\", \"a\"): %m", mtab);
- X }
- X}
- X
- X#endif /* UPDATE_MTAB */
- X
- Xstatic struct mntent *mnt_dup(mp)
- Xstruct mntent *mp;
- X{
- X struct mntent *new_mp = ALLOC(mntent);
- X
- X new_mp->mnt_fsname = strdup(mp->mnt_fsname);
- X new_mp->mnt_dir = strdup(mp->mnt_dir);
- X new_mp->mnt_type = strdup(mp->mnt_type);
- X new_mp->mnt_opts = strdup(mp->mnt_opts);
- X
- X new_mp->mnt_freq = mp->mnt_freq;
- X new_mp->mnt_passno = mp->mnt_passno;
- X
- X#ifdef FIXUP_MNTENT_DUP
- X /*
- X * Additional fields get dup'ed here
- X */
- X FIXUP_MNTENT_DUP(new_mp, mp);
- X#endif
- X
- X return new_mp;
- X}
- X
- X/*
- X * Read a mount table into memory
- X */
- Xmntlist *read_mtab(fs)
- Xchar *fs;
- X{
- X mntlist **mpp, *mhp;
- X
- X struct mntent *mep;
- X FILE *mfp = open_locked_mtab(mtab, "r+", fs);
- X
- X if (!mfp)
- X return 0;
- X
- X mpp = &mhp;
- X
- X/*
- X * XXX - In SunOS 4 there is (yet another) memory leak
- X * which loses 1K the first time getmntent is called.
- X * (jsp)
- X */
- X while (mep = getmntent(mfp)) {
- X /*
- X * Allocate a new slot
- X */
- X *mpp = ALLOC(mntlist);
- X
- X /*
- X * Copy the data returned by getmntent
- X */
- X (*mpp)->mnt = mnt_dup(mep);
- X
- X /*
- X * Move to next pointer
- X */
- X mpp = &(*mpp)->mnext;
- X }
- X *mpp = 0;
- X
- X#ifdef UPDATE_MTAB
- X /*
- X * If we are not updating the mount table then we
- X * can free the resources held here, otherwise they
- X * must be held until the mount table update is complete
- X */
- X mnt_file = mfp;
- X#else
- X endmntent(mfp);
- X#endif /* UPDATE_MTAB */
- X
- X return mhp;
- X}
- X
- X#endif /* READ_MTAB_FROM_FILE */
- END_OF_FILE
- if test 10879 -ne `wc -c <'config/mtab_file.c'`; then
- echo shar: \"'config/mtab_file.c'\" unpacked with wrong size!
- fi
- # end of 'config/mtab_file.c'
- fi
- if test -f 'csd/cmfs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'csd/cmfs.c'\"
- else
- echo shar: Extracting \"'csd/cmfs.c'\" \(9301 characters\)
- sed "s/^X//" >'csd/cmfs.c' <<'END_OF_FILE'
- X/*
- X * WorldWide File System
- X * Copyright (c) 1992,1993 Youki Kadobayashi
- X * Copyright (c) 1992,1993 Osaka University
- X * All rights reserved.
- X *
- X * Permission to use, copy, modify and distribute this software and its
- X * documentation is hereby granted, provided that the following conditions
- X * are met:
- X * 1. Both the copyright notice and this permission notice appear in
- X * all copies of the software, derivative works or modified versions,
- X * and any portions thereof, and that both notices appear in
- X * supporting documentation.
- X * 2. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the Osaka University
- X * and its contributors.
- X * 3. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
- X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- X *
- X * Osaka University requests users of this software to return to
- X *
- X * Youki Kadobayashi
- X * Department of Information and Computer Sciences
- X * Osaka University, Toyonaka 560, Osaka, Japan
- X *
- X * any improvements or extensions that they make and grant Osaka
- X * University the rights to redistribute these changes.
- X */
- X/* cmfs: cache manager file system.
- X * Perform access to cached information. Call delegate function xyz_miss()
- X * when cache missed.
- X */
- Xstatic char *AtFSid = "$Header: cmfs.c[109.0] Wed Nov 24 03:47:03 1993 youki-k@is.aist-nara.ac.jp saved $";
- X
- X#include "wfs.h"
- X#include "util.h"
- X#include "global.h"
- X
- X/*
- X * filehandle internals
- X
- X * parent child
- X * --------- --------
- X * parent_vol ---
- X * parent_dir ---
- X * child_vol == parent_vol
- X * child_dir == dir_id
- X * file_findid(...)->fsid == child_vol
- X * file_findid(...)->id == file_id
- X
- X * parent child "."
- X * --------- --------
- X * parent_vol == parent_vol
- X * parent_dir == parent_dir
- X * child_vol == child_vol
- X * child_dir == child_dir
- X
- X * parent child ".."
- X * --------- --------
- X * file_findname(, "..")->fsid == parent_vol
- X * file_findname(, "..")->id == parent_dir
- X * parent_vol == child_vol
- X * parent_dir == child_dir
- X * child_vol ---
- X * child_dir ---
- X *
- X * Note that dir_id and file_id is aliased as
- X * parent_dir and child_dir, respectively.
- X */
- Xvoid
- Xcmfs_getattr(c)
- Xwf_thrd *c;
- X/* in: rqstp, volp, fhp, reply */
- X/* out: dirp, filep */
- X{
- X static wf_file file;
- X
- X c->dirp = dir_findcache(c->parent_volp, c->fhp->dir_id);
- X if (c->dirp == (wf_dir *)0) {
- X#if 0
- X (*c->reply)(c, WF_ERR_NOENT);
- X return;
- X#else
- X /* fake that directory for nonexistent directory */
- X static wf_dir dir;
- X dir.id = c->fhp->dir_id;
- X c->dirp = &dir;
- X c->filep = (wf_file *)0;
- X#endif
- X } else {
- X c->filep = file_findid(c->dirp,
- X c->fhp->child_vol, c->fhp->file_id);
- X }
- X if (!c->filep) {
- X /* fake that file for nonexistent directory */
- X attr_initdir(&file.fattr);
- X file.fattr.fsid = c->fhp->child_vol;
- X file.id = file.fattr.fileid = c->fhp->file_id;
- X c->filep = &file;
- X }
- X if (c->filep->flag & WF_FILE_MUTABLE) {
- X /* Delegate gets notification of access, but not
- X * required to reflect current state right now.
- X * Getattr operation should be "cheap" however.
- X * Attribute caching mechanism is deferred to each
- X * underlying filesystem for now.
- X */
- X proto_getattr_miss(c);
- X }
- X (*c->reply)(c, WF_REP_OK);
- X}
- X
- Xvoid
- Xcmfs_lookup(c)
- Xwf_thrd *c;
- X/* in: rqstp, volp, fhp, fname, reply */
- X/* out: dotdotp, resfhp, filep */
- X{
- X wf_fh *resfhp; /* reply filehandle */
- X
- X /* stats */
- X c->child_volp->stats.n_request_lookup++;
- X
- X if (c->fname[0] == '.') {
- X wf_dir *dotdotp;
- X
- X dotdotp = dir_findcache(c->parent_volp,
- X c->fhp->parent_dir);
- X if (dotdotp == NULL || dotdotp->flag & WF_DIR_OBSOLETE) {
- X (*c->reply)(c, WF_ERR_STALE);
- X } else if (strcmp(c->fname, "..") == 0) {
- X /*
- X * dotdot
- X */
- X c->resfhp = resfhp = CLONE(c->fhp);
- X c->filep = file_findname(dotdotp, "..");
- X assert(c->filep != NULL);
- X resfhp->parent_vol = FSID(c->filep);
- X resfhp->parent_dir = FID(c->filep);
- X
- X c->filep = file_findname(dotdotp, ".");
- X assert(c->filep != NULL);
- X resfhp->child_vol = c->fhp->parent_vol;
- X resfhp->child_dir = c->fhp->parent_dir;
- X (*c->reply)(c, WF_REP_OK);
- X FREE(resfhp);
- X return;
- X } else if (strcmp(c->fname, ".") == 0) {
- X /*
- X * dot
- X */
- X c->filep = file_findid(dotdotp,
- X c->fhp->child_vol, c->fhp->child_dir);
- X c->resfhp = c->fhp;
- X (*c->reply)(c, WF_REP_OK);
- X return;
- X }
- X }
- X
- X /*
- X * get dotdotp
- X */
- X c->dotdotp = dir_findcache(c->child_volp, c->fhp->child_dir);
- X if (c->dotdotp == (wf_dir *)0 || c->dotdotp->flag & WF_DIR_OBSOLETE) {
- X (*c->reply)(c, WF_ERR_STALE);
- X return;
- X }
- X
- X /*
- X * find file in dotdotp
- X */
- X c->filep = file_findname(c->dotdotp, c->fname);
- X if (c->filep == (wf_file *)0) {
- X c->child_volp->stats.n_request_lookup_miss++;
- X proto_lookup_miss(c);
- X return;
- X }
- X
- X c->resfhp = resfhp = CLONE(c->fhp);
- X resfhp->parent_vol = c->fhp->child_vol;
- X resfhp->parent_dir = c->fhp->child_dir;
- X resfhp->child_vol = FSID(c->filep);
- X resfhp->child_dir = FID(c->filep);
- X (*c->reply)(c, WF_REP_OK);
- X FREE(resfhp);
- X}
- X
- X#ifdef TRACE
- Xstatic wf_trace *
- Xcmfs_readdir_trace(c)
- Xwf_thrd *c;
- X{
- X wf_trace *tracep;
- X
- X tracep = ALLOC(wf_trace);
- X tracep->time = gettime();
- X tracep->uid = c->uid;
- X tracep->client = c->client;
- X tracep->volume = c->fhp->child_vol;
- X tracep->dir = c->fhp->child_dir;
- X return tracep;
- X}
- X#endif
- X
- Xvoid
- Xcmfs_readdir(c)
- Xwf_thrd *c;
- X/* in: rqstp, volp, fhp, cookie, count, reply */
- X/* out: dirp, dotdotp, olddirp, filep */
- X{
- X /*
- X * assumption: consecutive queries will come in before
- X * asked directory gets kicked out of memory
- X */
- X#ifdef TRACE
- X wf_trace *tracep;
- X#endif
- X
- X /* stats */
- X c->child_volp->stats.n_request_readdir++;
- X
- X /* find file in dotdotp */
- X c->dotdotp = dir_findcache(c->parent_volp, c->fhp->parent_dir);
- X if (c->dotdotp == NULL) {
- X (*c->reply)(c, WF_ERR_NOENT);
- X return;
- X }
- X c->filep = file_findid(c->dotdotp,
- X c->fhp->child_vol, c->fhp->child_dir);
- X if (c->filep == NULL) {
- X /* file handle corrupt? */
- X (*c->reply)(c, WF_ERR_NOENT);
- X return;
- X }
- X
- X /*
- X * check if directory transfer is in progress
- X */
- X if (c->filep->thrdp) {
- X (*c->reply)(c, WF_ERR_ALREADY);
- X return;
- X }
- X
- X /*
- X * get dirp
- X */
- X c->dirp = dir_findcache(c->child_volp, c->fhp->child_dir);
- X
- X /*
- X * cache hit
- X */
- X if (c->dirp && !(c->dirp->flag & WF_DIR_OBSOLETE)) {
- X#ifdef TRACE
- X /*
- X * trace cache hit
- X */
- X unsigned long cookie;
- X bcopy(c->cookie, &cookie, sizeof(nfscookie));
- X if (cookie == 0) {
- X tracep = cmfs_readdir_trace(c);
- X tracep->op = WF_OP_READDIR;
- X tracep->hit = WF_CACHE_HIT;
- X trace_event(c, tracep);
- X }
- X#endif
- X (*c->reply)(c, WF_REP_OK);
- X return;
- X }
- X
- X /*
- X * cache missed
- X */
- X c->child_volp->stats.n_request_readdir_miss++;
- X c->olddirp = c->dirp;
- X#ifdef TRACE
- X /*
- X * trace cache miss
- X */
- X tracep = cmfs_readdir_trace(c);
- X tracep->op = WF_OP_READDIR;
- X tracep->hit = WF_CACHE_MISS;
- X trace_event(c, tracep);
- X#endif
- X proto_readdir_miss(c);
- X}
- X
- Xvoid
- Xcmfs_readlink(c)
- Xwf_thrd *c;
- X/* in: rqstp, volp, fhp, reply */
- X/* out: dirp, filep */
- X{
- X c->dirp = dir_findcache(c->parent_volp, c->fhp->dir_id);
- X if (c->dirp == (wf_dir *)0 || c->dirp->flag & WF_DIR_OBSOLETE) {
- X (*c->reply)(c, WF_ERR_STALE);
- X return;
- X }
- X c->filep = file_findid(c->dirp, c->fhp->child_vol, c->fhp->file_id);
- X assert(c->filep != (wf_file *)0);
- X if (c->filep->fattr.type != NFLNK) {
- X (*c->reply)(c, WF_ERR_NOENT);
- X return;
- X }
- X (*c->reply)(c, WF_REP_OK);
- X}
- X
- X#ifdef TRACE
- Xstatic wf_trace *
- Xcmfs_read_trace(c)
- Xwf_thrd *c;
- X{
- X wf_trace *tracep;
- X
- X tracep = ALLOC(wf_trace);
- X tracep->time = gettime();
- X tracep->uid = c->uid;
- X tracep->client = c->client;
- X tracep->volume = c->fhp->child_vol;
- X tracep->dir = c->fhp->dir_id;
- X tracep->file = c->fhp->file_id;
- X tracep->arg = (long) c->filep->fattr.size;
- X return tracep;
- X}
- X#endif
- X
- Xvoid
- Xcmfs_read(c)
- Xwf_thrd *c;
- X/* in: rqstp, volp, fhp, offset, count, totalcount, reply */
- X/* out: dirp, filep */
- X{
- X#ifdef TRACE
- X wf_trace *tracep;
- X#endif
- X /* stats */
- X c->child_volp->stats.n_request_read++;
- X
- X /*
- X * get dirp
- X */
- X c->dirp = dir_findcache(c->parent_volp, c->fhp->dir_id);
- X if (c->dirp == (wf_dir *)0 || c->dirp->flag & WF_DIR_OBSOLETE) {
- X (*c->reply)(c, WF_ERR_STALE);
- X return;
- X }
- X
- X /*
- X * find file in dirp
- X */
- X c->filep = file_findid(c->dirp, c->fhp->child_vol, c->fhp->file_id);
- X assert(c->filep != (wf_file *)0);
- X
- X /*
- X * check if file transfer is in progress
- X */
- X if (c->filep->thrdp) {
- X (*c->reply)(c, WF_ERR_ALREADY);
- X return;
- X }
- X
- X /*
- X * cache hit
- X */
- X if (file_findcache(c->child_volp, c->dirp, c->filep) == 0) {
- X#ifdef TRACE
- X /*
- X * trace cache hit
- X */
- X if (c->offset == 0) {
- X tracep = cmfs_read_trace(c);
- X tracep->op = WF_OP_READ;
- X tracep->hit = WF_CACHE_HIT;
- X trace_event(c, tracep);
- X }
- X#endif
- X (*c->reply)(c, WF_REP_OK);
- X return;
- X }
- X
- X /*
- X * cache missed
- X */
- X c->child_volp->stats.n_request_read_miss++;
- X#ifdef TRACE
- X /*
- X * trace cache missed
- X */
- X tracep = cmfs_read_trace(c);
- X tracep->op = WF_OP_READ;
- X tracep->hit = WF_CACHE_MISS;
- X trace_event(c, tracep);
- X#endif
- X proto_read_miss(c);
- X}
- END_OF_FILE
- if test 9301 -ne `wc -c <'csd/cmfs.c'`; then
- echo shar: \"'csd/cmfs.c'\" unpacked with wrong size!
- fi
- # end of 'csd/cmfs.c'
- fi
- if test -f 'csd/file.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'csd/file.c'\"
- else
- echo shar: Extracting \"'csd/file.c'\" \(9197 characters\)
- sed "s/^X//" >'csd/file.c' <<'END_OF_FILE'
- X/*
- X * WorldWide File System
- X * Copyright (c) 1992,1993 Youki Kadobayashi
- X * Copyright (c) 1992,1993 Osaka University
- X * All rights reserved.
- X *
- X * Permission to use, copy, modify and distribute this software and its
- X * documentation is hereby granted, provided that the following conditions
- X * are met:
- X * 1. Both the copyright notice and this permission notice appear in
- X * all copies of the software, derivative works or modified versions,
- X * and any portions thereof, and that both notices appear in
- X * supporting documentation.
- X * 2. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the Osaka University
- X * and its contributors.
- X * 3. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
- X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- X *
- X * Osaka University requests users of this software to return to
- X *
- X * Youki Kadobayashi
- X * Department of Information and Computer Sciences
- X * Osaka University, Toyonaka 560, Osaka, Japan
- X *
- X * any improvements or extensions that they make and grant Osaka
- X * University the rights to redistribute these changes.
- X */
- Xstatic char *AtFSid = "$Header: file.c[109.1] Tue Dec 7 23:37:58 1993 youki-k@is.aist-nara.ac.jp saved $";
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/file.h> /* for R_OK */
- X#ifndef R_OK
- X#include <unistd.h>
- X#endif
- X#include <fcntl.h> /* for O_WRONLY etc. */
- X#include "wfs.h"
- X#include "util.h"
- X#include "global.h"
- X
- Xstatic
- Xunsigned int type2mode[NFFIFO+1] = { /* depends on enum ftype */
- X 0, /* NFNON */
- X S_IFREG,
- X S_IFDIR,
- X S_IFBLK,
- X S_IFCHR,
- X S_IFLNK,
- X S_IFSOCK,
- X 0, /* NFBAD */
- X S_IFIFO
- X};
- X
- X#define WF_FILE_HASHSIZE 16
- X
- Xtypedef struct fcache {
- X wf_file *filep;
- X wf_dir *dirp;
- X} fcache;
- Xstatic fcache findid_cache[WF_FILE_HASHSIZE],
- X findname_cache[WF_FILE_HASHSIZE];
- X
- Xwf_file *
- Xfile_alloc()
- X{
- X wf_file *filep;
- X filep = ALLOC(wf_file);
- X return filep;
- X}
- X
- Xvoid
- Xfile_free(filep)
- Xwf_file *filep;
- X{
- X if (filep->name) free(filep->name);
- X if (filep->link) free(filep->link);
- X FREE(filep);
- X}
- X
- Xvoid
- Xfile_uncache(dirp)
- Xwf_dir *dirp;
- X{
- X int i = dirp->id % WF_FILE_HASHSIZE;
- X fcache *p;
- X
- X p = &findid_cache[i];
- X if (p->dirp == dirp) {
- X p->dirp = (wf_dir *) 0;
- X p->filep = (wf_file *) 0;
- X }
- X p = &findname_cache[i];
- X if (p->dirp == dirp) {
- X p->dirp = (wf_dir *) 0;
- X p->filep = (wf_file *) 0;
- X }
- X}
- X
- Xwf_file *
- Xfile_new(name, link, filetype, nlink, mode, uid, gid, size, time, fileid, fsid)
- Xchar *name, *link;
- Xftype filetype;
- Xu_int nlink, mode, uid, gid, fsid;
- Xlong size, time, fileid;
- X{
- X wf_file *filep = ALLOC(wf_file);
- X filep->name = name;
- X filep->crc = updcrc(0L, filep->name, strlen(filep->name)+1);
- X filep->link = link;
- X if (fileid == 0) {
- X filep->id = filep->fattr.fileid = filep->crc;
- X } else {
- X filep->id = filep->fattr.fileid = fileid;
- X }
- X
- X filep->fattr.type = filetype;
- X filep->fattr.mode = mode;
- X filep->fattr.mode |= type2mode[filetype];
- X filep->fattr.nlink = nlink;
- X filep->fattr.uid = uid;
- X filep->fattr.gid = gid;
- X filep->fattr.size = size;
- X filep->fattr.blocksize = 8192;
- X filep->fattr.blocks = compute_blocks(filep->fattr.size);
- X filep->fattr.fsid = fsid;
- X filep->fattr.atime.seconds = filep->fattr.mtime.seconds
- X = filep->fattr.ctime.seconds = time;
- X return filep;
- X}
- X
- Xvoid
- Xattr_initdir(attrp)
- Xfattr *attrp;
- X{
- X attrp->nlink = 2; /* should be updated later */
- X attrp->type = NFDIR;
- X attrp->mode = 0755;
- X attrp->mode |= type2mode[attrp->type];
- X attrp->size = 512;
- X attrp->blocksize = 8192;
- X attrp->blocks = compute_blocks(attrp->size);
- X}
- X
- Xvoid
- Xattr_initfile(attrp, size)
- Xfattr *attrp;
- Xlong size;
- X{
- X attrp->type = NFREG;
- X attrp->mode = 0644;
- X attrp->mode |= type2mode[attrp->type];
- X attrp->nlink = 1;
- X attrp->size = size;
- X attrp->blocksize = 8192;
- X attrp->blocks = compute_blocks(attrp->size);
- X}
- X
- Xunsigned int
- Xattr_touch(attrp)
- Xfattr *attrp;
- X{
- X return attrp->atime.seconds = attrp->mtime.seconds = gettime();
- X}
- X
- Xwf_file *
- Xfile_newvol(name)
- Xchar *name;
- X{
- X wf_file *filep;
- X fattr *attrp;
- X
- X filep = file_alloc();
- X filep->name = strdup(name);
- X filep->crc = updcrc(0L, name, strlen(name)+1);
- X attrp = &filep->fattr;
- X attr_initdir(attrp);
- X attr_touch(attrp);
- X return filep;
- X}
- X
- X/* find file by (filesystem id, file id). */
- Xwf_file *
- Xfile_findid(dirp, fsid, fileid)
- Xwf_dir *dirp;
- Xlong fsid, fileid;
- X{
- X wf_file *filep;
- X qelem *q_head = &dirp->file->q;
- X fcache *p;
- X
- X /*
- X * lookup cache
- X */
- X /* getattr operations are likely to be performed sequentially. */
- X p = &findid_cache[dirp->id % WF_FILE_HASHSIZE];
- X if (p->filep && p->dirp == dirp) {
- X filep = NEXT(wf_file, p->filep);
- X if (filep != HEAD(wf_file, q_head)
- X && FID(filep) == fileid && FSID(filep) == fsid) {
- X p->filep = filep;
- X return filep;
- X } else {
- X p->filep = (wf_file *) 0; /* stale */
- X }
- X }
- X
- X /*
- X * resort to exhaustive search
- X */
- X ITER(filep, wf_file, q_head) {
- X if (FID(filep) == fileid && FSID(filep) == fsid) {
- X p->filep = filep;
- X p->dirp = dirp;
- X return filep;
- X }
- X }
- X return NULL;
- X}
- X
- X/* find file by filename. */
- Xwf_file *
- Xfile_findname(dirp, name)
- Xwf_dir *dirp;
- Xchar *name;
- X{
- X wf_file *filep;
- X qelem *q_head = &dirp->file->q;
- X u_int crc;
- X fcache *p;
- X
- X /*
- X * lookup cache
- X */
- X /* lookup operations are likely to be performed sequentially.
- X * we declare another hashtable for fine tuning.
- X */
- X p = &findname_cache[dirp->id % WF_FILE_HASHSIZE];
- X if (p->filep && p->dirp == dirp) {
- X filep = NEXT(wf_file, p->filep);
- X if (filep != HEAD(wf_file, q_head)
- X && strcmp(filep->name, name) == 0) {
- X p->filep = filep;
- X return filep;
- X } else {
- X p->filep = (wf_file *) 0; /* stale */
- X }
- X }
- X
- X /*
- X * resort to exhaustive search
- X */
- X crc = updcrc(0L, name, strlen(name)+1);
- X ITER(filep, wf_file, q_head) {
- X if (crc == filep->crc
- X && strcmp(filep->name, name) == 0) {
- X p->filep = filep;
- X p->dirp = dirp;
- X return filep;
- X }
- X }
- X return NULL;
- X}
- X
- Xint
- Xfile_recv_init(volp, dirp, filep)
- Xwf_vol *volp;
- Xwf_dir *dirp;
- Xwf_file *filep;
- X{
- X int fd;
- X char path[MAXPATHLEN];
- X
- X sprintf(path, "%s/ongoing/xfer.%lx.%lx.%s", cs_topdir,
- X volp->id, dirp->id, filep->name);
- X fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0660);
- X if (fd < 0)
- X dlog("ftp_recv_init: couldn't create file");
- X return fd;
- X}
- X
- Xvoid
- Xfile_recv_finish(volp, dirp, filep)
- Xwf_vol *volp;
- Xwf_dir *dirp;
- Xwf_file *filep;
- X{
- X char path[MAXPATHLEN], path2[MAXPATHLEN];
- X
- X sprintf(path, "%s/ongoing/xfer.%lx.%lx.%s", cs_topdir,
- X volp->id, dirp->id, filep->name);
- X file_getpath(path2, volp, dirp, filep);
- X if (mkdirs(path2))
- X dir_realdir(path2, volp, dirp);
- X rename(path, path2);
- X}
- X
- Xvoid
- Xfile_recv_abort(volp, dirp, filep)
- Xwf_vol *volp;
- Xwf_dir *dirp;
- Xwf_file *filep;
- X{
- X char path[MAXPATHLEN], path2[MAXPATHLEN];
- X
- X sprintf(path, "%s/ongoing/xfer.%lx.%lx.%s", cs_topdir,
- X volp->id, dirp->id, filep->name);
- X sprintf(path2, "%s/stale/%s.%d/xfer.%lx.%lx.%s",
- X cs_topdir, cs_date, cs_serial,
- X volp->id, dirp->id, filep->name);
- X mkdirs(path2);
- X rename(path, path2);
- X}
- X
- Xvoid
- Xfile_getpath(buf, volp, dirp, filep)
- Xchar *buf;
- Xwf_vol *volp;
- Xwf_dir *dirp;
- Xwf_file *filep;
- X{
- X if (volp->flag & WF_VOL_DIRECTFILE) {
- X sprintf(buf, "%s/%s/%s",
- X volp->topdir, dirp->name, filep->name);
- X } else {
- X sprintf(buf, "%s/cache/%lx/%lx/%s",
- X cs_topdir, volp->id, dirp->id, filep->name);
- X }
- X}
- X
- X/* see if file is cached. */
- Xbool_t
- Xfile_findcache(volp, dirp, filep)
- Xwf_vol *volp;
- Xwf_dir *dirp;
- Xwf_file *filep;
- X{
- X struct stat s;
- X char path[MAXPATHLEN];
- X
- X file_getpath(path, volp, dirp, filep);
- X if (stat(path, &s) < 0)
- X return -1;
- X if (! (s.st_mode & S_IREAD) || (s.st_mode & S_IFMT) != S_IFREG)
- X return -1;
- X if (! (filep->flag & WF_FILE_MUTABLE)
- X && s.st_size != filep->fattr.size) {
- X /* XXX: update policy */
- X file_dispose(volp, dirp, filep);
- X return -1;
- X }
- X return 0;
- X}
- X
- X/* make that file stale. */
- Xvoid
- Xfile_dispose(volp, dirp, filep)
- Xwf_vol *volp;
- Xwf_dir *dirp;
- Xwf_file *filep;
- X{
- X char path[MAXPATHLEN], path2[MAXPATHLEN];
- X
- X file_getpath(path, volp, dirp, filep);
- X sprintf(path2, "%s/stale/%s.%d/file.%lx.%lx.%s",
- X cs_topdir, cs_date, cs_serial,
- X volp->id, dirp->id, filep->name);
- X mkdirs(path2);
- X rename(path, path2);
- X}
- X
- X/* WWUIP DIAG */
- Xvoid
- Xfile_inspect(reqp, name)
- Xwf_req *reqp;
- Xchar *name;
- X{
- X int id = reqp->id;
- X int ret;
- X wf_ih ih;
- X
- X ret = root_name2ih(name, &ih);
- X if (ret != WF_REP_OK) {
- X req_send(reqp, "513.%03d root_name2ih: error code %d.\n",
- X id, ret);
- X return;
- X }
- X req_send(reqp, "220-%03d fil %s\n", id, name);
- X req_send(reqp, "213-%03d name = %s\n", id, PROT(ih.filep->name));
- X req_send(reqp, "213-%03d link = %s\n", id, PROT(ih.filep->link));
- X req_send(reqp, "213-%03d id = %lx\n", id, ih.filep->id);
- X req_send(reqp, "213-%03d crc = %lx\n", id, ih.filep->crc);
- X req_send(reqp, "213-%03d flag = %x\n", id, ih.filep->flag);
- X req_send(reqp, "213-%03d type = %lx\n", id, ih.filep->fattr.type);
- X req_send(reqp, "213-%03d fsid = %lx\n", id, ih.filep->fattr.fsid);
- X req_send(reqp, "213.%03d fileid = %lx\n", id, ih.filep->fattr.fileid);
- X}
- X
- END_OF_FILE
- if test 9197 -ne `wc -c <'csd/file.c'`; then
- echo shar: \"'csd/file.c'\" unpacked with wrong size!
- fi
- # end of 'csd/file.c'
- fi
- if test -f 'csd/nfs_subr.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'csd/nfs_subr.c'\"
- else
- echo shar: Extracting \"'csd/nfs_subr.c'\" \(10559 characters\)
- sed "s/^X//" >'csd/nfs_subr.c' <<'END_OF_FILE'
- X/*
- X * WorldWide File System
- X * Copyright (c) 1992,1993 Youki Kadobayashi
- X * Copyright (c) 1992,1993 Osaka University
- X * All rights reserved.
- X *
- X * Permission to use, copy, modify and distribute this software and its
- X * documentation is hereby granted, provided that the following conditions
- X * are met:
- X * 1. Both the copyright notice and this permission notice appear in
- X * all copies of the software, derivative works or modified versions,
- X * and any portions thereof, and that both notices appear in
- X * supporting documentation.
- X * 2. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the Osaka University
- X * and its contributors.
- X * 3. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
- X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- X *
- X * Osaka University requests users of this software to return to
- X *
- X * Youki Kadobayashi
- X * Department of Information and Computer Sciences
- X * Osaka University, Toyonaka 560, Osaka, Japan
- X *
- X * any improvements or extensions that they make and grant Osaka
- X * University the rights to redistribute these changes.
- X */
- X/* nfsproc_whatever_2 */
- Xstatic char *AtFSid = "$Header: nfs_subr.c[109.0] Wed Nov 24 03:47:14 1993 youki-k@is.aist-nara.ac.jp saved $";
- X
- X#include "wfs.h"
- X#include "util.h"
- X#include "global.h"
- X
- X#define NFS
- X#define NFSCLIENT
- X#ifdef NFS_3
- Xtypedef nfs_fh fhandle_t;
- X#endif /* NFS_3 */
- X#include <sys/mount.h> /* for struct statfs */
- X#ifdef STATFS_HDR
- X#include STATFS_HDR /* for struct statfs */
- X#endif /* STATFS_HDR */
- X
- Xstatic void
- Xclient_info(c)
- Xwf_thrd *c;
- X{
- X struct authunix_parms *unix_cred;
- X sockaddr_in *sin;
- X
- X if (c->rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
- X unix_cred = (struct authunix_parms *) c->rqstp->rq_clntcred;
- X c->uid = unix_cred->aup_uid;
- X }
- X sin = svc_getcaller(c->rqstp->rq_xprt);
- X c->client = sin->sin_addr.s_addr;
- X}
- X
- Xvoid *
- Xnfsproc_null_2(argp, rqstp)
- Xvoid *argp;
- Xsvc_req *rqstp;
- X{
- X static char res;
- X return (void *) &res;
- X}
- X
- Xattrstat *
- Xnfsproc_getattr_2(argp, rqstp)
- Xnfs_fh *argp;
- Xsvc_req *rqstp;
- X{
- X wf_thrd *c;
- X static attrstat res;
- X wf_fh *fhp = (wf_fh *)argp;
- X wf_vol *parent_volp, *child_volp;
- X
- X /* auth */
- X if (fhp->world_id != cs_world) {
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_ACCES;
- X return &res;
- X }
- X
- X parent_volp = vol_findid(fhp->parent_vol);
- X if (fhp->parent_vol == fhp->child_vol)
- X child_volp = parent_volp;
- X else
- X child_volp = vol_findid(fhp->child_vol);
- X if (parent_volp == NULL || child_volp == NULL) {
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_STALE;
- X return &res;
- X }
- X c = thrd_alloc();
- X c->rqstp = CLONE(rqstp);
- X c->parent_volp = parent_volp;
- X c->child_volp = child_volp;
- X c->fhp = fhp;
- X c->reply = nfs_getattr_reply;
- X proto_getattr(c);
- X return (attrstat *)0;
- X}
- X
- Xattrstat *
- Xnfsproc_setattr_2(argp, rqstp)
- Xsattrargs *argp;
- Xsvc_req *rqstp;
- X{
- X static attrstat res;
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_ROFS;
- X return &res;
- X}
- X
- Xvoid *
- Xnfsproc_root_2(argp, rqstp)
- Xvoid *argp;
- Xsvc_req *rqstp;
- X{
- X static char res;
- X return (void *) &res;
- X}
- X
- Xdiropres *
- Xnfsproc_lookup_2(argp, rqstp)
- Xdiropargs *argp;
- Xsvc_req *rqstp;
- X{
- X wf_thrd *c;
- X static diropres res;
- X wf_fh *fhp = (wf_fh *) &argp->dir;
- X wf_vol *parent_volp, *child_volp;
- X
- X /* auth */
- X if (fhp->world_id != cs_world) {
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_ACCES;
- X return &res;
- X }
- X
- X parent_volp = vol_findid(fhp->parent_vol);
- X if (fhp->parent_vol == fhp->child_vol)
- X child_volp = parent_volp;
- X else
- X child_volp = vol_findid(fhp->child_vol);
- X if (parent_volp == NULL || child_volp == NULL) {
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_STALE;
- X return &res;
- X }
- X c = thrd_alloc();
- X c->rqstp = CLONE(rqstp);
- X c->parent_volp = parent_volp;
- X c->child_volp = child_volp;
- X c->fhp = fhp;
- X c->fname = argp->name;
- X c->reply = nfs_lookup_reply;
- X client_info(c);
- X /*
- X * gross hack
- X */
- X if (! (c->fname[0] == '.' && strncmp(c->fname, ".wwfs_", 6) == 0)) {
- X proto_lookup(c);
- X return (diropres *)0;
- X } else {
- X wf_fh *resfhp;
- X int ret;
- X /*
- X * Strict specification of NFS was successful in that it
- X * prohibited vendors to add diverse features.
- X * Meanwhile, the strictness necessitates brute force
- X * solution, which is much more uglier than ioctl()...
- X * I have long-term solution in mind however.
- X */
- X c->resfhp = resfhp = CLONE(fhp);
- X#if 0
- X if (strcmp(c->fname + 6, "host") == 0) {
- X resfhp->child_vol = WF_HOST_VOL_ID;
- X } else if (strcmp(c->fname + 6, "cwd") == 0) {
- X resfhp->child_vol = WF_CWD_VOL_ID;
- X }
- X#else
- X if (strcmp(c->fname + 6, "fh") == 0) {
- X resfhp->child_vol = WF_FH_VOL_ID;
- X }
- X#endif
- X else {
- X FREE(resfhp);
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_NOENT;
- X return &res;
- X }
- X resfhp->parent_vol = fhp->child_vol;
- X ret = cwd_fake(c, resfhp);
- X nfs_lookup_reply(c, ret);
- X FREE(resfhp);
- X return (diropres *)0;
- X }
- X}
- X
- Xreadlinkres *
- Xnfsproc_readlink_2(argp, rqstp)
- Xnfs_fh *argp;
- Xsvc_req *rqstp;
- X{
- X wf_thrd *c;
- X static readlinkres res;
- X wf_fh *fhp = (wf_fh *)argp;
- X wf_vol *parent_volp, *child_volp;
- X
- X /* auth */
- X if (fhp->world_id != cs_world) {
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_ACCES;
- X return &res;
- X }
- X
- X parent_volp = vol_findid(fhp->parent_vol);
- X if (fhp->parent_vol == fhp->child_vol)
- X child_volp = parent_volp;
- X else
- X child_volp = vol_findid(fhp->child_vol);
- X if (parent_volp == NULL || child_volp == NULL) {
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_STALE;
- X return &res;
- X }
- X c = thrd_alloc();
- X c->rqstp = CLONE(rqstp);
- X c->parent_volp = parent_volp;
- X c->child_volp = child_volp;
- X c->fhp = fhp;
- X c->reply = nfs_readlink_reply;
- X proto_readlink(c);
- X return (readlinkres *)0;
- X}
- X
- Xreadres *
- Xnfsproc_read_2(argp, rqstp)
- Xreadargs *argp;
- Xsvc_req *rqstp;
- X{
- X wf_thrd *c;
- X static readres res;
- X wf_fh *fhp = (wf_fh *) &argp->file;
- X wf_vol *parent_volp, *child_volp;
- X
- X /* auth */
- X if (fhp->world_id != cs_world) {
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_ACCES;
- X return &res;
- X }
- X
- X parent_volp = vol_findid(fhp->parent_vol);
- X if (fhp->parent_vol == fhp->child_vol)
- X child_volp = parent_volp;
- X else
- X child_volp = vol_findid(fhp->child_vol);
- X if (parent_volp == NULL || child_volp == NULL) {
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_STALE;
- X return &res;
- X }
- X c = thrd_alloc();
- X c->rqstp = CLONE(rqstp);
- X c->parent_volp = parent_volp;
- X c->child_volp = child_volp;
- X c->fhp = fhp;
- X c->offset = argp->offset;
- X c->count = argp->count;
- X c->totalcount = argp->totalcount;
- X c->reply = nfs_read_done;
- X client_info(c);
- X proto_read(c);
- X return (readres *)0;
- X}
- X
- Xvoid *
- Xnfsproc_writecache_2(argp, rqstp)
- Xvoid *argp;
- Xsvc_req *rqstp;
- X{
- X static char res;
- X return (void *)&res;
- X}
- X
- Xattrstat *
- Xnfsproc_write_2(argp, rqstp)
- Xwriteargs *argp;
- Xsvc_req *rqstp;
- X{
- X static attrstat res;
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_ROFS;
- X return &res;
- X}
- X
- Xdiropres *
- Xnfsproc_create_2(argp, rqstp)
- Xcreateargs *argp;
- Xsvc_req *rqstp;
- X{
- X static diropres res;
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_ROFS;
- X return &res;
- X}
- X
- Xnfsstat *
- Xnfsproc_remove_2(argp, rqstp)
- Xdiropargs *argp;
- Xsvc_req *rqstp;
- X{
- X static nfsstat res;
- X bzero(&res, sizeof(res));
- X res = NFSERR_ROFS;
- X return &res;
- X}
- X
- Xnfsstat *
- Xnfsproc_rename_2(argp, rqstp)
- Xrenameargs *argp;
- Xsvc_req *rqstp;
- X{
- X static nfsstat res;
- X bzero(&res, sizeof(res));
- X res = NFSERR_ROFS;
- X return &res;
- X}
- X
- Xnfsstat *
- Xnfsproc_link_2(argp, rqstp)
- Xlinkargs *argp;
- Xsvc_req *rqstp;
- X{
- X static nfsstat res;
- X bzero(&res, sizeof(res));
- X res = NFSERR_ROFS;
- X return &res;
- X}
- X
- Xnfsstat *
- Xnfsproc_symlink_2(argp, rqstp)
- Xsymlinkargs *argp;
- Xsvc_req *rqstp;
- X{
- X static nfsstat res;
- X bzero(&res, sizeof(res));
- X res = NFSERR_ROFS;
- X return &res;
- X}
- X
- Xdiropres *
- Xnfsproc_mkdir_2(argp, rqstp)
- Xcreateargs *argp;
- Xsvc_req *rqstp;
- X{
- X static diropres res;
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_ROFS;
- X return &res;
- X}
- X
- Xnfsstat *
- Xnfsproc_rmdir_2(argp, rqstp)
- Xdiropargs *argp;
- Xsvc_req *rqstp;
- X{
- X static nfsstat res;
- X bzero(&res, sizeof(res));
- X res = NFSERR_ROFS;
- X return &res;
- X}
- X
- Xreaddirres *
- Xnfsproc_readdir_2(argp, rqstp)
- Xreaddirargs *argp;
- Xsvc_req *rqstp;
- X{
- X wf_thrd *c;
- X static readdirres res;
- X wf_fh *fhp = (wf_fh *) &argp->dir;
- X wf_vol *parent_volp, *child_volp;
- X
- X bzero(&res, sizeof(res));
- X /* auth */
- X if (fhp->world_id != cs_world) {
- X res.status = NFSERR_ACCES;
- X return &res;
- X }
- X
- X parent_volp = vol_findid(fhp->parent_vol);
- X if (fhp->parent_vol == fhp->child_vol)
- X child_volp = parent_volp;
- X else
- X child_volp = vol_findid(fhp->child_vol);
- X if (parent_volp == NULL || child_volp == NULL) {
- X bzero(&res, sizeof(res));
- X res.status = NFSERR_STALE;
- X return &res;
- X }
- X c = thrd_alloc();
- X c->rqstp = CLONE(rqstp);
- X c->parent_volp = parent_volp;
- X c->child_volp = child_volp;
- X c->fhp = fhp;
- X bcopy(argp->cookie, c->cookie, sizeof(nfscookie));
- X c->count = argp->count;
- X c->reply = nfs_readdir_done;
- X client_info(c);
- X /*
- X * access control (only when access control file is present)
- X */
- X if (parent_volp->accp
- X && acc_check(parent_volp->accp, c->client, WF_ACC_NFS) < 0) {
- X (*c->reply)(c, WF_ERR_ACCES);
- X return (readdirres *)0;
- X }
- X proto_readdir(c);
- X return (readdirres *)0;
- X}
- X
- Xstatfsres *
- Xnfsproc_statfs_2(argp, rqstp)
- Xnfs_fh *argp;
- Xsvc_req *rqstp;
- X{
- X static statfsres res;
- X wf_fh *fhp = (wf_fh *) argp;
- X#ifdef ULTRIX_HACK
- X struct fs_data buf;
- X#else /* ULTRIX_HACK */
- X struct statfs buf;
- X#endif /* ULTRIX_HACK */
- X
- X bzero(&res, sizeof(res));
- X /* auth */
- X if (fhp->world_id != cs_world) {
- X res.status = NFSERR_ACCES;
- X return &res;
- X }
- X
- X /* statfs cache partition */
- X statfs(cs_topdir, &buf);
- X res.status = NFS_OK;
- X res.statfsres_u.reply.tsize = NFS_MAXDATA;
- X#ifdef ULTRIX_HACK
- X res.statfsres_u.reply.bsize = buf.fd_bsize;
- X res.statfsres_u.reply.blocks = buf.fd_btot / (buf.fd_bsize / 1024);
- X res.statfsres_u.reply.bfree = buf.fd_bfree / (buf.fd_bsize / 1024);
- X res.statfsres_u.reply.bavail = buf.fd_bfreen / (buf.fd_bsize / 1024);
- X#else /* ULTRIX_HACK */
- X res.statfsres_u.reply.bsize = buf.f_bsize;
- X res.statfsres_u.reply.blocks = buf.f_blocks;
- X res.statfsres_u.reply.bfree = buf.f_bfree;
- X#ifdef sgi /* or HAS_BAVAIL? */
- X /* return estimated 95% figure */
- X res.statfsres_u.reply.bavail = buf.f_bfree - (buf.f_bfree / 20);
- X#else /* sgi */
- X res.statfsres_u.reply.bavail = buf.f_bavail;
- X#endif /* sgi */
- X#endif /* ULTRIX_HACK */
- X return (statfsres *)&res;
- X}
- X
- END_OF_FILE
- if test 10559 -ne `wc -c <'csd/nfs_subr.c'`; then
- echo shar: \"'csd/nfs_subr.c'\" unpacked with wrong size!
- fi
- # end of 'csd/nfs_subr.c'
- fi
- if test -f 'csd/util.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'csd/util.c'\"
- else
- echo shar: Extracting \"'csd/util.c'\" \(8875 characters\)
- sed "s/^X//" >'csd/util.c' <<'END_OF_FILE'
- X/*
- X * WorldWide File System
- X * Copyright (c) 1992,1993 Youki Kadobayashi
- X * Copyright (c) 1992,1993 Osaka University
- X * All rights reserved.
- X *
- X * Permission to use, copy, modify and distribute this software and its
- X * documentation is hereby granted, provided that the following conditions
- X * are met:
- X * 1. Both the copyright notice and this permission notice appear in
- X * all copies of the software, derivative works or modified versions,
- X * and any portions thereof, and that both notices appear in
- X * supporting documentation.
- X * 2. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the Osaka University
- X * and its contributors.
- X * 3. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
- X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- X *
- X * Osaka University requests users of this software to return to
- X *
- X * Youki Kadobayashi
- X * Department of Information and Computer Sciences
- X * Osaka University, Toyonaka 560, Osaka, Japan
- X *
- X * any improvements or extensions that they make and grant Osaka
- X * University the rights to redistribute these changes.
- X */
- Xstatic char *AtFSid = "$Header: util.c[109.2] Sun Dec 19 02:49:00 1993 youki-k@is.aist-nara.ac.jp saved $";
- X
- X#include <sys/types.h>
- X#include <sys/file.h> /* R_OK */
- X#include <sys/stat.h> /* for struct stat */
- X#ifndef R_OK
- X#include <unistd.h>
- X#endif
- X#include <string.h> /* for strchr */
- X#ifdef __STDC__
- X#include <stdarg.h>
- X#else
- X#include <varargs.h>
- X#endif
- X#include "wfs.h"
- X#include "global.h"
- X#include "util.h"
- X
- X/* queue manipulation functions */
- Xqelem *
- Xq_alloc()
- X{
- X qelem *q;
- X q = (qelem *) ALLOC(qelem);
- X q->q_forw = q->q_back = q;
- X return q;
- X}
- X
- Xvoid
- Xq_insert(elem, pred)
- Xqelem *elem, *pred;
- X{
- X qelem *p = pred->q_forw;
- X elem->q_back = pred;
- X elem->q_forw = p;
- X pred->q_forw = elem;
- X p->q_back = elem;
- X}
- X
- Xvoid
- Xq_remove(elem)
- Xqelem *elem;
- X{
- X qelem *p = elem->q_forw;
- X qelem *p2 = elem->q_back;
- X p2->q_forw = p;
- X p->q_back = p2;
- X}
- X
- Xint
- Xq_len(elem)
- Xqelem *elem;
- X{
- X qelem *p;
- X int len = 0;
- X ITER(p, qelem, elem) {
- X ++len;
- X }
- X return len;
- X}
- X
- Xvoid
- Xq_allfree(head)
- Xqelem *head;
- X{
- X qelem *p, *p2;
- X ITER2(p, p2, qelem, head) {
- X FREE(p);
- X }
- X head->q_forw = head;
- X head->q_back = head;
- X}
- X
- X/* memory allocation functions */
- Xvoid *
- Xalloc_and_copy(db_alist v, vlen)
- Xdb_dcl
- Xvoid *v;
- Xint vlen;
- X{
- X void *p;
- X p = debug_malloc(db_alist vlen);
- X bcopy(v, p, vlen);
- X return p;
- X}
- X
- Xvoid *
- Xalloc_and_clear(db_alist vlen)
- Xdb_dcl
- Xint vlen;
- X{
- X void *v;
- X v = debug_malloc(db_alist vlen);
- X bzero(v, vlen);
- X return v;
- X}
- X
- Xvoid
- Xalloc_start()
- X{
- X#ifdef DEBUG_MALLOC
- X char path[MAXPATHLEN];
- X union dbmalloptarg m;
- X
- X sprintf(path, "%s/log/malloc.log", cs_topdir);
- X m.str = path;
- X dbmallopt(MALLOC_ERRFILE, &m);
- X#endif
- X}
- X
- X/* Dig a deep directory, if needed. Return number of mkdir calls made. */
- Xint
- Xmkdirs(path)
- Xchar *path;
- X{
- X /* strings are assumed to be writable. "-fwritable-strings" is
- X * required on some systems (e.g. NeXT).
- X */
- X char *p = path, *p2;
- X int calls = 0;
- X
- X p2 = strrchr(p, '/');
- X *p2 = '\0';
- X if (access(path, W_OK|X_OK) == 0) {
- X *p2 = '/';
- X return 0;
- X }
- X *p2 = '/';
- X while(p2 = strchr(p, '/')) {
- X *p2 = '\0';
- X if (access(path, F_OK) < 0) { /* D_OK ? */
- X mkdir(path, 0770);
- X ++calls;
- X }
- X *p2 = '/';
- X p = p2+1;
- X }
- X return calls;
- X}
- X
- Xint
- Xvalidate_dir(dir)
- Xchar *dir;
- X{
- X char path[MAXPATHLEN];
- X struct stat statbuf;
- X
- X if (stat(dir, &statbuf) < 0) {
- X return -1;
- X }
- X if (statbuf.st_mode & S_IFDIR) {
- X sprintf(path, "%s/usr", dir);
- X if (stat(path, &statbuf) == 0) {
- X errno = EINVAL; /* invalid argument */
- X return -1;
- X }
- X } else {
- X errno = ENOTDIR; /* not a directory */
- X return -1;
- X }
- X return 0;
- X}
- X
- Xvoid
- Xcsd_abort(ret)
- Xint ret;
- X{
- X syslog(LOG_INFO, "Exiting with status %d", ret);
- X exit(ret);
- X}
- X
- X/* create background process */
- Xint
- Xbackground()
- X{
- X int pid, retry = 0;
- X
- X resume:
- X pid = fork();
- X
- X /* firewall */
- X if (pid < 0 && retry < 5) {
- X sleep(1);
- X errno_diag();
- X ++retry;
- X goto resume;
- X }
- X
- X /* child */
- X if (pid == 0) {
- X cs_pid = getpid();
- X foreground = 0;
- X }
- X return pid;
- X}
- X
- X/* acquire privileged port. */
- Xint
- Xbind_resv_port(so, portp)
- Xint so;
- Xunsigned short *portp;
- X{
- X struct sockaddr_in sin;
- X unsigned short port;
- X int ret;
- X
- X#if 0
- X bzero(&sin, sizeof(sin));
- X sin.sin_family = AF_INET;
- X
- X port = IPPORT_RESERVED;
- X do {
- X --port;
- X sin.sin_port = htons(port);
- X ret = bind(so, (struct sockaddr *) &sin, sizeof (sin));
- X } while (ret < 0 && port > IPPORT_RESERVED/2);
- X
- X if (ret == 0) {
- X *portp = port;
- X }
- X return ret;
- X#else
- X /* Current version of csd does not require privileged port
- X * since it does not attempt to forward NFS packet, unlike amd.
- X * I guess conventional NFS server requires privileged port
- X * to authenticate request from clients.
- X */
- X port = 8000;
- X bzero(&sin, sizeof(sin));
- X sin.sin_family = AF_INET;
- X sin.sin_port = htons(port);
- X ret = bind(so, (struct sockaddr *) &sin, sizeof (sin));
- X if (ret < 0) {
- X errno_diag();
- X }
- X *portp = port;
- X return ret;
- X#endif
- X}
- X
- X/* do the printf to a stream socket. */
- X#ifdef __STDC__
- Xint
- Xtcp_send(int so, char *fmt, ...)
- X{
- X va_list ap;
- X static char buf[MAXPATHLEN + 32];
- X
- X va_start(ap, fmt);
- X vsprintf(buf, fmt, ap);
- X va_end(ap);
- X return send(so, buf, strlen(buf), 0);
- X}
- X#else
- X
- Xint
- Xtcp_send(va_alist)
- Xva_dcl
- X{
- X va_list ap;
- X int so;
- X char *fmt;
- X static char buf[MAXPATHLEN + 32];
- X
- X va_start(ap);
- X so = va_arg(ap, int);
- X fmt = va_arg(ap, char *);
- X vsprintf(buf, fmt, ap);
- X va_end(ap);
- X return send(so, buf, strlen(buf), 0);
- X}
- X#endif
- X
- X/* do the printf to a stream socket. */
- X#ifdef __STDC__
- Xint
- Xreq_send(wf_req *reqp, char *fmt, ...)
- X{
- X va_list ap;
- X static char buf[MAXPATHLEN + 32];
- X
- X va_start(ap, fmt);
- X vsprintf(buf, fmt, ap);
- X va_end(ap);
- X#ifdef DEBUG_UIP
- X dlog("%s.%d <- %s", inet_ntoa(reqp->sin.sin_addr),
- X ntohs(reqp->sin.sin_port), buf);
- X#endif
- X return sendto(reqp->so, buf, strlen(buf), 0,
- X (struct sockaddr *) &reqp->sin, sizeof(reqp->sin));
- X}
- X#else
- X
- Xint
- Xreq_send(va_alist)
- Xva_dcl
- X{
- X va_list ap;
- X wf_req *reqp;
- X char *fmt;
- X static char buf[MAXPATHLEN + 32];
- X
- X va_start(ap);
- X reqp = va_arg(ap, wf_req *);
- X fmt = va_arg(ap, char *);
- X vsprintf(buf, fmt, ap);
- X va_end(ap);
- X#ifdef DEBUG_UIP
- X dlog("%s.%d <- %s", inet_ntoa(reqp->sin.sin_addr),
- X ntohs(reqp->sin.sin_port), buf);
- X#endif
- X return sendto(reqp->so, buf, strlen(buf), 0,
- X (struct sockaddr *) &reqp->sin, sizeof(reqp->sin));
- X}
- X#endif
- X
- X/* daily. */
- X
- Xint cs_year;
- Xint cs_month = -1;
- Xint cs_day;
- Xchar cs_date[7];
- Xint cs_serial;
- X
- Xvoid
- Xgetdate()
- X{
- X struct tm *p;
- X long t = realtime();
- X#ifdef TRACE
- X if (cs_month >= 0)
- X trace_report();
- X#endif
- X /*
- X * set daily timer
- X */
- X dlog("daily: update time variables");
- X /* wake me up tomorrow */
- X timeout_set(t - (t % (24 * 3600)) + 24 * 3600, getdate, 0);
- X
- X /*
- X * set time variables
- X */
- X p = gmtime(&t);
- X cs_year = p->tm_year;
- X cs_month = p->tm_mon; /* beware: Jan=0, Dec=11. */
- X cs_day = p->tm_mday;
- X sprintf(cs_date, "%02d%02d%02d", cs_year, cs_month +1, cs_day);
- X cs_serial = 0;
- X}
- X
- X/* replacement for system(). */
- Xvoid
- Xunix_command(cmd)
- Xchar *cmd;
- X{
- X char *p, *p2;
- X int i, pid, status;
- X char *arg[16];
- X
- X switch (pid = fork()) {
- X case 0:
- X /* child process */
- X for (i = 0; i < NOFILE; ++i)
- X close(i);
- X for (p = cmd, i = 0; p2 = strchr(p, ' '); p = p2+1, ++i) {
- X *p2 = '\0';
- X arg[i] = p;
- X }
- X arg[i] = p;
- X arg[++i] = (char *)0;
- X execv(arg[0], arg);
- X exit(0);
- X case -1:
- X errno_diag();
- X return;
- X default:
- X /* parent process */
- X dlog(cmd);
- X wait(&status); /* XXX async wait3 version appropriate */
- X }
- X}
- X
- Xlong
- Xcompute_blocks(size)
- Xlong size;
- X{
- X /* fake st_blocks */
- X return ((size + 1024) / 1024 + 1);
- X}
- X
- X/* Basic part of tm2time came from: Atsushi Onoe <onoe@sm.sony.co.jp>
- X * If your libc has mktime() function, you can use it instead.
- X */
- Xstatic int m2yday[] = {
- X/*
- X * jan feb mar apr may jun jul aug sep oct nov dec
- X * 31 28 31 30 31 30 31 31 30 31 30 31
- X */
- X 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
- X};
- X
- Xtime_t
- Xtm2time(tm)
- Xstruct tm *tm;
- X{
- X int clock;
- X
- X clock = (tm->tm_year - 70) * 365 + (tm->tm_year - 72) / 4
- X + m2yday[tm->tm_mon] + tm->tm_mday;
- X if ((tm->tm_year - 72) / 4 == 0 && tm->tm_mon < 2)
- X --clock;
- X clock *= 24;
- X clock += tm->tm_hour;
- X clock *= 60;
- X clock += tm->tm_min;
- X clock *= 60;
- X clock += tm->tm_sec;
- X return ((time_t)clock);
- X}
- X
- X#ifndef DEBUG_MALLOC
- X#if defined(NeXT) || defined(vax) || defined(ultrix) || defined(sony) || defined(luna)
- Xchar *
- Xstrdup(str)
- XConst char *str;
- X{
- X char *sp;
- X int len;
- X
- X len = strlen(str);
- X sp = (char *) malloc(len+1);
- X bcopy(str, sp, len);
- X sp[len] = 0;
- X
- X return sp;
- X}
- X#endif
- X#endif
- END_OF_FILE
- if test 8875 -ne `wc -c <'csd/util.c'`; then
- echo shar: \"'csd/util.c'\" unpacked with wrong size!
- fi
- # end of 'csd/util.c'
- fi
- if test -f 'csd/vol.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'csd/vol.c'\"
- else
- echo shar: Extracting \"'csd/vol.c'\" \(11167 characters\)
- sed "s/^X//" >'csd/vol.c' <<'END_OF_FILE'
- X/*
- X * WorldWide File System
- X * Copyright (c) 1992,1993 Youki Kadobayashi
- X * Copyright (c) 1992,1993 Osaka University
- X * All rights reserved.
- X *
- X * Permission to use, copy, modify and distribute this software and its
- X * documentation is hereby granted, provided that the following conditions
- X * are met:
- X * 1. Both the copyright notice and this permission notice appear in
- X * all copies of the software, derivative works or modified versions,
- X * and any portions thereof, and that both notices appear in
- X * supporting documentation.
- X * 2. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the Osaka University
- X * and its contributors.
- X * 3. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
- X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- X *
- X * Osaka University requests users of this software to return to
- X *
- X * Youki Kadobayashi
- X * Department of Information and Computer Sciences
- X * Osaka University, Toyonaka 560, Osaka, Japan
- X *
- X * any improvements or extensions that they make and grant Osaka
- X * University the rights to redistribute these changes.
- X */
- X/* volume: caching, file io */
- Xstatic char *AtFSid = "$Header: vol.c[109.1] Tue Nov 30 02:47:12 1993 youki-k@is.aist-nara.ac.jp saved $";
- X
- X#include <sys/file.h> /* for R_OK */
- X#ifndef R_OK
- X#include <unistd.h>
- X#endif
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include "wfs.h"
- X#include "util.h"
- X#include "global.h"
- X
- Xextern qelem vol_head;
- Xqelem vol_head = { &vol_head, &vol_head };
- X
- Xwf_vol *
- Xvol_alloc()
- X{
- X wf_vol *volp;
- X volp = ALLOC(wf_vol);
- X volp->srvq = (wf_srvq *) q_alloc();
- X volp->dirp = (wf_dir *) q_alloc();
- X q_insert(volp, &vol_head);
- X return volp;
- X}
- X
- Xvoid
- Xvol_free(volp)
- Xwf_vol *volp;
- X{
- X if (volp->id == 0) {
- X syslog(LOG_WARNING, "volp->id == 0");
- X }
- X free(volp->dir);
- X FREE(volp->srvq);
- X FREE(volp->dirp);
- X q_remove(volp);
- X FREE(volp);
- X}
- X
- X/* find volume by id */
- Xwf_vol *
- Xvol_findid(id)
- Xlong id;
- X{
- X wf_vol *volp;
- X
- X /* search memory cache */
- X ITER(volp, wf_vol, &vol_head) {
- X if (volp->id == id) {
- X return volp;
- X }
- X }
- X return NULL;
- X}
- X
- X/* find volume by name */
- Xwf_vol *
- Xvol_findname(dir, name)
- Xchar *dir, *name;
- X{
- X wf_vol *volp;
- X
- X /* search memory cache */
- X ITER(volp, wf_vol, &vol_head) {
- X if (strcmp(volp->dir, dir) == 0
- X && strcmp(volp->name, name) == 0) {
- X return volp;
- X }
- X }
- X
- X /* search disk cache */
- X volp = vol_load(dir, name);
- X return volp;
- X}
- X
- Xstatic wf_vol *new_volp;
- Xstatic wf_srv *new_srvp;
- Xstatic int dir_count, srv_count;
- X
- Xstatic int
- Xvol_set_id(id)
- Xchar *id;
- X{
- X new_volp->id = atoi(id);
- X if (new_volp->id == WF_ROOT_VOL_ID) {
- X dlog("incorrect volume id");
- X return -1;
- X }
- X return 0;
- X}
- X
- Xint
- Xvol_set_name(name)
- Xchar *name;
- X{
- X dlog("obsolete entry: volume-name: ignored");
- X return 0;
- X}
- X
- Xint
- Xvol_set_ftp_server(hostname)
- Xchar *hostname;
- X{
- X if (srv_count > dir_count + 1) {
- X dlog("incorrect server-directory sequence");
- X return -1;
- X }
- X new_srvp = srv_findname(hostname);
- X if (new_srvp == (wf_srv *)0) {
- X return -1;
- X }
- X ++srv_count;
- X return 0;
- X}
- X
- Xint
- Xvol_set_ftp_directory(subdir)
- Xchar *subdir;
- X{
- X if (!new_srvp || dir_count > srv_count + 1) {
- X dlog("incorrect server-directory sequence");
- X return -1;
- X }
- X vol_addsrv(new_volp, new_srvp, subdir);
- X ++dir_count;
- X return 0;
- X}
- X
- Xstatic wf_cap ftp_cap[] = {
- X { "follow", WF_FTP_FOLLOW },
- X { "nostat", WF_FTP_NOSTAT },
- X { NULL, 0 }
- X};
- X
- Xint
- Xvol_set_ftp_options(flagstr)
- Xchar *flagstr;
- X{
- X long flag;
- X
- X if (!new_srvp) {
- X dlog("misplaced ftp-options");
- X return -1;
- X }
- X flag = parse_cap(ftp_cap, flagstr);
- X if (flag < 0) {
- X dlog("invalid ftp-options");
- X return -1;
- X }
- X new_srvp->variant = flag;
- X return 0;
- X}
- X
- Xint
- Xvol_set_ufs_directory(topdir)
- Xchar *topdir;
- X{
- X /*
- X * "topdir" can be either absolute or relative pathname.
- X * Relative pathname can be used to create volumes beneath
- X * WWFSDIR (assuming csd has chdir()ed there).
- X */
- X if (validate_dir(topdir) < 0) {
- X dlog("ufs-directory %s: %m", topdir);
- X return -1;
- X }
- X new_volp->flag |= WF_VOL_DIRECTFILE;
- X new_volp->topdir = strdup(topdir);
- X new_srvp = (wf_srv *)0;
- X if (MORE(&new_volp->srvq->q)) {
- X /* XXX more cleaner implementation desired but, for now, */
- X dlog("ufs-directory supercedes other server descriptions");
- X }
- X return 0;
- X}
- X
- Xint
- Xvol_set_description(desc)
- Xchar *desc;
- X{
- X /* simply ignore it for now */
- X return 0;
- X}
- X
- Xstatic wf_tailor vol_tailor[] = {
- X { "volume-id", vol_set_id },
- X { "volume-name", vol_set_name },
- X { "ftp-server", vol_set_ftp_server },
- X { "ftp-directory", vol_set_ftp_directory },
- X { "ftp-options", vol_set_ftp_options },
- X { "ufs-directory", vol_set_ufs_directory },
- X { "description", vol_set_description },
- X /*
- X * just for backward compatibility...
- X */
- X { "server", vol_set_ftp_server },
- X { "directory", vol_set_ftp_directory },
- X { NULL, (int (*)())0 }
- X};
- X
- Xint
- Xvol_bind(name, value)
- Xchar *name;
- Xchar *value;
- X{
- X return parse_tailor(vol_tailor, name, value);
- X}
- X
- Xwf_vol *
- Xvol_load(dir, name)
- Xchar *dir, *name;
- X{
- X char path[MAXPATHLEN];
- X struct stat statbuf;
- X
- X sprintf(path, "%s/vol/%s/%s.vol", cs_topdir, dir, name);
- X if (access(path, R_OK) < 0)
- X return (wf_vol *)0;
- X stat(path, &statbuf);
- X new_srvp = (wf_srv *)0;
- X dir_count = srv_count = 0;
- X new_volp = vol_alloc();
- X new_volp->dir = strdup(dir);
- X new_volp->name = strdup(name);
- X new_volp->accp = acc_findname(dir);
- X new_volp->mtime = statbuf.st_mtime;
- X
- X if (parse_conf(path, vol_bind) < 0) {
- X vol_free(new_volp);
- X return (wf_vol *)0;
- X }
- X if (new_volp->id == 0) {
- X dlog("%s: no volume id", path);
- X vol_free(new_volp);
- X return (wf_vol *)0;
- X }
- X return new_volp;
- X}
- X
- Xvoid
- Xvol_save(volp)
- Xwf_vol *volp;
- X{
- X FILE *fp;
- X wf_srvq *srvp;
- X char path[MAXPATHLEN];
- X
- X sprintf(path, "%s/vol/%s.vol", cs_topdir, volp->name);
- X mkdirs(path);
- X fp = fopen(path, "w");
- X if (! fp) return;
- X
- X /* write per volume info */
- X fprintf(fp, "volume-id:\t%d\n", volp->id);
- X
- X /* write server names */
- X ITER(srvp, wf_srvq, &volp->srvq->q) {
- X /* XXX provision for other access types required */
- X fprintf(fp, "ftp-server:\t%s\n", srvp->srv->name);
- X fprintf(fp, "ftp-directory:\t%s\n", srvp->info);
- X }
- X fclose(fp);
- X}
- X
- Xwf_conn *
- Xvol_getconn(volp)
- Xwf_vol *volp;
- X{
- X wf_conn *cp;
- X wf_srvq *srvq;
- X
- X if (volp->nconn < WF_VOL_MAXCONN) {
- X volp->flag &= ~WF_VOL_XCONN;
- X srvq = pol_select_srv(volp);
- X cp = srv_getconn(srvq);
- X if (cp) {
- X ++volp->nconn;
- X return cp;
- X }
- X } else {
- X volp->flag |= WF_VOL_XCONN;
- X }
- X return (wf_conn *)0;
- X}
- X
- Xwf_conn *
- Xvol_newconn(volp)
- Xwf_vol *volp;
- X{
- X wf_conn *cp;
- X wf_srvq *srvq;
- X
- X if (volp->nconn < WF_VOL_MAXCONN) {
- X volp->flag &= ~WF_VOL_XCONN;
- X srvq = pol_select_srv(volp);
- X cp = srv_newconn(srvq);
- X if (cp) {
- X ++volp->nconn;
- X return cp;
- X }
- X }
- X volp->flag |= WF_VOL_XCONN;
- X return (wf_conn *)0;
- X}
- X
- Xvoid
- Xvol_releaseconn(volp)
- Xwf_vol *volp;
- X{
- X warn_negative(--volp->nconn);
- X}
- X
- Xvoid
- Xvol_addsrv(volp, srvp, subdir)
- Xwf_vol *volp;
- Xwf_srv *srvp;
- Xchar *subdir;
- X{
- X wf_srvq *q = ALLOC(wf_srvq);
- X q->srv = srvp;
- X q->info = (void *)subdir;
- X q_insert(q, LAST(wf_srvq, &volp->srvq->q));
- X}
- X
- Xvoid
- Xvol_deletesrv(volp, srvp)
- Xwf_vol *volp;
- Xwf_srv *srvp;
- X{
- X wf_srvq *q, *q2;
- X qelem *q_head = &volp->srvq->q;
- X
- X ITER2 (q, q2, wf_srvq, q_head) {
- X if (q->srv == srvp) {
- X q_remove(q);
- X free(q->info);
- X FREE(q);
- X return;
- X }
- X }
- X syslog(LOG_WARNING, "vol_deletesrv: should not reach here");
- X}
- X
- Xlong
- Xvol_allocid(volp)
- Xwf_vol *volp;
- X{
- X /* Allocate a new directory id.
- X *
- X * NFS Version 2 Protocol Specification says:
- X * "fsid" is the file system identifier for the filesystem
- X * containing the file.
- X * "fileid" is a number that uniquely identifies the file
- X * within its file system.
- X *
- X * I think we satisfy this requirement by assigning a unique
- X * volume id to "fsid" and a file id to "fileid". Each fileid
- X * is guaranteed to be unique within given fsid.
- X */
- X
- X#define MAPSIZE 256
- X /* 256 came from "blocksize / sizeof(long)", which is sufficient
- X * I believe, since each volume can contain
- X * 256(longs) * 32(bits/long) = 8192 directories */
- X
- X int fd;
- X unsigned long bitmap[MAPSIZE];
- X long i, j;
- X char path[MAXPATHLEN];
- X
- X /*
- X * load bitmap
- X */
- X /* XXX tuning is possible for contiguous allocid */
- X sprintf(path, "%s/cache/%lx/dir/bitmap", cs_topdir, volp->id);
- X if (access(path, R_OK|W_OK) != 0) {
- X if (mkdirs(path))
- X dir_realdir(path, volp, (wf_dir *)0);
- X fd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0660);
- X memset(bitmap, 0xff, MAPSIZE * sizeof(long));
- X } else {
- X fd = open(path, O_RDWR, 0660);
- X read(fd, bitmap, MAPSIZE * sizeof(long));
- X }
- X
- X /*
- X * find unused bit and mark it
- X */
- X for (i = 0; bitmap[i] == 0; ++i) ;
- X j = ffs(bitmap[i]) - 1;
- X bitmap[i] &= ~(1 << j);
- X
- X /*
- X * save bitmap
- X */
- X /* XXX tuning is possible for contiguous allocid */
- X lseek(fd, 0L, 0);
- X write(fd, bitmap, MAPSIZE * sizeof(long));
- X close(fd);
- X
- X /*
- X * return allocated id
- X */
- X return (i * 8 * sizeof(long) + j + 1);
- X
- X}
- X
- Xvoid
- Xvol_destroyid(volp)
- Xwf_vol *volp;
- X{
- X char path[MAXPATHLEN];
- X
- X sprintf(path, "%s/cache/%lx/dir/bitmap", cs_topdir, volp->id);
- X unlink(path);
- X if (access(path, R_OK) == 0) {
- X dlog("could not unlink %s", path);
- X }
- X}
- X
- Xwf_dir *
- Xvol_newroot(volp)
- Xwf_vol *volp;
- X{
- X wf_dir *dirp;
- X long dirid;
- X int retry_count = 0;
- X char path[MAXPATHLEN], path2[MAXPATHLEN];
- X
- X retry:
- X dirid = vol_allocid(volp);
- X if (dirid != 1) {
- X if (++retry_count > 3) {
- X /* something is wrong.. */
- X errno_diag();
- X return (wf_dir *)0;
- X }
- X /* Oops. Possible causes are:
- X * - ID bitmap of this volume has been corrupted.
- X * - Someone deleted root directory cache (".../%lx/%lx/1").
- X */
- X dlog("Directory cache of volume %s deleted?", volp->name);
- X sprintf(path2, "%s/stale/%s.%d/%lx/",
- X cs_topdir, cs_date, cs_serial, volp->id);
- X mkdirs(path2);
- X sprintf(path, "/bin/mv %s/cache/%lx/dir %s",
- X cs_topdir, volp->id, path2);
- X unix_command(path);
- X cs_serial++;
- X goto retry;
- X }
- X /* Directory id 1 is just for sanity check.
- X * We use volume id instead, biased with WF_VOL_BASE, to avoid ID
- X * conflict with other volumes. Otherwise pwd doesn't work correctly.
- X */
- X dirp = dir_new(volp, WF_VOL_BASE + volp->id, 0, 0);
- X return dirp;
- X}
- X
- Xwf_dir *
- Xvol_findroot(volp)
- Xwf_vol *volp;
- X{
- X wf_dir *dirp;
- X
- X dirp = dir_findcache(volp, WF_VOL_BASE + volp->id);
- X return dirp;
- X}
- X
- Xvoid
- Xvol_inspect(reqp, name)
- Xwf_req *reqp;
- Xchar *name;
- X{
- X int ret;
- X wf_ih ih;
- X int id = reqp->id;
- X
- X ret = root_name2ih(name, &ih);
- X if (ret != WF_REP_OK) {
- X req_send(reqp, "513.%03d root_name2ih: error code %d.\n",
- X id, ret);
- X return;
- X }
- X req_send(reqp, "220-%03d vol %s\n", id, name);
- X req_send(reqp, "213-%03d name = %s\n", id, PROT(ih.child_volp->name));
- X req_send(reqp, "213-%03d id = %lx\n", id, ih.child_volp->id);
- X req_send(reqp, "213-%03d flag = %x\n", id, ih.child_volp->flag);
- X req_send(reqp, "213-%03d nconn = %d\n", id, ih.child_volp->nconn);
- X req_send(reqp, "213.%03d mtime = %ld (%20.20s)\n",
- X id, ih.child_volp->mtime, ctime(&ih.child_volp->mtime)+4);
- X}
- X
- END_OF_FILE
- if test 11167 -ne `wc -c <'csd/vol.c'`; then
- echo shar: \"'csd/vol.c'\" unpacked with wrong size!
- fi
- # end of 'csd/vol.c'
- fi
- if test -f 'libww/libww.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'libww/libww.c'\"
- else
- echo shar: Extracting \"'libww/libww.c'\" \(11229 characters\)
- sed "s/^X//" >'libww/libww.c' <<'END_OF_FILE'
- X/*
- X * WorldWide File System
- X * Copyright (c) 1992,1993 Youki Kadobayashi
- X * Copyright (c) 1992,1993 Osaka University
- X * All rights reserved.
- X *
- X * Permission to use, copy, modify and distribute this software and its
- X * documentation is hereby granted, provided that the following conditions
- X * are met:
- X * 1. Both the copyright notice and this permission notice appear in
- X * all copies of the software, derivative works or modified versions,
- X * and any portions thereof, and that both notices appear in
- X * supporting documentation.
- X * 2. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the Osaka University
- X * and its contributors.
- X * 3. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
- X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- X *
- X * Osaka University requests users of this software to return to
- X *
- X * Youki Kadobayashi
- X * Department of Information and Computer Sciences
- X * Osaka University, Toyonaka 560, Osaka, Japan
- X *
- X * any improvements or extensions that they make and grant Osaka
- X * University the rights to redistribute these changes.
- X */
- X/*
- X * libww: WWFS Application Programming Interface.
- X * This file is part of WWFS, the WorldWide File System.
- X *
- X * You do not want to link your program with libww.a if you have spliced
- X * libc routines in libc_wwfs.a and you are planning to link with it.
- X */
- Xstatic char *AtFSid = "$Header: libww.c[109.0] Wed Nov 24 03:49:15 1993 youki-k@is.aist-nara.ac.jp saved $";
- X
- X#include <sys/errno.h>
- Xextern int errno;
- X#include <sys/param.h>
- X#include <sys/stat.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- Xextern int h_errno; /* for BSDs */
- X
- X#ifdef _POSIX_SOURCE
- X#include <dirent.h>
- X#define DIRENT struct dirent
- X#else
- X#include <sys/dir.h>
- X#define DIRENT struct direct
- X#endif
- X#include <fcntl.h>
- X#include <stdio.h>
- X#if defined(__STDC__) || defined(STDC_HEADERS)
- X#include <stdlib.h>
- X#endif
- X#include <string.h>
- X#define LIBWW
- X#include "libww.h"
- X#include "parse.h"
- X
- X#define UIP_TCP_PORT 8002
- X#define UIP_UDP_PORT 8002
- X
- X#if 0
- Xstatic char cs_hostname[MAXHOSTNAMELEN];
- Xstatic struct sockaddr_in cs_sin;
- X#endif
- Xstatic char cs_path[MAXPATHLEN];
- Xstatic char *ww_mountdir;
- Xstatic struct sockaddr_in *ww_cshost;
- Xstatic int
- X uip_block=1, /* block by default */
- X uip_progress=0; /* don't show percentage indicator */
- X
- X#if 0
- Xchar *
- Xww_getaddr(path)
- Xchar *path;
- X{
- X /*
- X * Get the CS service address. We need pathname here, since
- X * clients can mount several CSs at different mount points.
- X * Gross hack is deployed here because we never want to deal
- X * with the diverse format of /etc/mtab. NFS protocol should
- X * have provided "getnfsinfo" operation that provides rudimentary
- X * information, so that we could contact the machine serving
- X * the filesystem via other network services...
- X */
- X
- X char *p;
- X struct stat statbuf;
- X int fd;
- X struct hostent *hp;
- X int retry = 0;
- X
- X /* "/mount/point/volume/dir/.wwfs_host" */
- X strcpy(cs_path, path);
- X p = strrchr(cs_path, '/');
- X if (p)
- X strcpy(p+1, ".wwfs_host");
- X else
- X strcpy(cs_path, ".wwfs_host"); /* within "." */
- X
- X /* get the hostname of CS */
- X fd = Open(cs_path, O_RDONLY, 0400);
- X if (fd < 0)
- X return NULL; /* not served by CS */
- X fstat(fd, &statbuf);
- X read(fd, cs_hostname, statbuf.st_size);
- X close(fd);
- X
- X dns_retry:
- X hp = gethostbyname(cs_hostname);
- X if (hp == (struct hostent *) 0) {
- X if (h_errno == TRY_AGAIN) {
- X if (++retry < 5) {
- X sleep(1);
- X goto dns_retry;
- X }
- X }
- X return NULL;
- X }
- X cs_sin.sin_family = hp->h_addrtype;
- X /*
- X * I use primary address here. If your cluster server have
- X * more than one interfaces, and if ipforwarding was set to 0,
- X * and if your client cannot reach primary address due to
- X * dropped ipforwarding, your network configuration is wrong.
- X */
- X bcopy(hp->h_addr_list[0], &cs_sin.sin_addr, hp->h_length);
- X return cs_hostname;
- X}
- X
- Xchar *
- Xww_path(path)
- Xchar *path;
- X{
- X /*
- X * Convert client-specific NFS pathname into CS's pathname,
- X * so that clients and CS can share a common namespace.
- X * e.g., "/mount/point/volume/dir/filename" -> "/volume/dir/filename"
- X */
- X
- X char *p;
- X struct stat statbuf;
- X int fd;
- X
- X /* "/mount/point/volume/dir/.wwfs_cwd" */
- X strcpy(cs_path, path);
- X p = strrchr(cs_path, '/');
- X if (p)
- X strcpy(p+1, ".wwfs_cwd");
- X else
- X strcpy(cs_path, ".wwfs_cwd"); /* within "." */
- X
- X /* get the current working directory within CS's namespace */
- X fd = Open(cs_path, O_RDONLY, 0400);
- X if (fd < 0)
- X return NULL; /* not served by CS */
- X fstat(fd, &statbuf);
- X read(fd, cs_path, statbuf.st_size);
- X close(fd);
- X
- X /* Finally we get it: "/volume/dir/filename" */
- X p = strrchr(path, '/'); /* basename */
- X if (p)
- X strcat(cs_path, p+1);
- X else
- X strcat(cs_path, path);
- X return cs_path;
- X}
- X#endif
- X
- Xchar *
- Xww_path(path)
- Xchar *path;
- X{
- X /*
- X * Convert client-specific NFS pathname into CS's pathname,
- X * so that clients and CS can share a common namespace.
- X * e.g., "/mount/point/volume/dir/filename" -> "+filehandle/filename"
- X */
- X
- X char *p;
- X struct stat statbuf;
- X int fd;
- X
- X /* "/mount/point/volume/dir/.wwfs_fh" */
- X strcpy(cs_path, path);
- X p = strrchr(cs_path, '/');
- X if (p)
- X strcpy(p+1, ".wwfs_fh");
- X else
- X strcpy(cs_path, ".wwfs_fh"); /* within "." */
- X
- X /* get the filehandle */
- X fd = Open(cs_path, O_RDONLY, 0400);
- X if (fd < 0)
- X return NULL; /* not served by csd */
- X fstat(fd, &statbuf);
- X cs_path[0] = '+';
- X read(fd, cs_path+1, statbuf.st_size);
- X close(fd);
- X
- X strcat(cs_path, "/");
- X /* Finally we get it: "+filehandle/filename" */
- X p = strrchr(path, '/'); /* basename */
- X if (p)
- X strcat(cs_path, p+1);
- X else
- X strcat(cs_path, path);
- X return cs_path;
- X}
- X
- Xstatic int
- Xww_set_cshost(cshost)
- Xchar *cshost;
- X{
- X struct hostent *hp;
- X int retry = 0;
- X
- X if (getenv("WW_CSHOST")) {
- X /* You may want to use another csd, e.g., for debugging... */
- X cshost = getenv("WW_CSHOST");
- X }
- X ww_cshost = malloc(sizeof (struct sockaddr_in));
- X
- X dns_retry:
- X hp = gethostbyname(cshost);
- X if (hp == (struct hostent *) 0) {
- X if (h_errno == TRY_AGAIN) {
- X if (++retry < 5) {
- X sleep(1);
- X goto dns_retry;
- X }
- X }
- X return NULL;
- X }
- X ww_cshost->sin_family = hp->h_addrtype;
- X /*
- X * I use primary address here. If your cluster server have
- X * more than one interfaces, and if ipforwarding was set to 0,
- X * and if your client cannot reach primary address due to
- X * dropped ipforwarding, your network configuration is wrong.
- X */
- X bcopy(hp->h_addr_list[0], &ww_cshost->sin_addr, hp->h_length);
- X return 0;
- X}
- X
- Xstatic int
- Xww_set_mountdir(mountdir)
- Xchar *mountdir;
- X{
- X if (getenv("WW_MOUNTDIR")) {
- X /* You may want to use another csd, e.g., for debugging... */
- X int len;
- X char *p;
- X
- X mountdir = getenv("WW_MOUNTDIR");
- X len = strlen(mountdir)+1;
- X p = malloc(len); /* GonzOS lacks strdup() */
- X bcopy(mountdir, p, len);
- X }
- X ww_mountdir = mountdir;
- X return 0;
- X}
- X
- Xstatic int
- Xww_set_dummy(dummy)
- Xchar *dummy;
- X{
- X return 0;
- X}
- X
- Xstatic wf_tailor ww_tailor[] = {
- X { "cshost", ww_set_cshost },
- X { "mountcmd", ww_set_dummy },
- X { "mountdir", ww_set_mountdir },
- X { NULL, (int (*)())0 }
- X};
- X
- Xstatic int
- Xww_bind(name, value)
- Xchar *name;
- Xchar *value;
- X{
- X return parse_tailor(ww_tailor, name, value);
- X}
- X
- Xchar *
- Xww_localpath(path)
- Xchar *path;
- X{
- X /*
- X * Convert CS's pathname into client-specific NFS pathname,
- X * so that clients can access it with canonical pathname.
- X * e.g., "/volume/dir/filename" -> "/mount/point/volume/dir/filename"
- X */
- X
- X if (! ww_mountdir) {
- X if (parse_conf("/etc/wwfs.conf", ww_bind) < 0)
- X return NULL; /* syntax error, or not a csd client */
- X if (! ww_mountdir)
- X return NULL;
- X }
- X strcpy(cs_path, ww_mountdir);
- X strcat(cs_path, path);
- X return cs_path;
- X}
- X
- Xint
- Xww_control(optname, optval)
- Xint optname;
- Xvoid *optval;
- X{
- X /* Control the behavior of wwfs client process. */
- X switch (optname) {
- X case UIP_BLOCK:
- X uip_block = *(int *)optval;
- X break;
- X case UIP_PROGRESS:
- X uip_progress = *(int *)optval;
- X break;
- X default:
- X return -1;
- X }
- X return 0;
- X}
- X
- X#define BUFLEN 1400 /* Ethernet MTU might be a good measure */
- Xstatic char buf[BUFLEN];
- X
- Xstatic int
- Xdo_socket()
- X{
- X int so, ret;
- X struct sockaddr_in sin;
- X
- X so = socket(AF_INET, SOCK_DGRAM, 0);
- X bzero(&sin, sizeof(sin));
- X sin.sin_family = AF_INET;
- X sin.sin_addr.s_addr = htonl(INADDR_ANY);
- X ret = bind(so, (struct sockaddr *) &sin, sizeof (sin));
- X if (ret < 0) {
- X close(so);
- X return -1;
- X }
- X return so;
- X}
- X
- Xstatic void
- Xdo_sendto(so, port, buf)
- Xint so, port;
- Xchar *buf;
- X{
- X ww_cshost->sin_port = htons(port);
- X sendto(so, buf, strlen(buf), 0,
- X (struct sockaddr *) ww_cshost, sizeof(*ww_cshost));
- X}
- X
- Xstatic void
- Xdo_recvfrom(so, buf)
- Xint so;
- Xchar *buf;
- X{
- X struct sockaddr_in from;
- X int fromlen;
- X
- X retry:
- X fromlen = sizeof(from);
- X recvfrom(so, buf, BUFLEN, 0,
- X (struct sockaddr *)&from, &fromlen);
- X if (from.sin_addr.s_addr != ww_cshost->sin_addr.s_addr)
- X goto retry;
- X return;
- X}
- X
- Xint
- Xww_get(subpath)
- Xchar *subpath;
- X{
- X /*
- X * No libc counterpart -- just retrieve a file/directory
- X * represented by a WWFS pathname (i.e., pathname with
- X * leading mount point dropped).
- X */
- X int so;
- X
- X if (! ww_cshost) {
- X if (parse_conf("/etc/wwfs.conf", ww_bind) < 0) {
- X errno = EINVAL; /* invalid configuration */
- X return -1; /* syntax error, or not a csd client */
- X }
- X if (! ww_cshost) {
- X errno = EINVAL; /* invalid configuration */
- X return -1;
- X }
- X }
- X if (uip_block) {
- X sprintf(buf, "RETR %s\n", subpath);
- X so = do_socket();
- X if (so < 0)
- X return -1;
- X do_sendto(so, UIP_UDP_PORT, buf);
- X while (1) {
- X do_recvfrom(so, buf);
- X /* parse it */
- X if (buf[3] == '.') {
- X if (buf[0] == '2') {
- X close(so);
- X return 0;
- X }
- X else if (buf[0] == '5') {
- X errno = EIO;
- X close(so);
- X return -1;
- X }
- X }
- X }
- X } else if (uip_progress) {
- X }
- X return 0;
- X}
- X
- Xint
- Xww_nfsget(path)
- Xchar *path;
- X{
- X /*
- X * No libc counterpart -- just retrieve a file/directory
- X * represented by an NFS pathname.
- X */
- X char *subpath;
- X int ret;
- X
- X if (subpath = ww_path(path)) {
- X ret = ww_get(subpath);
- X if (ret < 0)
- X return ret;
- X }
- X}
- X
- Xint
- Xww_open(path, flags, mode)
- Xchar *path;
- Xint flags;
- Xint mode;
- X{
- X /* Open the file, with pre- and post-processing as specified by
- X * ww_control().
- X */
- X char *subpath;
- X int ret;
- X
- X if (subpath = ww_path(path)) {
- X ret = ww_get(subpath);
- X if (ret < 0)
- X return ret;
- X /* possibly other protocols */
- X }
- X return Open(path, flags, mode);
- X}
- X
- XFILE *
- Xww_fopen(path, flags)
- Xchar *path;
- Xchar *flags;
- X{
- X /* FOpen the file, with pre- and post-processing as specified by
- X * ww_control().
- X */
- X char *subpath;
- X int ret;
- X
- X if (subpath = ww_path(path)) {
- X ret = ww_get(subpath);
- X if (ret < 0)
- X return NULL;
- X /* possibly other protocols */
- X }
- X return Fopen(path, flags);
- X}
- X
- XDIR *
- Xww_opendir(path)
- Xchar *path;
- X{
- X /* Open the dir, with pre- and post-processing as specified by
- X * ww_control().
- X */
- X char *subpath;
- X int ret;
- X
- X if (subpath = ww_path(path)) {
- X ret = ww_get(subpath);
- X if (ret < 0)
- X return NULL;
- X /* possibly other protocols */
- X }
- X return Opendir(path);
- X}
- X
- END_OF_FILE
- if test 11229 -ne `wc -c <'libww/libww.c'`; then
- echo shar: \"'libww/libww.c'\" unpacked with wrong size!
- fi
- # end of 'libww/libww.c'
- fi
- if test -f 'wwalk/Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'wwalk/Makefile'\"
- else
- echo shar: Extracting \"'wwalk/Makefile'\" \(1980 characters\)
- sed "s/^X//" >'wwalk/Makefile' <<'END_OF_FILE'
- X#
- X# Makefile for user-interface programs; part of Worldwide File System.
- X#
- X# Author: Youki Kadobayashi, Osaka University, Japan
- X# E-mail: <youki@wide.ad.jp>
- X#
- X#
- X# WorldWide File System
- X# Copyright (c) 1992,1993 Youki Kadobayashi
- X# Copyright (c) 1992,1993 Osaka University
- X# All rights reserved.
- X#
- X# Permission to use, copy, modify and distribute this software and its
- X# documentation is hereby granted, provided that the following conditions
- X# are met:
- X# 1. Both the copyright notice and this permission notice appear in
- X# all copies of the software, derivative works or modified versions,
- X# and any portions thereof, and that both notices appear in
- X# supporting documentation.
- X# 2. All advertising materials mentioning features or use of this software
- X# must display the following acknowledgement:
- X# This product includes software developed by the Osaka University
- X# and its contributors.
- X# 3. Neither the name of the University nor the names of its contributors
- X# may be used to endorse or promote products derived from this software
- X# without specific prior written permission.
- X#
- X# THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
- X# UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- X# WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- X#
- X# Osaka University requests users of this software to return to
- X#
- X# Youki Kadobayashi
- X# Department of Information and Computer Sciences
- X# Osaka University, Toyonaka 560, Osaka, Japan
- X#
- X# any improvements or extensions that they make and grant Osaka
- X# University the rights to redistribute these changes.
- X
- X# $Header: Makefile[109.0] Wed Nov 24 03:50:31 1993 youki-k@is.aist-nara.ac.jp saved $
- X#
- X
- X# To use alternative 'make' program, say gmake, type:
- X# gmake Make="gmake"
- XMake = make
- XMAK = $(Make) Make="$(Make)"
- XMKARG = -f ../Makefile.top PROG="wwalk" TOP=".."
- XSHELL = /bin/sh
- X
- Xall: wwalk
- X
- Xwwalk:
- X
- Xinstall-client clean baseline copyright version: FRC
- X @$(MAK) $(MKARG) $@
- X
- XFRC:
- END_OF_FILE
- if test 1980 -ne `wc -c <'wwalk/Makefile'`; then
- echo shar: \"'wwalk/Makefile'\" unpacked with wrong size!
- fi
- # end of 'wwalk/Makefile'
- fi
- if test -f 'wwmount/wwmount.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'wwmount/wwmount.c'\"
- else
- echo shar: Extracting \"'wwmount/wwmount.c'\" \(8847 characters\)
- sed "s/^X//" >'wwmount/wwmount.c' <<'END_OF_FILE'
- X/*
- X * WorldWide File System
- X * Copyright (c) 1992,1993 Youki Kadobayashi
- X * Copyright (c) 1992,1993 Osaka University
- X * All rights reserved.
- X *
- X * Permission to use, copy, modify and distribute this software and its
- X * documentation is hereby granted, provided that the following conditions
- X * are met:
- X * 1. Both the copyright notice and this permission notice appear in
- X * all copies of the software, derivative works or modified versions,
- X * and any portions thereof, and that both notices appear in
- X * supporting documentation.
- X * 2. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the Osaka University
- X * and its contributors.
- X * 3. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
- X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- X *
- X * Osaka University requests users of this software to return to
- X *
- X * Youki Kadobayashi
- X * Department of Information and Computer Sciences
- X * Osaka University, Toyonaka 560, Osaka, Japan
- X *
- X * any improvements or extensions that they make and grant Osaka
- X * University the rights to redistribute these changes.
- X */
- X/* WWFS mount */
- Xstatic char *AtFSid = "$Header: wwmount.c[109.0] Wed Nov 24 03:49:37 1993 youki-k@is.aist-nara.ac.jp saved $";
- X
- X#include "am.h" /* amd compatibility */
- X
- X/* NFS headers and definitions */
- X#define NFS
- X#define NFSCLIENT
- X#ifdef NFS_3
- Xtypedef nfs_fh fhandle_t;
- X#endif /* NFS_3 */
- X#include <sys/mount.h>
- X#ifdef NFS_HDR
- X#include NFS_HDR
- X#endif /* NFS_HDR */
- X
- X/* miscellaneous headers */
- X#include <sys/signal.h>
- X#include <sys/stat.h>
- X#include <string.h> /* for strchr */
- X#include "cs_prot.h"
- X
- X/* definition of behaviour */
- X#define CSMNT_TIMEO 22
- X#define CSMNT_RETRANS 5
- X#define CSMNT_AC 8
- X#define CSMNT_RETRY 10000
- X#define BGRND 1
- X#define ISBGRND 2
- Xint opflags = 0;
- X#ifdef MOUNTED
- Xchar *mtab = MOUNTED;
- X#endif /* MOUNTED */
- Xtime_t clock_valid = 0;
- Xint mypid;
- X
- Xvoid
- Xusage(name)
- Xchar *name;
- X{
- X fprintf(stderr, "Usage: %s server_host local_dir\n", name);
- X}
- X
- Xvoid
- Xcompute_mntent_options(mntp, fs_name, mp_name)
- Xstruct mntent *mntp;
- Xchar *fs_name, *mp_name;
- X{
- X char *opts;
- X opts = malloc(64);
- X mntp->mnt_dir = mp_name;
- X mntp->mnt_fsname = fs_name;
- X mntp->mnt_type = MNTTYPE_WWFS; /* or MTAB_TYPE_NFS; */
- X sprintf(opts, "soft,timeo=%d,retrans=%d,acregmax=%d",
- X CSMNT_TIMEO, CSMNT_RETRANS, CSMNT_AC);
- X mntp->mnt_opts = opts;
- X mntp->mnt_freq = 0;
- X mntp->mnt_passno = 0;
- X}
- X
- Xvoid
- Xcompute_nfs_options(nfs_argsp)
- Xstruct nfs_args *nfs_argsp;
- X{
- X nfs_argsp->flags = NFSMNT_SOFT | NFSMNT_HOSTNAME
- X | NFSMNT_TIMEO | NFSMNT_RETRANS;
- X nfs_argsp->timeo = CSMNT_TIMEO;
- X nfs_argsp->retrans = CSMNT_RETRANS;
- X nfs_argsp->rsize = nfs_argsp->wsize = NFS_MAXDATA;
- X#if defined(NFSMNT_NOAC) && !defined(sony_news)
- X nfs_argsp->flags |= NFSMNT_NOAC;
- X#else /* NFSMNT_NOAC */
- X#if defined(NFSMNT_ACREGMIN) && defined(NFSMNT_ACREGMAX)
- X nfs_argsp->flags |= NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
- X nfs_argsp->acregmin = nfs_argsp->acregmax = CSMNT_AC;
- X nfs_argsp->flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX;
- X nfs_argsp->acdirmin = nfs_argsp->acdirmax = CSMNT_AC;
- X#endif
- X#endif /* NFSMNT_NOAC */
- X}
- X
- Xint
- Xcompute_mount_flags()
- X{
- X int flags;
- X#ifdef NFS_4
- X flags = M_NEWTYPE;
- X#else
- X flags = 0;
- X#endif
- X flags |= M_RDONLY | M_NOSUID;
- X return flags;
- X}
- X
- Xchar *
- Xcompute_fs_name(s)
- Xchar *s;
- X{
- X char *fs_name;
- X char *p;
- X fs_name = malloc(strlen(s)+16);
- X strcpy(fs_name, s);
- X#ifndef HOSTNAMESZ
- X#define SHORT_MOUNT_NAME
- X#endif /* HOSTNAMESZ */
- X#ifdef SHORT_MOUNT_NAME
- X if (p = strchr(fs_name, '.'))
- X *p = '\0';
- X#endif
- X#ifdef HOSTNAMESZ
- X if (strlen(fs_name) >= HOSTNAMESZ)
- X strcpy(fs_name + HOSTNAMESZ - 8, "..");
- X#endif
- X if (strchr(fs_name, ':') == NULL) {
- X strcat(fs_name, ":wwfs");
- X }
- X return fs_name;
- X}
- X
- X/* code below is derived from NET2 mount.c */
- X
- Xint
- Xcompute_bindings(nfs_argsp, host, dir)
- Xstruct nfs_args *nfs_argsp;
- Xchar *host, *dir;
- X{
- X int retry;
- X struct hostent *hp;
- X struct sockaddr_in *sinp = ALLOC(sockaddr_in);
- X u_short nfs_port;
- X cs_fhres *resp = ALLOC(cs_fhres);
- X
- X /* get 'sockaddr_in' of the file server */
- X bzero(sinp, sizeof (*sinp));
- X if ((hp = gethostbyname(host)) == NULL) {
- X plog(XLOG_ERROR,
- X "mount: Can't get network address for host %s\n", host);
- X return (-1);
- X }
- X bcopy(hp->h_addr, &(sinp->sin_addr), sizeof(sinp->sin_addr));
- X
- X /* try several times contacting server */
- X retry = CSMNT_RETRY;
- X resp->status = ETIMEDOUT; /* Mark not yet successful */
- X while (retry > 0) {
- X nfs_port = contact_server(sinp, resp);
- X if (nfs_port) {
- X break;
- X }
- X if (--retry > 0) {
- X if (opflags & BGRND) {
- X opflags &= ~BGRND;
- X if (fork())
- X return (-1);
- X else
- X opflags |= ISBGRND;
- X }
- X sleep(20);
- X }
- X }
- X
- X /* abort if error */
- X if (resp->status) {
- X if (opflags & ISBGRND)
- X exit(1);
- X plog(XLOG_ERROR, "Mount RPC error on %s", host);
- X errno = resp->status;
- X perror((char *)NULL);
- X return (-1);
- X }
- X
- X /* set nfs_argsp */
- X#if defined(__osf__) && defined(__alpha)
- X sinp->sin_family = htons(AF_INET); /* DEC OSF/1 bug? */
- X#else
- X sinp->sin_family = AF_INET;
- X#endif
- X sinp->sin_port = htons(nfs_port);
- X NFS_SA_DREF(*nfs_argsp, sinp)
- X NFS_FH_DREF(nfs_argsp->fh, (NFS_FH_TYPE) &resp->cs_fhres_u.file);
- X nfs_argsp->hostname = host;
- X
- X return 0;
- X}
- X
- Xint
- Xcontact_server(sinp, resp)
- Xstruct sockaddr_in *sinp;
- Xcs_fhres *resp;
- X{
- X CLIENT *clntp;
- X enum clnt_stat clnt_stat;
- X struct timeval create_try, call_try;
- X int so = RPC_ANYSOCK;
- X int nfs_port;
- X char fake_arg;
- X
- X sinp->sin_family = AF_INET;
- X sinp->sin_port = htons(0);
- X create_try.tv_sec = 10;
- X create_try.tv_usec = 0;
- X if ((clntp = clntudp_create(sinp, CS_PROGRAM, CS_VERSION,
- X create_try, &so)) == NULL) {
- X if ((opflags & ISBGRND) == 0)
- X clnt_pcreateerror("Failed to clntudp_create()");
- X return 0;
- X } else {
- X clntp->cl_auth = authunix_create_default();
- X /* try CS_PROC_REGISTER */
- X call_try.tv_sec = 10;
- X call_try.tv_usec = 0;
- X clnt_stat = clnt_call(clntp, CS_PROC_REGISTER,
- X xdr_void, &fake_arg, /* in */
- X xdr_cs_fhres, resp, /* out */
- X call_try);
- X /* ignore results for now */
- X
- X /* try CS_PROC_GETPORT */
- X call_try.tv_sec = 10;
- X call_try.tv_usec = 0;
- X clnt_stat = clnt_call(clntp, CS_PROC_GETPORT,
- X xdr_void, &fake_arg, /* in */
- X xdr_int, &nfs_port, /* out */
- X call_try);
- X if (clnt_stat != RPC_SUCCESS) {
- X if ((opflags & ISBGRND) == 0)
- X clnt_perror(clntp, "Failed to CS_PROC_REGISTER");
- X return 0;
- X } else {
- X auth_destroy(clntp->cl_auth);
- X clnt_destroy(clntp);
- X return nfs_port;
- X }
- X }
- X}
- X
- Xint
- Xmount_fs(mntp, flags, mnt_data, retry, type)
- Xstruct mntent *mntp;
- Xint flags;
- Xcaddr_t mnt_data; /* nfs_args actually */
- Xint retry;
- XMTYPE_TYPE type;
- X{
- X int error;
- X#ifdef MNTINFO_DEV
- X struct stat stb;
- X#endif /* MNTINFO_DEV */
- X
- X#ifdef FASCIST_DF_COMMAND
- X /* Oh my SGI! */
- X if (strcmp(mntp->mnt_type, MNTTYPE_WWFS) == 0) {
- X mntp->mnt_type = FASCIST_DF_COMMAND;
- X }
- X#endif /* FASCIST_DF_COMMAND */
- X
- X error = MOUNT_TRAP(type, mntp, flags, mnt_data);
- X if (error < 0) {
- X plog(XLOG_ERROR, "mount failed on %s: errno=%d", mntp->mnt_dir,
- X errno);
- X return (-1);
- X }
- X
- X#ifdef UPDATE_MTAB
- X#ifdef MNTINFO_DEV
- X /*
- X * Add the extra dev= field to the mount table.
- X */
- X if (lstat(mntp->mnt_dir, &stb) == 0) {
- X char *zopts = (char *) malloc(strlen(mntp->mnt_opts) + 32);
- X if (sizeof(stb.st_dev) == 2) {
- X /* e.g. SunOS 4.1 */
- X sprintf(zopts, "%s,%s=%s%04lx", mntp->mnt_opts,
- X MNTINFO_DEV, MNTINFO_PREF,
- X (u_long) stb.st_dev & 0xffff);
- X } else {
- X /* e.g. System Vr4 */
- X sprintf(zopts, "%s,%s=%s%08lx", mntp->mnt_opts,
- X MNTINFO_DEV, MNTINFO_PREF,
- X (u_long) stb.st_dev);
- X }
- X mntp->mnt_opts = zopts;
- X }
- X#endif /* MNTINFO_DEV */
- X
- X#ifdef FIXUP_MNTENT
- X /*
- X * Additional fields in struct mntent
- X * are fixed up here
- X */
- X FIXUP_MNTENT(mntp);
- X#endif
- X
- X write_mntent(mntp);
- X#endif /* UPDATE_MTAB */
- X
- X return 0;
- X}
- X
- X#ifdef MOUNT_HELPER_SOURCE
- X#include MOUNT_HELPER_SOURCE
- X#endif /* MOUNT_HELPER_SOURCE */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X struct nfs_args nfs_args;
- X struct mntent mnt;
- X int flags, ret;
- X char *fs_name, *mp_name, *hostname;
- X
- X if (argc != 3) {
- X usage(argv[0]);
- X exit(1);
- X }
- X /* amd compat code */
- X mypid = getpid();
- X
- X hostname = argv[1];
- X mp_name = argv[2];
- X fs_name = compute_fs_name(argv[1]);
- X bzero(&nfs_args, sizeof (nfs_args));
- X compute_nfs_options(&nfs_args);
- X compute_mntent_options(&mnt, fs_name, mp_name);
- X ret = compute_bindings(&nfs_args, hostname, mp_name);
- X if (ret < 0) exit(1);
- X
- X flags = compute_mount_flags();
- X ret = mount_fs(&mnt, flags, (caddr_t) &nfs_args, 1, MOUNT_TYPE_NFS);
- X return ret;
- X}
- X
- END_OF_FILE
- if test 8847 -ne `wc -c <'wwmount/wwmount.c'`; then
- echo shar: \"'wwmount/wwmount.c'\" unpacked with wrong size!
- fi
- # end of 'wwmount/wwmount.c'
- fi
- echo shar: End of archive 14 \(of 22\).
- cp /dev/null ark14isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 22 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-