home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume41 / wwfs / part14 < prev    next >
Encoding:
Text File  |  1994-01-17  |  88.7 KB  |  3,833 lines

  1. Newsgroups: comp.sources.misc
  2. From: youki-k@is.aist-nara.ac.jp (Youki Kadobayashi)
  3. Subject: v41i099:  wwfs - WorldWide File System, Part14/22
  4. Message-ID: <1994Jan17.202407.20204@sparky.sterling.com>
  5. X-Md4-Signature: 2ca560d064717142f548dfb8b58e445f
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Nara Institute of Science and Technology, Japan
  8. Date: Mon, 17 Jan 1994 20:24:07 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: youki-k@is.aist-nara.ac.jp (Youki Kadobayashi)
  12. Posting-number: Volume 41, Issue 99
  13. Archive-name: wwfs/part14
  14. Environment: UNIX, inet
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  config/mtab_file.c csd/cmfs.c csd/file.c csd/nfs_subr.c
  21. #   csd/util.c csd/vol.c libww/libww.c wwalk/Makefile
  22. #   wwmount/wwmount.c
  23. # Wrapped by kent@sparky on Sun Jan 16 17:48:36 1994
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 14 (of 22)."'
  27. if test -f 'config/mtab_file.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'config/mtab_file.c'\"
  29. else
  30.   echo shar: Extracting \"'config/mtab_file.c'\" \(10879 characters\)
  31.   sed "s/^X//" >'config/mtab_file.c' <<'END_OF_FILE'
  32. X/*
  33. X * Copyright (c) 1990 Jan-Simon Pendry
  34. X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  35. X * Copyright (c) 1990 The Regents of the University of California.
  36. X * All rights reserved.
  37. X *
  38. X * This code is derived from software contributed to Berkeley by
  39. X * Jan-Simon Pendry at Imperial College, London.
  40. X *
  41. X * Redistribution and use in source and binary forms, with or without
  42. X * modification, are permitted provided that the following conditions
  43. X * are met:
  44. X * 1. Redistributions of source code must retain the above copyright
  45. X *    notice, this list of conditions and the following disclaimer.
  46. X * 2. Redistributions in binary form must reproduce the above copyright
  47. X *    notice, this list of conditions and the following disclaimer in the
  48. X *    documentation and/or other materials provided with the distribution.
  49. X * 3. All advertising materials mentioning features or use of this software
  50. X *    must display the following acknowledgement:
  51. X *      This product includes software developed by the University of
  52. X *      California, Berkeley and its contributors.
  53. X * 4. Neither the name of the University nor the names of its contributors
  54. X *    may be used to endorse or promote products derived from this software
  55. X *    without specific prior written permission.
  56. X *
  57. X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  58. X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  59. X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  60. X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  61. X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  62. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  63. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  64. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  65. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  66. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  67. X * SUCH DAMAGE.
  68. X *
  69. X *    %W% (Berkeley) %G%
  70. X *
  71. X * $Id: mtab_file.c,v 5.2.2.1 1992/02/09 15:10:42 jsp beta $
  72. X *
  73. X */
  74. X
  75. X#include "am.h"
  76. X
  77. X#ifdef READ_MTAB_FROM_FILE
  78. X
  79. X#ifdef USE_FCNTL
  80. X#include <fcntl.h>
  81. X#else
  82. X#include <sys/file.h>
  83. X#endif /* USE_FCNTL */
  84. X
  85. X#ifdef UPDATE_MTAB
  86. X
  87. X/*
  88. X * Do strict /etc/mtab locking
  89. X */
  90. X#define    MTAB_LOCKING
  91. X
  92. X/*
  93. X * Firewall mtab entries
  94. X */
  95. X#define    MTAB_STRIPNL
  96. X
  97. X#include <sys/stat.h>
  98. Xstatic FILE *mnt_file;
  99. X
  100. X/*
  101. X * If the system is being trashed by something, then
  102. X * opening mtab may fail with ENFILE.  So, go to sleep
  103. X * for a second and try again. (Yes - this has happened to me.)
  104. X *
  105. X * Note that this *may* block the automounter, oh well. 
  106. X * If we get to this state then things are badly wrong anyway...
  107. X *
  108. X * Give the system 10 seconds to recover but then give up.
  109. X * Hopefully something else will exit and free up some file
  110. X * table slots in that time.
  111. X */
  112. X#define    NFILE_RETRIES    10 /* seconds */
  113. X
  114. X#ifdef MTAB_LOCKING
  115. X#ifdef LOCK_FCNTL
  116. Xstatic int lock(fd)
  117. X{
  118. X    int rc;
  119. X    struct flock lk;
  120. X
  121. X    lk.l_type = F_WRLCK;
  122. X    lk.l_whence = 0;
  123. X    lk.l_start = 0;
  124. X    lk.l_len = 0;
  125. X
  126. Xagain:
  127. X    rc = fcntl(fd, F_SETLKW, (caddr_t) &lk);
  128. X    if (rc < 0 && (errno == EACCES || errno == EAGAIN)) {
  129. X#ifdef DEBUG
  130. X        dlog("Blocked, trying to obtain exclusive mtab lock");
  131. X#endif /* DEBUG */
  132. X        sleep(1);
  133. X        goto again;
  134. X    }
  135. X    return rc;
  136. X}
  137. X#else
  138. X#define lock(fd) (flock((fd), LOCK_EX))
  139. X#endif /* LOCK_FCNTL */
  140. X#endif /* MTAB_LOCKING */
  141. X
  142. Xstatic FILE *open_locked_mtab(mtab_file, mode, fs)
  143. Xchar *mtab_file;
  144. Xchar *mode;
  145. Xchar *fs;
  146. X{
  147. X    FILE *mfp = 0;
  148. X
  149. X#ifdef UPDATE_MTAB
  150. X    /*
  151. X     * There is a possible race condition if two processes enter
  152. X     * this routine at the same time.  One will be blocked by the
  153. X     * exclusive lock below (or by the shared lock in setmntent)
  154. X     * and by the time the second process has the exclusive lock
  155. X     * it will be on the wrong underlying object.  To check for this
  156. X     * the mtab file is stat'ed before and after all the locking
  157. X     * sequence, and if it is a different file then we assume that
  158. X     * it may be the wrong file (only "may", since there is another
  159. X     * race between the initial stat and the setmntent).
  160. X     *
  161. X     * Simpler solutions to this problem are invited...
  162. X     */
  163. X    int racing = 2;
  164. X#ifdef MTAB_LOCKING
  165. X    int rc;
  166. X    int retries = 0;
  167. X    struct stat st_before, st_after;
  168. X#endif /* MTAB_LOCKING */
  169. X
  170. X    if (mnt_file) {
  171. X#ifdef DEBUG
  172. X        dlog("Forced close on %s in read_mtab", mtab_file);
  173. X#endif /* DEBUG */
  174. X        endmntent(mnt_file);
  175. X        mnt_file = 0;
  176. X    }
  177. X
  178. X#ifdef MTAB_LOCKING
  179. Xagain:
  180. X    if (mfp) {
  181. X        endmntent(mfp);
  182. X        mfp = 0;
  183. X    }
  184. X
  185. X    clock_valid = 0;
  186. X    if (stat(mtab_file, &st_before) < 0) {
  187. X        plog(XLOG_ERROR, "%s: stat: %m", mtab_file);
  188. X        if (errno == ESTALE) {
  189. X            /* happens occasionally */
  190. X            sleep(1);
  191. X            goto again;
  192. X        }
  193. X        return 0;
  194. X    }
  195. X#endif /* MTAB_LOCKING */
  196. X#endif /* UPDATE_MTAB */
  197. X
  198. Xeacces:
  199. X    mfp = setmntent(mtab_file, mode);
  200. X    if (!mfp) {
  201. X        /*
  202. X         * Since setmntent locks the descriptor, it
  203. X         * is possible it can fail... so retry if
  204. X         * needed.
  205. X         */
  206. X        if (errno == EACCES || errno == EAGAIN) {
  207. X#ifdef DEBUG
  208. X            dlog("Blocked, trying to obtain exclusive mtab lock");
  209. X#endif /* DEBUG */
  210. X            goto eacces;
  211. X        } else if (errno == ENFILE && retries++ < NFILE_RETRIES) {
  212. X            sleep(1);
  213. X            goto eacces;
  214. X        }
  215. X
  216. X        plog(XLOG_ERROR, "setmntent(\"%s\", \"%s\"): %m", mtab_file, mode);
  217. X        return 0;
  218. X    }
  219. X
  220. X#ifdef MTAB_LOCKING
  221. X#ifdef UPDATE_MTAB
  222. X    /*
  223. X     * At this point we have an exclusive lock on the mount list,
  224. X     * but it may be the wrong one so...
  225. X     */
  226. X
  227. X    /*
  228. X     * Need to get an exclusive lock on the current
  229. X     * mount table until we have a new copy written
  230. X     * out, when the lock is released in free_mntlist.
  231. X     * flock is good enough since the mount table is
  232. X     * not shared between machines.
  233. X     */
  234. X    do
  235. X        rc = lock(fileno(mfp));
  236. X    while (rc < 0 && errno == EINTR);
  237. X    if (rc < 0) {
  238. X        plog(XLOG_ERROR, "Couldn't lock %s: %m", mtab_file);
  239. X        endmntent(mfp);
  240. X        return 0;
  241. X    }
  242. X    /*
  243. X     * Now check whether the mtab file has changed under our feet
  244. X     */
  245. X    if (stat(mtab_file, &st_after) < 0) {
  246. X        plog(XLOG_ERROR, "%s: stat", mtab_file);
  247. X        goto again;
  248. X    }
  249. X
  250. X    if (st_before.st_dev != st_after.st_dev ||
  251. X        st_before.st_ino != st_after.st_ino) {
  252. X            struct timeval tv;
  253. X            if (racing == 0) {
  254. X                /* Sometimes print a warning */
  255. X                plog(XLOG_WARNING,
  256. X                    "Possible mount table race - retrying %s", fs);
  257. X            }
  258. X            racing = (racing+1) & 3;
  259. X            /*
  260. X             * Take a nap.  From: Doug Kingston <dpk@morgan.com>
  261. X             */
  262. X            tv.tv_sec = 0;
  263. X            tv.tv_usec = (mypid & 0x07) << 17;
  264. X            if (tv.tv_usec)
  265. X                if (select(0, (voidp) 0, (voidp) 0, (voidp) 0, &tv) < 0)
  266. X                    plog(XLOG_WARNING, "mtab nap failed: %m");
  267. X
  268. X            goto again;
  269. X    }
  270. X#endif /* UPDATE_MTAB */
  271. X#endif /* MTAB_LOCKING */
  272. X
  273. X    return mfp;
  274. X}
  275. X
  276. X/*
  277. X * Unlock the mount table
  278. X */
  279. Xvoid unlock_mntlist P((void));
  280. Xvoid unlock_mntlist()
  281. X{
  282. X    /*
  283. X     * Release file lock, by closing the file
  284. X     */
  285. X    if (mnt_file) {
  286. X        endmntent(mnt_file);
  287. X        mnt_file = 0;
  288. X    }
  289. X}
  290. X
  291. X/*
  292. X * Write out a mount list
  293. X */
  294. Xvoid rewrite_mtab(mp)
  295. Xmntlist *mp;
  296. X{
  297. X    FILE *mfp;
  298. X    int error = 0;
  299. X
  300. X    /*
  301. X     * Concoct a temporary name in the same
  302. X     * directory as the target mount table
  303. X     * so that rename() will work.
  304. X     */
  305. X    char tmpname[64];
  306. X    int retries;
  307. X    int tmpfd;
  308. X    char *cp;
  309. X    char *mcp = mtab;
  310. X    cp = strrchr(mcp, '/');
  311. X    if (cp) {
  312. X        bcopy(mcp, tmpname, cp - mcp);
  313. X        tmpname[cp-mcp] = '\0';
  314. X    } else {
  315. X        plog(XLOG_WARNING, "No '/' in mtab (%s), using \".\" as tmp directory", mtab);
  316. X        tmpname[0] = '.'; tmpname[1] = '\0';
  317. X    }
  318. X    strcat(tmpname, "/mtabXXXXXX");
  319. X    mktemp(tmpname);
  320. X    retries = 0;
  321. Xenfile1:
  322. X    if ((tmpfd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
  323. X        if (errno == ENFILE && retries++ < NFILE_RETRIES) {
  324. X            sleep(1);
  325. X            goto enfile1;
  326. X        }
  327. X        plog(XLOG_ERROR, "%s: open: %m", tmpname);
  328. X        return;
  329. X    }
  330. X    if (close(tmpfd) < 0)
  331. X        plog(XLOG_ERROR, "Couldn't close tmp file descriptor: %m");
  332. X
  333. X    retries = 0;
  334. Xenfile2:
  335. X    mfp = setmntent(tmpname, "w");
  336. X    if (!mfp) {
  337. X        if (errno == ENFILE && retries++ < NFILE_RETRIES) {
  338. X            sleep(1);
  339. X            goto enfile2;
  340. X        }
  341. X        plog(XLOG_ERROR, "setmntent(\"%s\", \"w\"): %m", tmpname);
  342. X        error = 1;
  343. X        goto out;
  344. X    }
  345. X
  346. X    while (mp) {
  347. X        if (mp->mnt) {
  348. X            if (addmntent(mfp, mp->mnt)) {
  349. X                plog(XLOG_ERROR, "Can't write entry to %s", tmpname);
  350. X                error = 1;
  351. X                goto out;
  352. X            }
  353. X        }
  354. X        mp = mp->mnext;
  355. X    }
  356. X
  357. X    /*
  358. X     * SunOS 4.1 manuals say that the return code from entmntent()
  359. X     * is always 1 and to treat as a void.  That means we need to
  360. X     * call fflush() to make sure the new mtab file got written.
  361. X     */
  362. X    if (fflush(mfp)) {
  363. X        plog(XLOG_ERROR, "flush new mtab file: %m");
  364. X        error = 1;
  365. X        goto out;
  366. X    }
  367. X
  368. X    (void) endmntent(mfp);
  369. X
  370. X    /*
  371. X     * Rename temporary mtab to real mtab
  372. X     */
  373. X    if (rename(tmpname, mtab) < 0) {
  374. X        plog(XLOG_ERROR, "rename %s to %s: %m", tmpname, mtab);
  375. X        error = 1;
  376. X        goto out;
  377. X    }
  378. X
  379. Xout:
  380. X    if (error)
  381. X        (void) unlink(tmpname);
  382. X}
  383. X
  384. X#ifdef MTAB_STRIPNL
  385. Xstatic void mtab_stripnl(s)
  386. Xchar *s;
  387. X{
  388. X    do {
  389. X        s = strchr(s, '\n');
  390. X        if (s)
  391. X            *s++ = ' ';
  392. X    } while (s);
  393. X}
  394. X#endif /* MTAB_STRIPNL */
  395. X
  396. X/*
  397. X * Append a mntent structure to the
  398. X * current mount table.
  399. X */
  400. Xvoid write_mntent(mp)
  401. Xstruct mntent *mp;
  402. X{
  403. X    int retries = 0;
  404. X    FILE *mfp;
  405. Xenfile:
  406. X    mfp = open_locked_mtab(mtab, "a", mp->mnt_dir);
  407. X    if (mfp) {
  408. X#ifdef MTAB_STRIPNL
  409. X        mtab_stripnl(mp->mnt_opts);
  410. X#endif /* MTAB_STRIPNL */
  411. X        if (addmntent(mfp, mp))
  412. X            plog(XLOG_ERROR, "Couldn't write %s: %m", mtab);
  413. X        if (fflush(mfp))
  414. X            plog(XLOG_ERROR, "Couldn't flush %s: %m", mtab);
  415. X        (void) endmntent(mfp);
  416. X    } else {
  417. X        if (errno == ENFILE && retries < NFILE_RETRIES) {
  418. X            sleep(1);
  419. X            goto enfile;
  420. X        }
  421. X        plog(XLOG_ERROR, "setmntent(\"%s\", \"a\"): %m", mtab);
  422. X    }
  423. X}
  424. X
  425. X#endif /* UPDATE_MTAB */
  426. X
  427. Xstatic struct mntent *mnt_dup(mp)
  428. Xstruct mntent *mp;
  429. X{
  430. X    struct mntent *new_mp = ALLOC(mntent);
  431. X
  432. X    new_mp->mnt_fsname = strdup(mp->mnt_fsname);
  433. X    new_mp->mnt_dir = strdup(mp->mnt_dir);
  434. X    new_mp->mnt_type = strdup(mp->mnt_type);
  435. X    new_mp->mnt_opts = strdup(mp->mnt_opts);
  436. X
  437. X    new_mp->mnt_freq = mp->mnt_freq;
  438. X    new_mp->mnt_passno = mp->mnt_passno;
  439. X
  440. X#ifdef FIXUP_MNTENT_DUP
  441. X    /*
  442. X     * Additional fields get dup'ed here
  443. X     */
  444. X    FIXUP_MNTENT_DUP(new_mp, mp);
  445. X#endif
  446. X
  447. X    return new_mp;
  448. X}
  449. X
  450. X/*
  451. X * Read a mount table into memory
  452. X */
  453. Xmntlist *read_mtab(fs)
  454. Xchar *fs;
  455. X{
  456. X    mntlist **mpp, *mhp;
  457. X
  458. X    struct mntent *mep;
  459. X    FILE *mfp = open_locked_mtab(mtab, "r+", fs);
  460. X
  461. X    if (!mfp)
  462. X        return 0;
  463. X
  464. X    mpp = &mhp;
  465. X
  466. X/*
  467. X * XXX - In SunOS 4 there is (yet another) memory leak
  468. X * which loses 1K the first time getmntent is called.
  469. X * (jsp)
  470. X */
  471. X    while (mep = getmntent(mfp)) {
  472. X        /*
  473. X         * Allocate a new slot
  474. X         */
  475. X        *mpp = ALLOC(mntlist);
  476. X
  477. X        /*
  478. X         * Copy the data returned by getmntent
  479. X         */
  480. X        (*mpp)->mnt = mnt_dup(mep);
  481. X
  482. X        /*
  483. X         * Move to next pointer
  484. X         */
  485. X        mpp = &(*mpp)->mnext;
  486. X    }
  487. X    *mpp = 0;
  488. X
  489. X#ifdef UPDATE_MTAB
  490. X    /*
  491. X     * If we are not updating the mount table then we
  492. X     * can free the resources held here, otherwise they
  493. X     * must be held until the mount table update is complete
  494. X     */
  495. X    mnt_file = mfp;
  496. X#else
  497. X    endmntent(mfp);
  498. X#endif /* UPDATE_MTAB */
  499. X
  500. X    return mhp;
  501. X}
  502. X
  503. X#endif /* READ_MTAB_FROM_FILE */
  504. END_OF_FILE
  505.   if test 10879 -ne `wc -c <'config/mtab_file.c'`; then
  506.     echo shar: \"'config/mtab_file.c'\" unpacked with wrong size!
  507.   fi
  508.   # end of 'config/mtab_file.c'
  509. fi
  510. if test -f 'csd/cmfs.c' -a "${1}" != "-c" ; then 
  511.   echo shar: Will not clobber existing file \"'csd/cmfs.c'\"
  512. else
  513.   echo shar: Extracting \"'csd/cmfs.c'\" \(9301 characters\)
  514.   sed "s/^X//" >'csd/cmfs.c' <<'END_OF_FILE'
  515. X/* 
  516. X * WorldWide File System
  517. X * Copyright (c) 1992,1993 Youki Kadobayashi
  518. X * Copyright (c) 1992,1993 Osaka University
  519. X * All rights reserved.
  520. X *
  521. X * Permission to use, copy, modify and distribute this software and its
  522. X * documentation is hereby granted, provided that the following conditions
  523. X * are met:
  524. X * 1. Both the copyright notice and this permission notice appear in
  525. X *    all copies of the software, derivative works or modified versions,
  526. X *    and any portions thereof, and that both notices appear in
  527. X *    supporting documentation.
  528. X * 2. All advertising materials mentioning features or use of this software
  529. X *    must display the following acknowledgement:
  530. X *      This product includes software developed by the Osaka University
  531. X *      and its contributors.
  532. X * 3. Neither the name of the University nor the names of its contributors
  533. X *    may be used to endorse or promote products derived from this software
  534. X *    without specific prior written permission.
  535. X *
  536. X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
  537. X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  538. X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  539. X *
  540. X * Osaka University requests users of this software to return to
  541. X *
  542. X *  Youki Kadobayashi
  543. X *  Department of Information and Computer Sciences
  544. X *  Osaka University, Toyonaka 560, Osaka, Japan
  545. X *
  546. X * any improvements or extensions that they make and grant Osaka
  547. X * University the rights to redistribute these changes.
  548. X */
  549. X/* cmfs: cache manager file system.
  550. X * Perform access to cached information. Call delegate function xyz_miss()
  551. X * when cache missed.
  552. X */
  553. Xstatic char *AtFSid = "$Header: cmfs.c[109.0] Wed Nov 24 03:47:03 1993 youki-k@is.aist-nara.ac.jp saved $";
  554. X
  555. X#include "wfs.h"
  556. X#include "util.h"
  557. X#include "global.h"
  558. X
  559. X/*
  560. X * filehandle internals
  561. X
  562. X * parent                child
  563. X * ---------                --------
  564. X * parent_vol                ---
  565. X * parent_dir                ---
  566. X * child_vol            ==    parent_vol
  567. X * child_dir            ==    dir_id
  568. X * file_findid(...)->fsid    ==    child_vol
  569. X * file_findid(...)->id        ==    file_id
  570. X
  571. X * parent                child "."
  572. X * ---------                --------
  573. X * parent_vol            ==    parent_vol
  574. X * parent_dir            ==    parent_dir
  575. X * child_vol            ==    child_vol
  576. X * child_dir            ==    child_dir
  577. X
  578. X * parent                child ".."
  579. X * ---------                --------
  580. X * file_findname(, "..")->fsid    ==    parent_vol
  581. X * file_findname(, "..")->id    ==    parent_dir
  582. X * parent_vol            ==    child_vol
  583. X * parent_dir            ==    child_dir
  584. X * child_vol                ---
  585. X * child_dir                ---
  586. X *
  587. X * Note that dir_id and file_id is aliased as
  588. X * parent_dir and child_dir, respectively.
  589. X */
  590. Xvoid
  591. Xcmfs_getattr(c)
  592. Xwf_thrd *c;
  593. X/* in: rqstp, volp, fhp, reply */
  594. X/* out: dirp, filep */
  595. X{
  596. X    static wf_file file;
  597. X
  598. X    c->dirp = dir_findcache(c->parent_volp, c->fhp->dir_id);
  599. X    if (c->dirp == (wf_dir *)0) {
  600. X#if 0
  601. X        (*c->reply)(c, WF_ERR_NOENT);
  602. X        return;
  603. X#else
  604. X        /* fake that directory for nonexistent directory */
  605. X        static wf_dir dir;
  606. X        dir.id = c->fhp->dir_id;
  607. X        c->dirp = &dir;
  608. X        c->filep = (wf_file *)0;
  609. X#endif
  610. X    } else {
  611. X        c->filep = file_findid(c->dirp,
  612. X                       c->fhp->child_vol, c->fhp->file_id);
  613. X    }
  614. X    if (!c->filep) {
  615. X        /* fake that file for nonexistent directory */
  616. X        attr_initdir(&file.fattr);
  617. X        file.fattr.fsid = c->fhp->child_vol;
  618. X        file.id = file.fattr.fileid = c->fhp->file_id;
  619. X        c->filep = &file;
  620. X    }
  621. X    if (c->filep->flag & WF_FILE_MUTABLE) {
  622. X        /* Delegate gets notification of access, but not
  623. X         * required to reflect current state right now.
  624. X         * Getattr operation should be "cheap" however.
  625. X         * Attribute caching mechanism is deferred to each
  626. X         * underlying filesystem for now.
  627. X         */
  628. X        proto_getattr_miss(c);
  629. X    }
  630. X    (*c->reply)(c, WF_REP_OK);
  631. X}
  632. X
  633. Xvoid
  634. Xcmfs_lookup(c)
  635. Xwf_thrd *c;
  636. X/* in: rqstp, volp, fhp, fname, reply */
  637. X/* out: dotdotp, resfhp, filep */
  638. X{
  639. X    wf_fh        *resfhp;    /* reply filehandle */
  640. X
  641. X    /* stats */
  642. X    c->child_volp->stats.n_request_lookup++;
  643. X
  644. X    if (c->fname[0] == '.') {
  645. X        wf_dir *dotdotp;
  646. X
  647. X        dotdotp = dir_findcache(c->parent_volp,
  648. X                    c->fhp->parent_dir);
  649. X        if (dotdotp == NULL || dotdotp->flag & WF_DIR_OBSOLETE) {
  650. X            (*c->reply)(c, WF_ERR_STALE);
  651. X        } else if (strcmp(c->fname, "..") == 0) {
  652. X            /*
  653. X             * dotdot
  654. X             */
  655. X            c->resfhp = resfhp = CLONE(c->fhp);
  656. X            c->filep = file_findname(dotdotp, "..");
  657. X            assert(c->filep != NULL);
  658. X            resfhp->parent_vol = FSID(c->filep);
  659. X            resfhp->parent_dir = FID(c->filep);
  660. X
  661. X            c->filep = file_findname(dotdotp, ".");
  662. X            assert(c->filep != NULL);
  663. X            resfhp->child_vol = c->fhp->parent_vol;
  664. X            resfhp->child_dir = c->fhp->parent_dir;
  665. X            (*c->reply)(c, WF_REP_OK);
  666. X            FREE(resfhp);
  667. X            return;
  668. X        } else if (strcmp(c->fname, ".") == 0) {
  669. X            /*
  670. X             * dot
  671. X             */
  672. X            c->filep = file_findid(dotdotp,
  673. X                           c->fhp->child_vol, c->fhp->child_dir);
  674. X            c->resfhp = c->fhp;
  675. X            (*c->reply)(c, WF_REP_OK);
  676. X            return;
  677. X        }
  678. X    }
  679. X
  680. X    /*
  681. X     * get dotdotp
  682. X     */
  683. X    c->dotdotp = dir_findcache(c->child_volp, c->fhp->child_dir);
  684. X    if (c->dotdotp == (wf_dir *)0 || c->dotdotp->flag & WF_DIR_OBSOLETE) {
  685. X        (*c->reply)(c, WF_ERR_STALE);
  686. X        return;
  687. X    }
  688. X
  689. X    /*
  690. X     * find file in dotdotp
  691. X     */
  692. X    c->filep = file_findname(c->dotdotp, c->fname);
  693. X    if (c->filep == (wf_file *)0) {
  694. X        c->child_volp->stats.n_request_lookup_miss++;
  695. X        proto_lookup_miss(c);
  696. X        return;
  697. X    }
  698. X
  699. X    c->resfhp = resfhp = CLONE(c->fhp);
  700. X    resfhp->parent_vol = c->fhp->child_vol;
  701. X    resfhp->parent_dir = c->fhp->child_dir;
  702. X    resfhp->child_vol = FSID(c->filep);
  703. X    resfhp->child_dir = FID(c->filep);
  704. X    (*c->reply)(c, WF_REP_OK);
  705. X    FREE(resfhp);
  706. X}
  707. X
  708. X#ifdef TRACE
  709. Xstatic wf_trace *
  710. Xcmfs_readdir_trace(c)
  711. Xwf_thrd *c;
  712. X{
  713. X    wf_trace *tracep;
  714. X
  715. X    tracep = ALLOC(wf_trace);
  716. X    tracep->time = gettime();
  717. X    tracep->uid = c->uid;
  718. X    tracep->client = c->client;
  719. X    tracep->volume = c->fhp->child_vol;
  720. X    tracep->dir = c->fhp->child_dir;
  721. X    return tracep;
  722. X}
  723. X#endif
  724. X
  725. Xvoid
  726. Xcmfs_readdir(c)
  727. Xwf_thrd *c;
  728. X/* in: rqstp, volp, fhp, cookie, count, reply */
  729. X/* out: dirp, dotdotp, olddirp, filep */
  730. X{
  731. X    /*
  732. X     * assumption: consecutive queries will come in before
  733. X     * asked directory gets kicked out of memory
  734. X     */
  735. X#ifdef TRACE
  736. X    wf_trace *tracep;
  737. X#endif
  738. X
  739. X    /* stats */
  740. X    c->child_volp->stats.n_request_readdir++;
  741. X
  742. X    /* find file in dotdotp */
  743. X    c->dotdotp = dir_findcache(c->parent_volp, c->fhp->parent_dir);
  744. X    if (c->dotdotp == NULL) {
  745. X        (*c->reply)(c, WF_ERR_NOENT);
  746. X        return;
  747. X    }
  748. X    c->filep = file_findid(c->dotdotp,
  749. X                   c->fhp->child_vol, c->fhp->child_dir);
  750. X    if (c->filep == NULL) {
  751. X        /* file handle corrupt? */
  752. X        (*c->reply)(c, WF_ERR_NOENT);
  753. X        return;
  754. X    }
  755. X
  756. X    /*
  757. X     * check if directory transfer is in progress
  758. X     */
  759. X    if (c->filep->thrdp) {
  760. X        (*c->reply)(c, WF_ERR_ALREADY);
  761. X        return;
  762. X    }
  763. X
  764. X    /*
  765. X     * get dirp
  766. X     */
  767. X    c->dirp = dir_findcache(c->child_volp, c->fhp->child_dir);
  768. X
  769. X    /*
  770. X     * cache hit
  771. X     */
  772. X    if (c->dirp && !(c->dirp->flag & WF_DIR_OBSOLETE)) {
  773. X#ifdef TRACE
  774. X        /*
  775. X         * trace cache hit
  776. X         */
  777. X        unsigned long cookie;
  778. X        bcopy(c->cookie, &cookie, sizeof(nfscookie));
  779. X        if (cookie == 0) {
  780. X            tracep = cmfs_readdir_trace(c);
  781. X            tracep->op = WF_OP_READDIR;
  782. X            tracep->hit = WF_CACHE_HIT;
  783. X            trace_event(c, tracep);
  784. X        }
  785. X#endif
  786. X        (*c->reply)(c, WF_REP_OK);
  787. X        return;
  788. X    }
  789. X
  790. X    /*
  791. X     * cache missed
  792. X     */
  793. X    c->child_volp->stats.n_request_readdir_miss++;
  794. X    c->olddirp = c->dirp;
  795. X#ifdef TRACE
  796. X    /*
  797. X     * trace cache miss
  798. X     */
  799. X    tracep = cmfs_readdir_trace(c);
  800. X    tracep->op = WF_OP_READDIR;
  801. X    tracep->hit = WF_CACHE_MISS;
  802. X    trace_event(c, tracep);
  803. X#endif
  804. X    proto_readdir_miss(c);
  805. X}
  806. X
  807. Xvoid
  808. Xcmfs_readlink(c)
  809. Xwf_thrd *c;
  810. X/* in: rqstp, volp, fhp, reply */
  811. X/* out: dirp, filep */
  812. X{
  813. X    c->dirp = dir_findcache(c->parent_volp, c->fhp->dir_id);
  814. X    if (c->dirp == (wf_dir *)0 || c->dirp->flag & WF_DIR_OBSOLETE) {
  815. X        (*c->reply)(c, WF_ERR_STALE);
  816. X        return;
  817. X    }
  818. X    c->filep = file_findid(c->dirp, c->fhp->child_vol, c->fhp->file_id);
  819. X    assert(c->filep != (wf_file *)0);
  820. X    if (c->filep->fattr.type != NFLNK) {
  821. X        (*c->reply)(c, WF_ERR_NOENT);
  822. X        return;
  823. X    }
  824. X    (*c->reply)(c, WF_REP_OK);
  825. X}
  826. X
  827. X#ifdef TRACE
  828. Xstatic wf_trace *
  829. Xcmfs_read_trace(c)
  830. Xwf_thrd *c;
  831. X{
  832. X    wf_trace *tracep;
  833. X
  834. X    tracep = ALLOC(wf_trace);
  835. X    tracep->time = gettime();
  836. X    tracep->uid = c->uid;
  837. X    tracep->client = c->client;
  838. X    tracep->volume = c->fhp->child_vol;
  839. X    tracep->dir = c->fhp->dir_id;
  840. X    tracep->file = c->fhp->file_id;
  841. X    tracep->arg = (long) c->filep->fattr.size;
  842. X    return tracep;
  843. X}
  844. X#endif
  845. X
  846. Xvoid
  847. Xcmfs_read(c)
  848. Xwf_thrd *c;
  849. X/* in: rqstp, volp, fhp, offset, count, totalcount, reply */
  850. X/* out: dirp, filep */
  851. X{
  852. X#ifdef TRACE
  853. X    wf_trace *tracep;
  854. X#endif
  855. X    /* stats */
  856. X    c->child_volp->stats.n_request_read++;
  857. X
  858. X    /*
  859. X     * get dirp
  860. X     */
  861. X    c->dirp = dir_findcache(c->parent_volp, c->fhp->dir_id);
  862. X    if (c->dirp == (wf_dir *)0 || c->dirp->flag & WF_DIR_OBSOLETE) {
  863. X        (*c->reply)(c, WF_ERR_STALE);
  864. X        return;
  865. X    }
  866. X
  867. X    /*
  868. X     * find file in dirp
  869. X     */
  870. X    c->filep = file_findid(c->dirp, c->fhp->child_vol, c->fhp->file_id);
  871. X    assert(c->filep != (wf_file *)0);
  872. X
  873. X    /*
  874. X     * check if file transfer is in progress
  875. X     */
  876. X    if (c->filep->thrdp) {
  877. X        (*c->reply)(c, WF_ERR_ALREADY);
  878. X        return;
  879. X    }
  880. X
  881. X    /*
  882. X     * cache hit
  883. X     */
  884. X    if (file_findcache(c->child_volp, c->dirp, c->filep) == 0) {
  885. X#ifdef TRACE
  886. X        /*
  887. X         * trace cache hit
  888. X         */
  889. X        if (c->offset == 0) {
  890. X            tracep = cmfs_read_trace(c);
  891. X            tracep->op = WF_OP_READ;
  892. X            tracep->hit = WF_CACHE_HIT;
  893. X            trace_event(c, tracep);
  894. X        }
  895. X#endif
  896. X        (*c->reply)(c, WF_REP_OK);
  897. X        return;
  898. X    }
  899. X
  900. X    /*
  901. X     * cache missed
  902. X     */
  903. X    c->child_volp->stats.n_request_read_miss++;
  904. X#ifdef TRACE
  905. X    /*
  906. X     * trace cache missed
  907. X     */
  908. X    tracep = cmfs_read_trace(c);
  909. X    tracep->op = WF_OP_READ;
  910. X    tracep->hit = WF_CACHE_MISS;
  911. X    trace_event(c, tracep);
  912. X#endif
  913. X    proto_read_miss(c);
  914. X}
  915. END_OF_FILE
  916.   if test 9301 -ne `wc -c <'csd/cmfs.c'`; then
  917.     echo shar: \"'csd/cmfs.c'\" unpacked with wrong size!
  918.   fi
  919.   # end of 'csd/cmfs.c'
  920. fi
  921. if test -f 'csd/file.c' -a "${1}" != "-c" ; then 
  922.   echo shar: Will not clobber existing file \"'csd/file.c'\"
  923. else
  924.   echo shar: Extracting \"'csd/file.c'\" \(9197 characters\)
  925.   sed "s/^X//" >'csd/file.c' <<'END_OF_FILE'
  926. X/* 
  927. X * WorldWide File System
  928. X * Copyright (c) 1992,1993 Youki Kadobayashi
  929. X * Copyright (c) 1992,1993 Osaka University
  930. X * All rights reserved.
  931. X *
  932. X * Permission to use, copy, modify and distribute this software and its
  933. X * documentation is hereby granted, provided that the following conditions
  934. X * are met:
  935. X * 1. Both the copyright notice and this permission notice appear in
  936. X *    all copies of the software, derivative works or modified versions,
  937. X *    and any portions thereof, and that both notices appear in
  938. X *    supporting documentation.
  939. X * 2. All advertising materials mentioning features or use of this software
  940. X *    must display the following acknowledgement:
  941. X *      This product includes software developed by the Osaka University
  942. X *      and its contributors.
  943. X * 3. Neither the name of the University nor the names of its contributors
  944. X *    may be used to endorse or promote products derived from this software
  945. X *    without specific prior written permission.
  946. X *
  947. X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
  948. X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  949. X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  950. X *
  951. X * Osaka University requests users of this software to return to
  952. X *
  953. X *  Youki Kadobayashi
  954. X *  Department of Information and Computer Sciences
  955. X *  Osaka University, Toyonaka 560, Osaka, Japan
  956. X *
  957. X * any improvements or extensions that they make and grant Osaka
  958. X * University the rights to redistribute these changes.
  959. X */
  960. Xstatic char *AtFSid = "$Header: file.c[109.1] Tue Dec  7 23:37:58 1993 youki-k@is.aist-nara.ac.jp saved $";
  961. X
  962. X#include <sys/types.h>
  963. X#include <sys/stat.h>
  964. X#include <sys/file.h>        /* for R_OK */
  965. X#ifndef R_OK
  966. X#include <unistd.h>
  967. X#endif
  968. X#include <fcntl.h>        /* for O_WRONLY etc. */
  969. X#include "wfs.h"
  970. X#include "util.h"
  971. X#include "global.h"
  972. X
  973. Xstatic
  974. Xunsigned int type2mode[NFFIFO+1] = {    /* depends on enum ftype */
  975. X    0,        /* NFNON */
  976. X    S_IFREG,
  977. X    S_IFDIR,
  978. X    S_IFBLK,
  979. X    S_IFCHR,
  980. X    S_IFLNK,
  981. X    S_IFSOCK,
  982. X    0,        /* NFBAD */
  983. X    S_IFIFO
  984. X};
  985. X
  986. X#define    WF_FILE_HASHSIZE    16
  987. X
  988. Xtypedef struct fcache {
  989. X        wf_file *filep;
  990. X        wf_dir    *dirp;
  991. X} fcache;
  992. Xstatic fcache findid_cache[WF_FILE_HASHSIZE],
  993. X    findname_cache[WF_FILE_HASHSIZE];
  994. X
  995. Xwf_file *
  996. Xfile_alloc()
  997. X{
  998. X    wf_file *filep;
  999. X    filep = ALLOC(wf_file);
  1000. X    return filep;
  1001. X}
  1002. X
  1003. Xvoid
  1004. Xfile_free(filep)
  1005. Xwf_file *filep;
  1006. X{
  1007. X    if (filep->name) free(filep->name);
  1008. X    if (filep->link) free(filep->link);
  1009. X    FREE(filep);
  1010. X}
  1011. X
  1012. Xvoid
  1013. Xfile_uncache(dirp)
  1014. Xwf_dir *dirp;
  1015. X{
  1016. X    int i = dirp->id % WF_FILE_HASHSIZE;
  1017. X    fcache *p;
  1018. X
  1019. X    p = &findid_cache[i];
  1020. X    if (p->dirp == dirp) {
  1021. X        p->dirp = (wf_dir *) 0;
  1022. X        p->filep = (wf_file *) 0;
  1023. X    }
  1024. X    p = &findname_cache[i];
  1025. X    if (p->dirp == dirp) {
  1026. X        p->dirp = (wf_dir *) 0;
  1027. X        p->filep = (wf_file *) 0;
  1028. X    }
  1029. X}
  1030. X
  1031. Xwf_file *
  1032. Xfile_new(name, link, filetype, nlink, mode, uid, gid, size, time, fileid, fsid)
  1033. Xchar *name, *link;
  1034. Xftype filetype;
  1035. Xu_int nlink, mode, uid, gid, fsid;
  1036. Xlong size, time, fileid;
  1037. X{
  1038. X    wf_file *filep = ALLOC(wf_file);
  1039. X    filep->name = name;
  1040. X    filep->crc = updcrc(0L, filep->name, strlen(filep->name)+1);
  1041. X    filep->link = link;
  1042. X    if (fileid == 0) {
  1043. X        filep->id = filep->fattr.fileid = filep->crc;
  1044. X    } else {
  1045. X        filep->id = filep->fattr.fileid = fileid;
  1046. X    }
  1047. X
  1048. X    filep->fattr.type = filetype;
  1049. X    filep->fattr.mode = mode;
  1050. X    filep->fattr.mode |= type2mode[filetype];
  1051. X    filep->fattr.nlink = nlink;
  1052. X    filep->fattr.uid = uid;
  1053. X    filep->fattr.gid = gid;
  1054. X    filep->fattr.size = size;
  1055. X    filep->fattr.blocksize = 8192;
  1056. X    filep->fattr.blocks = compute_blocks(filep->fattr.size);
  1057. X    filep->fattr.fsid = fsid;
  1058. X    filep->fattr.atime.seconds = filep->fattr.mtime.seconds
  1059. X        = filep->fattr.ctime.seconds = time;
  1060. X    return filep;
  1061. X}
  1062. X
  1063. Xvoid
  1064. Xattr_initdir(attrp)
  1065. Xfattr *attrp;
  1066. X{
  1067. X    attrp->nlink = 2;        /* should be updated later */
  1068. X    attrp->type = NFDIR;
  1069. X    attrp->mode = 0755;
  1070. X    attrp->mode |= type2mode[attrp->type];
  1071. X    attrp->size = 512;
  1072. X    attrp->blocksize = 8192;
  1073. X    attrp->blocks = compute_blocks(attrp->size);
  1074. X}
  1075. X
  1076. Xvoid
  1077. Xattr_initfile(attrp, size)
  1078. Xfattr *attrp;
  1079. Xlong size;
  1080. X{
  1081. X    attrp->type = NFREG;
  1082. X    attrp->mode = 0644;
  1083. X    attrp->mode |= type2mode[attrp->type];
  1084. X    attrp->nlink = 1;
  1085. X    attrp->size = size;
  1086. X    attrp->blocksize = 8192;
  1087. X    attrp->blocks = compute_blocks(attrp->size);
  1088. X}
  1089. X
  1090. Xunsigned int
  1091. Xattr_touch(attrp)
  1092. Xfattr *attrp;
  1093. X{
  1094. X    return attrp->atime.seconds = attrp->mtime.seconds = gettime();
  1095. X}
  1096. X
  1097. Xwf_file *
  1098. Xfile_newvol(name)
  1099. Xchar *name;
  1100. X{
  1101. X    wf_file *filep;
  1102. X    fattr *attrp;
  1103. X
  1104. X    filep = file_alloc();
  1105. X    filep->name = strdup(name);
  1106. X    filep->crc = updcrc(0L, name, strlen(name)+1);
  1107. X    attrp = &filep->fattr;
  1108. X    attr_initdir(attrp);
  1109. X    attr_touch(attrp);
  1110. X    return filep;
  1111. X}
  1112. X
  1113. X/* find file by (filesystem id, file id). */
  1114. Xwf_file *
  1115. Xfile_findid(dirp, fsid, fileid)
  1116. Xwf_dir *dirp;
  1117. Xlong fsid, fileid;
  1118. X{
  1119. X    wf_file *filep;
  1120. X    qelem *q_head = &dirp->file->q;
  1121. X    fcache *p;
  1122. X
  1123. X    /*
  1124. X     * lookup cache
  1125. X     */
  1126. X    /* getattr operations are likely to be performed sequentially. */
  1127. X    p = &findid_cache[dirp->id % WF_FILE_HASHSIZE];
  1128. X    if (p->filep && p->dirp == dirp) {
  1129. X        filep = NEXT(wf_file, p->filep);
  1130. X        if (filep != HEAD(wf_file, q_head)
  1131. X            && FID(filep) == fileid && FSID(filep) == fsid) {
  1132. X            p->filep = filep;
  1133. X            return filep;
  1134. X        } else {
  1135. X            p->filep = (wf_file *) 0;    /* stale */
  1136. X        }
  1137. X    }
  1138. X
  1139. X    /*
  1140. X     * resort to exhaustive search
  1141. X     */
  1142. X    ITER(filep, wf_file, q_head) {
  1143. X        if (FID(filep) == fileid && FSID(filep) == fsid) {
  1144. X            p->filep = filep;
  1145. X            p->dirp = dirp;
  1146. X            return filep;
  1147. X        }
  1148. X    }
  1149. X    return NULL;
  1150. X}
  1151. X
  1152. X/* find file by filename. */
  1153. Xwf_file *
  1154. Xfile_findname(dirp, name)
  1155. Xwf_dir *dirp;
  1156. Xchar *name;
  1157. X{
  1158. X    wf_file *filep;
  1159. X    qelem *q_head = &dirp->file->q;
  1160. X    u_int crc;
  1161. X    fcache *p;
  1162. X
  1163. X    /*
  1164. X     * lookup cache
  1165. X     */
  1166. X    /* lookup operations are likely to be performed sequentially.
  1167. X     * we declare another hashtable for fine tuning.
  1168. X     */
  1169. X    p = &findname_cache[dirp->id % WF_FILE_HASHSIZE];
  1170. X    if (p->filep && p->dirp == dirp) {
  1171. X        filep = NEXT(wf_file, p->filep);
  1172. X        if (filep != HEAD(wf_file, q_head)
  1173. X            && strcmp(filep->name, name) == 0) {
  1174. X            p->filep = filep;
  1175. X            return filep;
  1176. X        } else {
  1177. X            p->filep = (wf_file *) 0;    /* stale */
  1178. X        }
  1179. X    }
  1180. X
  1181. X    /*
  1182. X     * resort to exhaustive search
  1183. X     */
  1184. X    crc = updcrc(0L, name, strlen(name)+1);
  1185. X    ITER(filep, wf_file, q_head) {
  1186. X        if (crc == filep->crc
  1187. X            && strcmp(filep->name, name) == 0) {
  1188. X            p->filep = filep;
  1189. X            p->dirp = dirp;
  1190. X            return filep;
  1191. X        }
  1192. X    }
  1193. X    return NULL;
  1194. X}
  1195. X
  1196. Xint
  1197. Xfile_recv_init(volp, dirp, filep)
  1198. Xwf_vol *volp;
  1199. Xwf_dir *dirp;
  1200. Xwf_file *filep;
  1201. X{
  1202. X    int fd;
  1203. X    char path[MAXPATHLEN];
  1204. X
  1205. X    sprintf(path, "%s/ongoing/xfer.%lx.%lx.%s", cs_topdir,
  1206. X        volp->id, dirp->id, filep->name);
  1207. X    fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0660);
  1208. X    if (fd < 0)
  1209. X        dlog("ftp_recv_init: couldn't create file");
  1210. X    return fd;
  1211. X}
  1212. X
  1213. Xvoid
  1214. Xfile_recv_finish(volp, dirp, filep)
  1215. Xwf_vol *volp;
  1216. Xwf_dir *dirp;
  1217. Xwf_file *filep;
  1218. X{
  1219. X    char path[MAXPATHLEN], path2[MAXPATHLEN];
  1220. X
  1221. X    sprintf(path, "%s/ongoing/xfer.%lx.%lx.%s", cs_topdir,
  1222. X        volp->id, dirp->id, filep->name);
  1223. X    file_getpath(path2, volp, dirp, filep);
  1224. X    if (mkdirs(path2))
  1225. X        dir_realdir(path2, volp, dirp);
  1226. X    rename(path, path2);
  1227. X}
  1228. X
  1229. Xvoid
  1230. Xfile_recv_abort(volp, dirp, filep)
  1231. Xwf_vol *volp;
  1232. Xwf_dir *dirp;
  1233. Xwf_file *filep;
  1234. X{
  1235. X    char path[MAXPATHLEN], path2[MAXPATHLEN];
  1236. X
  1237. X    sprintf(path, "%s/ongoing/xfer.%lx.%lx.%s", cs_topdir,
  1238. X        volp->id, dirp->id, filep->name);
  1239. X    sprintf(path2, "%s/stale/%s.%d/xfer.%lx.%lx.%s",
  1240. X        cs_topdir, cs_date, cs_serial,
  1241. X        volp->id, dirp->id, filep->name);
  1242. X    mkdirs(path2);
  1243. X    rename(path, path2);
  1244. X}
  1245. X
  1246. Xvoid
  1247. Xfile_getpath(buf, volp, dirp, filep)
  1248. Xchar *buf;
  1249. Xwf_vol *volp;
  1250. Xwf_dir *dirp;
  1251. Xwf_file *filep;
  1252. X{
  1253. X    if (volp->flag & WF_VOL_DIRECTFILE) {
  1254. X        sprintf(buf, "%s/%s/%s",
  1255. X            volp->topdir, dirp->name, filep->name);
  1256. X    } else {
  1257. X        sprintf(buf, "%s/cache/%lx/%lx/%s",
  1258. X            cs_topdir, volp->id, dirp->id, filep->name);
  1259. X    }
  1260. X}
  1261. X
  1262. X/* see if file is cached. */
  1263. Xbool_t
  1264. Xfile_findcache(volp, dirp, filep)
  1265. Xwf_vol *volp;
  1266. Xwf_dir *dirp;
  1267. Xwf_file *filep;
  1268. X{
  1269. X    struct stat s;
  1270. X    char path[MAXPATHLEN];
  1271. X
  1272. X    file_getpath(path, volp, dirp, filep);
  1273. X    if (stat(path, &s) < 0)
  1274. X        return -1;
  1275. X    if (! (s.st_mode & S_IREAD) || (s.st_mode & S_IFMT) != S_IFREG)
  1276. X        return -1;
  1277. X    if (! (filep->flag & WF_FILE_MUTABLE)
  1278. X        && s.st_size != filep->fattr.size) {
  1279. X        /* XXX: update policy */
  1280. X        file_dispose(volp, dirp, filep);
  1281. X        return -1;
  1282. X    }
  1283. X    return 0;
  1284. X}
  1285. X
  1286. X/* make that file stale. */
  1287. Xvoid
  1288. Xfile_dispose(volp, dirp, filep)
  1289. Xwf_vol *volp;
  1290. Xwf_dir *dirp;
  1291. Xwf_file *filep;
  1292. X{
  1293. X    char path[MAXPATHLEN], path2[MAXPATHLEN];
  1294. X
  1295. X    file_getpath(path, volp, dirp, filep);
  1296. X    sprintf(path2, "%s/stale/%s.%d/file.%lx.%lx.%s",
  1297. X        cs_topdir, cs_date, cs_serial,
  1298. X        volp->id, dirp->id, filep->name);
  1299. X    mkdirs(path2);
  1300. X    rename(path, path2);
  1301. X}
  1302. X
  1303. X/* WWUIP DIAG */
  1304. Xvoid
  1305. Xfile_inspect(reqp, name)
  1306. Xwf_req *reqp;
  1307. Xchar *name;
  1308. X{
  1309. X    int id = reqp->id;
  1310. X    int ret;
  1311. X    wf_ih ih;
  1312. X
  1313. X    ret = root_name2ih(name, &ih);
  1314. X    if (ret != WF_REP_OK) {
  1315. X        req_send(reqp, "513.%03d root_name2ih: error code %d.\n",
  1316. X             id, ret);
  1317. X        return;
  1318. X    }
  1319. X    req_send(reqp, "220-%03d fil %s\n", id, name);
  1320. X    req_send(reqp, "213-%03d name = %s\n", id, PROT(ih.filep->name));
  1321. X    req_send(reqp, "213-%03d link = %s\n", id, PROT(ih.filep->link));
  1322. X    req_send(reqp, "213-%03d id = %lx\n", id, ih.filep->id);
  1323. X    req_send(reqp, "213-%03d crc = %lx\n", id, ih.filep->crc);
  1324. X    req_send(reqp, "213-%03d flag = %x\n", id, ih.filep->flag);
  1325. X    req_send(reqp, "213-%03d type = %lx\n", id, ih.filep->fattr.type);
  1326. X    req_send(reqp, "213-%03d fsid = %lx\n", id, ih.filep->fattr.fsid);
  1327. X    req_send(reqp, "213.%03d fileid = %lx\n", id, ih.filep->fattr.fileid);
  1328. X}
  1329. X
  1330. END_OF_FILE
  1331.   if test 9197 -ne `wc -c <'csd/file.c'`; then
  1332.     echo shar: \"'csd/file.c'\" unpacked with wrong size!
  1333.   fi
  1334.   # end of 'csd/file.c'
  1335. fi
  1336. if test -f 'csd/nfs_subr.c' -a "${1}" != "-c" ; then 
  1337.   echo shar: Will not clobber existing file \"'csd/nfs_subr.c'\"
  1338. else
  1339.   echo shar: Extracting \"'csd/nfs_subr.c'\" \(10559 characters\)
  1340.   sed "s/^X//" >'csd/nfs_subr.c' <<'END_OF_FILE'
  1341. X/* 
  1342. X * WorldWide File System
  1343. X * Copyright (c) 1992,1993 Youki Kadobayashi
  1344. X * Copyright (c) 1992,1993 Osaka University
  1345. X * All rights reserved.
  1346. X *
  1347. X * Permission to use, copy, modify and distribute this software and its
  1348. X * documentation is hereby granted, provided that the following conditions
  1349. X * are met:
  1350. X * 1. Both the copyright notice and this permission notice appear in
  1351. X *    all copies of the software, derivative works or modified versions,
  1352. X *    and any portions thereof, and that both notices appear in
  1353. X *    supporting documentation.
  1354. X * 2. All advertising materials mentioning features or use of this software
  1355. X *    must display the following acknowledgement:
  1356. X *      This product includes software developed by the Osaka University
  1357. X *      and its contributors.
  1358. X * 3. Neither the name of the University nor the names of its contributors
  1359. X *    may be used to endorse or promote products derived from this software
  1360. X *    without specific prior written permission.
  1361. X *
  1362. X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
  1363. X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  1364. X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  1365. X *
  1366. X * Osaka University requests users of this software to return to
  1367. X *
  1368. X *  Youki Kadobayashi
  1369. X *  Department of Information and Computer Sciences
  1370. X *  Osaka University, Toyonaka 560, Osaka, Japan
  1371. X *
  1372. X * any improvements or extensions that they make and grant Osaka
  1373. X * University the rights to redistribute these changes.
  1374. X */
  1375. X/* nfsproc_whatever_2 */
  1376. Xstatic char *AtFSid = "$Header: nfs_subr.c[109.0] Wed Nov 24 03:47:14 1993 youki-k@is.aist-nara.ac.jp saved $";
  1377. X
  1378. X#include "wfs.h"
  1379. X#include "util.h"
  1380. X#include "global.h"
  1381. X
  1382. X#define NFS
  1383. X#define NFSCLIENT
  1384. X#ifdef NFS_3
  1385. Xtypedef nfs_fh fhandle_t;
  1386. X#endif /* NFS_3 */
  1387. X#include <sys/mount.h>        /* for struct statfs */
  1388. X#ifdef STATFS_HDR
  1389. X#include STATFS_HDR        /* for struct statfs */
  1390. X#endif /* STATFS_HDR */
  1391. X
  1392. Xstatic void
  1393. Xclient_info(c)
  1394. Xwf_thrd *c;
  1395. X{
  1396. X    struct authunix_parms *unix_cred;
  1397. X    sockaddr_in *sin;
  1398. X
  1399. X    if (c->rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
  1400. X        unix_cred = (struct authunix_parms *) c->rqstp->rq_clntcred;
  1401. X        c->uid = unix_cred->aup_uid;
  1402. X    }
  1403. X    sin = svc_getcaller(c->rqstp->rq_xprt);
  1404. X    c->client = sin->sin_addr.s_addr;
  1405. X}
  1406. X
  1407. Xvoid *
  1408. Xnfsproc_null_2(argp, rqstp)
  1409. Xvoid *argp;
  1410. Xsvc_req *rqstp;
  1411. X{
  1412. X    static char res;
  1413. X    return (void *) &res;
  1414. X}
  1415. X
  1416. Xattrstat *
  1417. Xnfsproc_getattr_2(argp, rqstp)
  1418. Xnfs_fh *argp;
  1419. Xsvc_req *rqstp;
  1420. X{
  1421. X    wf_thrd *c;
  1422. X    static attrstat res;
  1423. X    wf_fh *fhp = (wf_fh *)argp;
  1424. X    wf_vol *parent_volp, *child_volp;
  1425. X
  1426. X    /* auth */
  1427. X    if (fhp->world_id != cs_world) {
  1428. X        bzero(&res, sizeof(res));
  1429. X        res.status = NFSERR_ACCES;
  1430. X        return &res;
  1431. X    }
  1432. X
  1433. X    parent_volp = vol_findid(fhp->parent_vol);
  1434. X    if (fhp->parent_vol == fhp->child_vol)
  1435. X        child_volp = parent_volp;
  1436. X    else
  1437. X        child_volp = vol_findid(fhp->child_vol);
  1438. X    if (parent_volp == NULL || child_volp == NULL) {
  1439. X        bzero(&res, sizeof(res));
  1440. X        res.status = NFSERR_STALE;
  1441. X        return &res;
  1442. X    }
  1443. X    c = thrd_alloc();
  1444. X    c->rqstp = CLONE(rqstp);
  1445. X    c->parent_volp = parent_volp;
  1446. X    c->child_volp = child_volp;
  1447. X    c->fhp = fhp;
  1448. X    c->reply = nfs_getattr_reply;
  1449. X    proto_getattr(c);
  1450. X    return (attrstat *)0;
  1451. X}
  1452. X
  1453. Xattrstat *
  1454. Xnfsproc_setattr_2(argp, rqstp)
  1455. Xsattrargs *argp;
  1456. Xsvc_req *rqstp;
  1457. X{
  1458. X    static attrstat res;
  1459. X    bzero(&res, sizeof(res));
  1460. X    res.status = NFSERR_ROFS;
  1461. X    return &res;
  1462. X}
  1463. X
  1464. Xvoid *
  1465. Xnfsproc_root_2(argp, rqstp)
  1466. Xvoid *argp;
  1467. Xsvc_req *rqstp;
  1468. X{
  1469. X    static char res;
  1470. X    return (void *) &res;
  1471. X}
  1472. X
  1473. Xdiropres *
  1474. Xnfsproc_lookup_2(argp, rqstp)
  1475. Xdiropargs *argp;
  1476. Xsvc_req *rqstp;
  1477. X{
  1478. X    wf_thrd *c;
  1479. X    static diropres res;
  1480. X    wf_fh *fhp = (wf_fh *) &argp->dir;
  1481. X    wf_vol *parent_volp, *child_volp;
  1482. X
  1483. X    /* auth */
  1484. X    if (fhp->world_id != cs_world) {
  1485. X        bzero(&res, sizeof(res));
  1486. X        res.status = NFSERR_ACCES;
  1487. X        return &res;
  1488. X    }
  1489. X
  1490. X    parent_volp = vol_findid(fhp->parent_vol);
  1491. X    if (fhp->parent_vol == fhp->child_vol)
  1492. X        child_volp = parent_volp;
  1493. X    else
  1494. X        child_volp = vol_findid(fhp->child_vol);
  1495. X    if (parent_volp == NULL || child_volp == NULL) {
  1496. X        bzero(&res, sizeof(res));
  1497. X        res.status = NFSERR_STALE;
  1498. X        return &res;
  1499. X    }
  1500. X    c = thrd_alloc();
  1501. X    c->rqstp = CLONE(rqstp);
  1502. X    c->parent_volp = parent_volp;
  1503. X    c->child_volp = child_volp;
  1504. X    c->fhp = fhp;
  1505. X    c->fname = argp->name;
  1506. X    c->reply = nfs_lookup_reply;
  1507. X    client_info(c);
  1508. X    /*
  1509. X     * gross hack
  1510. X     */
  1511. X    if (! (c->fname[0] == '.' && strncmp(c->fname, ".wwfs_", 6) == 0)) {
  1512. X        proto_lookup(c);
  1513. X        return (diropres *)0;
  1514. X    } else {
  1515. X        wf_fh *resfhp;
  1516. X        int ret;
  1517. X        /*
  1518. X         * Strict specification of NFS was successful in that it
  1519. X         * prohibited vendors to add diverse features.
  1520. X         * Meanwhile, the strictness necessitates brute force
  1521. X         * solution, which is much more uglier than ioctl()...
  1522. X         * I have long-term solution in mind however.
  1523. X         */
  1524. X        c->resfhp = resfhp = CLONE(fhp);
  1525. X#if 0
  1526. X        if (strcmp(c->fname + 6, "host") == 0) {
  1527. X            resfhp->child_vol = WF_HOST_VOL_ID;
  1528. X        } else if (strcmp(c->fname + 6, "cwd") == 0) {
  1529. X            resfhp->child_vol = WF_CWD_VOL_ID;
  1530. X        }
  1531. X#else
  1532. X        if (strcmp(c->fname + 6, "fh") == 0) {
  1533. X            resfhp->child_vol = WF_FH_VOL_ID;
  1534. X        }
  1535. X#endif
  1536. X        else {
  1537. X            FREE(resfhp);
  1538. X            bzero(&res, sizeof(res));
  1539. X            res.status = NFSERR_NOENT;
  1540. X            return &res;
  1541. X        }
  1542. X        resfhp->parent_vol = fhp->child_vol;
  1543. X        ret = cwd_fake(c, resfhp);
  1544. X        nfs_lookup_reply(c, ret);
  1545. X        FREE(resfhp);
  1546. X        return (diropres *)0;
  1547. X    }
  1548. X}
  1549. X
  1550. Xreadlinkres *
  1551. Xnfsproc_readlink_2(argp, rqstp)
  1552. Xnfs_fh *argp;
  1553. Xsvc_req *rqstp;
  1554. X{
  1555. X    wf_thrd *c;
  1556. X    static readlinkres res;
  1557. X    wf_fh *fhp = (wf_fh *)argp;
  1558. X    wf_vol *parent_volp, *child_volp;
  1559. X
  1560. X    /* auth */
  1561. X    if (fhp->world_id != cs_world) {
  1562. X        bzero(&res, sizeof(res));
  1563. X        res.status = NFSERR_ACCES;
  1564. X        return &res;
  1565. X    }
  1566. X
  1567. X    parent_volp = vol_findid(fhp->parent_vol);
  1568. X    if (fhp->parent_vol == fhp->child_vol)
  1569. X        child_volp = parent_volp;
  1570. X    else
  1571. X        child_volp = vol_findid(fhp->child_vol);
  1572. X    if (parent_volp == NULL || child_volp == NULL) {
  1573. X        bzero(&res, sizeof(res));
  1574. X        res.status = NFSERR_STALE;
  1575. X        return &res;
  1576. X    }
  1577. X    c = thrd_alloc();
  1578. X    c->rqstp = CLONE(rqstp);
  1579. X    c->parent_volp = parent_volp;
  1580. X    c->child_volp = child_volp;
  1581. X    c->fhp = fhp;
  1582. X    c->reply = nfs_readlink_reply;
  1583. X    proto_readlink(c);
  1584. X    return (readlinkres *)0;
  1585. X}
  1586. X
  1587. Xreadres *
  1588. Xnfsproc_read_2(argp, rqstp)
  1589. Xreadargs *argp;
  1590. Xsvc_req *rqstp;
  1591. X{
  1592. X    wf_thrd *c;
  1593. X    static readres res;
  1594. X    wf_fh *fhp = (wf_fh *) &argp->file;
  1595. X    wf_vol *parent_volp, *child_volp;
  1596. X
  1597. X    /* auth */
  1598. X    if (fhp->world_id != cs_world) {
  1599. X        bzero(&res, sizeof(res));
  1600. X        res.status = NFSERR_ACCES;
  1601. X        return &res;
  1602. X    }
  1603. X
  1604. X    parent_volp = vol_findid(fhp->parent_vol);
  1605. X    if (fhp->parent_vol == fhp->child_vol)
  1606. X        child_volp = parent_volp;
  1607. X    else
  1608. X        child_volp = vol_findid(fhp->child_vol);
  1609. X    if (parent_volp == NULL || child_volp == NULL) {
  1610. X        bzero(&res, sizeof(res));
  1611. X        res.status = NFSERR_STALE;
  1612. X        return &res;
  1613. X    }
  1614. X    c = thrd_alloc();
  1615. X    c->rqstp = CLONE(rqstp);
  1616. X    c->parent_volp = parent_volp;
  1617. X    c->child_volp = child_volp;
  1618. X    c->fhp = fhp;
  1619. X    c->offset = argp->offset;
  1620. X    c->count = argp->count;
  1621. X    c->totalcount = argp->totalcount;
  1622. X    c->reply = nfs_read_done;
  1623. X    client_info(c);
  1624. X    proto_read(c);
  1625. X    return (readres *)0;
  1626. X}
  1627. X
  1628. Xvoid *
  1629. Xnfsproc_writecache_2(argp, rqstp)
  1630. Xvoid *argp;
  1631. Xsvc_req *rqstp;
  1632. X{
  1633. X    static char res;
  1634. X    return (void *)&res;
  1635. X}
  1636. X
  1637. Xattrstat *
  1638. Xnfsproc_write_2(argp, rqstp)
  1639. Xwriteargs *argp;
  1640. Xsvc_req *rqstp;
  1641. X{
  1642. X    static attrstat res;
  1643. X    bzero(&res, sizeof(res));
  1644. X    res.status = NFSERR_ROFS;
  1645. X    return &res;
  1646. X}
  1647. X
  1648. Xdiropres *
  1649. Xnfsproc_create_2(argp, rqstp)
  1650. Xcreateargs *argp;
  1651. Xsvc_req *rqstp;
  1652. X{
  1653. X    static diropres res;
  1654. X    bzero(&res, sizeof(res));
  1655. X    res.status = NFSERR_ROFS;
  1656. X    return &res;
  1657. X}
  1658. X
  1659. Xnfsstat *
  1660. Xnfsproc_remove_2(argp, rqstp)
  1661. Xdiropargs *argp;
  1662. Xsvc_req *rqstp;
  1663. X{
  1664. X    static nfsstat res;
  1665. X    bzero(&res, sizeof(res));
  1666. X    res = NFSERR_ROFS;
  1667. X    return &res;
  1668. X}
  1669. X
  1670. Xnfsstat *
  1671. Xnfsproc_rename_2(argp, rqstp)
  1672. Xrenameargs *argp;
  1673. Xsvc_req *rqstp;
  1674. X{
  1675. X    static nfsstat res;
  1676. X    bzero(&res, sizeof(res));
  1677. X    res = NFSERR_ROFS;
  1678. X    return &res;
  1679. X}
  1680. X
  1681. Xnfsstat *
  1682. Xnfsproc_link_2(argp, rqstp)
  1683. Xlinkargs *argp;
  1684. Xsvc_req *rqstp;
  1685. X{
  1686. X    static nfsstat res;
  1687. X    bzero(&res, sizeof(res));
  1688. X    res = NFSERR_ROFS;
  1689. X    return &res;
  1690. X}
  1691. X
  1692. Xnfsstat *
  1693. Xnfsproc_symlink_2(argp, rqstp)
  1694. Xsymlinkargs *argp;
  1695. Xsvc_req *rqstp;
  1696. X{
  1697. X    static nfsstat res;
  1698. X    bzero(&res, sizeof(res));
  1699. X    res = NFSERR_ROFS;
  1700. X    return &res;
  1701. X}
  1702. X
  1703. Xdiropres *
  1704. Xnfsproc_mkdir_2(argp, rqstp)
  1705. Xcreateargs *argp;
  1706. Xsvc_req *rqstp;
  1707. X{
  1708. X    static diropres res;
  1709. X    bzero(&res, sizeof(res));
  1710. X    res.status = NFSERR_ROFS;
  1711. X    return &res;
  1712. X}
  1713. X
  1714. Xnfsstat *
  1715. Xnfsproc_rmdir_2(argp, rqstp)
  1716. Xdiropargs *argp;
  1717. Xsvc_req *rqstp;
  1718. X{
  1719. X    static nfsstat res;
  1720. X    bzero(&res, sizeof(res));
  1721. X    res = NFSERR_ROFS;
  1722. X    return &res;
  1723. X}
  1724. X
  1725. Xreaddirres *
  1726. Xnfsproc_readdir_2(argp, rqstp)
  1727. Xreaddirargs *argp;
  1728. Xsvc_req *rqstp;
  1729. X{
  1730. X    wf_thrd *c;
  1731. X    static readdirres res;
  1732. X    wf_fh *fhp = (wf_fh *) &argp->dir;
  1733. X    wf_vol *parent_volp, *child_volp;
  1734. X
  1735. X    bzero(&res, sizeof(res));
  1736. X    /* auth */
  1737. X    if (fhp->world_id != cs_world) {
  1738. X        res.status = NFSERR_ACCES;
  1739. X        return &res;
  1740. X    }
  1741. X
  1742. X    parent_volp = vol_findid(fhp->parent_vol);
  1743. X    if (fhp->parent_vol == fhp->child_vol)
  1744. X        child_volp = parent_volp;
  1745. X    else
  1746. X        child_volp = vol_findid(fhp->child_vol);
  1747. X    if (parent_volp == NULL || child_volp == NULL) {
  1748. X        bzero(&res, sizeof(res));
  1749. X        res.status = NFSERR_STALE;
  1750. X        return &res;
  1751. X    }
  1752. X    c = thrd_alloc();
  1753. X    c->rqstp = CLONE(rqstp);
  1754. X    c->parent_volp = parent_volp;
  1755. X    c->child_volp = child_volp;
  1756. X    c->fhp = fhp;
  1757. X    bcopy(argp->cookie, c->cookie, sizeof(nfscookie));
  1758. X    c->count = argp->count;
  1759. X    c->reply = nfs_readdir_done;
  1760. X    client_info(c);
  1761. X    /*
  1762. X     * access control (only when access control file is present)
  1763. X     */
  1764. X    if (parent_volp->accp
  1765. X        && acc_check(parent_volp->accp, c->client, WF_ACC_NFS) < 0) {
  1766. X        (*c->reply)(c, WF_ERR_ACCES);
  1767. X        return (readdirres *)0;
  1768. X    }
  1769. X    proto_readdir(c);
  1770. X    return (readdirres *)0;
  1771. X}
  1772. X
  1773. Xstatfsres *
  1774. Xnfsproc_statfs_2(argp, rqstp)
  1775. Xnfs_fh *argp;
  1776. Xsvc_req *rqstp;
  1777. X{
  1778. X    static statfsres res;
  1779. X    wf_fh *fhp = (wf_fh *) argp;
  1780. X#ifdef ULTRIX_HACK
  1781. X    struct fs_data buf;
  1782. X#else /* ULTRIX_HACK */
  1783. X    struct statfs buf;
  1784. X#endif /* ULTRIX_HACK */
  1785. X
  1786. X    bzero(&res, sizeof(res));
  1787. X    /* auth */
  1788. X    if (fhp->world_id != cs_world) {
  1789. X        res.status = NFSERR_ACCES;
  1790. X        return &res;
  1791. X    }
  1792. X
  1793. X    /* statfs cache partition */
  1794. X    statfs(cs_topdir, &buf);
  1795. X    res.status = NFS_OK;
  1796. X    res.statfsres_u.reply.tsize = NFS_MAXDATA;
  1797. X#ifdef ULTRIX_HACK
  1798. X    res.statfsres_u.reply.bsize = buf.fd_bsize;
  1799. X    res.statfsres_u.reply.blocks = buf.fd_btot / (buf.fd_bsize / 1024);
  1800. X    res.statfsres_u.reply.bfree = buf.fd_bfree / (buf.fd_bsize / 1024);
  1801. X    res.statfsres_u.reply.bavail = buf.fd_bfreen / (buf.fd_bsize / 1024);
  1802. X#else /* ULTRIX_HACK */
  1803. X    res.statfsres_u.reply.bsize = buf.f_bsize;
  1804. X    res.statfsres_u.reply.blocks = buf.f_blocks;
  1805. X    res.statfsres_u.reply.bfree = buf.f_bfree;
  1806. X#ifdef sgi    /* or HAS_BAVAIL? */
  1807. X    /* return estimated 95% figure */
  1808. X    res.statfsres_u.reply.bavail = buf.f_bfree - (buf.f_bfree / 20);
  1809. X#else /* sgi */
  1810. X    res.statfsres_u.reply.bavail = buf.f_bavail;
  1811. X#endif /* sgi */
  1812. X#endif /* ULTRIX_HACK */
  1813. X    return (statfsres *)&res;
  1814. X}
  1815. X
  1816. END_OF_FILE
  1817.   if test 10559 -ne `wc -c <'csd/nfs_subr.c'`; then
  1818.     echo shar: \"'csd/nfs_subr.c'\" unpacked with wrong size!
  1819.   fi
  1820.   # end of 'csd/nfs_subr.c'
  1821. fi
  1822. if test -f 'csd/util.c' -a "${1}" != "-c" ; then 
  1823.   echo shar: Will not clobber existing file \"'csd/util.c'\"
  1824. else
  1825.   echo shar: Extracting \"'csd/util.c'\" \(8875 characters\)
  1826.   sed "s/^X//" >'csd/util.c' <<'END_OF_FILE'
  1827. X/* 
  1828. X * WorldWide File System
  1829. X * Copyright (c) 1992,1993 Youki Kadobayashi
  1830. X * Copyright (c) 1992,1993 Osaka University
  1831. X * All rights reserved.
  1832. X *
  1833. X * Permission to use, copy, modify and distribute this software and its
  1834. X * documentation is hereby granted, provided that the following conditions
  1835. X * are met:
  1836. X * 1. Both the copyright notice and this permission notice appear in
  1837. X *    all copies of the software, derivative works or modified versions,
  1838. X *    and any portions thereof, and that both notices appear in
  1839. X *    supporting documentation.
  1840. X * 2. All advertising materials mentioning features or use of this software
  1841. X *    must display the following acknowledgement:
  1842. X *      This product includes software developed by the Osaka University
  1843. X *      and its contributors.
  1844. X * 3. Neither the name of the University nor the names of its contributors
  1845. X *    may be used to endorse or promote products derived from this software
  1846. X *    without specific prior written permission.
  1847. X *
  1848. X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
  1849. X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  1850. X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  1851. X *
  1852. X * Osaka University requests users of this software to return to
  1853. X *
  1854. X *  Youki Kadobayashi
  1855. X *  Department of Information and Computer Sciences
  1856. X *  Osaka University, Toyonaka 560, Osaka, Japan
  1857. X *
  1858. X * any improvements or extensions that they make and grant Osaka
  1859. X * University the rights to redistribute these changes.
  1860. X */
  1861. Xstatic char *AtFSid = "$Header: util.c[109.2] Sun Dec 19 02:49:00 1993 youki-k@is.aist-nara.ac.jp saved $";
  1862. X
  1863. X#include <sys/types.h>
  1864. X#include <sys/file.h>        /* R_OK */
  1865. X#include <sys/stat.h>        /* for struct stat */
  1866. X#ifndef R_OK
  1867. X#include <unistd.h>
  1868. X#endif
  1869. X#include <string.h>        /* for strchr */
  1870. X#ifdef __STDC__
  1871. X#include <stdarg.h>
  1872. X#else
  1873. X#include <varargs.h>
  1874. X#endif
  1875. X#include "wfs.h"
  1876. X#include "global.h"
  1877. X#include "util.h"
  1878. X
  1879. X/* queue manipulation functions */
  1880. Xqelem *
  1881. Xq_alloc()
  1882. X{
  1883. X    qelem *q;
  1884. X    q = (qelem *) ALLOC(qelem);
  1885. X    q->q_forw = q->q_back = q;
  1886. X    return q;
  1887. X}
  1888. X
  1889. Xvoid
  1890. Xq_insert(elem, pred)
  1891. Xqelem *elem, *pred;
  1892. X{
  1893. X    qelem *p = pred->q_forw;
  1894. X    elem->q_back = pred;
  1895. X    elem->q_forw = p;
  1896. X    pred->q_forw = elem;
  1897. X    p->q_back = elem;
  1898. X}
  1899. X
  1900. Xvoid
  1901. Xq_remove(elem)
  1902. Xqelem *elem;
  1903. X{
  1904. X    qelem *p = elem->q_forw;
  1905. X    qelem *p2 = elem->q_back;
  1906. X    p2->q_forw = p;
  1907. X    p->q_back = p2;
  1908. X}
  1909. X
  1910. Xint
  1911. Xq_len(elem)
  1912. Xqelem *elem;
  1913. X{
  1914. X    qelem *p;
  1915. X    int len = 0;
  1916. X    ITER(p, qelem, elem) {
  1917. X        ++len;
  1918. X    }
  1919. X    return len;
  1920. X}
  1921. X
  1922. Xvoid
  1923. Xq_allfree(head)
  1924. Xqelem *head;
  1925. X{
  1926. X    qelem *p, *p2;
  1927. X    ITER2(p, p2, qelem, head) {
  1928. X        FREE(p);
  1929. X    }
  1930. X    head->q_forw = head;
  1931. X    head->q_back = head;
  1932. X}
  1933. X
  1934. X/* memory allocation functions */
  1935. Xvoid *
  1936. Xalloc_and_copy(db_alist        v, vlen)
  1937. Xdb_dcl
  1938. Xvoid *v;
  1939. Xint vlen;
  1940. X{
  1941. X    void *p;
  1942. X    p = debug_malloc(db_alist vlen);
  1943. X    bcopy(v, p, vlen);
  1944. X    return p;
  1945. X}
  1946. X
  1947. Xvoid *
  1948. Xalloc_and_clear(db_alist    vlen)
  1949. Xdb_dcl
  1950. Xint vlen;
  1951. X{
  1952. X    void *v;
  1953. X    v = debug_malloc(db_alist vlen);
  1954. X    bzero(v, vlen);
  1955. X    return v;
  1956. X}
  1957. X
  1958. Xvoid
  1959. Xalloc_start()
  1960. X{
  1961. X#ifdef DEBUG_MALLOC
  1962. X    char path[MAXPATHLEN];
  1963. X    union dbmalloptarg m;
  1964. X
  1965. X    sprintf(path, "%s/log/malloc.log", cs_topdir);
  1966. X    m.str = path;
  1967. X    dbmallopt(MALLOC_ERRFILE, &m);
  1968. X#endif
  1969. X}
  1970. X
  1971. X/* Dig a deep directory, if needed. Return number of mkdir calls made. */
  1972. Xint
  1973. Xmkdirs(path)
  1974. Xchar *path;
  1975. X{
  1976. X    /* strings are assumed to be writable. "-fwritable-strings" is
  1977. X     * required on some systems (e.g. NeXT).
  1978. X     */
  1979. X    char *p = path, *p2;
  1980. X    int calls = 0;
  1981. X
  1982. X    p2 = strrchr(p, '/');
  1983. X    *p2 = '\0';
  1984. X    if (access(path, W_OK|X_OK) == 0) {
  1985. X        *p2 = '/';
  1986. X        return 0;
  1987. X    }
  1988. X    *p2 = '/';
  1989. X    while(p2 = strchr(p, '/')) {
  1990. X        *p2 = '\0';
  1991. X        if (access(path, F_OK) < 0) {    /* D_OK ? */
  1992. X            mkdir(path, 0770);
  1993. X            ++calls;
  1994. X        }
  1995. X        *p2 = '/';
  1996. X        p = p2+1;
  1997. X    }
  1998. X    return calls;
  1999. X}
  2000. X
  2001. Xint
  2002. Xvalidate_dir(dir)
  2003. Xchar *dir;
  2004. X{
  2005. X    char path[MAXPATHLEN];
  2006. X    struct stat statbuf;
  2007. X
  2008. X    if (stat(dir, &statbuf) < 0) {
  2009. X        return -1;
  2010. X    }
  2011. X    if (statbuf.st_mode & S_IFDIR) {
  2012. X        sprintf(path, "%s/usr", dir);
  2013. X        if (stat(path, &statbuf) == 0) {
  2014. X            errno = EINVAL;        /* invalid argument */
  2015. X            return -1;
  2016. X        }
  2017. X    } else {
  2018. X        errno = ENOTDIR;        /* not a directory */
  2019. X        return -1;
  2020. X    }
  2021. X    return 0;
  2022. X}
  2023. X
  2024. Xvoid
  2025. Xcsd_abort(ret)
  2026. Xint ret;
  2027. X{
  2028. X    syslog(LOG_INFO, "Exiting with status %d", ret);
  2029. X    exit(ret);
  2030. X}
  2031. X
  2032. X/* create background process */
  2033. Xint
  2034. Xbackground()
  2035. X{
  2036. X    int pid, retry = 0;
  2037. X
  2038. X resume:
  2039. X    pid = fork();
  2040. X
  2041. X    /* firewall */
  2042. X    if (pid < 0 && retry < 5) {
  2043. X        sleep(1);
  2044. X        errno_diag();
  2045. X        ++retry;
  2046. X        goto resume;
  2047. X    }
  2048. X
  2049. X    /* child */
  2050. X    if (pid == 0) {
  2051. X        cs_pid = getpid();
  2052. X        foreground = 0;
  2053. X    }
  2054. X    return pid;
  2055. X}
  2056. X
  2057. X/* acquire privileged port. */
  2058. Xint
  2059. Xbind_resv_port(so, portp)
  2060. Xint so;
  2061. Xunsigned short *portp;
  2062. X{
  2063. X    struct sockaddr_in sin;
  2064. X    unsigned short port;
  2065. X    int ret;
  2066. X
  2067. X#if 0
  2068. X    bzero(&sin, sizeof(sin));
  2069. X    sin.sin_family = AF_INET;
  2070. X
  2071. X    port = IPPORT_RESERVED;
  2072. X    do {
  2073. X        --port;
  2074. X        sin.sin_port = htons(port);
  2075. X        ret = bind(so, (struct sockaddr *) &sin, sizeof (sin));
  2076. X    } while (ret < 0 && port > IPPORT_RESERVED/2);
  2077. X
  2078. X    if (ret == 0) {
  2079. X        *portp = port;
  2080. X    }
  2081. X    return ret;
  2082. X#else
  2083. X    /* Current version of csd does not require privileged port
  2084. X     * since it does not attempt to forward NFS packet, unlike amd.
  2085. X     * I guess conventional NFS server requires privileged port
  2086. X     * to authenticate request from clients.
  2087. X     */
  2088. X    port = 8000;
  2089. X    bzero(&sin, sizeof(sin));
  2090. X    sin.sin_family = AF_INET;
  2091. X    sin.sin_port = htons(port);
  2092. X    ret = bind(so, (struct sockaddr *) &sin, sizeof (sin));
  2093. X    if (ret < 0) {
  2094. X        errno_diag();
  2095. X    }
  2096. X    *portp = port;
  2097. X    return ret;
  2098. X#endif
  2099. X}
  2100. X
  2101. X/* do the printf to a stream socket. */
  2102. X#ifdef __STDC__
  2103. Xint
  2104. Xtcp_send(int so, char *fmt, ...)
  2105. X{
  2106. X    va_list ap;
  2107. X    static char buf[MAXPATHLEN + 32];
  2108. X
  2109. X    va_start(ap, fmt);
  2110. X    vsprintf(buf, fmt, ap);
  2111. X    va_end(ap);
  2112. X    return send(so, buf, strlen(buf), 0);
  2113. X}
  2114. X#else
  2115. X
  2116. Xint
  2117. Xtcp_send(va_alist)
  2118. Xva_dcl
  2119. X{
  2120. X    va_list ap;
  2121. X    int so;
  2122. X    char *fmt;
  2123. X    static char buf[MAXPATHLEN + 32];
  2124. X
  2125. X    va_start(ap);
  2126. X    so = va_arg(ap, int);
  2127. X    fmt = va_arg(ap, char *);
  2128. X    vsprintf(buf, fmt, ap);
  2129. X    va_end(ap);
  2130. X    return send(so, buf, strlen(buf), 0);
  2131. X}
  2132. X#endif
  2133. X
  2134. X/* do the printf to a stream socket. */
  2135. X#ifdef __STDC__
  2136. Xint
  2137. Xreq_send(wf_req *reqp, char *fmt, ...)
  2138. X{
  2139. X    va_list ap;
  2140. X    static char buf[MAXPATHLEN + 32];
  2141. X
  2142. X    va_start(ap, fmt);
  2143. X    vsprintf(buf, fmt, ap);
  2144. X    va_end(ap);
  2145. X#ifdef DEBUG_UIP
  2146. X    dlog("%s.%d <- %s", inet_ntoa(reqp->sin.sin_addr),
  2147. X         ntohs(reqp->sin.sin_port), buf);
  2148. X#endif
  2149. X    return sendto(reqp->so, buf, strlen(buf), 0,
  2150. X              (struct sockaddr *) &reqp->sin, sizeof(reqp->sin));
  2151. X}
  2152. X#else
  2153. X
  2154. Xint
  2155. Xreq_send(va_alist)
  2156. Xva_dcl
  2157. X{
  2158. X    va_list ap;
  2159. X    wf_req *reqp;
  2160. X    char *fmt;
  2161. X    static char buf[MAXPATHLEN + 32];
  2162. X
  2163. X    va_start(ap);
  2164. X    reqp = va_arg(ap, wf_req *);
  2165. X    fmt = va_arg(ap, char *);
  2166. X    vsprintf(buf, fmt, ap);
  2167. X    va_end(ap);
  2168. X#ifdef DEBUG_UIP
  2169. X    dlog("%s.%d <- %s", inet_ntoa(reqp->sin.sin_addr),
  2170. X         ntohs(reqp->sin.sin_port), buf);
  2171. X#endif
  2172. X    return sendto(reqp->so, buf, strlen(buf), 0,
  2173. X              (struct sockaddr *) &reqp->sin, sizeof(reqp->sin));
  2174. X}
  2175. X#endif
  2176. X
  2177. X/* daily. */
  2178. X
  2179. Xint cs_year;
  2180. Xint cs_month = -1;
  2181. Xint cs_day;
  2182. Xchar cs_date[7];
  2183. Xint cs_serial;
  2184. X
  2185. Xvoid
  2186. Xgetdate()
  2187. X{
  2188. X    struct tm *p;
  2189. X    long t = realtime();
  2190. X#ifdef TRACE
  2191. X    if (cs_month >= 0)
  2192. X        trace_report();
  2193. X#endif
  2194. X    /*
  2195. X     * set daily timer
  2196. X     */
  2197. X    dlog("daily: update time variables");
  2198. X    /* wake me up tomorrow */
  2199. X    timeout_set(t - (t % (24 * 3600)) + 24 * 3600, getdate, 0);
  2200. X
  2201. X    /*
  2202. X     * set time variables
  2203. X     */
  2204. X    p = gmtime(&t);
  2205. X    cs_year = p->tm_year;
  2206. X    cs_month = p->tm_mon;    /* beware: Jan=0, Dec=11. */
  2207. X    cs_day = p->tm_mday;
  2208. X    sprintf(cs_date, "%02d%02d%02d", cs_year, cs_month +1, cs_day);
  2209. X    cs_serial = 0;
  2210. X}
  2211. X
  2212. X/* replacement for system(). */
  2213. Xvoid
  2214. Xunix_command(cmd)
  2215. Xchar *cmd;
  2216. X{
  2217. X    char *p, *p2;
  2218. X    int i, pid, status;
  2219. X    char *arg[16];
  2220. X
  2221. X    switch (pid = fork()) {
  2222. X    case 0:
  2223. X        /* child process */
  2224. X        for (i = 0; i < NOFILE; ++i)
  2225. X            close(i);
  2226. X        for (p = cmd, i = 0; p2 = strchr(p, ' '); p = p2+1, ++i) {
  2227. X            *p2 = '\0';
  2228. X            arg[i] = p;
  2229. X        }
  2230. X        arg[i] = p;
  2231. X        arg[++i] = (char *)0;
  2232. X        execv(arg[0], arg);
  2233. X        exit(0);
  2234. X    case -1:
  2235. X        errno_diag();
  2236. X        return;
  2237. X    default:
  2238. X        /* parent process */
  2239. X        dlog(cmd);
  2240. X        wait(&status);    /* XXX async wait3 version appropriate */
  2241. X    }
  2242. X}
  2243. X
  2244. Xlong
  2245. Xcompute_blocks(size)
  2246. Xlong size;
  2247. X{
  2248. X    /* fake st_blocks */
  2249. X    return ((size + 1024) / 1024 + 1);
  2250. X}
  2251. X
  2252. X/* Basic part of tm2time came from: Atsushi Onoe <onoe@sm.sony.co.jp>
  2253. X * If your libc has mktime() function, you can use it instead.
  2254. X */
  2255. Xstatic int m2yday[] = {
  2256. X/*
  2257. X *    jan feb mar  apr may  jun  jul  aug  sep  oct  nov  dec
  2258. X *    31  28  31   30   31   30   31   31   30   31   30   31
  2259. X */
  2260. X    0,  31, 59,  90, 120, 151, 181, 212, 243, 273, 304, 334
  2261. X};
  2262. X
  2263. Xtime_t
  2264. Xtm2time(tm)
  2265. Xstruct tm *tm;
  2266. X{
  2267. X    int clock;
  2268. X
  2269. X    clock = (tm->tm_year - 70) * 365 + (tm->tm_year - 72) / 4
  2270. X        + m2yday[tm->tm_mon] + tm->tm_mday;
  2271. X    if ((tm->tm_year - 72) / 4 == 0 && tm->tm_mon < 2)
  2272. X        --clock;
  2273. X    clock *= 24;
  2274. X    clock += tm->tm_hour;
  2275. X    clock *= 60;
  2276. X    clock += tm->tm_min;
  2277. X    clock *= 60;
  2278. X    clock += tm->tm_sec;
  2279. X    return ((time_t)clock);
  2280. X}
  2281. X
  2282. X#ifndef DEBUG_MALLOC
  2283. X#if defined(NeXT) || defined(vax) || defined(ultrix) || defined(sony) || defined(luna)
  2284. Xchar *
  2285. Xstrdup(str)
  2286. XConst char *str;
  2287. X{
  2288. X    char *sp;
  2289. X    int len;
  2290. X
  2291. X    len = strlen(str);
  2292. X    sp = (char *) malloc(len+1);
  2293. X    bcopy(str, sp, len);
  2294. X    sp[len] = 0;
  2295. X
  2296. X    return sp;
  2297. X}
  2298. X#endif
  2299. X#endif
  2300. END_OF_FILE
  2301.   if test 8875 -ne `wc -c <'csd/util.c'`; then
  2302.     echo shar: \"'csd/util.c'\" unpacked with wrong size!
  2303.   fi
  2304.   # end of 'csd/util.c'
  2305. fi
  2306. if test -f 'csd/vol.c' -a "${1}" != "-c" ; then 
  2307.   echo shar: Will not clobber existing file \"'csd/vol.c'\"
  2308. else
  2309.   echo shar: Extracting \"'csd/vol.c'\" \(11167 characters\)
  2310.   sed "s/^X//" >'csd/vol.c' <<'END_OF_FILE'
  2311. X/* 
  2312. X * WorldWide File System
  2313. X * Copyright (c) 1992,1993 Youki Kadobayashi
  2314. X * Copyright (c) 1992,1993 Osaka University
  2315. X * All rights reserved.
  2316. X *
  2317. X * Permission to use, copy, modify and distribute this software and its
  2318. X * documentation is hereby granted, provided that the following conditions
  2319. X * are met:
  2320. X * 1. Both the copyright notice and this permission notice appear in
  2321. X *    all copies of the software, derivative works or modified versions,
  2322. X *    and any portions thereof, and that both notices appear in
  2323. X *    supporting documentation.
  2324. X * 2. All advertising materials mentioning features or use of this software
  2325. X *    must display the following acknowledgement:
  2326. X *      This product includes software developed by the Osaka University
  2327. X *      and its contributors.
  2328. X * 3. Neither the name of the University nor the names of its contributors
  2329. X *    may be used to endorse or promote products derived from this software
  2330. X *    without specific prior written permission.
  2331. X *
  2332. X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
  2333. X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  2334. X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  2335. X *
  2336. X * Osaka University requests users of this software to return to
  2337. X *
  2338. X *  Youki Kadobayashi
  2339. X *  Department of Information and Computer Sciences
  2340. X *  Osaka University, Toyonaka 560, Osaka, Japan
  2341. X *
  2342. X * any improvements or extensions that they make and grant Osaka
  2343. X * University the rights to redistribute these changes.
  2344. X */
  2345. X/* volume: caching, file io */
  2346. Xstatic char *AtFSid = "$Header: vol.c[109.1] Tue Nov 30 02:47:12 1993 youki-k@is.aist-nara.ac.jp saved $";
  2347. X
  2348. X#include <sys/file.h>        /* for R_OK */
  2349. X#ifndef R_OK
  2350. X#include <unistd.h>
  2351. X#endif
  2352. X#include <sys/types.h>
  2353. X#include <sys/stat.h>
  2354. X#include <stdio.h>
  2355. X#include "wfs.h"
  2356. X#include "util.h"
  2357. X#include "global.h"
  2358. X
  2359. Xextern qelem vol_head;
  2360. Xqelem vol_head = { &vol_head, &vol_head };
  2361. X
  2362. Xwf_vol *
  2363. Xvol_alloc()
  2364. X{
  2365. X    wf_vol *volp;
  2366. X    volp = ALLOC(wf_vol);
  2367. X    volp->srvq = (wf_srvq *) q_alloc();
  2368. X    volp->dirp = (wf_dir *) q_alloc();
  2369. X    q_insert(volp, &vol_head);
  2370. X    return volp;
  2371. X}
  2372. X
  2373. Xvoid
  2374. Xvol_free(volp)
  2375. Xwf_vol *volp;
  2376. X{
  2377. X    if (volp->id == 0) {
  2378. X        syslog(LOG_WARNING, "volp->id == 0");
  2379. X    }
  2380. X    free(volp->dir);
  2381. X    FREE(volp->srvq);
  2382. X    FREE(volp->dirp);
  2383. X    q_remove(volp);
  2384. X    FREE(volp);
  2385. X}
  2386. X
  2387. X/* find volume by id */
  2388. Xwf_vol *
  2389. Xvol_findid(id)
  2390. Xlong id;
  2391. X{
  2392. X    wf_vol *volp;
  2393. X
  2394. X    /* search memory cache */
  2395. X    ITER(volp, wf_vol, &vol_head) {
  2396. X        if (volp->id == id) {
  2397. X            return volp;
  2398. X        }
  2399. X    }
  2400. X    return NULL;
  2401. X}
  2402. X
  2403. X/* find volume by name */
  2404. Xwf_vol *
  2405. Xvol_findname(dir, name)
  2406. Xchar *dir, *name;
  2407. X{
  2408. X    wf_vol *volp;
  2409. X
  2410. X    /* search memory cache */
  2411. X    ITER(volp, wf_vol, &vol_head) {
  2412. X        if (strcmp(volp->dir, dir) == 0
  2413. X            && strcmp(volp->name, name) == 0) {
  2414. X            return volp;
  2415. X        }
  2416. X    }
  2417. X
  2418. X    /* search disk cache */
  2419. X    volp = vol_load(dir, name);
  2420. X    return volp;
  2421. X}
  2422. X
  2423. Xstatic wf_vol *new_volp;
  2424. Xstatic wf_srv *new_srvp;
  2425. Xstatic int dir_count, srv_count;
  2426. X
  2427. Xstatic int
  2428. Xvol_set_id(id)
  2429. Xchar *id;
  2430. X{
  2431. X    new_volp->id = atoi(id);
  2432. X    if (new_volp->id == WF_ROOT_VOL_ID) {
  2433. X        dlog("incorrect volume id");
  2434. X        return -1;
  2435. X    }
  2436. X    return 0;
  2437. X}
  2438. X
  2439. Xint
  2440. Xvol_set_name(name)
  2441. Xchar *name;
  2442. X{
  2443. X    dlog("obsolete entry: volume-name: ignored");
  2444. X    return 0;
  2445. X}
  2446. X
  2447. Xint
  2448. Xvol_set_ftp_server(hostname)
  2449. Xchar *hostname;
  2450. X{
  2451. X    if (srv_count > dir_count + 1) {
  2452. X        dlog("incorrect server-directory sequence");
  2453. X        return -1;
  2454. X    }
  2455. X    new_srvp = srv_findname(hostname);
  2456. X    if (new_srvp == (wf_srv *)0) {
  2457. X        return -1;
  2458. X    }
  2459. X    ++srv_count;
  2460. X    return 0;
  2461. X}
  2462. X
  2463. Xint
  2464. Xvol_set_ftp_directory(subdir)
  2465. Xchar *subdir;
  2466. X{
  2467. X    if (!new_srvp || dir_count > srv_count + 1) {
  2468. X        dlog("incorrect server-directory sequence");
  2469. X        return -1;
  2470. X    }
  2471. X    vol_addsrv(new_volp, new_srvp, subdir);
  2472. X    ++dir_count;
  2473. X    return 0;
  2474. X}
  2475. X
  2476. Xstatic wf_cap ftp_cap[] = {
  2477. X    { "follow", WF_FTP_FOLLOW },
  2478. X    { "nostat", WF_FTP_NOSTAT },
  2479. X    { NULL, 0 }
  2480. X};
  2481. X
  2482. Xint
  2483. Xvol_set_ftp_options(flagstr)
  2484. Xchar *flagstr;
  2485. X{
  2486. X    long flag;
  2487. X
  2488. X    if (!new_srvp) {
  2489. X        dlog("misplaced ftp-options");
  2490. X        return -1;
  2491. X    }
  2492. X    flag = parse_cap(ftp_cap, flagstr);
  2493. X    if (flag < 0) {
  2494. X        dlog("invalid ftp-options");
  2495. X        return -1;
  2496. X    }
  2497. X    new_srvp->variant = flag;
  2498. X    return 0;
  2499. X}
  2500. X
  2501. Xint
  2502. Xvol_set_ufs_directory(topdir)
  2503. Xchar *topdir;
  2504. X{
  2505. X    /*
  2506. X     * "topdir" can be either absolute or relative pathname.
  2507. X     * Relative pathname can be used to create volumes beneath
  2508. X     * WWFSDIR (assuming csd has chdir()ed there).
  2509. X     */
  2510. X    if (validate_dir(topdir) < 0) {
  2511. X        dlog("ufs-directory %s: %m", topdir);
  2512. X        return -1;
  2513. X    }
  2514. X    new_volp->flag |= WF_VOL_DIRECTFILE;
  2515. X    new_volp->topdir = strdup(topdir);
  2516. X    new_srvp = (wf_srv *)0;
  2517. X    if (MORE(&new_volp->srvq->q)) {
  2518. X        /* XXX more cleaner implementation desired but, for now, */
  2519. X        dlog("ufs-directory supercedes other server descriptions");
  2520. X    }
  2521. X    return 0;
  2522. X}
  2523. X
  2524. Xint
  2525. Xvol_set_description(desc)
  2526. Xchar *desc;
  2527. X{
  2528. X    /* simply ignore it for now */
  2529. X    return 0;
  2530. X}
  2531. X
  2532. Xstatic wf_tailor vol_tailor[] = {
  2533. X    { "volume-id", vol_set_id },
  2534. X    { "volume-name", vol_set_name },
  2535. X    { "ftp-server", vol_set_ftp_server },
  2536. X    { "ftp-directory", vol_set_ftp_directory },
  2537. X    { "ftp-options", vol_set_ftp_options },
  2538. X    { "ufs-directory", vol_set_ufs_directory },
  2539. X    { "description", vol_set_description },
  2540. X    /*
  2541. X     * just for backward compatibility...
  2542. X     */
  2543. X    { "server", vol_set_ftp_server },
  2544. X    { "directory", vol_set_ftp_directory },
  2545. X    { NULL, (int (*)())0 }
  2546. X};
  2547. X
  2548. Xint
  2549. Xvol_bind(name, value)
  2550. Xchar *name;
  2551. Xchar *value;
  2552. X{
  2553. X    return parse_tailor(vol_tailor, name, value);
  2554. X}
  2555. X
  2556. Xwf_vol *
  2557. Xvol_load(dir, name)
  2558. Xchar *dir, *name;
  2559. X{
  2560. X    char path[MAXPATHLEN];
  2561. X    struct stat statbuf;
  2562. X
  2563. X    sprintf(path, "%s/vol/%s/%s.vol", cs_topdir, dir, name);
  2564. X    if (access(path, R_OK) < 0)
  2565. X        return (wf_vol *)0;
  2566. X    stat(path, &statbuf);
  2567. X    new_srvp = (wf_srv *)0;
  2568. X    dir_count = srv_count = 0;
  2569. X    new_volp = vol_alloc();
  2570. X    new_volp->dir = strdup(dir);
  2571. X    new_volp->name = strdup(name);
  2572. X    new_volp->accp = acc_findname(dir);
  2573. X    new_volp->mtime = statbuf.st_mtime;
  2574. X
  2575. X    if (parse_conf(path, vol_bind) < 0) {
  2576. X        vol_free(new_volp);
  2577. X        return (wf_vol *)0;
  2578. X    }
  2579. X    if (new_volp->id == 0) {
  2580. X        dlog("%s: no volume id", path);
  2581. X        vol_free(new_volp);
  2582. X        return (wf_vol *)0;
  2583. X    }
  2584. X    return new_volp;
  2585. X}
  2586. X
  2587. Xvoid
  2588. Xvol_save(volp)
  2589. Xwf_vol *volp;
  2590. X{
  2591. X    FILE *fp;
  2592. X    wf_srvq *srvp;
  2593. X    char path[MAXPATHLEN];
  2594. X
  2595. X    sprintf(path, "%s/vol/%s.vol", cs_topdir, volp->name);
  2596. X    mkdirs(path);
  2597. X    fp = fopen(path, "w");
  2598. X    if (! fp) return;
  2599. X
  2600. X    /* write per volume info */
  2601. X    fprintf(fp, "volume-id:\t%d\n", volp->id);
  2602. X
  2603. X    /* write server names */
  2604. X    ITER(srvp, wf_srvq, &volp->srvq->q) {
  2605. X        /* XXX provision for other access types required */
  2606. X        fprintf(fp, "ftp-server:\t%s\n", srvp->srv->name);
  2607. X        fprintf(fp, "ftp-directory:\t%s\n", srvp->info);
  2608. X    }
  2609. X    fclose(fp);
  2610. X}
  2611. X
  2612. Xwf_conn *
  2613. Xvol_getconn(volp)
  2614. Xwf_vol *volp;
  2615. X{
  2616. X    wf_conn *cp;
  2617. X    wf_srvq *srvq;
  2618. X
  2619. X    if (volp->nconn < WF_VOL_MAXCONN) {
  2620. X        volp->flag &= ~WF_VOL_XCONN;
  2621. X        srvq = pol_select_srv(volp);
  2622. X        cp = srv_getconn(srvq);
  2623. X        if (cp) {
  2624. X            ++volp->nconn;
  2625. X            return cp;
  2626. X        }
  2627. X    } else {
  2628. X        volp->flag |= WF_VOL_XCONN;
  2629. X    }
  2630. X    return (wf_conn *)0;
  2631. X}
  2632. X
  2633. Xwf_conn *
  2634. Xvol_newconn(volp)
  2635. Xwf_vol *volp;
  2636. X{
  2637. X    wf_conn *cp;
  2638. X    wf_srvq *srvq;
  2639. X
  2640. X    if (volp->nconn < WF_VOL_MAXCONN) {
  2641. X        volp->flag &= ~WF_VOL_XCONN;
  2642. X        srvq = pol_select_srv(volp);
  2643. X        cp = srv_newconn(srvq);
  2644. X        if (cp) {
  2645. X            ++volp->nconn;
  2646. X            return cp;
  2647. X        }
  2648. X    }
  2649. X    volp->flag |= WF_VOL_XCONN;
  2650. X    return (wf_conn *)0;
  2651. X}
  2652. X
  2653. Xvoid
  2654. Xvol_releaseconn(volp)
  2655. Xwf_vol *volp;
  2656. X{
  2657. X    warn_negative(--volp->nconn);
  2658. X}
  2659. X
  2660. Xvoid
  2661. Xvol_addsrv(volp, srvp, subdir)
  2662. Xwf_vol *volp;
  2663. Xwf_srv *srvp;
  2664. Xchar *subdir;
  2665. X{
  2666. X    wf_srvq *q = ALLOC(wf_srvq);
  2667. X    q->srv = srvp;
  2668. X    q->info = (void *)subdir;
  2669. X    q_insert(q, LAST(wf_srvq, &volp->srvq->q));
  2670. X}
  2671. X
  2672. Xvoid
  2673. Xvol_deletesrv(volp, srvp)
  2674. Xwf_vol *volp;
  2675. Xwf_srv *srvp;
  2676. X{
  2677. X    wf_srvq *q, *q2;
  2678. X    qelem *q_head = &volp->srvq->q;
  2679. X
  2680. X    ITER2 (q, q2, wf_srvq, q_head) {
  2681. X        if (q->srv == srvp) {
  2682. X            q_remove(q);
  2683. X            free(q->info);
  2684. X            FREE(q);
  2685. X            return;
  2686. X        }
  2687. X    }
  2688. X    syslog(LOG_WARNING, "vol_deletesrv: should not reach here");
  2689. X}
  2690. X
  2691. Xlong
  2692. Xvol_allocid(volp)
  2693. Xwf_vol *volp;
  2694. X{
  2695. X    /* Allocate a new directory id.
  2696. X     *
  2697. X     * NFS Version 2 Protocol Specification says:
  2698. X     * "fsid" is the file system identifier for the filesystem
  2699. X     * containing the file.
  2700. X     * "fileid" is a number that uniquely identifies the file
  2701. X     * within its file system.
  2702. X     *
  2703. X     * I think we satisfy this requirement by assigning a unique
  2704. X     * volume id to "fsid" and a file id to "fileid". Each fileid
  2705. X     * is guaranteed to be unique within given fsid.
  2706. X     */
  2707. X
  2708. X#define    MAPSIZE    256
  2709. X    /* 256 came from "blocksize / sizeof(long)", which is sufficient
  2710. X     * I believe, since each volume can contain
  2711. X     * 256(longs) * 32(bits/long) = 8192 directories */
  2712. X
  2713. X    int fd;
  2714. X    unsigned long bitmap[MAPSIZE];
  2715. X    long i, j;
  2716. X    char path[MAXPATHLEN];
  2717. X
  2718. X    /*
  2719. X     * load bitmap
  2720. X     */
  2721. X    /* XXX tuning is possible for contiguous allocid */
  2722. X    sprintf(path, "%s/cache/%lx/dir/bitmap", cs_topdir, volp->id);
  2723. X    if (access(path, R_OK|W_OK) != 0) {
  2724. X        if (mkdirs(path))
  2725. X            dir_realdir(path, volp, (wf_dir *)0);
  2726. X        fd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0660);
  2727. X        memset(bitmap, 0xff, MAPSIZE * sizeof(long));
  2728. X    } else {
  2729. X        fd = open(path, O_RDWR, 0660);
  2730. X        read(fd, bitmap, MAPSIZE * sizeof(long));
  2731. X    }
  2732. X
  2733. X    /*
  2734. X     * find unused bit and mark it
  2735. X     */
  2736. X    for (i = 0; bitmap[i] == 0; ++i) ;
  2737. X    j = ffs(bitmap[i]) - 1;
  2738. X    bitmap[i] &= ~(1 << j);
  2739. X
  2740. X    /*
  2741. X     * save bitmap 
  2742. X     */
  2743. X    /* XXX tuning is possible for contiguous allocid */
  2744. X    lseek(fd, 0L, 0);
  2745. X    write(fd, bitmap, MAPSIZE * sizeof(long));
  2746. X    close(fd);
  2747. X
  2748. X    /*
  2749. X     * return allocated id
  2750. X     */
  2751. X    return (i * 8 * sizeof(long) + j + 1);
  2752. X
  2753. X}
  2754. X
  2755. Xvoid
  2756. Xvol_destroyid(volp)
  2757. Xwf_vol *volp;
  2758. X{
  2759. X    char path[MAXPATHLEN];
  2760. X
  2761. X    sprintf(path, "%s/cache/%lx/dir/bitmap", cs_topdir, volp->id);
  2762. X    unlink(path);
  2763. X    if (access(path, R_OK) == 0) {
  2764. X        dlog("could not unlink %s", path);
  2765. X    }
  2766. X}
  2767. X
  2768. Xwf_dir *
  2769. Xvol_newroot(volp)
  2770. Xwf_vol *volp;
  2771. X{
  2772. X    wf_dir *dirp;
  2773. X    long dirid;
  2774. X    int retry_count = 0;
  2775. X    char path[MAXPATHLEN], path2[MAXPATHLEN];
  2776. X
  2777. X retry:
  2778. X    dirid = vol_allocid(volp);
  2779. X    if (dirid != 1) {
  2780. X        if (++retry_count > 3) {
  2781. X            /* something is wrong.. */
  2782. X            errno_diag();
  2783. X            return (wf_dir *)0;
  2784. X        }
  2785. X        /* Oops. Possible causes are:
  2786. X         * - ID bitmap of this volume has been corrupted.
  2787. X         * - Someone deleted root directory cache (".../%lx/%lx/1").
  2788. X         */
  2789. X        dlog("Directory cache of volume %s deleted?", volp->name);
  2790. X        sprintf(path2, "%s/stale/%s.%d/%lx/",
  2791. X            cs_topdir, cs_date, cs_serial, volp->id);
  2792. X        mkdirs(path2);
  2793. X        sprintf(path, "/bin/mv %s/cache/%lx/dir %s",
  2794. X            cs_topdir, volp->id, path2);
  2795. X        unix_command(path);
  2796. X        cs_serial++;
  2797. X        goto retry;
  2798. X    }
  2799. X    /* Directory id 1 is just for sanity check.
  2800. X     * We use volume id instead, biased with WF_VOL_BASE, to avoid ID
  2801. X     * conflict with other volumes. Otherwise pwd doesn't work correctly.
  2802. X     */
  2803. X    dirp = dir_new(volp, WF_VOL_BASE + volp->id, 0, 0);
  2804. X    return dirp;
  2805. X}
  2806. X
  2807. Xwf_dir *
  2808. Xvol_findroot(volp)
  2809. Xwf_vol *volp;
  2810. X{
  2811. X    wf_dir *dirp;
  2812. X
  2813. X    dirp = dir_findcache(volp, WF_VOL_BASE + volp->id);
  2814. X    return dirp;
  2815. X}
  2816. X
  2817. Xvoid
  2818. Xvol_inspect(reqp, name)
  2819. Xwf_req *reqp;
  2820. Xchar *name;
  2821. X{
  2822. X    int ret;
  2823. X    wf_ih ih;
  2824. X    int id = reqp->id;
  2825. X
  2826. X    ret = root_name2ih(name, &ih);
  2827. X    if (ret != WF_REP_OK) {
  2828. X        req_send(reqp, "513.%03d root_name2ih: error code %d.\n",
  2829. X             id, ret);
  2830. X        return;
  2831. X    }
  2832. X    req_send(reqp, "220-%03d vol %s\n", id, name);
  2833. X    req_send(reqp, "213-%03d name = %s\n", id, PROT(ih.child_volp->name));
  2834. X    req_send(reqp, "213-%03d id = %lx\n", id, ih.child_volp->id);
  2835. X    req_send(reqp, "213-%03d flag = %x\n", id, ih.child_volp->flag);
  2836. X    req_send(reqp, "213-%03d nconn = %d\n", id, ih.child_volp->nconn);
  2837. X    req_send(reqp, "213.%03d mtime = %ld (%20.20s)\n",
  2838. X         id, ih.child_volp->mtime, ctime(&ih.child_volp->mtime)+4);
  2839. X}
  2840. X
  2841. END_OF_FILE
  2842.   if test 11167 -ne `wc -c <'csd/vol.c'`; then
  2843.     echo shar: \"'csd/vol.c'\" unpacked with wrong size!
  2844.   fi
  2845.   # end of 'csd/vol.c'
  2846. fi
  2847. if test -f 'libww/libww.c' -a "${1}" != "-c" ; then 
  2848.   echo shar: Will not clobber existing file \"'libww/libww.c'\"
  2849. else
  2850.   echo shar: Extracting \"'libww/libww.c'\" \(11229 characters\)
  2851.   sed "s/^X//" >'libww/libww.c' <<'END_OF_FILE'
  2852. X/* 
  2853. X * WorldWide File System
  2854. X * Copyright (c) 1992,1993 Youki Kadobayashi
  2855. X * Copyright (c) 1992,1993 Osaka University
  2856. X * All rights reserved.
  2857. X *
  2858. X * Permission to use, copy, modify and distribute this software and its
  2859. X * documentation is hereby granted, provided that the following conditions
  2860. X * are met:
  2861. X * 1. Both the copyright notice and this permission notice appear in
  2862. X *    all copies of the software, derivative works or modified versions,
  2863. X *    and any portions thereof, and that both notices appear in
  2864. X *    supporting documentation.
  2865. X * 2. All advertising materials mentioning features or use of this software
  2866. X *    must display the following acknowledgement:
  2867. X *      This product includes software developed by the Osaka University
  2868. X *      and its contributors.
  2869. X * 3. Neither the name of the University nor the names of its contributors
  2870. X *    may be used to endorse or promote products derived from this software
  2871. X *    without specific prior written permission.
  2872. X *
  2873. X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
  2874. X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  2875. X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  2876. X *
  2877. X * Osaka University requests users of this software to return to
  2878. X *
  2879. X *  Youki Kadobayashi
  2880. X *  Department of Information and Computer Sciences
  2881. X *  Osaka University, Toyonaka 560, Osaka, Japan
  2882. X *
  2883. X * any improvements or extensions that they make and grant Osaka
  2884. X * University the rights to redistribute these changes.
  2885. X */
  2886. X/*
  2887. X * libww: WWFS Application Programming Interface.
  2888. X * This file is part of WWFS, the WorldWide File System.
  2889. X *
  2890. X * You do not want to link your program with libww.a if you have spliced
  2891. X * libc routines in libc_wwfs.a and you are planning to link with it.
  2892. X */
  2893. Xstatic char *AtFSid = "$Header: libww.c[109.0] Wed Nov 24 03:49:15 1993 youki-k@is.aist-nara.ac.jp saved $";
  2894. X
  2895. X#include <sys/errno.h>
  2896. Xextern int errno;
  2897. X#include <sys/param.h>
  2898. X#include <sys/stat.h>
  2899. X#include <sys/socket.h>
  2900. X#include <netinet/in.h>
  2901. X#include <netdb.h>
  2902. Xextern  int h_errno;    /* for BSDs */
  2903. X
  2904. X#ifdef _POSIX_SOURCE
  2905. X#include <dirent.h>
  2906. X#define    DIRENT    struct dirent
  2907. X#else
  2908. X#include <sys/dir.h>
  2909. X#define    DIRENT    struct direct
  2910. X#endif
  2911. X#include <fcntl.h>
  2912. X#include <stdio.h>
  2913. X#if defined(__STDC__) || defined(STDC_HEADERS)
  2914. X#include <stdlib.h>
  2915. X#endif
  2916. X#include <string.h>
  2917. X#define    LIBWW
  2918. X#include "libww.h"
  2919. X#include "parse.h"
  2920. X
  2921. X#define    UIP_TCP_PORT    8002
  2922. X#define    UIP_UDP_PORT    8002
  2923. X
  2924. X#if 0
  2925. Xstatic char    cs_hostname[MAXHOSTNAMELEN];
  2926. Xstatic struct sockaddr_in cs_sin;
  2927. X#endif
  2928. Xstatic char    cs_path[MAXPATHLEN];
  2929. Xstatic char    *ww_mountdir;
  2930. Xstatic struct sockaddr_in *ww_cshost;
  2931. Xstatic int
  2932. X    uip_block=1,        /* block by default */
  2933. X    uip_progress=0;        /* don't show percentage indicator */
  2934. X
  2935. X#if 0
  2936. Xchar *
  2937. Xww_getaddr(path)
  2938. Xchar *path;
  2939. X{
  2940. X    /*
  2941. X     * Get the CS service address.  We need pathname here, since
  2942. X     * clients can mount several CSs at different mount points.
  2943. X     * Gross hack is deployed here because we never want to deal
  2944. X     * with the diverse format of /etc/mtab.  NFS protocol should
  2945. X     * have provided "getnfsinfo" operation that provides rudimentary
  2946. X     * information, so that we could contact the machine serving
  2947. X     * the filesystem via other network services...
  2948. X     */
  2949. X
  2950. X    char *p;
  2951. X    struct stat statbuf;
  2952. X    int fd;
  2953. X    struct hostent *hp;
  2954. X    int retry = 0;
  2955. X
  2956. X    /* "/mount/point/volume/dir/.wwfs_host" */
  2957. X    strcpy(cs_path, path);
  2958. X    p = strrchr(cs_path, '/');
  2959. X    if (p)
  2960. X        strcpy(p+1, ".wwfs_host");
  2961. X    else
  2962. X        strcpy(cs_path, ".wwfs_host");    /* within "." */
  2963. X
  2964. X    /* get the hostname of CS */
  2965. X    fd = Open(cs_path, O_RDONLY, 0400);
  2966. X    if (fd < 0)
  2967. X        return NULL;        /* not served by CS */
  2968. X    fstat(fd, &statbuf);
  2969. X    read(fd, cs_hostname, statbuf.st_size);
  2970. X    close(fd);
  2971. X
  2972. X dns_retry:
  2973. X    hp = gethostbyname(cs_hostname);
  2974. X    if (hp == (struct hostent *) 0) {
  2975. X        if (h_errno == TRY_AGAIN) {
  2976. X            if (++retry < 5) {
  2977. X                sleep(1);
  2978. X                goto dns_retry;
  2979. X            }
  2980. X        }
  2981. X        return NULL;
  2982. X    }
  2983. X    cs_sin.sin_family = hp->h_addrtype;
  2984. X    /*
  2985. X     * I use primary address here. If your cluster server have
  2986. X     * more than one interfaces, and if ipforwarding was set to 0,
  2987. X     * and if your client cannot reach primary address due to
  2988. X     * dropped ipforwarding, your network configuration is wrong.
  2989. X     */
  2990. X    bcopy(hp->h_addr_list[0], &cs_sin.sin_addr, hp->h_length);
  2991. X    return cs_hostname;
  2992. X}
  2993. X
  2994. Xchar *
  2995. Xww_path(path)
  2996. Xchar *path;
  2997. X{
  2998. X    /*
  2999. X     * Convert client-specific NFS pathname into CS's pathname,
  3000. X     * so that clients and CS can share a common namespace.
  3001. X     * e.g., "/mount/point/volume/dir/filename" -> "/volume/dir/filename"
  3002. X     */
  3003. X
  3004. X    char *p;
  3005. X    struct stat statbuf;
  3006. X    int fd;
  3007. X
  3008. X    /* "/mount/point/volume/dir/.wwfs_cwd" */
  3009. X    strcpy(cs_path, path);
  3010. X    p = strrchr(cs_path, '/');
  3011. X    if (p)
  3012. X        strcpy(p+1, ".wwfs_cwd");
  3013. X    else
  3014. X        strcpy(cs_path, ".wwfs_cwd");    /* within "." */
  3015. X
  3016. X    /* get the current working directory within CS's namespace */
  3017. X    fd = Open(cs_path, O_RDONLY, 0400);
  3018. X    if (fd < 0)
  3019. X        return NULL;        /* not served by CS */
  3020. X    fstat(fd, &statbuf);
  3021. X    read(fd, cs_path, statbuf.st_size);
  3022. X    close(fd);
  3023. X
  3024. X    /* Finally we get it: "/volume/dir/filename" */
  3025. X    p = strrchr(path, '/');        /* basename */
  3026. X    if (p)
  3027. X        strcat(cs_path, p+1);
  3028. X    else
  3029. X        strcat(cs_path, path);
  3030. X    return cs_path;
  3031. X}
  3032. X#endif
  3033. X
  3034. Xchar *
  3035. Xww_path(path)
  3036. Xchar *path;
  3037. X{
  3038. X    /*
  3039. X     * Convert client-specific NFS pathname into CS's pathname,
  3040. X     * so that clients and CS can share a common namespace.
  3041. X     * e.g., "/mount/point/volume/dir/filename" -> "+filehandle/filename"
  3042. X     */
  3043. X
  3044. X    char *p;
  3045. X    struct stat statbuf;
  3046. X    int fd;
  3047. X
  3048. X    /* "/mount/point/volume/dir/.wwfs_fh" */
  3049. X    strcpy(cs_path, path);
  3050. X    p = strrchr(cs_path, '/');
  3051. X    if (p)
  3052. X        strcpy(p+1, ".wwfs_fh");
  3053. X    else
  3054. X        strcpy(cs_path, ".wwfs_fh");    /* within "." */
  3055. X
  3056. X    /* get the filehandle */
  3057. X    fd = Open(cs_path, O_RDONLY, 0400);
  3058. X    if (fd < 0)
  3059. X        return NULL;        /* not served by csd */
  3060. X    fstat(fd, &statbuf);
  3061. X    cs_path[0] = '+';
  3062. X    read(fd, cs_path+1, statbuf.st_size);
  3063. X    close(fd);
  3064. X
  3065. X    strcat(cs_path, "/");
  3066. X    /* Finally we get it: "+filehandle/filename" */
  3067. X    p = strrchr(path, '/');        /* basename */
  3068. X    if (p)
  3069. X        strcat(cs_path, p+1);
  3070. X    else
  3071. X        strcat(cs_path, path);
  3072. X    return cs_path;
  3073. X}
  3074. X
  3075. Xstatic int
  3076. Xww_set_cshost(cshost)
  3077. Xchar *cshost;
  3078. X{
  3079. X    struct hostent *hp;
  3080. X    int retry = 0;
  3081. X
  3082. X    if (getenv("WW_CSHOST")) {
  3083. X        /* You may want to use another csd, e.g., for debugging... */
  3084. X        cshost = getenv("WW_CSHOST");
  3085. X    }
  3086. X    ww_cshost = malloc(sizeof (struct sockaddr_in));
  3087. X
  3088. X dns_retry:
  3089. X    hp = gethostbyname(cshost);
  3090. X    if (hp == (struct hostent *) 0) {
  3091. X        if (h_errno == TRY_AGAIN) {
  3092. X            if (++retry < 5) {
  3093. X                sleep(1);
  3094. X                goto dns_retry;
  3095. X            }
  3096. X        }
  3097. X        return NULL;
  3098. X    }
  3099. X    ww_cshost->sin_family = hp->h_addrtype;
  3100. X    /*
  3101. X     * I use primary address here. If your cluster server have
  3102. X     * more than one interfaces, and if ipforwarding was set to 0,
  3103. X     * and if your client cannot reach primary address due to
  3104. X     * dropped ipforwarding, your network configuration is wrong.
  3105. X     */
  3106. X    bcopy(hp->h_addr_list[0], &ww_cshost->sin_addr, hp->h_length);
  3107. X    return 0;
  3108. X}
  3109. X
  3110. Xstatic int
  3111. Xww_set_mountdir(mountdir)
  3112. Xchar *mountdir;
  3113. X{
  3114. X    if (getenv("WW_MOUNTDIR")) {
  3115. X        /* You may want to use another csd, e.g., for debugging... */
  3116. X        int len;
  3117. X        char *p;
  3118. X
  3119. X        mountdir = getenv("WW_MOUNTDIR");
  3120. X        len = strlen(mountdir)+1;
  3121. X        p = malloc(len);    /* GonzOS lacks strdup() */
  3122. X        bcopy(mountdir, p, len);
  3123. X    }
  3124. X    ww_mountdir = mountdir;
  3125. X    return 0;
  3126. X}
  3127. X
  3128. Xstatic int
  3129. Xww_set_dummy(dummy)
  3130. Xchar *dummy;
  3131. X{
  3132. X    return 0;
  3133. X}
  3134. X
  3135. Xstatic wf_tailor ww_tailor[] = {
  3136. X    { "cshost", ww_set_cshost },
  3137. X    { "mountcmd", ww_set_dummy },
  3138. X    { "mountdir", ww_set_mountdir },
  3139. X    { NULL, (int (*)())0 }
  3140. X};
  3141. X
  3142. Xstatic int
  3143. Xww_bind(name, value)
  3144. Xchar *name;
  3145. Xchar *value;
  3146. X{
  3147. X    return parse_tailor(ww_tailor, name, value);
  3148. X}
  3149. X
  3150. Xchar *
  3151. Xww_localpath(path)
  3152. Xchar *path;
  3153. X{
  3154. X    /*
  3155. X     * Convert CS's pathname into client-specific NFS pathname,
  3156. X     * so that clients can access it with canonical pathname.
  3157. X     * e.g., "/volume/dir/filename" -> "/mount/point/volume/dir/filename"
  3158. X     */
  3159. X
  3160. X    if (! ww_mountdir) {
  3161. X        if (parse_conf("/etc/wwfs.conf", ww_bind) < 0)
  3162. X            return NULL;    /* syntax error, or not a csd client */
  3163. X        if (! ww_mountdir)
  3164. X            return NULL;
  3165. X    }
  3166. X    strcpy(cs_path, ww_mountdir);
  3167. X    strcat(cs_path, path);
  3168. X    return cs_path;
  3169. X}
  3170. X
  3171. Xint
  3172. Xww_control(optname, optval)
  3173. Xint optname;
  3174. Xvoid *optval;
  3175. X{
  3176. X    /* Control the behavior of wwfs client process. */
  3177. X    switch (optname) {
  3178. X    case UIP_BLOCK:
  3179. X        uip_block = *(int *)optval;
  3180. X        break;
  3181. X    case UIP_PROGRESS:
  3182. X        uip_progress = *(int *)optval;
  3183. X        break;
  3184. X    default:
  3185. X        return -1;
  3186. X    }
  3187. X    return 0;
  3188. X}
  3189. X
  3190. X#define    BUFLEN    1400        /* Ethernet MTU might be a good measure */
  3191. Xstatic char buf[BUFLEN];
  3192. X
  3193. Xstatic int
  3194. Xdo_socket()
  3195. X{
  3196. X    int so, ret;
  3197. X    struct sockaddr_in sin;
  3198. X
  3199. X    so = socket(AF_INET, SOCK_DGRAM, 0);
  3200. X    bzero(&sin, sizeof(sin));
  3201. X    sin.sin_family = AF_INET;
  3202. X    sin.sin_addr.s_addr = htonl(INADDR_ANY);
  3203. X    ret = bind(so, (struct sockaddr *) &sin, sizeof (sin));
  3204. X    if (ret < 0) {
  3205. X        close(so);
  3206. X        return -1;
  3207. X    }
  3208. X    return so;
  3209. X}
  3210. X
  3211. Xstatic void
  3212. Xdo_sendto(so, port, buf)
  3213. Xint so, port;
  3214. Xchar *buf;
  3215. X{
  3216. X    ww_cshost->sin_port = htons(port);
  3217. X    sendto(so, buf, strlen(buf), 0,
  3218. X           (struct sockaddr *) ww_cshost, sizeof(*ww_cshost));
  3219. X}
  3220. X
  3221. Xstatic void
  3222. Xdo_recvfrom(so, buf)
  3223. Xint so;
  3224. Xchar *buf;
  3225. X{
  3226. X    struct sockaddr_in from;
  3227. X    int fromlen;
  3228. X
  3229. X retry:
  3230. X    fromlen = sizeof(from);
  3231. X    recvfrom(so, buf, BUFLEN, 0,
  3232. X         (struct sockaddr *)&from, &fromlen);
  3233. X    if (from.sin_addr.s_addr != ww_cshost->sin_addr.s_addr)
  3234. X        goto retry;
  3235. X    return;
  3236. X}
  3237. X
  3238. Xint
  3239. Xww_get(subpath)
  3240. Xchar *subpath;
  3241. X{
  3242. X    /*
  3243. X     * No libc counterpart -- just retrieve a file/directory
  3244. X     * represented by a WWFS pathname (i.e., pathname with
  3245. X     * leading mount point dropped).
  3246. X     */
  3247. X    int so;
  3248. X
  3249. X    if (! ww_cshost) {
  3250. X        if (parse_conf("/etc/wwfs.conf", ww_bind) < 0) {
  3251. X            errno = EINVAL;    /* invalid configuration */
  3252. X            return -1;    /* syntax error, or not a csd client */
  3253. X        }
  3254. X        if (! ww_cshost) {
  3255. X            errno = EINVAL;    /* invalid configuration */
  3256. X            return -1;
  3257. X        }
  3258. X    }
  3259. X    if (uip_block) {
  3260. X        sprintf(buf, "RETR %s\n", subpath);
  3261. X        so = do_socket();
  3262. X        if (so < 0)
  3263. X            return -1;
  3264. X        do_sendto(so, UIP_UDP_PORT, buf);
  3265. X        while (1) {
  3266. X            do_recvfrom(so, buf);
  3267. X            /* parse it */
  3268. X            if (buf[3] == '.') {
  3269. X                if (buf[0] == '2') {
  3270. X                    close(so);
  3271. X                    return 0;
  3272. X                }
  3273. X                else if (buf[0] == '5') {
  3274. X                    errno = EIO;
  3275. X                    close(so);
  3276. X                    return -1;
  3277. X                }
  3278. X            }
  3279. X        }
  3280. X    } else if (uip_progress) {
  3281. X    }
  3282. X    return 0;
  3283. X}
  3284. X
  3285. Xint
  3286. Xww_nfsget(path)
  3287. Xchar *path;
  3288. X{
  3289. X    /*
  3290. X     * No libc counterpart -- just retrieve a file/directory
  3291. X     * represented by an NFS pathname.
  3292. X     */
  3293. X    char *subpath;
  3294. X    int ret;
  3295. X
  3296. X    if (subpath = ww_path(path)) {
  3297. X        ret = ww_get(subpath);
  3298. X        if (ret < 0)
  3299. X            return ret;
  3300. X    }
  3301. X}
  3302. X
  3303. Xint
  3304. Xww_open(path, flags, mode)
  3305. Xchar *path;
  3306. Xint flags;
  3307. Xint mode;
  3308. X{
  3309. X    /* Open the file, with pre- and post-processing as specified by
  3310. X     * ww_control().
  3311. X     */
  3312. X    char *subpath;
  3313. X    int ret;
  3314. X
  3315. X    if (subpath = ww_path(path)) {
  3316. X        ret = ww_get(subpath);
  3317. X        if (ret < 0)
  3318. X            return ret;
  3319. X        /* possibly other protocols */
  3320. X    }
  3321. X    return Open(path, flags, mode);
  3322. X}
  3323. X
  3324. XFILE *
  3325. Xww_fopen(path, flags)
  3326. Xchar *path;
  3327. Xchar *flags;
  3328. X{
  3329. X    /* FOpen the file, with pre- and post-processing as specified by
  3330. X     * ww_control().
  3331. X     */
  3332. X    char *subpath;
  3333. X    int ret;
  3334. X
  3335. X    if (subpath = ww_path(path)) {
  3336. X        ret = ww_get(subpath);
  3337. X        if (ret < 0)
  3338. X            return NULL;
  3339. X        /* possibly other protocols */
  3340. X    }
  3341. X    return Fopen(path, flags);
  3342. X}
  3343. X
  3344. XDIR *
  3345. Xww_opendir(path)
  3346. Xchar *path;
  3347. X{
  3348. X    /* Open the dir, with pre- and post-processing as specified by
  3349. X     * ww_control().
  3350. X     */
  3351. X    char *subpath;
  3352. X    int ret;
  3353. X
  3354. X    if (subpath = ww_path(path)) {
  3355. X        ret = ww_get(subpath);
  3356. X        if (ret < 0)
  3357. X            return NULL;
  3358. X        /* possibly other protocols */
  3359. X    }
  3360. X    return Opendir(path);
  3361. X}
  3362. X
  3363. END_OF_FILE
  3364.   if test 11229 -ne `wc -c <'libww/libww.c'`; then
  3365.     echo shar: \"'libww/libww.c'\" unpacked with wrong size!
  3366.   fi
  3367.   # end of 'libww/libww.c'
  3368. fi
  3369. if test -f 'wwalk/Makefile' -a "${1}" != "-c" ; then 
  3370.   echo shar: Will not clobber existing file \"'wwalk/Makefile'\"
  3371. else
  3372.   echo shar: Extracting \"'wwalk/Makefile'\" \(1980 characters\)
  3373.   sed "s/^X//" >'wwalk/Makefile' <<'END_OF_FILE'
  3374. X#
  3375. X# Makefile for user-interface programs; part of Worldwide File System.
  3376. X#
  3377. X# Author:    Youki Kadobayashi, Osaka University, Japan
  3378. X#        E-mail: <youki@wide.ad.jp>
  3379. X#
  3380. X# 
  3381. X# WorldWide File System
  3382. X# Copyright (c) 1992,1993 Youki Kadobayashi
  3383. X# Copyright (c) 1992,1993 Osaka University
  3384. X# All rights reserved.
  3385. X#
  3386. X# Permission to use, copy, modify and distribute this software and its
  3387. X# documentation is hereby granted, provided that the following conditions
  3388. X# are met:
  3389. X# 1. Both the copyright notice and this permission notice appear in
  3390. X#    all copies of the software, derivative works or modified versions,
  3391. X#    and any portions thereof, and that both notices appear in
  3392. X#    supporting documentation.
  3393. X# 2. All advertising materials mentioning features or use of this software
  3394. X#    must display the following acknowledgement:
  3395. X#      This product includes software developed by the Osaka University
  3396. X#      and its contributors.
  3397. X# 3. Neither the name of the University nor the names of its contributors
  3398. X#    may be used to endorse or promote products derived from this software
  3399. X#    without specific prior written permission.
  3400. X#
  3401. X# THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
  3402. X# UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  3403. X# WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  3404. X#
  3405. X# Osaka University requests users of this software to return to
  3406. X#
  3407. X#  Youki Kadobayashi
  3408. X#  Department of Information and Computer Sciences
  3409. X#  Osaka University, Toyonaka 560, Osaka, Japan
  3410. X#
  3411. X# any improvements or extensions that they make and grant Osaka
  3412. X# University the rights to redistribute these changes.
  3413. X
  3414. X# $Header: Makefile[109.0] Wed Nov 24 03:50:31 1993 youki-k@is.aist-nara.ac.jp saved $
  3415. X#
  3416. X
  3417. X# To use alternative 'make' program, say gmake, type:
  3418. X#    gmake Make="gmake"
  3419. XMake = make
  3420. XMAK  = $(Make) Make="$(Make)"
  3421. XMKARG = -f ../Makefile.top PROG="wwalk" TOP=".."
  3422. XSHELL = /bin/sh
  3423. X
  3424. Xall:    wwalk
  3425. X
  3426. Xwwalk:
  3427. X
  3428. Xinstall-client clean baseline copyright version: FRC
  3429. X    @$(MAK) $(MKARG) $@
  3430. X
  3431. XFRC:
  3432. END_OF_FILE
  3433.   if test 1980 -ne `wc -c <'wwalk/Makefile'`; then
  3434.     echo shar: \"'wwalk/Makefile'\" unpacked with wrong size!
  3435.   fi
  3436.   # end of 'wwalk/Makefile'
  3437. fi
  3438. if test -f 'wwmount/wwmount.c' -a "${1}" != "-c" ; then 
  3439.   echo shar: Will not clobber existing file \"'wwmount/wwmount.c'\"
  3440. else
  3441.   echo shar: Extracting \"'wwmount/wwmount.c'\" \(8847 characters\)
  3442.   sed "s/^X//" >'wwmount/wwmount.c' <<'END_OF_FILE'
  3443. X/* 
  3444. X * WorldWide File System
  3445. X * Copyright (c) 1992,1993 Youki Kadobayashi
  3446. X * Copyright (c) 1992,1993 Osaka University
  3447. X * All rights reserved.
  3448. X *
  3449. X * Permission to use, copy, modify and distribute this software and its
  3450. X * documentation is hereby granted, provided that the following conditions
  3451. X * are met:
  3452. X * 1. Both the copyright notice and this permission notice appear in
  3453. X *    all copies of the software, derivative works or modified versions,
  3454. X *    and any portions thereof, and that both notices appear in
  3455. X *    supporting documentation.
  3456. X * 2. All advertising materials mentioning features or use of this software
  3457. X *    must display the following acknowledgement:
  3458. X *      This product includes software developed by the Osaka University
  3459. X *      and its contributors.
  3460. X * 3. Neither the name of the University nor the names of its contributors
  3461. X *    may be used to endorse or promote products derived from this software
  3462. X *    without specific prior written permission.
  3463. X *
  3464. X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND OSAKA
  3465. X * UNIVERSITY DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  3466. X * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  3467. X *
  3468. X * Osaka University requests users of this software to return to
  3469. X *
  3470. X *  Youki Kadobayashi
  3471. X *  Department of Information and Computer Sciences
  3472. X *  Osaka University, Toyonaka 560, Osaka, Japan
  3473. X *
  3474. X * any improvements or extensions that they make and grant Osaka
  3475. X * University the rights to redistribute these changes.
  3476. X */
  3477. X/* WWFS mount */
  3478. Xstatic char *AtFSid = "$Header: wwmount.c[109.0] Wed Nov 24 03:49:37 1993 youki-k@is.aist-nara.ac.jp saved $";
  3479. X
  3480. X#include "am.h"        /* amd compatibility */
  3481. X
  3482. X/* NFS headers and definitions */
  3483. X#define NFS
  3484. X#define NFSCLIENT
  3485. X#ifdef NFS_3
  3486. Xtypedef nfs_fh fhandle_t;
  3487. X#endif /* NFS_3 */
  3488. X#include <sys/mount.h>
  3489. X#ifdef NFS_HDR
  3490. X#include NFS_HDR
  3491. X#endif /* NFS_HDR */
  3492. X
  3493. X/* miscellaneous headers */
  3494. X#include <sys/signal.h>
  3495. X#include <sys/stat.h>
  3496. X#include <string.h>            /* for strchr */
  3497. X#include "cs_prot.h"
  3498. X
  3499. X/* definition of behaviour */
  3500. X#define    CSMNT_TIMEO    22
  3501. X#define    CSMNT_RETRANS    5
  3502. X#define    CSMNT_AC    8
  3503. X#define    CSMNT_RETRY    10000
  3504. X#define    BGRND    1
  3505. X#define    ISBGRND    2
  3506. Xint opflags = 0;
  3507. X#ifdef MOUNTED
  3508. Xchar *mtab = MOUNTED;
  3509. X#endif /* MOUNTED */
  3510. Xtime_t clock_valid = 0;
  3511. Xint mypid;
  3512. X
  3513. Xvoid
  3514. Xusage(name)
  3515. Xchar *name;
  3516. X{
  3517. X    fprintf(stderr, "Usage: %s server_host local_dir\n", name);
  3518. X}
  3519. X
  3520. Xvoid
  3521. Xcompute_mntent_options(mntp, fs_name, mp_name)
  3522. Xstruct mntent *mntp;
  3523. Xchar *fs_name, *mp_name;
  3524. X{
  3525. X    char *opts;
  3526. X    opts = malloc(64);
  3527. X    mntp->mnt_dir = mp_name;
  3528. X    mntp->mnt_fsname = fs_name;
  3529. X    mntp->mnt_type = MNTTYPE_WWFS;        /* or MTAB_TYPE_NFS; */
  3530. X    sprintf(opts, "soft,timeo=%d,retrans=%d,acregmax=%d",
  3531. X        CSMNT_TIMEO, CSMNT_RETRANS, CSMNT_AC);
  3532. X    mntp->mnt_opts = opts;
  3533. X    mntp->mnt_freq = 0;
  3534. X    mntp->mnt_passno = 0;
  3535. X}
  3536. X
  3537. Xvoid
  3538. Xcompute_nfs_options(nfs_argsp)
  3539. Xstruct nfs_args *nfs_argsp;
  3540. X{
  3541. X    nfs_argsp->flags = NFSMNT_SOFT | NFSMNT_HOSTNAME
  3542. X        | NFSMNT_TIMEO | NFSMNT_RETRANS;
  3543. X    nfs_argsp->timeo = CSMNT_TIMEO;
  3544. X    nfs_argsp->retrans = CSMNT_RETRANS;
  3545. X    nfs_argsp->rsize = nfs_argsp->wsize = NFS_MAXDATA;
  3546. X#if defined(NFSMNT_NOAC) && !defined(sony_news)
  3547. X    nfs_argsp->flags |= NFSMNT_NOAC;
  3548. X#else /* NFSMNT_NOAC */
  3549. X#if defined(NFSMNT_ACREGMIN) && defined(NFSMNT_ACREGMAX)
  3550. X    nfs_argsp->flags |= NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
  3551. X    nfs_argsp->acregmin = nfs_argsp->acregmax = CSMNT_AC;
  3552. X    nfs_argsp->flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX;
  3553. X    nfs_argsp->acdirmin = nfs_argsp->acdirmax = CSMNT_AC;
  3554. X#endif
  3555. X#endif /* NFSMNT_NOAC */
  3556. X}
  3557. X
  3558. Xint
  3559. Xcompute_mount_flags()
  3560. X{
  3561. X    int flags;
  3562. X#ifdef NFS_4
  3563. X    flags = M_NEWTYPE;
  3564. X#else
  3565. X    flags = 0;
  3566. X#endif
  3567. X    flags |= M_RDONLY | M_NOSUID;
  3568. X    return flags;
  3569. X}
  3570. X
  3571. Xchar *
  3572. Xcompute_fs_name(s)
  3573. Xchar *s;
  3574. X{
  3575. X    char *fs_name;
  3576. X    char *p;
  3577. X    fs_name = malloc(strlen(s)+16);
  3578. X    strcpy(fs_name, s);
  3579. X#ifndef HOSTNAMESZ
  3580. X#define SHORT_MOUNT_NAME
  3581. X#endif /* HOSTNAMESZ */
  3582. X#ifdef SHORT_MOUNT_NAME
  3583. X    if (p = strchr(fs_name, '.'))
  3584. X        *p = '\0';
  3585. X#endif
  3586. X#ifdef HOSTNAMESZ
  3587. X    if (strlen(fs_name) >= HOSTNAMESZ)
  3588. X        strcpy(fs_name + HOSTNAMESZ - 8, "..");
  3589. X#endif
  3590. X    if (strchr(fs_name, ':') == NULL) {
  3591. X        strcat(fs_name, ":wwfs");
  3592. X    }
  3593. X    return fs_name;
  3594. X}
  3595. X
  3596. X/* code below is derived from NET2 mount.c */
  3597. X
  3598. Xint
  3599. Xcompute_bindings(nfs_argsp, host, dir)
  3600. Xstruct nfs_args *nfs_argsp;
  3601. Xchar *host, *dir;
  3602. X{
  3603. X    int retry;
  3604. X    struct hostent *hp;
  3605. X    struct sockaddr_in *sinp = ALLOC(sockaddr_in);
  3606. X    u_short nfs_port;
  3607. X    cs_fhres *resp = ALLOC(cs_fhres);
  3608. X
  3609. X    /* get 'sockaddr_in' of the file server */
  3610. X    bzero(sinp, sizeof (*sinp));
  3611. X    if ((hp = gethostbyname(host)) == NULL) {
  3612. X        plog(XLOG_ERROR,
  3613. X             "mount: Can't get network address for host %s\n", host);
  3614. X        return (-1);
  3615. X    }
  3616. X    bcopy(hp->h_addr, &(sinp->sin_addr), sizeof(sinp->sin_addr));
  3617. X
  3618. X    /* try several times contacting server */
  3619. X    retry = CSMNT_RETRY;
  3620. X    resp->status = ETIMEDOUT;    /* Mark not yet successful */
  3621. X    while (retry > 0) {
  3622. X        nfs_port = contact_server(sinp, resp);
  3623. X        if (nfs_port) {
  3624. X            break;
  3625. X        }
  3626. X        if (--retry > 0) {
  3627. X            if (opflags & BGRND) {
  3628. X                opflags &= ~BGRND;
  3629. X                if (fork())
  3630. X                    return (-1);
  3631. X                else
  3632. X                    opflags |= ISBGRND;
  3633. X            } 
  3634. X            sleep(20);
  3635. X        }
  3636. X    }
  3637. X
  3638. X    /* abort if error */
  3639. X    if (resp->status) {
  3640. X        if (opflags & ISBGRND)
  3641. X            exit(1);
  3642. X        plog(XLOG_ERROR, "Mount RPC error on %s", host);
  3643. X        errno = resp->status;
  3644. X        perror((char *)NULL);
  3645. X        return (-1);
  3646. X    }
  3647. X
  3648. X    /* set nfs_argsp */
  3649. X#if defined(__osf__) && defined(__alpha)
  3650. X    sinp->sin_family = htons(AF_INET);    /* DEC OSF/1 bug? */
  3651. X#else
  3652. X    sinp->sin_family = AF_INET;
  3653. X#endif
  3654. X    sinp->sin_port = htons(nfs_port);
  3655. X    NFS_SA_DREF(*nfs_argsp, sinp)
  3656. X    NFS_FH_DREF(nfs_argsp->fh, (NFS_FH_TYPE) &resp->cs_fhres_u.file);
  3657. X    nfs_argsp->hostname = host;
  3658. X
  3659. X    return 0;
  3660. X}
  3661. X
  3662. Xint
  3663. Xcontact_server(sinp, resp)
  3664. Xstruct sockaddr_in *sinp;
  3665. Xcs_fhres *resp;
  3666. X{
  3667. X    CLIENT *clntp;
  3668. X    enum clnt_stat clnt_stat;
  3669. X    struct timeval create_try, call_try;
  3670. X    int so = RPC_ANYSOCK;
  3671. X    int nfs_port;
  3672. X    char fake_arg;
  3673. X
  3674. X    sinp->sin_family = AF_INET;
  3675. X    sinp->sin_port = htons(0);
  3676. X    create_try.tv_sec = 10;
  3677. X    create_try.tv_usec = 0;
  3678. X    if ((clntp = clntudp_create(sinp, CS_PROGRAM, CS_VERSION,
  3679. X                    create_try, &so)) == NULL) {
  3680. X        if ((opflags & ISBGRND) == 0)
  3681. X            clnt_pcreateerror("Failed to clntudp_create()");
  3682. X        return 0;
  3683. X    } else {
  3684. X        clntp->cl_auth = authunix_create_default();
  3685. X        /* try CS_PROC_REGISTER */
  3686. X        call_try.tv_sec = 10;
  3687. X        call_try.tv_usec = 0;
  3688. X        clnt_stat = clnt_call(clntp, CS_PROC_REGISTER,
  3689. X                      xdr_void, &fake_arg, /* in */
  3690. X                      xdr_cs_fhres, resp, /* out */
  3691. X                      call_try);
  3692. X        /* ignore results for now */
  3693. X
  3694. X        /* try CS_PROC_GETPORT */
  3695. X        call_try.tv_sec = 10;
  3696. X        call_try.tv_usec = 0;
  3697. X        clnt_stat = clnt_call(clntp, CS_PROC_GETPORT,
  3698. X                      xdr_void, &fake_arg, /* in */
  3699. X                      xdr_int, &nfs_port, /* out */
  3700. X                      call_try);
  3701. X        if (clnt_stat != RPC_SUCCESS) {
  3702. X            if ((opflags & ISBGRND) == 0)
  3703. X                clnt_perror(clntp, "Failed to CS_PROC_REGISTER");
  3704. X            return 0;
  3705. X        } else {
  3706. X            auth_destroy(clntp->cl_auth);
  3707. X            clnt_destroy(clntp);
  3708. X            return nfs_port;
  3709. X        }
  3710. X    }
  3711. X}
  3712. X
  3713. Xint
  3714. Xmount_fs(mntp, flags, mnt_data, retry, type)
  3715. Xstruct mntent *mntp;
  3716. Xint flags;
  3717. Xcaddr_t mnt_data;    /* nfs_args actually */
  3718. Xint retry;
  3719. XMTYPE_TYPE type;
  3720. X{
  3721. X    int error;
  3722. X#ifdef MNTINFO_DEV
  3723. X    struct stat stb;
  3724. X#endif /* MNTINFO_DEV */
  3725. X
  3726. X#ifdef FASCIST_DF_COMMAND
  3727. X    /* Oh my SGI! */
  3728. X    if (strcmp(mntp->mnt_type, MNTTYPE_WWFS) == 0) {
  3729. X        mntp->mnt_type = FASCIST_DF_COMMAND;
  3730. X    }
  3731. X#endif /* FASCIST_DF_COMMAND */
  3732. X
  3733. X    error = MOUNT_TRAP(type, mntp, flags, mnt_data);
  3734. X    if (error < 0) {
  3735. X        plog(XLOG_ERROR, "mount failed on %s: errno=%d", mntp->mnt_dir,
  3736. X            errno);
  3737. X        return (-1);
  3738. X    }
  3739. X
  3740. X#ifdef UPDATE_MTAB
  3741. X#ifdef MNTINFO_DEV
  3742. X    /*
  3743. X     * Add the extra dev= field to the mount table.
  3744. X     */
  3745. X    if (lstat(mntp->mnt_dir, &stb) == 0) {
  3746. X        char *zopts = (char *) malloc(strlen(mntp->mnt_opts) + 32);
  3747. X        if (sizeof(stb.st_dev) == 2) {
  3748. X            /* e.g. SunOS 4.1 */
  3749. X            sprintf(zopts, "%s,%s=%s%04lx", mntp->mnt_opts,
  3750. X                MNTINFO_DEV, MNTINFO_PREF,
  3751. X                (u_long) stb.st_dev & 0xffff);
  3752. X        } else {
  3753. X            /* e.g. System Vr4 */
  3754. X            sprintf(zopts, "%s,%s=%s%08lx", mntp->mnt_opts,
  3755. X                MNTINFO_DEV, MNTINFO_PREF,
  3756. X                (u_long) stb.st_dev);
  3757. X        }
  3758. X        mntp->mnt_opts = zopts;
  3759. X    }
  3760. X#endif /* MNTINFO_DEV */
  3761. X
  3762. X#ifdef FIXUP_MNTENT
  3763. X    /*
  3764. X     * Additional fields in struct mntent
  3765. X     * are fixed up here
  3766. X     */
  3767. X    FIXUP_MNTENT(mntp);
  3768. X#endif
  3769. X
  3770. X    write_mntent(mntp);
  3771. X#endif /* UPDATE_MTAB */
  3772. X
  3773. X    return 0;
  3774. X}
  3775. X
  3776. X#ifdef MOUNT_HELPER_SOURCE
  3777. X#include MOUNT_HELPER_SOURCE
  3778. X#endif /* MOUNT_HELPER_SOURCE */
  3779. X
  3780. Xmain(argc, argv)
  3781. Xint argc;
  3782. Xchar **argv;
  3783. X{
  3784. X    struct nfs_args nfs_args;
  3785. X    struct mntent mnt;
  3786. X    int flags, ret;
  3787. X    char *fs_name, *mp_name, *hostname;
  3788. X
  3789. X    if (argc != 3) {
  3790. X        usage(argv[0]);
  3791. X        exit(1);
  3792. X    }
  3793. X    /* amd compat code */
  3794. X    mypid = getpid();
  3795. X
  3796. X    hostname = argv[1];
  3797. X    mp_name = argv[2];
  3798. X    fs_name = compute_fs_name(argv[1]);
  3799. X    bzero(&nfs_args, sizeof (nfs_args));
  3800. X    compute_nfs_options(&nfs_args);
  3801. X    compute_mntent_options(&mnt, fs_name, mp_name);
  3802. X    ret = compute_bindings(&nfs_args, hostname, mp_name);
  3803. X    if (ret < 0) exit(1);
  3804. X
  3805. X    flags = compute_mount_flags();
  3806. X    ret = mount_fs(&mnt, flags, (caddr_t) &nfs_args, 1, MOUNT_TYPE_NFS);
  3807. X    return ret;
  3808. X}
  3809. X
  3810. END_OF_FILE
  3811.   if test 8847 -ne `wc -c <'wwmount/wwmount.c'`; then
  3812.     echo shar: \"'wwmount/wwmount.c'\" unpacked with wrong size!
  3813.   fi
  3814.   # end of 'wwmount/wwmount.c'
  3815. fi
  3816. echo shar: End of archive 14 \(of 22\).
  3817. cp /dev/null ark14isdone
  3818. MISSING=""
  3819. 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
  3820.     if test ! -f ark${I}isdone ; then
  3821.     MISSING="${MISSING} ${I}"
  3822.     fi
  3823. done
  3824. if test "${MISSING}" = "" ; then
  3825.     echo You have unpacked all 22 archives.
  3826.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  3827. else
  3828.     echo You still must unpack the following archives:
  3829.     echo "        " ${MISSING}
  3830. fi
  3831. exit 0
  3832. exit 0 # Just in case...
  3833.