home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume42 / alex / part05 < prev    next >
Encoding:
Internet Message Format  |  1994-03-30  |  87.7 KB

  1. From: vac@CS.CMU.EDU (Vincent.Cate)
  2. Newsgroups: comp.sources.misc
  3. Subject: v42i043:  alex - NFS/FTP global filesystem, Part05/13
  4. Date: 30 Mar 1994 15:42:09 -0600
  5. Organization: Sterling Software
  6. Sender: root@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <2ncrnh$gp6@sparky.sterling.com>
  9. X-Md4-Signature: 7ad6967f7a352d3a9110ae1d187f0d50
  10.  
  11. Submitted-by: vac@CS.CMU.EDU (Vincent.Cate)
  12. Posting-number: Volume 42, Issue 43
  13. Archive-name: alex/part05
  14. Environment: Most Unix machines - with 100 MB to 10 GB of free disk
  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:  alexsrvr/src/Makefile alexsrvr/src/dirtoinfo.c
  21. # Wrapped by kent@sparky on Tue Mar 29 21:56:19 1994
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 5 (of 13)."'
  25. if test -f 'alexsrvr/src/Makefile' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'alexsrvr/src/Makefile'\"
  27. else
  28.   echo shar: Extracting \"'alexsrvr/src/Makefile'\" \(7473 characters\)
  29.   sed "s/^X//" >'alexsrvr/src/Makefile' <<'END_OF_FILE'
  30. X
  31. X# You probably only want to edit config.h to install Alex.
  32. X
  33. X# for prof both CF and LDF need "-p"
  34. X
  35. X# CFLAGS= -g -O -p -pg
  36. XCFLAGS= -O
  37. X
  38. X# -g -pg
  39. XLDFLAGS= 
  40. X
  41. XRPCGEN=    rpcgen
  42. XCC= cc
  43. X
  44. X#------------------------------End of configuration section.
  45. X
  46. X
  47. XNFSOBJS= nfs_prot_svc.o nfs_prot_xdr.o unfsd.o init.o fh.o 
  48. X
  49. XMOUNTOBJS= mount_svc.o mount_xdr.o unfsmntd.o fh.o alexlib.o phonehome.o \
  50. X           readinfo.o cmucs.o compat.o
  51. X
  52. XALEXOBJS= alex.o dirtoinfo.o ftpparent.o ftpchild.o alexlib.o remtimezone.o \
  53. X          stringtotime.o readinfo.o cmucs.o compat.o phonehome.o
  54. X
  55. X
  56. Xall: local.h basic alexfsck evictor printinfo 
  57. X
  58. Xlocal.h:
  59. X    echo '/* Put local config.h options in here.  Use #undef if needed. */' > local.h
  60. X
  61. X# Basic is what is needed to get started.
  62. Xbasic: alexd alexmountd
  63. X
  64. Xalexd:  ${NFSOBJS} ${ALEXOBJS} defs
  65. X    ${CC} $(LDFLAGS) -o alexd ${NFSOBJS} ${ALEXOBJS} -lm `/bin/csh -f libdefs`
  66. X
  67. Xalexmountd: ${MOUNTOBJS}
  68. X    ${CC} $(LDFLAGS) -o alexmountd ${MOUNTOBJS} `/bin/csh -f libdefs`
  69. X
  70. X
  71. X# Non basic
  72. X#
  73. Xevictor: evictor.o alexlib.o cmucs.o phonehome.o
  74. X    ${CC} ${LDFLAGS} -o evictor evictor.o alexlib.o cmucs.o compat.o phonehome.o
  75. X
  76. Xalexfsck: readinfo.o alexlib.o alexfsck.o cmucs.o compat.o phonehome.o
  77. X    ${CC} -o alexfsck alexfsck.o alexlib.o readinfo.o cmucs.o compat.o phonehome.o
  78. X
  79. Xprintinfo: printinfo.c
  80. X    ${CC} ${CFLAGS} -o printinfo printinfo.c
  81. X
  82. Xdefs: defs.o alexlib.o cmucs.o compat.o phonehome.o 
  83. X    ${CC} ${LDFLAGS} -o defs defs.o alexlib.o cmucs.o compat.o phonehome.o
  84. X
  85. X
  86. X# -----------------  major items above minor things below --------------------
  87. X
  88. X# if you do not have yacc just say "make noyacc" and then do "make"       
  89. Xnoyacc:
  90. X    touch stringtotime.c 
  91. X
  92. Xstringtotime.c: stringtotime.y
  93. X    /bin/rm stringtotime.c
  94. X    yacc -v stringtotime.y
  95. X    mv y.tab.c stringtotime.c
  96. X
  97. Xstringtotime.o: stringtotime.c
  98. X    ${CC} ${CFLAGS} -c -DYYDEBUG stringtotime.c
  99. X
  100. Xstringtotime: stringtotime.o stringtotimemain.o alexlib.o phonehome.o
  101. X    cc -o stringtotime stringtotime.o stringtotimemain.o alexlib.o phonehome.o
  102. X
  103. Xremtimezone: stringtotime.o remtimezonemain.o alexlib.o phonehome.o remtimezone.o
  104. X    cc -o remtimezone stringtotime.o remtimezonemain.o alexlib.o phonehome.o remtimezone.o
  105. X
  106. X
  107. X#  Installation stuff  -----------------------------------------------------
  108. X
  109. Xinstall: all installbasic defs
  110. X    /bin/csh -f install nonbasic
  111. X
  112. Xinstallbasic: basic defs
  113. X    /bin/csh -f install basic
  114. X
  115. X#  NFS Stuff ------------------------------------------------------------------
  116. X
  117. Xnorpcgen:
  118. X    touch nfs_prot.h
  119. X    touch nfs_prot_svc.c
  120. X    touch nfs_prot_xdr.c
  121. X    touch mount.h
  122. X    touch mount_svc.c
  123. X    touch mount_xdr.c
  124. X
  125. Xnfs_prot.h: nfs_prot.x config.nfs.h
  126. X    ${RPCGEN} -h -o $@ nfs_prot.x
  127. X
  128. Xnfs_prot_svc.c: nfs_prot.x config.nfs.h
  129. X    ${RPCGEN} -s udp nfs_prot.x | \
  130. X    sed \
  131. X        -e 's/main()/main(argc,argv,envp) int argc; char **argv, **envp; /' \
  132. X         -e 's/pmap_unset(/init_Log(); pmap_unset(/' \
  133. X        -e 's/RPC_ANYSOCK/makesock(NFS_PORT, NFS_MAXDATA)/' \
  134. X        -e 's/svc_run();/unfsd_init(argc,argv,envp); svc_run();/' \
  135. X        > $@
  136. X
  137. Xnfs_prot_xdr.c: nfs_prot.x config.nfs.h
  138. X    ${RPCGEN} -c -o $@ nfs_prot.x
  139. X
  140. X
  141. X
  142. Xmount.h: mount.x config.nfs.h
  143. X    ${RPCGEN} -h -o $@ mount.x
  144. X
  145. Xmount_svc.c: mount.x config.nfs.h
  146. X    ${RPCGEN} -s udp mount.x | \
  147. X    sed \
  148. X        -e 's/main()/main(argc,argv) int argc; char **argv;/' \
  149. X         -e 's/pmap_unset(/init_Log(); pmap_unset(/' \
  150. X        -e 's/svc_run();/unfsmntd_init(argc,argv); svc_run();/' \
  151. X        > $@
  152. X
  153. Xmount_xdr.c: mount.x config.nfs.h
  154. X    ${RPCGEN} -c -o $@ mount.x
  155. X
  156. X#  misc    ---------------------------------------------------------------------
  157. X
  158. Xclean:
  159. X    rm -rf *.o nfs_prot_svc.c nfs_prot_xdr.c nfs_prot.h y.tab.h \
  160. X        stringtotime.c mount_svc.c mount_xdr.c mount.h  alexd alexmountd \
  161. X        printinfo defs alexfsck evictor y.output
  162. X
  163. X
  164. X# could make and install "UidStr" but not needed 
  165. X
  166. XUidStr:
  167. X    cat /etc/passwd /etc/passwds | awk -f UidStrA.awk | sort -nu | awk -f UidStrB.awk > UidStr
  168. X
  169. X
  170. X#  To get and make a new version of the software ------------------------------
  171. X#
  172. X#  Different people like "getalex", "patchalex", and "updatealex" so 
  173. X#  we actually have all of them though they do similar things.  The
  174. X#  "srclinks" gives you symlinks to the latest source.
  175. X#
  176. X#  Except for "alpha" and "new" you need to run "make install" and
  177. X#  then either "grepnkill alexd" to restart or "start.alex" for coldstart.
  178. X
  179. X# Recommended - gets latest stuff, compiles, install, and starts things up
  180. Xalpha:
  181. X    /bin/csh -f getalex alex.alpha.tar.Z
  182. X
  183. X# Latest "stable" code.
  184. Xnew:
  185. X    /bin/csh -f getalex alex.tar.Z
  186. X
  187. X# Good for small changes.  If whole new files have been added it will miss them.
  188. X# But as new files are not added very often this usually works.
  189. Xpatch:
  190. X    /bin/csh -f patchalex
  191. X
  192. X# Copies all release files that have changed since last time.  
  193. Xupdate:
  194. X    /bin/csh -f updatealex
  195. X
  196. X# Just make symlinks to all of the source files.
  197. Xsrclinks:
  198. X    mv -f /usr/alexsrvr/src /usr/alexsrvr/src.old
  199. X    sh cp-rs /alex/edu/cmu/cs/sp/alex/src/alexsrvr/src /usr/alexsrvr/src
  200. X    echo "You can go back to real files by doing a     make new"
  201. X    echo " "
  202. X    echo "Your current directory has changed"
  203. X    pwd
  204. X
  205. X# Only first timers should do this 
  206. X# If there is a running server it will die and this will not finish
  207. Xalllinks:
  208. X    echo "This should only be run to get Alex the first time."
  209. X    echo "This should only be run as  alexsrvr."
  210. X    echo "If either of these is not true, you have 15 seconds to stop this."
  211. X    sleep 15
  212. X    (if [ ! -d /usr/alexsrvr/.old ] ; then mkdir /usr/alexsrvr/.old; fi ;\
  213. X     touch /usr/alexsrvr/tmp                                            ;\
  214. X     mv -f /usr/alexsrvr/* /usr/alexsrvr/.old                           ;\
  215. X     sh cp-rs /alex/edu/cmu/cs/sp/alex/src/alexsrvr /usr/alexsrvr       ;\
  216. X     /bin/rm -f /usr/alexsrvr/bin/*                                     ;\
  217. X     cd /usr/alexsrvr/src                                               ;\
  218. X     make install                                                       ;\
  219. X     echo "Run /usr/alexsrvr/bin/start.alex as root"                     )
  220. X
  221. X
  222. X# Get and compile archie
  223. Xarchie:
  224. X    /bin/csh -f /alex/edu/cmu/cs/sp/alex/user/bin/getpackage archie
  225. X
  226. X#  These are sort of development things ----------------------------------------
  227. X
  228. XLINTFLAGS = -abchx -DDEBUG 
  229. Xalexlint:
  230. X    lint -u alexlib.c dirtoinfo.c alex.c ftpparent.c ftpchild.c remtimezone.c stringtotime.c \
  231. X        unfsd.c fh.c readinfo.c phonehome.c
  232. X
  233. Xmountlint:
  234. X    lint -u alexlib.c unfsmntd.c fh.c readinfo.c
  235. X
  236. Xrcs:
  237. X    rcsci -q -l unfsd.c init.c fh.c alex.c ftpparent.c ftpchild.c dirtoinfo.c \
  238. X        alexlib.c phonehome.c remtimezone.c stringtotime.y readinfo.c \
  239. X        remtimezone.c mount.x nfs_prot.x alex.h alexincs.h \
  240. X                   config.h config.nfs.h Makefile makerelease printinfo.c \
  241. X                alexfsck.c evictor.c getalex defs.c install scripts/* \
  242. X                updatealex patchalex
  243. X
  244. Xbackup:
  245. X    cp *.x backups
  246. X    cp *.c backups
  247. X    cp *.h backups
  248. X    cp *.y backups
  249. X    cp Makefile backups
  250. X    cp getalex updatealex patchalex backups
  251. X    cp makerelease backups
  252. X
  253. Xrelease:
  254. X    makerelease
  255. X
  256. Xreleaseget:
  257. X    cp getalex /../alex/usr/anon/src
  258. X
  259. X
  260. X# include dependencies    -------------------------------------------------------
  261. X
  262. Xnfs_prot_svc.o nfs_prot_xdr.o unfsd.o fh.o init.o: nfs_prot.h config.nfs.h
  263. X
  264. Xmount_svc.o mount_xdr.o unfsmntd.o: mount.h config.nfs.h
  265. X
  266. Xfh.o unfsd.o init.o: unfsd.h fh.h config.nfs.h
  267. X
  268. Xftpparent.o ftpchild.o: alexftp.h
  269. X
  270. Xinit.o fh.o unfsd.o dirtoinfo.o ftpparent.o ftpchild.o alexlib.o \
  271. Xremtimezone.o alexmain.o remtimezonemain.o stringtotimemain.o \
  272. Xstringtotime.o stringtotime.c alex.o readinfo.o unfsmntd.o evictor.o \
  273. Xphonehome.o defs.o alexfsck.o: alex.h alexincs.h config.h local.h
  274. X
  275. X
  276. X
  277. END_OF_FILE
  278.   if test 7473 -ne `wc -c <'alexsrvr/src/Makefile'`; then
  279.     echo shar: \"'alexsrvr/src/Makefile'\" unpacked with wrong size!
  280.   fi
  281.   # end of 'alexsrvr/src/Makefile'
  282. fi
  283. if test -f 'alexsrvr/src/dirtoinfo.c' -a "${1}" != "-c" ; then 
  284.   echo shar: Will not clobber existing file \"'alexsrvr/src/dirtoinfo.c'\"
  285. else
  286.   echo shar: Extracting \"'alexsrvr/src/dirtoinfo.c'\" \(77292 characters\)
  287.   sed "s/^X//" >'alexsrvr/src/dirtoinfo.c' <<'END_OF_FILE'
  288. X
  289. X/* Copyright (c) 1992 Vincent Cate
  290. X * All Rights Reserved.
  291. X *
  292. X * Permission to use and modify this software and its documentation
  293. X * is hereby granted, provided that both the copyright notice and this
  294. X * permission notice appear in all copies of the software, derivative works
  295. X * or modified versions, and any portions thereof, and that both notices
  296. X * appear in supporting documentation.  This software or any derivate works
  297. X * may not be sold or distributed without prior written approval from
  298. X * Vincent Cate.
  299. X *
  300. X * THE SOFTWARE IS PROVIDED "AS IS" AND VINCENT CATE DISCLAIMS ALL
  301. X * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  302. X * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL
  303. X * VINCENT CATE BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
  304. X * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  305. X * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  306. X * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  307. X * OR PERFORMANCE OF THIS SOFTWARE.
  308. X *
  309. X * Users of this software agree to return to Vincent Cate any improvements
  310. X * or extensions that they make and grant Vincent Cate the rights to
  311. X * redistribute these changes.
  312. X *
  313. X */
  314. X
  315. X/* Todo:
  316. X *
  317. X * Does not handle places with filenames with spaces.  It would not
  318. X * be hard to do but then places that put extra stuff on the line would
  319. X * mess up (but that seems more fair really).
  320. X
  321. X *
  322. X *
  323. X
  324. X
  325. X */
  326. X
  327. X
  328. X/* Exports:
  329. X *    DirToInfo()    -   reads in a .alex.dir file and writes out a .alex.info
  330. X */
  331. X
  332. X
  333. X#ifdef EXECUTABLE
  334. X/*
  335. XFor security reasons I did not want to have executables show up as executable.
  336. XHowever, Durand wanted it and I said if he hacked it up I would include
  337. Xthe patchs.  Here are the comments from email from  durand alain denis 
  338. X<Alain.Durand@inria.fr> where he sent in EXECUTABLE hack.
  339. X
  340. XThe right way to do this is to add another field to .alex.info.  Too many 
  341. Xthings to do.
  342. X
  343. X>Basically, the idea is to catch the "x" bit when converting from
  344. X>.alex.dir to .alex.info (in dirtoinfo.c, in XXXTokensToParsedDir),
  345. X>faking a link with a special "-1" linkname to keep track of the information
  346. X>(in alexlib.c OneLineOut) and then, when reading the .alex.info file,
  347. X>(in readinfo.c ParseOneLine) tracking down this fake link,
  348. X> marking the file executable (Current->Executable) and then giving the
  349. X>file the correct rights (ATypeToStatMode) according to its executable flag.
  350. X>
  351. X>At first, I wanted to add an field in the .alex.info files to store the
  352. X>executable state of the files, but then I couldn't figure out a way to
  353. X>restart alex... I tried to modify the HostList, RootAlexInfo,... accordingly
  354. X>but it didn't work. So I use this trick to fake a link "-1". This have also
  355. X>the advantage to stay compatible with the original version...
  356. X>
  357. X
  358. XThis is ugly, for sure.  XXXX
  359. X*/
  360. X#endif
  361. X
  362. X#include "alexincs.h"
  363. X#include "alex.h"
  364. X
  365. X#ifdef ONLYSHOWREADABLE
  366. X#define ONLYSHOWREADABLEINT     1
  367. X#else
  368. X#define ONLYSHOWREADABLEINT    0
  369. X#endif
  370. X
  371. X/* returns 1 if not a normal file or directory 
  372. X */
  373. Xint SpecialFile(Current)
  374. Xstruct ParsedDir *Current;
  375. X{
  376. X    int Result;
  377. X
  378. X    Result=(streql(Current->Name, ".")        ||
  379. X            streql(Current->Name, "..")       ||
  380. X            streql(Current->Name, ALEXERROR)  ||
  381. X            streql(Current->Name, ALEXUPDATE) ||
  382. X            streql(Current->Name, ALEXDIR)    ||
  383. X            streql(Current->Name, ALEXINFO));
  384. X
  385. X    return(Result);
  386. X}
  387. X
  388. Xint SpecialFileOrError(Current)
  389. Xstruct ParsedDir *Current;
  390. X{
  391. X    int Result;
  392. X
  393. X    Result=(SpecialFile(Current) || (Current->Type == AERRORMESSAGE));
  394. X
  395. X    return(Result);
  396. X}
  397. X
  398. X
  399. Xint StringToTimeInt(s, Now)
  400. Xchar *s;
  401. Xstruct timeb *Now;
  402. X{
  403. X    struct timeb  Then;
  404. X    int status, Result;
  405. X
  406. X    Log2("StringToTimeInt input is  ", s);
  407. X
  408. X    status=StringToTimeb(s, Now, &Then);
  409. X
  410. X    if (status != AOK) {
  411. X        LogN("StringToTimeInt got back bad status and time of ", (int) Then.time);
  412. X        Result=Now->time;
  413. X    } else {
  414. X        Result=Then.time;
  415. X        if (Result > Now->time+60) {           
  416. X            LogN("StringToTimeInt  error future modification time after parsing ", Result);
  417. X            Log2("StringToTimeInt  error future ", s);
  418. X            LogN("Zone was ", (int) Then.timezone);
  419. X            if (Result <= (Now->time + (Then.timezone*60))) {   /* Could it be Greenwich? */
  420. X                Log("StringToTimeInt XXX fudging timezone to Greenwich ");
  421. X                Result -= Then.timezone*60;
  422. X            } else {
  423. X                Log("StringToTimeInt setting time to Now");
  424. X                Result=Now->time - (Now->time % 60);            /* round back an hour          */
  425. X                                                    /* otherwise caching fails badly as file  */
  426. X                                                    /* looks like it is changing all the time */
  427. X            }
  428. X        }
  429. X    }
  430. X
  431. X    LogN("StringToTimeInt returning ", Result);
  432. X    return(Result);
  433. X}
  434. X
  435. X
  436. X
  437. Xchar Month[12][5] ={"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  438. X                    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  439. X
  440. Xint IsAMonth(token)
  441. Xchar *token;
  442. X{
  443. X    int i;
  444. X
  445. X    for (i=0; i<12; i++) {
  446. X        if (strcasecmp(token, Month[i]) == 0) {
  447. X            return(1);
  448. X        }
  449. X    }
  450. X
  451. X    /* Log2("Was expecting a month but got ", token); */
  452. X    return(0);
  453. X}
  454. X
  455. X
  456. X
  457. X
  458. X
  459. Xint IsThreeSepNums(token, sep)
  460. Xchar *token;
  461. Xchar sep;
  462. X{
  463. X    int n1, n2, n3, Result;
  464. X
  465. X    n1=n2=n3=0;
  466. X    Result=1;
  467. X    while((*token != 0) && (isdigit(*token))) {
  468. X        n1=1;
  469. X        token++;
  470. X    }
  471. X
  472. X    if (*token++ != sep) Result=0;
  473. X
  474. X    while((*token != 0) && (isdigit(*token))) {
  475. X        n2=1;
  476. X        token++;
  477. X    }
  478. X
  479. X    if (*token++ != sep) Result=0;
  480. X    
  481. X    while((*token != 0) && (isdigit(*token))) {
  482. X        n3=1;
  483. X        token++;
  484. X    }
  485. X
  486. X    if (n1 && n2 && n3 && Result) {
  487. X        return(1);
  488. X    } else {
  489. X        return(0);
  490. X    }
  491. X}
  492. X
  493. X/*  returns true if token is of the form     7/11/90 */
  494. Xint IsSlashDate(token)
  495. Xchar *token;
  496. X{
  497. X    return(IsThreeSepNums(token, '/'));
  498. X}
  499. X
  500. X/*  returns true if token is of the form     11:01:15 */
  501. Xint IsTimeWithSecs(token)
  502. Xchar *token;
  503. X{
  504. X    return(IsThreeSepNums(token, ':'));
  505. X}
  506. X
  507. X/* 
  508. XABCODE   FIL      V         56       2669         16  7/11/90 11:01:15 PDH515
  509. XCGRID    GIF      V       8192          3          5  7/30/91  7:50:27 PDH515
  510. X
  511. XFUSION   89-00012 V         80        299          3  5/03/89 14:27:15 FUSION
  512. XFUSION   89-00013 V         80       2346         28  5/03/89 14:30:35 FUSION
  513. X
  514. X/alex/edu/columbia/cc/cuvmb
  515. X$$READ   ME       V         73         70          1 12/04/91 15:58:46 TCM301
  516. X$CUANON  DOC      V         72         33          1  2/15/89 17:56:46 TCM301
  517. X
  518. X */
  519. X
  520. Xint IsIBM(Tokens, NumTokens) 
  521. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  522. Xint NumTokens;
  523. X{
  524. X    return((NumTokens >= 7) && IsSlashDate(Tokens[6]) && IsTimeWithSecs(Tokens[7]));
  525. X}
  526. X
  527. X
  528. X/*
  529. X/alex/uk/ac/hensa/micros
  530. XFiles matching pattern '*' in directory '.' :
  531. X
  532. X00contents                    719 bytes   4 Feb 1993 16:15
  533. Xjob.txt                      2005 bytes   4 Feb 1993 16:11
  534. Xnewsfile                     1240 bytes   4 Feb 1993 16:15
  535. X
  536. X
  537. XDirectories matching pattern '*':
  538. X
  539. Xchest                    <DIRECTORY>     12 Feb 1993 14:25
  540. Xcti                      <DIRECTORY>      3 Nov 1992 12:08
  541. Xdocs                     <DIRECTORY>     25 Nov 1992 14:45
  542. Xtools                    <DIRECTORY>      3 Nov 1992 23:50
  543. Xx                        <DIRECTORY>      3 Nov 1992 23:51
  544. X*/
  545. X
  546. Xint IsHENSA(Tokens, NumTokens)
  547. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  548. Xint NumTokens;
  549. X{
  550. X    if (NumTokens<1) return 0;
  551. X    if (streql(Tokens[0],"Files")) return 1;
  552. X    if (streql(Tokens[0],"Directories")) return 1;
  553. X    if (NumTokens>2 && streql(Tokens[1],"<DIRECTORY>")) return 1;
  554. X    if (NumTokens>3 && streql(Tokens[2],"bytes")) return 1;
  555. X    return 0;
  556. X}
  557. X
  558. X/*
  559. X *    Novel.  From /alex/edu/usu/netlab2:
  560. X- [R----F--] jrd                  1646       May 07 21:43    index
  561. Xd [R----F--] jrd                   512       Aug 24 20:06    netwire
  562. Xd [R----F--] jrd                   512       Aug 21 18:44    pktdrvr
  563. X
  564. X
  565. X      or /alex/com/wordperfect/ftp
  566. X
  567. Xd [R----F--] scotteh               512       Aug 24 20:05    msdos
  568. X- [R----F--] scotteh                74       Jun 29 17:12    read.me
  569. X0     1       2                     3         4   5  6        7
  570. X*/
  571. X
  572. Xint IsNOVEL(Tokens, NumTokens)
  573. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  574. Xint NumTokens;
  575. X{
  576. X    if (NumTokens != 8) return(0);
  577. X    if ((Tokens[0][0] != 'd') && (Tokens[0][0] != '-') || Tokens[0][1] != 0) return(0);
  578. X    if (Tokens[1][0] != '[') return(0);
  579. X    Log("IsNovel");
  580. X    return(1);
  581. X}
  582. X
  583. Xint NOVELTokensToParsedDir(Tokens, NumTokens, Current, Now)
  584. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  585. Xint NumTokens;
  586. Xstruct ParsedDir *Current;
  587. Xstruct timeb *Now;
  588. X{
  589. X    int Result;
  590. X    char TimeForParsing[200];
  591. X
  592. X    LogN("NOVELTokensToParsedDir", NumTokens);
  593. X
  594. X    (void) strcpy(Current->Name, Tokens[7]);          /* filename */
  595. X
  596. X    if (Tokens[0][0] == 'd') {
  597. X        Current->Type=ADIR; 
  598. X    } else {
  599. X        Current->Type=AFILE; 
  600. X#ifdef EXECUTABLE
  601. X        Current->Executable = 0;                      /* Not Yet Implemented */
  602. X#endif
  603. X    }
  604. X
  605. X    Current->Size=atoi(Tokens[3]);  
  606. X
  607. X    (void) strcpy(TimeForParsing, Tokens[4]);
  608. X    (void) strcat(TimeForParsing, " ");
  609. X    (void) strcat(TimeForParsing, Tokens[5]);
  610. X    (void) strcat(TimeForParsing, " ");
  611. X    (void) strcat(TimeForParsing, Tokens[6]);
  612. X    Current->Date = (unsigned int) StringToTimeInt(TimeForParsing, Now);
  613. X    LogN("NOVELTokensToParsedDir Date ", Current->Date);
  614. X
  615. X    if (strlen(Current->Name) > 1) {
  616. X        Result=AOK;
  617. X    } else {
  618. X        Result=AFAIL;
  619. X    }
  620. X
  621. X    return(Result);
  622. X}
  623. X
  624. X/*
  625. XPS:<ANONYMOUS>
  626. X    1752(07)  3-Nov-90 14:49:55 00-README.TXT.2
  627. X    1298(07) 30-Jun-90 20:18:15 ACCOUNTS.INFO.5
  628. X   10823(07) 24-Oct-87 17:05:57 BINTNXVMS.C.1
  629. X */
  630. X
  631. Xint IsTOPS20(Tokens, NumTokens)
  632. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  633. Xint NumTokens;
  634. X{
  635. X    return((NumTokens >=3) && HasChar(Tokens[0], '(') && IsTimeWithSecs(Tokens[2]));  /* had '\(' XXX */
  636. X}
  637. X
  638. X
  639. X/*
  640. X
  641. X/alex/il/ac/tau/vm
  642. XFUSION   89-00008 V         80       2281         26  5/03/89 14:25:54 FUSION
  643. XFUSION   89-00009 V         80       2061         24  5/03/89 14:26:18 FUSION
  644. XFUSION   89-00010 V         80       2025         21  5/03/89 14:26:41 FUSION
  645. XFUSION   89-00011 V         80       2264         25  5/03/89 14:27:08 FUSION
  646. XFUSION   89-00012 V         80        299          3  5/03/89 14:27:15 FUSION
  647. XFUSION   89-00013 V         80       2346         28  5/03/89 14:30:35 FUSION
  648. X
  649. X/alex/edu/columbia/cc/cuvmb
  650. X$$READ   ME       V         73         70          1 12/04/91 15:58:46 TCM301
  651. X$CUANON  DOC      V         72         33          1  2/15/89 17:56:46 TCM301
  652. X$CULOCAL DOC      V         72         36          1  2/06/89 16:58:02 TCM301
  653. X$CUMXHOS DOC      V         73         47          1  9/05/89 13:17:52 TCM301
  654. X
  655. X*/
  656. X
  657. Xint IBMTokensToParsedDir(Tokens, NumTokens, Current, Now)
  658. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  659. Xint NumTokens;
  660. Xstruct ParsedDir *Current;
  661. Xstruct timeb *Now;
  662. X{
  663. X    int Result;
  664. X    char TimeForParsing[200];
  665. X
  666. X    LogN("IBMTokensToParsedDir", NumTokens);
  667. X
  668. X    (void) strcpy(Current->Name, Tokens[0]);          /* basename */
  669. X
  670. X    if (streql(Tokens[1], "DISK")) {                  /* extension */
  671. X        Current->Type=ADIR; 
  672. X    } else {
  673. X        Current->Type=AFILE; 
  674. X#ifdef EXECUTABLE
  675. X                Current->Executable = 0;        /* Not Yet Implemented */
  676. X#endif
  677. X        (void) strcat(Current->Name, ".");
  678. X        (void) strcat(Current->Name, Tokens[1]);
  679. X    }
  680. X
  681. X    ToLower(Current->Name);
  682. X
  683. X    Current->Size=atoi(Tokens[3]) * atoi(Tokens[4]);           /* just a guess */
  684. X
  685. X
  686. X    (void) strcpy(TimeForParsing, Tokens[6]);
  687. X    (void) strcat(TimeForParsing, " ");
  688. X    (void) strcat(TimeForParsing, Tokens[7]);
  689. X    Current->Date = (unsigned int) StringToTimeInt(TimeForParsing, Now);
  690. X
  691. X
  692. X    if (strlen(Current->Name) > 1) {
  693. X        Result=AOK;
  694. X    } else {
  695. X        Result=AFAIL;
  696. X    }
  697. X
  698. X    return(Result);
  699. X}
  700. X
  701. X
  702. X
  703. Xint UNKNOWNTokensToParsedDir(Tokens, NumTokens, Current)
  704. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  705. Xint NumTokens;
  706. Xstruct ParsedDir *Current;
  707. X{
  708. X    int wasadir;
  709. X
  710. X    LogN("UNKNOWNTokensToParsedDir", NumTokens);
  711. X
  712. X    if (NumTokens < 1) return(AFAIL);
  713. X
  714. X    if ((strcasecmp(Tokens[0], "Total") == 0) && (NumTokens <= 2)) {
  715. X        Log("UNKNOWNTokensToParsedDir skipping Total ");
  716. X        if (NumTokens == 2) {
  717. X            Log2("UNKNOWNTokensToParsedDir full line was     Total ", Tokens[1]);
  718. X        }
  719. X        return(AFAIL);
  720. X    }
  721. X
  722. X    if ((NumTokens == 2) && (strcasecmp(Tokens[1], "unreadable") == 0)) {
  723. X        Log("UNKNOWNTokensToParsedDir combining unreadable ");
  724. X        (void) strcpy(Current->Name, "ALEX Message: ");
  725. X        (void) strcat(Current->Name, Tokens[0]);
  726. X        (void) strcat(Current->Name, " ");
  727. X        (void) strcat(Current->Name, Tokens[1]);
  728. X        Current->Type=AFILE;
  729. X        Current->Size=0;   
  730. X        return(AOK);                         /* maybe we play with protections someday  XXX */
  731. X    }
  732. X
  733. X    (void) strcpy(Current->Name, Tokens[0]);
  734. X    wasadir=RemoveTrailingSlash(Current->Name);
  735. X
  736. X    if (wasadir) {
  737. X        Current->Type=ADIR;
  738. X    } else {
  739. X        Current->Type=AFILE;
  740. X#ifdef EXECUTABLE
  741. X                Current->Executable = 0;        /* Not Yet Implemented */
  742. X#endif
  743. X    }
  744. X
  745. X    Current->Size=1;            /* just one byte to get things started */
  746. X
  747. X    if (Current->Name[0] != '/') {
  748. X        return(AOK);
  749. X    } else {   
  750. X        return(AFAIL);
  751. X    }
  752. X}
  753. X
  754. X/*
  755. XDECVMS
  756. XANNOUNCEMENTS.TXT;1        11   2-MAY-1991 15:31 [ANONYMOUS] (RWED,RWED,RE,)
  757. X00-DIRECTORY.FULL;2      4842  25-NOV-1992 19:21 AUI$TEX (RE,RWED,RE,RE)
  758. X                          ^-- 512 byte blocks
  759. XDECVMS2
  760. X.NEWSRC;1            10-OCT-1991 11:20:33    23606/47     (RWED,RWED,RE,)
  761. X                                                ^-- bytes
  762. X
  763. X
  764. X */
  765. Xint DECVMSTokensToParsedDir(Tokens, NumTokens, Current, Now)
  766. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  767. Xint NumTokens;
  768. Xstruct ParsedDir *Current;
  769. Xstruct timeb *Now;
  770. X{
  771. X    char TimeForParsing[MAXTOKENLEN];
  772. X    char *tmp;
  773. X    int loc, j, NumBlocks;
  774. X
  775. X    LogN("DECVMSTokensToParsedDir", NumTokens);
  776. X
  777. X    (void) strcpy(Current->Name, Tokens[0]);
  778. X
  779. X    for (tmp=Current->Name; *tmp != 0; tmp++) {
  780. X        if (isupper(*tmp)) {
  781. X            *tmp=tolower(*tmp);
  782. X        }
  783. X        if (*tmp==';') {
  784. X            *tmp=0;                        /* we don't need no stinking semicolons */
  785. X        }
  786. X    }
  787. X
  788. X    loc=WhereString(Current->Name, "]");
  789. X    if (loc>=0) {                          /* if has directory path get rid of it */
  790. X        for (j=0; j<(loc+1); j++) {
  791. X            Current->Name[j]=Current->Name[j+loc+1];
  792. X        }
  793. X    }
  794. X
  795. X    loc=WhereString(Current->Name, ".dir");         /* use as type info but get rid of it */
  796. X    if (loc>=0) {
  797. X        Current->Name[loc]=0;                           /* chop him */
  798. X        Current->Type=ADIR;
  799. X    } else {
  800. X        Current->Type=AFILE;
  801. X#ifdef EXECUTABLE
  802. X                Current->Executable = 0;        /* Not Yet Implemented */
  803. X#endif
  804. X
  805. X    }
  806. X
  807. X    if (HasChar(Tokens[3], '/')) {                      /* is this DECVMS2 */
  808. X        (void) strcpy(TimeForParsing, Tokens[1]);
  809. X        (void) strcat(TimeForParsing, " ");
  810. X        (void) strcat(TimeForParsing, Tokens[2]);
  811. X        Current->Date = (unsigned int) StringToTimeInt(TimeForParsing, Now);
  812. X        Current->Size= atoi(Tokens[3]);             /* sizes almost right - modulo cr/lf -> lf */
  813. X    } else {
  814. X        (void) strcpy(TimeForParsing, Tokens[2]);
  815. X        (void) strcat(TimeForParsing, " ");
  816. X        (void) strcat(TimeForParsing, Tokens[3]);
  817. X        Current->Date = (unsigned int) StringToTimeInt(TimeForParsing, Now);
  818. X        NumBlocks=atoi(Tokens[1]);                  /* use blocks to estimate size  */
  819. X        if (NumBlocks > 1) {
  820. X            Current->Size=512*(NumBlocks-1);        /* much better to be low than high with NFS */
  821. X        } else {
  822. X            if (Current->Type==ADIR) {
  823. X                Current->Size=512;         
  824. X            } else {
  825. X                Current->Size=1;                    /* much better to be low than high with NFS */
  826. X            }
  827. X        }
  828. X    }
  829. X
  830. X    return(AOK);
  831. X}
  832. X
  833. X
  834. X/*  Input:   "foo.bar"
  835. X *  Output:  "foo"
  836. X *  Destructive
  837. X */
  838. XCutAtLastDot(s)
  839. Xchar *s;
  840. X{
  841. X    char *LastDot;
  842. X
  843. X    LastDot = rindex(s, '.');
  844. X
  845. X    if (LastDot != NULL) {
  846. X        *LastDot = 0;
  847. X    }
  848. X}
  849. X
  850. X
  851. X/*  Input  00README.TXT.1,7    
  852. X *    or   MAC.DIRECTORY.1
  853. X *
  854. X *  Output: 00readme.txt       return(0)
  855. X *    or    mac                return(1)
  856. X */
  857. Xint DECTENTokensToParsedDir(Tokens, NumTokens, Current)
  858. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  859. Xint NumTokens;
  860. Xstruct ParsedDir *Current;
  861. X{
  862. X    int i;
  863. X
  864. X    LogN("DECTENTokensToParsedDir", NumTokens); 
  865. X    (void) strcpy(Current->Name, Tokens[0]);
  866. X    ToLower(Current->Name);
  867. X
  868. X    i=WhereString(Current->Name, ".directory");
  869. X    if (i>=0) {
  870. X        Current->Name[i]=0;                               /* chop him */
  871. X        Current->Type=ADIR;
  872. X    } else {
  873. X        CutAtLastDot(Current->Name);
  874. X        Current->Type=AFILE;
  875. X#ifdef EXECUTABLE
  876. X        Current->Executable = 0;        /* Not Yet Implemented */
  877. X#endif
  878. X    }
  879. X
  880. X    return(AOK);
  881. X}
  882. X
  883. Xint HENSATokensToParsedDir(Tokens, NumTokens, Current, Now)
  884. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  885. Xint NumTokens;
  886. Xstruct ParsedDir *Current;
  887. Xstruct timeb *Now;
  888. X{
  889. X    char TimeForParsing[MAXTOKENLEN];
  890. X    int i=0;
  891. X
  892. X    LogN("HENSATokensToParsedDir", NumTokens);
  893. X
  894. X    if (NumTokens<6) return (AFAIL);
  895. X    (void) strcpy(Current->Name, Tokens[0]);
  896. X    if (streql(Tokens[1],"<DIRECTORY>")) {
  897. X    Current->Type=ADIR;
  898. X    Current->Size=512;
  899. X        i=2;
  900. X    } else {
  901. X        if (streql(Tokens[2],"bytes")) {
  902. X             Current->Type=AFILE;
  903. X#ifdef EXECUTABLE
  904. X             Current->Executable = 0;   /* Not Yet Implemented */
  905. X#endif
  906. X             Current->Size=atoi(Tokens[1]);
  907. X             i=3;
  908. X        }
  909. X    }
  910. X    if (i) {
  911. X    sprintf(TimeForParsing,"%s-%s-%s %s",Tokens[i],Tokens[i+1],Tokens[i+2],Tokens[i+3]);
  912. X    Current->Date = (unsigned int) StringToTimeInt(TimeForParsing, Now);
  913. X    return(AOK);
  914. X    }
  915. X    return(AFAIL);
  916. X}
  917. X
  918. X
  919. X/*  Input:    00-README.TXT.2
  920. X *
  921. X *  Output:   00-readme.txt
  922. X */
  923. X
  924. Xint TOPS20TokensToParsedDir(Tokens, NumTokens, Current)
  925. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  926. Xint NumTokens;
  927. Xstruct ParsedDir *Current;
  928. X{
  929. X    LogN("TOPS20TokensToParsedDir", NumTokens);
  930. X
  931. X    (void) strcpy(Current->Name, Tokens[NumTokens+1]);
  932. X    ToLower(Current->Name);
  933. X    CutAtLastDot(Current->Name);
  934. X    Current->Type=AFILE;
  935. X#ifdef EXECUTABLE
  936. X        Current->Executable = 0;        /* Not Yet Implemented */
  937. X#endif
  938. X
  939. X    return(AOK);
  940. X}
  941. X
  942. X/*  Returns true if s is of the form "drwxr-xr-x"
  943. X *
  944. X *  Some day I should profile alex and see how slow and silly this is XXXX
  945. X *     d  if the entry is a directory;
  946. X *     b  if the entry is a block-type special file;
  947. X *     c  if the entry is a character-type special file;
  948. X *     l  if the entry is a symbolic link;
  949. X *     s  if the entry is a socket, or
  950. X *     -  if the entry is a plain file.
  951. X *
  952. X *     r  if the file is readable;
  953. X *     w  if the file is writable;
  954. X *     x  if the file is executable;
  955. X *     -  if the indicated permission is not granted.
  956. X */
  957. X
  958. X/*  for each character we have 1 integer.
  959. X *  Each integer has more than 10 bits, but we use 10 as 10 booleans
  960. X *    indicating if that character is ok in that position.
  961. X */
  962. X
  963. Xunsigned int BitArrayStd[256];
  964. Xunsigned int BitArrayReadFile[256];
  965. Xunsigned int BitArrayReadDir[256];
  966. X
  967. X/*  AIX needs the DFL if NFS mounted */
  968. Xchar BitInputStd[10][10]=     {"DFLdbcls-", "r-", "w-", "xsS-", "r-", "w-", "xsS-", "r-", "w-", "xstS-"};
  969. Xchar BitInputReadFile[10][10]={"DFLdbcls-", "r-", "w-", "xsS-", "r",  "w-", "xsS-", "r",  "w-", "xstS-"};
  970. Xchar BitInputReadDir[10][10]= {"DFLdbcls-", "r-", "w-", "xsS-", "r",  "w-", "xsS",  "r",  "w-", "xstS"};
  971. X
  972. X
  973. XInitBitArray(Input, BitArray)
  974. Xchar Input[10][10];
  975. Xunsigned int BitArray[256];
  976. X{
  977. X    int i, j, bit, c;
  978. X
  979. X    for (i=0; i<256; i++) {
  980. X        BitArray[i]=0;
  981. X    }
  982. X
  983. X    bit = 1;
  984. X    for (i=0; i<10; i++) {
  985. X        for (j=0; Input[i][j] != 0; j++) {
  986. X            c=Input[i][j];
  987. X            BitArray[c] |= bit;
  988. X        }
  989. X        bit = bit << 1;
  990. X    }
  991. X}
  992. X
  993. X/* This should become a fast table lookup XXXX */
  994. Xint IsUnixProtections(s, OnlyIfReadable)
  995. Xchar *s;
  996. Xint  OnlyIfReadable;
  997. X{
  998. X    int IsDir, i;
  999. X    static int NeedInit=1;
  1000. X    unsigned int *BitArrayPtr, bit; 
  1001. X
  1002. X    if (NeedInit) {
  1003. X        InitBitArray(BitInputStd,      BitArrayStd);
  1004. X        InitBitArray(BitInputReadFile, BitArrayReadFile);
  1005. X        InitBitArray(BitInputReadDir,  BitArrayReadDir);
  1006. X        NeedInit=0;
  1007. X    }
  1008. X
  1009. X    /* if (strlen(s) != 10) return(0);   No because it messes up when 2 fields merge as in:
  1010. X     *     drwxrwsr-x130 root     274          3072 Sep 12 08:37 pub         */
  1011. X
  1012. X    if (strlen(s) < 10) return(0); 
  1013. X
  1014. X    IsDir = (*s == 'd');
  1015. X
  1016. X    if (OnlyIfReadable) {
  1017. X        if (IsDir) {
  1018. X            BitArrayPtr=BitArrayReadDir;
  1019. X        } else {
  1020. X            BitArrayPtr=BitArrayReadFile;
  1021. X        }
  1022. X    } else {
  1023. X        BitArrayPtr=BitArrayStd;
  1024. X    }    
  1025. X
  1026. X    bit = 1;
  1027. X    for (i=0; i<10; i++) {
  1028. X        if ((BitArrayPtr[*s++] & bit) == 0) return(0);
  1029. X        bit = bit << 1;
  1030. X    }
  1031. X
  1032. X    return(1);                          /* really looks like Unix */
  1033. X}
  1034. X
  1035. X
  1036. XIsUNIX(Tokens, NumTokens, OnlyIfReadable)
  1037. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  1038. Xint NumTokens;
  1039. Xint OnlyIfReadable;
  1040. X{
  1041. X    return((NumTokens > 2) && (IsUnixProtections(Tokens[0], OnlyIfReadable)));
  1042. X}
  1043. X
  1044. XIsHPUX(Tokens, NumTokens, OnlyIfReadable)
  1045. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  1046. Xint NumTokens;
  1047. Xint OnlyIfReadable;
  1048. X{
  1049. X    return((NumTokens > 2) && (IsUnixProtections(Tokens[1], OnlyIfReadable)));
  1050. X}
  1051. X
  1052. X
  1053. X
  1054. Xint IsTime(s)
  1055. Xchar *s;
  1056. X{
  1057. X    if (isdigit(s[0]) && isdigit(s[1]) && (s[2] == ':') && isdigit(s[3]) && isdigit(s[4])) {
  1058. X        return(1);
  1059. X    } else {
  1060. X        return(0);
  1061. X    }
  1062. X}
  1063. X
  1064. X
  1065. X/*
  1066. XCLDATA:[ANONYMOUS_FTP.FILES]
  1067. X
  1068. X00README.TXT;7              6   9-APR-1991 18:14 [ANONYMOUS] (RWED,RE,RE,RE)
  1069. XALEX.DIR;1                  8  18-OCT-1990 07:20 [ANONYMOUS] (RWED,RE,RE,RE)
  1070. XANNOUNCEMENTS.TXT;1        11   2-MAY-1991 15:31 [ANONYMOUS] (RWED,RWED,RE,)
  1071. X
  1072. X*/
  1073. X
  1074. XIsDECVMS(Tokens, NumTokens)
  1075. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  1076. Xint NumTokens;
  1077. X{
  1078. X    return((NumTokens >=4) && HasChar(Tokens[0], ';') && IsTime(Tokens[3])); 
  1079. X}
  1080. X
  1081. X/*
  1082. X.NEWSRC;1            10-OCT-1991 11:20:33    23606/47     (RWED,RWED,RE,)
  1083. XFTPD.LOG;2367        22-OCT-1991 21:08:36        0/0      (RWED,RWED,RE,)
  1084. XM51X.GIF;2           29-NOV-1990 12:15:29   118327/232    (RWED,RWED,RE,RE)
  1085. XM57.GIF;1            31-MAR-1991 11:38:21    47425/93     (RWED,RWED,RE,RE)
  1086. X*/
  1087. X
  1088. XIsDECVMS2(Tokens, NumTokens)
  1089. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  1090. Xint NumTokens;
  1091. X{
  1092. X    return ((NumTokens >= 4) &&  HasChar(Tokens[0], ';') && IsTime(Tokens[2])  && 
  1093. X                  HasChar(Tokens[3], '/'));
  1094. X}
  1095. X
  1096. X  
  1097. X       
  1098. X/* 
  1099. X *  Returns 1 if is right type 
  1100. X */ 
  1101. Xint IsRightType(Tokens, NumTokens, TypeOfDir) 
  1102. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  1103. Xint NumTokens;
  1104. Xint TypeOfDir;
  1105. X{
  1106. X    switch(TypeOfDir) {
  1107. X        case UNIX:     return(IsUNIX(Tokens, NumTokens, ONLYSHOWREADABLEINT)); 
  1108. X        case HPUX:     return(IsHPUX(Tokens, NumTokens, ONLYSHOWREADABLEINT)); 
  1109. X        case DECVMS:   return(IsDECVMS(Tokens, NumTokens) || IsDECVMS2(Tokens, NumTokens)); 
  1110. X        case HENSA:    return(IsHENSA(Tokens,NumTokens));
  1111. X        case NOVEL:    return(IsNOVEL(Tokens,NumTokens));
  1112. X#ifndef ONLYSAFEPARSE
  1113. X        case IBM:      return(IsIBM(Tokens, NumTokens)); 
  1114. X        case TOPS20:   return(IsTOPS20(Tokens, NumTokens));   
  1115. X/*        case DECTEN:   return(IsDECTEN(Tokens, NumTokens)); */
  1116. X        case UNKNOWN:   return(NumTokens > 0);
  1117. X#endif
  1118. X        default:        return(0); 
  1119. X    }
  1120. X}
  1121. X
  1122. Xint TokensToParsedDir(Tokens, NumTokens, TypeOfDir, Current, Now, DirPath, HostPath)
  1123. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  1124. Xint NumTokens;
  1125. Xint TypeOfDir;
  1126. Xstruct ParsedDir *Current;
  1127. Xstruct timeb *Now;
  1128. Xchar *DirPath;
  1129. Xchar *HostPath;
  1130. X{
  1131. X    int Result;
  1132. X    char buf[100];
  1133. X
  1134. X    switch(TypeOfDir) {
  1135. X        case UNIX:     Result=UNIXTokensToParsedDir(Tokens, NumTokens, Current, Now, 
  1136. X                                              DirPath, HostPath, 0);
  1137. X                       break;
  1138. X        case HPUX:     Result=UNIXTokensToParsedDir(Tokens, NumTokens, Current, Now, 
  1139. X                                              DirPath, HostPath, 1);
  1140. X                       break;
  1141. X        case DECVMS:   Result=DECVMSTokensToParsedDir(Tokens, NumTokens, Current, Now);
  1142. X                       break;
  1143. X        case NOVEL:    Result=NOVELTokensToParsedDir(Tokens, NumTokens, Current, Now);
  1144. X                       break;
  1145. X        case HENSA:    Result=HENSATokensToParsedDir(Tokens, NumTokens, Current, Now);
  1146. X                       break;
  1147. X
  1148. X#ifndef ONLYSAFEPARSE
  1149. X        case IBM:      Result=IBMTokensToParsedDir(Tokens, NumTokens, Current, Now);
  1150. X                       break;
  1151. X        case TOPS20:   Result=TOPS20TokensToParsedDir(Tokens, NumTokens, Current);
  1152. X                       break;
  1153. X        case DECTEN:   Result=DECTENTokensToParsedDir(Tokens, NumTokens, Current);
  1154. X                       break;
  1155. X#endif
  1156. X        case UNKNOWN:  Result=UNKNOWNTokensToParsedDir(Tokens, NumTokens, Current);
  1157. X                       break;
  1158. X        default:
  1159. X             AlexAssert(FALSE);
  1160. X    }
  1161. X
  1162. X    Log2("TokensToParsedDir Date", DateStr((time_t) Current->Date, buf));
  1163. X    return(Result);
  1164. X}
  1165. X
  1166. X
  1167. X
  1168. X
  1169. X/*  Do this democratically.  We vote on it and whoever gets the most votes wins.
  1170. X *
  1171. X */
  1172. X#define NUMVOTES 5
  1173. Xint DetermineTypeOfDir(DirFile)
  1174. XFILE *DirFile;
  1175. X{
  1176. X    char line[MAXPATH];
  1177. X    int TypeVotes[MaxHostType+3];
  1178. X    char Tokens[MAXTOKENS][MAXTOKENLEN];
  1179. X    int i, Winner, InputOk, NumTokens, NumLines;
  1180. X
  1181. X    for (i=0; i<=UNKNOWN; i++) {
  1182. X        TypeVotes[i]=0;
  1183. X    }
  1184. X
  1185. X    InputOk=1; 
  1186. X    NumLines=0;
  1187. X    for (i=0; i<NUMVOTES && InputOk; i++) {
  1188. X        if (fgets(line, MAXPATH, DirFile) == NULL) {
  1189. X            InputOk=0;
  1190. X        } else {
  1191. X            NumLines++;
  1192. X
  1193. X            NumTokens=LineToTokens(line, Tokens);
  1194. X            if (NumTokens>0) {                               
  1195. X                if (IsUNIX(Tokens, NumTokens, 0)) {
  1196. X                    TypeVotes[UNIX]++;
  1197. X
  1198. X                } else if  (IsDECVMS(Tokens, NumTokens)) {
  1199. X                    TypeVotes[DECVMS]++;
  1200. X
  1201. X                } else if  (IsDECVMS2(Tokens, NumTokens)) {
  1202. X                    TypeVotes[DECVMS]++;
  1203. X
  1204. X                } else if  (IsHPUX(Tokens, NumTokens, 0)) {
  1205. X                    TypeVotes[HPUX]++;
  1206. X
  1207. X                } else if (IsNOVEL(Tokens, NumTokens)) {
  1208. X                    TypeVotes[NOVEL]++;
  1209. X
  1210. X                } else if (IsHENSA(Tokens, NumTokens)) {
  1211. X                    TypeVotes[HENSA]++;
  1212. X
  1213. X#ifndef ONLYSAFEPARSE
  1214. X                } else if (IsTOPS20(Tokens, NumTokens)) {
  1215. X                    TypeVotes[TOPS20]++;
  1216. X
  1217. X                } else if  (IsIBM(Tokens, NumTokens)) {
  1218. X                    TypeVotes[IBM]++;
  1219. X#endif
  1220. X                }
  1221. X
  1222. X              /*  TypeVotes[DECTEN]+=IsDECTEN(Tokens, NumTokens);  */
  1223. X            }
  1224. X        }
  1225. X    }        
  1226. X
  1227. X    Winner=UNKNOWN;
  1228. X    for (i=0; i<=UNKNOWN; i++) {
  1229. X        if (TypeVotes[i] > TypeVotes[Winner]) { 
  1230. X            Winner=i;
  1231. X        }
  1232. X    }
  1233. X
  1234. X    LogT("DetermineTypeOfDir returning ", Winner);
  1235. X    LogN("DetermineTypeOfDir winner had ", TypeVotes[Winner]);
  1236. X    if (Winner==UNKNOWN) {
  1237. X        LogN("DetermineTypeOfDir lines checked ", NumLines);
  1238. X    }
  1239. X
  1240. X    return(Winner);
  1241. X}
  1242. X
  1243. X/*
  1244. X *  Input "alexdir" is a path for a file of the form:
  1245. X
  1246. Xdrwxr-xr-x  2 1092     tty           512 Mar 27 01:57 china-related
  1247. X-r--r--r--  1 root     tty         20182 Nov  5  1988 virus.patch
  1248. X-r--r--r--341 root     tty        220680 Nov  5  1988 foobar
  1249. Xlrwxr-xr-x  1 50       21             23 Aug 15 16:04 comp.sources.3b1 -> usenet/comp.sources.3b1
  1250. X-rw-r--r--  2 vac      warp       61574 Aug 26 02:59 space-companies
  1251. Xdrwxrwxr-x1693 7        21          39936 Aug 11 23:46 faces
  1252. Xdrwxr-xr-x  2 vac      warp        1024 Aug 18 23:51 space-investors.mail
  1253. X-rw-r--r--  1 1092     tty         28575 May  7 15:54 comm1.c
  1254. Xdrwxrwsr-x  2 27847    101          9216 Jul 24 04:44 gif
  1255. Xdrwxr-sr-x  2 27847    101           512 Nov 30  1990 gray
  1256. Xdr-xr-xr-x 23 ftp           daemon        512 Jun 20 15:41 pub
  1257. Xdrwxrwxrwx  2 ftp           none          512 May 21 01:37 tmp
  1258. Xlrwxrwxrwx  1 root     wheel           1 May 29 11:33 ftp -> .
  1259. Xdrwxrwxrwx   2 3             80 Jul 19 11:33 incomming
  1260. Xdr-xr-xr-x   4 3            240 Oct 10  1990 pub
  1261. Xlrwxrwxrwx  1 root     wheel          11 May 29 11:30 news.pub -> .r/news.pub
  1262. X            0  1        2              3  4  5   6     7
  1263. X                                                  .   
  1264. X                                                  50 
  1265. X
  1266. XHPUX:
  1267. Xdir        drwxrwxrwx+  2 librarianftp          1024 Feb  2 16:35 drop_box
  1268. X
  1269. X *  "name" is a string like "virus.patch"
  1270. X *
  1271. X */
  1272. X
  1273. XUNIXTokensToParsedDir(Tokens, NumTokens, Current, Now, DirPath, HostPath, ProtIndex)
  1274. Xchar Tokens[MAXTOKENS][MAXTOKENLEN];
  1275. Xint NumTokens;
  1276. Xstruct ParsedDir *Current;
  1277. Xstruct timeb *Now;
  1278. Xchar *DirPath, *HostPath;
  1279. X{
  1280. X    int LookingForMonth, MonthIndex, i, Result;
  1281. X    char TimeForParsing[MAXTOKENLEN];
  1282. X    char FilePath[MAXPATH];
  1283. X
  1284. X    LookingForMonth=1;
  1285. X    for (i=2; (i<NumTokens) && LookingForMonth; i++) {
  1286. X        if (IsAMonth(Tokens[i])) {
  1287. X            LookingForMonth=0;
  1288. X            MonthIndex=i;
  1289. X        }
  1290. X    }
  1291. X
  1292. X    if (LookingForMonth) {
  1293. X        Log2("UNIXTokensToParsedDir ERROR no month", Tokens[0]);
  1294. X        return(AFAIL);
  1295. X    }
  1296. X
  1297. X    if (MonthIndex+3 >= NumTokens) {
  1298. X        LogN("UNIXTokensToParsedDir ERROR not enough tokens", NumTokens);
  1299. X        return(AFAIL);
  1300. X    }
  1301. X
  1302. X    Current->Size = atoi(Tokens[MonthIndex-1]);                 /* on Unix we get a real size */
  1303. X
  1304. X    (void) strcpy(TimeForParsing, Tokens[MonthIndex]);          /* month */
  1305. X    (void) strcat(TimeForParsing, " ");
  1306. X    (void) strcat(TimeForParsing, Tokens[MonthIndex+1]);        /* day */
  1307. X    (void) strcat(TimeForParsing, " ");
  1308. X    (void) strcat(TimeForParsing, Tokens[MonthIndex+2]);        /* time or year */
  1309. X
  1310. X    Current->Date = (unsigned int) StringToTimeInt(TimeForParsing, Now);
  1311. X
  1312. X    (void) strcpy(Current->Name, Tokens[MonthIndex+3]);         /* name */
  1313. X
  1314. X    RemoveThroughSlash(Current->Name);                          /* "./foo" --> "foo"  */
  1315. X
  1316. X    Result=AOK;
  1317. X    switch(Tokens[ProtIndex][0]) {
  1318. X        case 'D':
  1319. X        case 'd': Current->Type=ADIR;   
  1320. X                  if (Current->Size < 512) Current->Size=512;   /* microsoft.com shows dirs as 0 */
  1321. X#ifdef ONLYSAFEPARSE
  1322. X                  if (NumTokens > MonthIndex+4) {
  1323. X                      LogN("UNIXTokensToParsedDir ERROR too many tokens", NumTokens);
  1324. X                      Result=AFAIL;
  1325. X                  }
  1326. X#endif
  1327. X                  break;
  1328. X
  1329. X        case 'F':
  1330. X        case '-': Current->Type=AFILE;  
  1331. X#ifdef EXECUTABLE
  1332. X                if (Tokens[ProtIndex][3] == 'x') { /* -rwx */
  1333. X                    Current->Executable = 1;
  1334. X                } else {
  1335. X                    Current->Executable = 0;
  1336. X                }
  1337. X#endif
  1338. X
  1339. X#ifdef ONLYSAFEPARSE
  1340. X                  if (NumTokens > MonthIndex+4) {
  1341. X                      LogN("UNIXTokensToParsedDir ERROR too many tokens", NumTokens);
  1342. X                      Result=AFAIL;
  1343. X                  }
  1344. X#endif
  1345. X                  break;
  1346. X
  1347. X        case 'L':
  1348. X        case 'l': Current->Type=ALINK; 
  1349. X                               if (MonthIndex+5 >= NumTokens) {
  1350. X                                   LogN("UNIXTokensToParsedDir ERROR not enough tokens", NumTokens);
  1351. X                                   Result=AFAIL;
  1352. X                               } else {
  1353. X                                   (void) strcpy(Current->SymLink, Tokens[MonthIndex+5]);
  1354. X                                   (void) strcpy(FilePath, DirPath);
  1355. X                                   (void) strcat(FilePath, "/");
  1356. X                                   (void) strcat(FilePath, Current->Name);
  1357. X                                   Result=OkSymLink(FilePath, Current->SymLink, HostPath);
  1358. X                               }
  1359. X                                        break;
  1360. X        default:
  1361. X            Log("UNIXTokensToParsedDir ERROR did not understand file type");
  1362. X            Result=AFAIL;
  1363. X            break;
  1364. X    }
  1365. X
  1366. X                                            /* should never happen any more  XXXX  */
  1367. X    if (Current->Name[0] == '/') {
  1368. X         Log2("UNIXTokensToParsedDir ERROR can not deal with leading / ", Current->Name);
  1369. X         Result=AFAIL;
  1370. X    }
  1371. X
  1372. X    LogT("UNIXTokensToParsedDir returning ", Result);
  1373. X    return(Result);
  1374. X}
  1375. X
  1376. X
  1377. X#if defined(__386BSD__) || defined(ALPHAOSF) || defined(__NetBSD__)
  1378. X/*  Emulate this.
  1379. X */
  1380. Xvoid ftime(struct timeb *Now)
  1381. X{
  1382. X  time_t _now=time(NULL);
  1383. X  struct tm *_Now=localtime(&_now);
  1384. X  Now->time=_now;
  1385. X  Now->millitm=0;
  1386. X  Now->timezone=_Now->tm_gmtoff/60;
  1387. X  Now->dstflag=_Now->tm_isdst;
  1388. X}
  1389. X#endif
  1390. X
  1391. X/* It is not possible to tell who adjusts for daylight savings and
  1392. X   who does not.  So after each daylight savings switch we have to
  1393. X   check back with each host.  This routine is used to check if the
  1394. X   date we have on record as our last checking date is prior to the
  1395. X   last time change - which would mean it is stale info.
  1396. X*/
  1397. X
  1398. Xdouble LastTimeChange = 0;                 /* cleared once a day in alex.c */
  1399. X
  1400. Xint PriorToTimeChange(SecsSinceChecked)
  1401. Xdouble SecsSinceChecked;
  1402. X{
  1403. X    static double SecsSinceTC = 0;
  1404. X    long Spring, Fall;
  1405. X    struct timeb Then;
  1406. X    int Status, Result;
  1407. X    struct timeb Now;
  1408. X
  1409. X    if (LastTimeChange == 0) {
  1410. X        ftime(&Now);
  1411. X
  1412. X        Status = StringToTimeb("October 31", &Now, &Then);
  1413. X        if (Status != AOK) {
  1414. X            ToLog(DBERROR, "PriorToTimeChange can not parse Fall");
  1415. X            flushLog();
  1416. X            exit(-1);
  1417. X        }
  1418. X        Fall = Then.time;
  1419. X        LogN("PriorToTimeChange Fall", (int) Fall);
  1420. X
  1421. X        Status = StringToTimeb("April 30", &Now, &Then);
  1422. X        if (Status != AOK) {
  1423. X            ToLog(DBERROR, "PriorToTimeChange can not parse Spring");
  1424. X            flushLog();
  1425. X            exit(-1);
  1426. X        }
  1427. X        Spring = Then.time;
  1428. X        LogN("PriorToTimeChange Spring", (int) Spring);
  1429. X
  1430. X        /* StringToTimeb gets the closest matching date (could be in future). */
  1431. X        /* For this we don't want anything in future.                         */
  1432. X
  1433. X        if (((Fall < Now.time) && (Fall > Spring)) || (Spring > Now.time)) {
  1434. X            LastTimeChange = Fall;
  1435. X        } else {
  1436. X            LastTimeChange = Spring;
  1437. X        } 
  1438. X
  1439. X        SecsSinceTC = TimeInSeconds() - LastTimeChange;
  1440. X
  1441. X        LogN("PriorToTimeChange SecsSinceTC ", (int) SecsSinceTC);
  1442. X    }
  1443. X
  1444. X    Result = SecsSinceChecked > SecsSinceTC;
  1445. X
  1446. X    LogN("PriorToTimeChange returning ", Result);
  1447. X    return(Result);
  1448. X}
  1449. X
  1450. X
  1451. X/*  Caller will call at most once per .alex.info even with failure.
  1452. X */
  1453. Xint GetRemoteNow(HostPtr, Now)
  1454. Xstruct HostEntry *HostPtr;
  1455. Xstruct timeb *Now;
  1456. X{
  1457. X    char Name[100];
  1458. X    int TimeZone;
  1459. X    int OldTimeZone;
  1460. X    double SecsSinceChecked;
  1461. X    double Start, Finish, Elapse;
  1462. X
  1463. X    AlexAssert(HostPtr != NULL);
  1464. X
  1465. X    ftime(Now);
  1466. X
  1467. X    OldTimeZone=HostPtr->TimeZone;
  1468. X    TimeZone   =HostPtr->TimeZone;
  1469. X
  1470. X    Start = TimeInSeconds();
  1471. X    SecsSinceChecked = Start - HostPtr->TimeLastCheck;
  1472. X
  1473. X    if (((TimeZone >= RemTimeZoneFAIL) && (SecsSinceChecked > ADAY))    || 
  1474. X          (SecsSinceChecked > TRUSTTIMEZONE)  ||
  1475. X          (PriorToTimeChange(SecsSinceChecked) &&
  1476. X                  (HostPtr->Type != NOANONFTP) && (HostPtr->Type != ADOMAIN)) ||
  1477. X          (SecsSinceChecked > TRUSTHOSTTYPE)) {
  1478. X
  1479. X        ToLog(DBPERF2, "GetRemoteNow old timezone of %d     lastcheck %d    ssc %lf \n",  
  1480. X                                         OldTimeZone, HostPtr->TimeLastCheck, SecsSinceChecked);
  1481. X
  1482. X        PathToHostName(HostPtr->Path, Name);
  1483. X        TimeZone=RemTimeZone(Name);
  1484. X        Finish = TimeInSeconds();     
  1485. X        TotalRTZCalls++;                  /* perf stuff */
  1486. X        Elapse = Finish - Start;          /* perf stuff */
  1487. X        TotalRTZTime += Elapse;           /* perf stuff */
  1488. X        TotalRTZTimeSQ += Elapse*Elapse ; /* perf stuff */
  1489. X        HostPtr->TimeZone = TimeZone;     /* Save in cache - could be RemTimeZoneFAIL   */
  1490. X        HostPtr->TimeLastCheck = (int) Finish;
  1491. X    }
  1492. X
  1493. X
  1494. X    if (TimeZone < RemTimeZoneFAIL) {     
  1495. X        Now->timezone=TimeZone;                  /* return real one */
  1496. X    } else {                                     /* failed so can't use TimeZone */
  1497. X        Now->timezone=OldTimeZone;               /* return old zone        */
  1498. X    } 
  1499. X
  1500. X    if (Now->timezone >= RemTimeZoneFAIL) {
  1501. X        Now->timezone=DEFAULTTIMEZONE;           /* Don't know what it is so use default */
  1502. X    }
  1503. X
  1504. X    LogN("GetRemoteNow returning ", (int) Now->timezone);
  1505. X    return(AOK);
  1506. X}
  1507. X
  1508. X
  1509. X
  1510. Xchar *CopyTillSlash(in, out)
  1511. Xchar *in;
  1512. Xchar *out;
  1513. X{
  1514. X    char *tmp;
  1515. X   
  1516. X    tmp=out; 
  1517. X    while ((*in != 0) && (*in != '/')) {
  1518. X        *tmp++ = *in++;
  1519. X    }
  1520. X    *tmp=0;
  1521. X
  1522. X    return(out);
  1523. X}
  1524. X
  1525. X
  1526. X
  1527. X/*  In the case of a HostAlias we need to get the symlink 
  1528. X */
  1529. Xint HostToParsedDir(Host, HostName, Current)
  1530. Xstruct HostEntry *Host;
  1531. Xchar *HostName;
  1532. Xstruct ParsedDir *Current;
  1533. X{
  1534. X    int Result;
  1535. X
  1536. X    ClearParsedDirEntry(Current);
  1537. X    (void) strcpy(Current->Name, HostName);
  1538. X
  1539. X    Result=AOK;
  1540. X    Current->SymLink[0]=0;                                   /* set up defaults */
  1541. X    if (Host->Type != HOSTALIAS) {
  1542. X        Current->Type=AHOST;                                 /* Any host -> AHOST (mostly ADIR) */
  1543. X    } else {
  1544. X        Current->Type=ALINK;                                 /* HOSTALIASes are ALINKs     */
  1545. X        AlexAssert(Host->SymLink != NULL);                   /* We check when read in file */
  1546. X        (void) strcpy(Current->SymLink, Host->SymLink);
  1547. X    }
  1548. X
  1549. X    Current->Inode=0;
  1550. X    Current->Size=512;
  1551. X    Current->Date=TimeInSeconds();        /* could make things look like they change */
  1552. X
  1553. X    return(Result);
  1554. X}
  1555. X
  1556. X
  1557. X/*  This was a terrible linear time algorithm that was just put in place
  1558. X *  temporarily, but stayed.  This should be fixed.  HostsTable needs
  1559. X *  to be made into a tree.
  1560. X *
  1561. X *  Note that DirPWS is something like /edu/cmu/cs/nectar/furmint/
  1562. X */
  1563. X
  1564. Xint OutputHostsBefore(AIfile, NextHost, DirPWS, DPWSlen, Name)
  1565. XFILE *AIfile;
  1566. Xint NextHost;
  1567. Xchar *DirPWS;
  1568. Xint DPWSlen;
  1569. Xchar *Name;
  1570. X{
  1571. X    static char LastHostName[MAXPATH];
  1572. X    static int  LastNextHost=-1;
  1573. X
  1574. X    char HostName[100], FullName[MAXPATH];
  1575. X    struct ParsedDir Current;
  1576. X    int Status, Done;
  1577. X
  1578. X    (void) strcpy(FullName, DirPWS);             /* dir path with slash */
  1579. X    (void) strcat(FullName, Name);
  1580. X
  1581. X    Log2("OutputHostsBefore with ", FullName);
  1582. X
  1583. X    if (NextHost != LastNextHost) {              /* need to know if continuing or startin over */
  1584. X        if ((CountOccurrences(DirPWS, '/') -1) >= MAXPARTSINHOSTNAME) {  /* if so then no host in dir */
  1585. X             NextHost=HostsInTable;
  1586. X        }
  1587. X        LastHostName[0]=0;
  1588. X        LastNextHost=NextHost;
  1589. X    }
  1590. X
  1591. X    Done=0;
  1592. X    for( ; !Done && NextHost<HostsInTable; ) {
  1593. X        Status = strcmp(HostsTable[NextHost]->Path, FullName);
  1594. X        if (Status >= 0) {                       
  1595. X            Done=1;
  1596. X        } else {
  1597. X            Status=strncmp(HostsTable[NextHost]->Path, DirPWS, DPWSlen);
  1598. X            if (Status == 0) {                                             /* is in dir */
  1599. X                CopyTillSlash(&(HostsTable[NextHost]->Path[DPWSlen]), HostName);
  1600. X
  1601. X                if (!streql(HostName, LastHostName)) {
  1602. X                    Log2("OutputHostsBefore found ", HostName);
  1603. X                    Status=HostToParsedDir(HostsTable[NextHost], HostName, &Current);
  1604. X                    if (Status == AOK) {
  1605. X                        if ((HostsTable[NextHost]->Type == HOSTALIAS) &&
  1606. X                            (HostsTable[NextHost]->PathLen > DPWSlen+strlen(HostName))) {
  1607. X                            Current.Type=ADOMAIN;
  1608. X                            Current.SymLink[0]=0;
  1609. X                        }
  1610. X                        OneLineOut(AIfile, &Current);
  1611. X                    }
  1612. X                    (void) strcpy(LastHostName,HostName);
  1613. X                }
  1614. X
  1615. X            }
  1616. X            NextHost++;
  1617. X        }
  1618. X    }
  1619. X            
  1620. X    LogN("OutputHostsBefore returning ", NextHost);
  1621. X    LastNextHost=NextHost;
  1622. X
  1623. X    return(NextHost);
  1624. X}
  1625. X
  1626. X
  1627. X
  1628. X
  1629. X/*  If there is a .alex.error in DirPath output it to the Sream AIfile
  1630. X *     in the correct format for a .alex.info.
  1631. X *
  1632. X *  Return:
  1633. X *            AOK - no .alex.error file found 
  1634. X *  AERRORMESSAGE - added an error message to stream
  1635. X *          AFAIL - error occurred
  1636. X *
  1637. X */
  1638. Xint AddAnyErrorToStream(AIfile, DirPath)
  1639. XFILE *AIfile;
  1640. Xchar *DirPath;
  1641. X{
  1642. X    char AlexErrorPath[MAXPATH];
  1643. X    struct ParsedDir Current;
  1644. X    int Status;
  1645. X
  1646. X    (void) strcpy(AlexErrorPath, DirPath);
  1647. X    (void) strcat(AlexErrorPath, SLASHALEXERROR);
  1648. X
  1649. X    Status=AOK;
  1650. X    if (LiteStat(AlexErrorPath) == AFILE) {
  1651. X        ClearParsedDirEntry(&Current);
  1652. X
  1653. X        Status=StringFromFile(AlexErrorPath, Current.Name);
  1654. X        if (Status != AOK) {
  1655. X            ToLog(DBERROR, "AddAnyErrorToStream ERROR BUG .alex.error empty %s\n", AlexErrorPath);
  1656. X        } else {
  1657. X            Log2("AddAnyErrorToStream got error string ", Current.Name);
  1658. X            Current.Inode=InodeNext++;                           /* allocate a new inode */
  1659. X            Current.Size=0;
  1660. X            Current.Date=TimeInSeconds();
  1661. X            Current.Type=AERRORMESSAGE;
  1662. X            Current.CacheStatus=0;
  1663. X            Current.SymLink[0]=0;
  1664. X            Status=OneLineOut(AIfile, &Current);
  1665. X            if (Status == AOK) {
  1666. X                Status = AERRORMESSAGE;
  1667. X            } 
  1668. X            if (fprintf(AIfile, "%c%c\n", METACHAR, ERRORCHAR) == EOF) {
  1669. X                error1("AddAnyErrorToStream could not write ERRORCHAR");
  1670. X                Status=AFAIL;
  1671. X            }
  1672. X        }
  1673. X    }
  1674. X
  1675. X    LogT("AddAnyErrorToStream  returning ", Status);
  1676. X    return(Status);
  1677. X}
  1678. X
  1679. X#ifdef CHECKFORLOOPS
  1680. X/*  Returns 0 if none of parents are same,
  1681. X *    else number of ../ to have in symlink.
  1682. X */
  1683. Xint NumUpForSameDir(DirPath, ParentDirPath, DirName)
  1684. Xchar *DirPath, *ParentDirPath, *DirName;
  1685. X{
  1686. X    char WorkingDirPath[MAXPATH], Tmp[MAXPATH];
  1687. X    char ParentDirName[MAXPATH];
  1688. X    char ParentAlexDir[MAXPATH], AlexDir[MAXPATH];
  1689. X    int  Result, NumUp;
  1690. X
  1691. X    Result=0;
  1692. X    NumUp=1;
  1693. X
  1694. X    (void) strcpy(WorkingDirPath, ParentDirPath);
  1695. X
  1696. X    while (!Result && strlen(WorkingDirPath) > CACHEDIRLEN && HasString(WorkingDirPath, DirName)) {
  1697. X        ToLog(6, "NumUpForSameDir checking for looping %s\n", DirPath);
  1698. X        PathToFileName(WorkingDirPath, ParentDirName); 
  1699. X        if (streql(DirName, ParentDirName)) {
  1700. X            ToLog(DBRPC, "NumUpForSameDir checking for looping %s \n", DirPath);
  1701. X            (void) strcpy(AlexDir, DirPath);
  1702. X            (void) strcat(AlexDir, SLASHALEXDIR);
  1703. X            (void) strcpy(ParentAlexDir, WorkingDirPath);
  1704. X            (void) strcat(ParentAlexDir, SLASHALEXDIR);
  1705. X            if (FilesAreEqual(AlexDir, ParentAlexDir) == AOK) {
  1706. X                ToLog(DBMAJOR, "NumUpForSameDir for sure we are looping %s \n", DirPath);
  1707. X                Result=NumUp;
  1708. X            }
  1709. X        }
  1710. X        PathToDir(WorkingDirPath, Tmp);
  1711. X        (void) strcpy(WorkingDirPath, Tmp);
  1712. X        NumUp++;
  1713. X    }
  1714. X
  1715. X    return(Result);
  1716. X}
  1717. X   
  1718. X#endif 
  1719. X
  1720. X/*  DirPath = path for directory we are updating .alex.info in
  1721. X *
  1722. X *  We go to parent of this to get "." and ".."
  1723. X *  We also output entries for ".alex.dir" and ".alex.info" (info is fixed up later)
  1724. X */
  1725. Xint OutputExtras(AIfile, DirPath, UidStr, NumUp, PtrNewestDate)
  1726. XFILE *AIfile;
  1727. Xchar *DirPath;
  1728. Xchar *UidStr;
  1729. Xint  *NumUp;
  1730. Xunsigned int  *PtrNewestDate;
  1731. X{
  1732. X    struct ParsedDir Current;
  1733. X#ifdef DOTCHECK
  1734. X    struct ParsedDir DotCurrent, DotDotCurrent;
  1735. X#endif
  1736. X    char TmpPath[MAXPATH], Name[MAXPATH];
  1737. X    char AlexInfoDir[MAXPATH], AlexInfoPath[MAXPATH];
  1738. X    struct ActiveAlexInfo AAI;
  1739. X    struct stat StatBuf;
  1740. X    static char CACHEDIRPARENT[MAXPATH]="";
  1741. X    int    Result, Status, NeedDot, NeedDotDot, OutputCurrent;
  1742. X
  1743. X    Log2("OutputExtras ", DirPath);
  1744. X
  1745. X    if (CACHEDIRPARENT[0] == 0) {
  1746. X        PathToDir(CACHEDIRVAR, CACHEDIRPARENT);
  1747. X        Log2("OutputExtras CACHEDIRPARENT ", CACHEDIRPARENT);
  1748. X    }
  1749. X
  1750. X    PathToFileName(DirPath, Name);                    /* name to look for in the .alex.info */
  1751. X    PathToDir(DirPath, AlexInfoDir);                  /* directory .alex.info would be in   */
  1752. X
  1753. X    if (streql(AlexInfoDir, CACHEDIRPARENT)) {
  1754. X        strcpy(AlexInfoPath, ROOTALEXINFO);           
  1755. X    } else {
  1756. X        (void) strcpy(AlexInfoPath, AlexInfoDir);
  1757. X        (void) strcat(AlexInfoPath, SLASHALEXINFO);
  1758. X    }
  1759. X
  1760. X    if (LiteStat(AlexInfoPath) != AFILE) {          
  1761. X        Log2("OutputExtras ERROR parent had bad .alex.info file ", AlexInfoPath);
  1762. X        return(AFAIL);
  1763. X    }
  1764. X
  1765. X    if (ALEXINFOINOPEN(AlexInfoPath, &AAI, UidStr, NORECURSION) != AOK) {
  1766. X        Log2("OutputExtras ERROR could not open .alex.info file ", AlexInfoPath);
  1767. X        return(AFAIL);
  1768. X    }
  1769. X
  1770. X    NeedDot=1;                 /* we read through our parents .alex.info to get our . and .. */
  1771. X    NeedDotDot=1;              
  1772. X    OutputCurrent=0;
  1773. X                     /* At one point the idea of having the time on "." be the update time   */
  1774. X                     /* Occured to me, and I set the .Date below, but it does not work.      */
  1775. X                     /* The way lookup_2/readinfo work it ends up that it reads the parents  */
  1776. X                     /* So that the times and sizes on "." and ".." don't matter much.       */
  1777. X                     /* In fact the inode number used for pwd may be all that really matters */
  1778. X    while((AlexInfoInNext(&AAI, &Current) == AOK) && (NeedDot || NeedDotDot)) {
  1779. X        if (NeedDot && streql(Current.Name, Name)) {
  1780. X            Log2("OutputExtras found listing for current in parent ", Name);
  1781. X#ifdef DOTCHECK
  1782. X            CopyParsedDir(&Current, &DotCurrent);
  1783. X#endif
  1784. X            (void) strcpy(Current.Name, ".");
  1785. X            if ((Current.Type == ADIR) && (*PtrNewestDate < Current.Date)) {
  1786. X                *PtrNewestDate = Current.Date;
  1787. X            }
  1788. X            NeedDot=0;
  1789. X            OutputCurrent=1;
  1790. X        }
  1791. X
  1792. X        if (!OutputCurrent && NeedDotDot && streql(Current.Name, ".")) {
  1793. X            Log2("OutputExtras found parents info ", Current.Name);
  1794. X#ifdef DOTCHECK
  1795. X            CopyParsedDir(&Current, &DotDotCurrent);
  1796. X#endif
  1797. X            (void) strcpy(Current.Name, "..");
  1798. X            NeedDotDot=0;
  1799. X            OutputCurrent=1;
  1800. X        }
  1801. X
  1802. X        if (OutputCurrent) {
  1803. X            Status=OneLineOut(AIfile, &Current);
  1804. X            if (Status != AOK) {
  1805. X                ToLog(DBERROR, "OutputExtras ERROR BUG can not OneLineOut AIfile");
  1806. X                (void) AlexInfoInClose(&AAI);
  1807. X                return(AFAIL);
  1808. X            }
  1809. X            OutputCurrent=0;
  1810. X        }
  1811. X    }
  1812. X
  1813. X    (void) AlexInfoInClose(&AAI);                                    /* done with parent */
  1814. X
  1815. X    if (NeedDot || NeedDotDot) {
  1816. X        ToLog(DBERROR, "OutputExtras ERROR BUG did not get both . and .. ");
  1817. X        return(AOLD);                                                /* update parent */
  1818. X    }
  1819. X
  1820. X    Result=Status;
  1821. X    if ((Result == AOK)   
  1822. X#ifdef DOTCHECK
  1823. X                            /* check for things like sgi.com:sgi sgi.sgi.com sgi.sgi.com:sgi */
  1824. X           && (DotCurrent.Type != AHOST) 
  1825. X        /* && (DotDotCurrent.Date == DotCurrent.Date) 
  1826. X         * && (DotDotCurrent.Size == DotCurrent.Size) */   /* for now don't filter on date/size */
  1827. X#endif
  1828. X        ) { 
  1829. X#ifdef CHECKFORLOOPS
  1830. X        *NumUp=NumUpForSameDir(DirPath, AlexInfoDir, Name);
  1831. X        if (*NumUp > 0) {
  1832. X            Result = MAKELINKSTOPARENT;
  1833. X        }
  1834. X#endif
  1835. X    }
  1836. X
  1837. X    if ((Result == AOK) && streql(Name, "alex") && (strlen(DirPath) > CACHEDIRLEN)) {
  1838. X        Result = MAKELINKSTOALEX;       /* may or may not depending on number of "com" "edu" .. */
  1839. X    }   
  1840. X
  1841. X    if (streql(DirPath, CACHEDIRVAR)) {                                  /* add in README file */
  1842. X        Log("Going to add /alex/README");
  1843. X        (void) strcpy(TmpPath, DirPath);
  1844. X        (void) strcat(TmpPath, "/README");
  1845. X        Status=lstat(TmpPath, &StatBuf);
  1846. X        if (Status != 0) {
  1847. X            (void) CheckAlexReadme(TmpPath);
  1848. X            Status=lstat(TmpPath, &StatBuf);
  1849. X        }
  1850. X        if (Status == 0) {
  1851. X            ClearParsedDirEntry(&Current);
  1852. X            Current.Inode=InodeNext++;
  1853. X            (void) strcpy(Current.Name, "README");
  1854. X            Current.Size=StatBuf.st_size;
  1855. X            Current.Date=StatBuf.st_mtime;           /* will be time of copy but close enough */
  1856. X            Current.Type=AFILE;
  1857. X            Current.CacheStatus=1;
  1858. X            Current.SymLink[0]=0;
  1859. X            OneLineOut(AIfile, &Current);
  1860. X            if (Status != AOK) {
  1861. X                ToLog(DBERROR, "OutputExtras ERROR BUG can not OneLineOut AIfile");
  1862. X                return(AFAIL);
  1863. X            }
  1864. X        }
  1865. X    } 
  1866. X
  1867. X    if (DEBUGLEVEL >= DBDOTALEX) {
  1868. X        (void) strcpy(TmpPath, DirPath);
  1869. X        (void) strcat(TmpPath, SLASHALEXDIR);
  1870. X        Status=lstat(TmpPath, &StatBuf);
  1871. X        if (Status == 0) {
  1872. X            ClearParsedDirEntry(&Current);
  1873. X            Current.Inode=InodeNext++;
  1874. X            (void) strcpy(Current.Name, ALEXDIR);
  1875. X            Current.Size=StatBuf.st_size;
  1876. X            Current.Date=StatBuf.st_mtime;
  1877. X            Current.Type=AFILE;
  1878. X            Current.CacheStatus=1;
  1879. X            Current.SymLink[0]=0;
  1880. X            OneLineOut(AIfile, &Current);
  1881. X            if (Status != AOK) {
  1882. X                ToLog(DBERROR, "OutputExtras ERROR BUG can not OneLineOut AIfile");
  1883. X                return(AFAIL);
  1884. X            }
  1885. X        } else {
  1886. X            Log2("OutputExtras - error no .alex.dir for ", TmpPath);
  1887. X        }
  1888. X
  1889. X        ClearParsedDirEntry(&Current);
  1890. X        Current.Inode=BOGUSINODE;                    /* temporary values - we fix later */
  1891. X        (void) strcpy(Current.Name, ALEXINFO);
  1892. X        Current.Size=BOGUSINODE;
  1893. X        Current.Date=BOGUSINODE;
  1894. X        Current.Type=AFILE;
  1895. X        Current.CacheStatus=1;
  1896. X        Current.SymLink[0]=0;
  1897. X        Status=OneLineOut(AIfile, &Current);
  1898. X
  1899. X        if (Status != AOK) {
  1900. X            ToLog(DBERROR, "OutputExtras ERROR BUG can not OneLineOut AIfile");
  1901. X            return(AFAIL);
  1902. X        }
  1903. X    }
  1904. X
  1905. X
  1906. X    LogT("OutputExtras returning ", Result);
  1907. X    return(Result);
  1908. X}
  1909. X   
  1910. X
  1911. X
  1912. Xint OutputMetaData(AIfile, Version, UpdateDate, NewestDate, TypeOfDir,
  1913. X             PartsInHostName, AddAnyErrorStatus)
  1914. XFILE *AIfile;
  1915. Xint  Version;
  1916. Xunsigned int UpdateDate, NewestDate;
  1917. Xint TypeOfDir, PartsInHostName, AddAnyErrorStatus;
  1918. X{
  1919. X    int Status, SizeOk;
  1920. X
  1921. X    Status=AOK;
  1922. X    if (TypeOfDir == UNIX) {
  1923. X       SizeOk=1;
  1924. X    } else {
  1925. X       SizeOk=0;
  1926. X    }
  1927. X
  1928. X
  1929. X    if (fprintf(AIfile, "%c%c %d\n", METACHAR, VERSCHAR, Version) == EOF) {
  1930. X        error1("OutputMetaData could not write Version ");
  1931. X        Status=AFAIL;
  1932. X
  1933. X    } else if (fprintf(AIfile, "%c%c %u\n", METACHAR, DATECHAR, UpdateDate) == EOF) {
  1934. X        error1("OutputMetaData could not write UpdateDate ");
  1935. X        Status=AFAIL;
  1936. X
  1937. X    } else if (fprintf(AIfile, "%c%c %u\n", METACHAR, NEWCHAR, NewestDate) == EOF) {
  1938. X        error1("OutputMetaData could not write NewestDate ");
  1939. X        Status=AFAIL;
  1940. X
  1941. X    } else if (fprintf(AIfile, "%c%c %d\n", METACHAR, SIZECHAR, SizeOk) == EOF) {
  1942. X        error1("OutputMetaData could not write SizeOk ");
  1943. X        Status=AFAIL;
  1944. X
  1945. X    } else if (fprintf(AIfile, "%c%c %d\n", METACHAR, HOSTPARTSCHAR, PartsInHostName) == EOF) {
  1946. X        error1("OutputMetaData could not write PartsInHostName ");
  1947. X        Status=AFAIL;
  1948. X
  1949. X                                    /* Also can happen in AddAnyErrorToStream() */
  1950. X    } else if (AddAnyErrorStatus == AERRORMESSAGE) {
  1951. X        if (fprintf(AIfile, "%c%c\n", METACHAR, ERRORCHAR) == EOF) {
  1952. X            error1("OutputMetaData could not write ERRORCHAR");
  1953. X            Status=AFAIL;
  1954. X        }
  1955. X    }
  1956. X
  1957. X
  1958. X    LogT("OutputMetaData returning ", Status);
  1959. X    return(Status);
  1960. X}
  1961. X
  1962. X
  1963. X/*  Performance reporting 
  1964. X *  XXXX YYYY
  1965. X *
  1966. X *  Called when old .alex.info entry for a file was out of date.
  1967. X *  Input includes directory and the ParsedDir for new entry in .alex.info.
  1968. X *
  1969. X *  We only get a reasonable approximation of staleness stats.
  1970. X *  File could change, read stale, then change again so looking like read was ok.
  1971. X *  Could have read while stale, then been flushed from cache.
  1972. X *
  1973. X *  Return 
  1974. X *      AFAIL if not in cache - (caller removes if is in cache)
  1975. X */
  1976. Xint ReportStaleStats(Dir, CurrentPtr)
  1977. Xchar *Dir;
  1978. Xstruct ParsedDir *CurrentPtr;
  1979. X{
  1980. X    char Path[MAXPATH];
  1981. X    struct stat StatBuf;
  1982. X    int ModTimeMinusATime, ATimeMinusMTime, StaleNess;
  1983. X    int Result;
  1984. X
  1985. X    (void) strcpy(Path, Dir);
  1986. X    (void) strcat(Path, "/");
  1987. X    (void) strcat(Path, CurrentPtr->Name);
  1988. X
  1989. X    Result=AlexStat(Path, &StatBuf);
  1990. X
  1991. X    if (Result == AFAIL) {
  1992. X        ToLog(DBPERF, "ReportStaleStats  stale but not in cache \n", Path);
  1993. X    } else {
  1994. X        ToLog(DBPERF, "ReportStaleStats RawData mtime=%d  atime=%d  modtime=%d  %s \n", 
  1995. X                  (int) StatBuf.st_mtime, (int) StatBuf.st_atime, (int) CurrentPtr->Date, Path);
  1996. X
  1997. X        ModTimeMinusATime = (int) (CurrentPtr->Date - StatBuf.st_atime);
  1998. X        ATimeMinusMTime = (int) StatBuf.st_atime - StatBuf.st_mtime;
  1999. X
  2000. X        StaleNess=0;
  2001. X        if (ATimeMinusMTime < 0) {
  2002. X            ToLog(DBPERF, "ReportStaleStats  updated after last read %d\n", ATimeMinusMTime);
  2003. X        } else {
  2004. X            if (ModTimeMinusATime > 0) {            
  2005. X                ToLog(DBPERF, "ReportStaleStats changed after we read file\n");  /* StaleNess==0 */
  2006. X            } else if (ModTimeMinusATime < 0) {
  2007. X                ToLog(DBPERF, "ReportStaleStats should have changed before we read stale data\n");
  2008. X                StaleNess= abs(ModTimeMinusATime);
  2009. X                if (ATimeMinusMTime < StaleNess) {
  2010. X                    StaleNess=ATimeMinusMTime;
  2011. X                    ToLog(DBPERF, "ReportStaleStats StaleData used closer after last update %d\n",
  2012. X                                                              StaleNess);
  2013. X                } else {
  2014. X                    ToLog(DBPERF, "ReportStaleStats StaleData used before current update%d \n",
  2015. X                                                              StaleNess);
  2016. X                }
  2017. X            }
  2018. X        }
  2019. X  
  2020. X        if (CurrentPtr->Date < StatBuf.st_mtime) {
  2021. X            ToLog(DBPERF, "ReportStaleStats  the mod time is before we FTPed it\n");
  2022. X            StaleNess=0;
  2023. X        }
  2024. X
  2025. X        if (StaleNess > 60) { 
  2026. X            ToLog(DBPERF, "ReportStaleStats StaleDataInfo  %d seconds == %f days  for %s \n",
  2027. X                      StaleNess, StaleNess/86400.0, Path);
  2028. X            TotalStaleFiles++;
  2029. X            TotalStaleSecs += StaleNess;
  2030. X        } 
  2031. X    }
  2032. X    return(Result);
  2033. X}
  2034. X
  2035. X
  2036. Xint RmDirNameIfThere(dir, name)
  2037. Xchar *dir, *name;
  2038. X{
  2039. X    char tmp[MAXPATH];
  2040. X    int Result, Type;
  2041. X
  2042. X    (void) strcpy(tmp, dir);
  2043. X    (void) strcat(tmp, "/");
  2044. X    (void) strcat(tmp, name);
  2045. X
  2046. X
  2047. X    Type=LiteStat(tmp);                            /* not from .alex.info */
  2048. X
  2049. X    switch (Type) {
  2050. X        case ADIR:     Log2("RmDirNameIfThere is RecursiveRming ", tmp);
  2051. X                       Result=RecursiveRm(tmp, __FILE__, __LINE__, DONOTWAIT);
  2052. X                       break;
  2053. X
  2054. X        case AFILE:    Log2("RmDirNameIfThere is unlinking ", tmp);
  2055. X                       Result=unlink(tmp);
  2056. X                       break;
  2057. X
  2058. X        case AFAIL:    Log2("RmDirNameIfThere was not there ", tmp);
  2059. X                       break;
  2060. X
  2061. X        default:       Result=AFAIL;
  2062. X                       LogT("RmDirNameIfThere ERROR bad type ", Type);
  2063. X    }
  2064. X
  2065. X    if (Result != AOK) {
  2066. X        Log2("RmDirNameIfThere did not remove ", tmp);
  2067. X        Result=AFAIL;
  2068. X    } else {
  2069. X        Log2("RmDirNameIfThere removed ", tmp);
  2070. X    }
  2071. X
  2072. X    return(Result);
  2073. X}
  2074. X
  2075. X
  2076. X
  2077. X/*  Assumes files are sorted so we must be sure they are !!!!
  2078. X *
  2079. X *  Input:   filenames for .alex.info.old, .alex.info.tmp and .alex.info
  2080. X *                 the .alex.info.old can be /dev/null
  2081. X *
  2082. X *  Function:
  2083. X *           Remove files and directories that were around but are no longer
  2084. X *           Patchs up Inode numbers in cases where files already had inodes 
  2085. X *
  2086. X *  Algorithm:
  2087. X *           work down the 2 sorted lists sort of like a merge
  2088. X *  New:
  2089. X *        If there is a .alex.error, then there is not a new .alex.info, and we
  2090. X *        really want to keep the old info as it is better than the new.  So,
  2091. X *        we should add an error message, but keep old stuff around.
  2092. X */
  2093. Xint FixInodesAndRemoveOld(AlexInfoOld, AlexInfoTmp, AlexInfo, UidStr, 
  2094. X         UpdateDate, NewestDate, TypeOfDir, PartsInHostName, AddAnyErrorStatus, HaveAlexDir)
  2095. Xchar *AlexInfoOld, *AlexInfoTmp, *AlexInfo, *UidStr;
  2096. Xunsigned int UpdateDate, NewestDate;
  2097. Xint PartsInHostName;
  2098. Xint TypeOfDir, AddAnyErrorStatus, HaveAlexDir;
  2099. X{
  2100. X    struct ActiveAlexInfo OldAIF, TmpAIF;
  2101. X    FILE *AIfile;
  2102. X    char dir[MAXPATH];
  2103. X    int Status, TmpFull, RemovedSomething;
  2104. X    struct ParsedDir CurrentOld, CurrentTmp, Current;
  2105. X    long AlexInfoLoc, FileLength;
  2106. X    struct stat StatBuf;
  2107. X
  2108. X    Log2("FixInodesAndRemoveOld ", AlexInfoOld);
  2109. X
  2110. X    PathToDir(AlexInfo, dir);
  2111. X
  2112. X    if (ALEXINFOINOPEN(AlexInfoOld, &OldAIF, UidStr, NORECURSION) != AOK) {
  2113. X        error2("FixInodesAndRemoveOld could not open", AlexInfoOld);
  2114. X        return(AFAIL);
  2115. X    } else {
  2116. X        Log2("FixInodesAndRemoveOld has file open for read ", AlexInfoOld);
  2117. X    }
  2118. X
  2119. X    if (ALEXINFOINOPEN(AlexInfoTmp, &TmpAIF, UidStr, NORECURSION) != AOK) {
  2120. X        Log2("FixInodesAndRemoveOld could not open", AlexInfoTmp);
  2121. X        (void) AlexInfoInClose(&OldAIF);
  2122. X        (void) AlexInfoInClose(&TmpAIF);
  2123. X        return(AFAIL);
  2124. X    } else {
  2125. X        Log2("FixInodesAndRemoveOld has file open for read ", AlexInfoTmp);
  2126. X    }
  2127. X
  2128. X    AIfile=AFOPEN(AlexInfo,"w+");
  2129. X    if (AIfile==NULL) {
  2130. X        error2("FixInodesAndRemoveOld could not open", AlexInfo);
  2131. X        (void) AlexInfoInClose(&OldAIF);
  2132. X        (void) AlexInfoInClose(&TmpAIF);
  2133. X        return(AFAIL);
  2134. X    } 
  2135. X
  2136. X    OutputMetaData(AIfile, ALEXINFOVERSION, UpdateDate, NewestDate, TypeOfDir, 
  2137. X                PartsInHostName, AddAnyErrorStatus);
  2138. X    
  2139. X
  2140. X    RemovedSomething=0;
  2141. X    CurrentOld.Name[0]=0;
  2142. X    CurrentTmp.Name[0]=0;
  2143. X    AlexInfoLoc= -1;
  2144. X    TmpFull=0;
  2145. X    while (1) {
  2146. X        if((AlexInfoLoc == -1) && streql(CurrentTmp.Name, ALEXINFO)) {   
  2147. X            AlexInfoLoc=ftell(AIfile);                /* remember this spot we fix later */
  2148. X            LogN("FixInodesAndRemoveOld just did ftell ", (int) AlexInfoLoc);
  2149. X        }
  2150. X
  2151. X        Status=strcmp(CurrentTmp.Name, CurrentOld.Name);
  2152. X        ToLog(10, "FixInodesAndRemoveOld : %s : %d : %s   t=%d\n", CurrentTmp.Name,
  2153. X                                Status, CurrentOld.Name, (int) TmpFull);
  2154. X
  2155. X        if (Status == 0) {                                                   /* matched !!!!!! */
  2156. X            if (TmpFull) {
  2157. X                if (!SpecialFile(&CurrentTmp)) {
  2158. X                    CurrentTmp.Inode=CurrentOld.Inode;        /* was already around use inode #  */
  2159. X
  2160. X                    if (CurrentTmp.Date != CurrentOld.Date) {          /* if has been updated    */
  2161. X                        if ((CurrentTmp.Type == AFILE) ||              /* and is a file or type has changed */
  2162. X                            (SimpleType(CurrentTmp.Type) != SimpleType(CurrentOld.Type))) { 
  2163. X                            Log2("FixInodesAndRemoveOld thinks this is old ", CurrentTmp.Name);
  2164. X                            if (ReportStaleStats(dir, &CurrentTmp) != AFAIL) {
  2165. X                                (void) RmDirNameIfThere(dir, CurrentOld.Name); /* then remove from cache */
  2166. X                                RemovedSomething++;
  2167. X                            }
  2168. X                        } else {
  2169. X                            switch (CurrentTmp.Type) {
  2170. X                                case ADOMAIN:
  2171. X                                case AHOST:
  2172. X                                    /* CurrentTmp.Date=CurrentOld.Date;  */
  2173. X                                    CurrentTmp.Date= 0;       /* make hosts old so don't check too often */
  2174. X                                    Log2("FixInodesAndRemoveOld setting date back on ", CurrentTmp.Name);
  2175. X                                    break;
  2176. X
  2177. X                                case ADIR:
  2178. X                                    Log2("FixInodesAndRemoveOld subdirectory has changed", CurrentTmp.Name);
  2179. X                                    break;
  2180. X
  2181. X                                case ALINK:
  2182. X                                    Log2("FixInodesAndRemoveOld have a new link value", CurrentTmp.Name);
  2183. X                                    break;
  2184. X                                case AERRORMESSAGE:
  2185. X                                    Log2("FixInodesAndRemoveOld have an errormessage ", CurrentTmp.Name);
  2186. X                                    break;
  2187. X                                default:
  2188. X                                    ToLog(DBERROR, "FixInodesAndRemoveOld ERROR BUG %s\n", CurrentTmp.Name);
  2189. X                                    break;
  2190. X                            }
  2191. X                        }
  2192. X                    }
  2193. X                }          
  2194. X                OneLineOut(AIfile, &CurrentTmp);
  2195. X                TmpFull=0;
  2196. X            }
  2197. X
  2198. X            if(AlexInfoInNext(&TmpAIF, &CurrentTmp) != AOK) break;   /* check CurrentTmp first */
  2199. X            TmpFull=1;
  2200. X            if(AlexInfoInNext(&OldAIF, &CurrentOld) != AOK) break;
  2201. X            Log2(CurrentTmp.Name, CurrentOld.Name);
  2202. X
  2203. X        } else if (Status > 0) {
  2204. X            if (!SpecialFileOrError(&CurrentOld)) {
  2205. X                if (AddAnyErrorStatus == AERRORMESSAGE) {
  2206. X                     if (CurrentOld.Type <= ADIR) {
  2207. X                         OneLineOut(AIfile, &CurrentOld);         /* if no new .alex.info copy old */
  2208. X                     }
  2209. X                } else {
  2210. X                     Log2("FixInodesAndRemoveOld Greater so rming ", CurrentOld.Name);
  2211. X                    (void) RmDirNameIfThere(dir, CurrentOld.Name);       /* gone so remove it */
  2212. X                    RemovedSomething++;
  2213. X                }
  2214. X            }
  2215. X
  2216. X            if(AlexInfoInNext(&OldAIF, &CurrentOld) != AOK) break;
  2217. X            Log2("Just a new old ", CurrentOld.Name);
  2218. X        } else {
  2219. X            Log2("FixInodesAndRemoveOld less so advancing past ", CurrentTmp.Name);
  2220. X            if (TmpFull) {
  2221. X                CurrentTmp.Inode=InodeNext++;                           /* allocate a new inode */
  2222. X                OneLineOut(AIfile, &CurrentTmp);
  2223. X                TmpFull=0;
  2224. X            }
  2225. X            if(AlexInfoInNext(&TmpAIF, &CurrentTmp) != AOK) break;
  2226. X            Log2("Just a new Tmp ", CurrentTmp.Name);
  2227. X            TmpFull=1;
  2228. X        }      
  2229. X    }                                                                                 /* while */
  2230. X
  2231. X
  2232. X    while(AlexInfoInNext(&OldAIF, &CurrentOld) == AOK) {             /* deal with rest of Old */
  2233. X        Log2("FixInodesAndRemoveOld rest-of-old ", CurrentOld.Name);
  2234. X        if (!SpecialFileOrError(&CurrentOld)) {
  2235. X            if (AddAnyErrorStatus == AERRORMESSAGE) {
  2236. X                 if (CurrentOld.Type <= ADIR) {
  2237. X                     OneLineOut(AIfile, &CurrentOld);                    /* if no new .alex.info copy old */
  2238. X                 }
  2239. X            } else {
  2240. X                (void) RmDirNameIfThere(dir, CurrentOld.Name);       /* gone so remove it */
  2241. X                RemovedSomething++;
  2242. X            }
  2243. X        }
  2244. X    }
  2245. X    (void) AlexInfoInClose(&OldAIF);
  2246. X
  2247. X    if ((HaveAlexDir || (AddAnyErrorStatus == AERRORMESSAGE)) && (RemovedSomething==0)) {
  2248. X        TotalUnchangedDirs++;
  2249. X    }
  2250. X
  2251. X    do {                                                             /* deal with rest Tmp */
  2252. X        if (TmpFull) {
  2253. X            Log2("FixInodesAndRemoveOld rest-of-tmp ", CurrentTmp.Name);
  2254. X            if((AlexInfoLoc == -1) && streql(CurrentTmp.Name, ALEXINFO)) {   
  2255. X                Log("FixInodesAndRemoveOld about to ftell (2) ");
  2256. X                AlexInfoLoc=ftell(AIfile);                /* remember this spot we fix later */
  2257. X                LogN("FixInodesAndRemoveOld just did ftell (3) ", (int) AlexInfoLoc);
  2258. X            } else {
  2259. X                if (!SpecialFile(&CurrentTmp)) {
  2260. X                    CurrentTmp.Inode=InodeNext++;                    /* allocate a new inode */
  2261. X                }
  2262. X            }
  2263. X            OneLineOut(AIfile, &CurrentTmp);
  2264. X        }
  2265. X        TmpFull=1;                                               /* if we loop we will have data */
  2266. X    } while(AlexInfoInNext(&TmpAIF, &CurrentTmp) == AOK);         
  2267. X
  2268. X    (void) AlexInfoInClose(&TmpAIF);
  2269. X    Status = AOK;
  2270. X
  2271. X    fflush(AIfile);
  2272. X    if (DEBUGLEVEL >=  DBDOTALEX) {
  2273. X        Log("FixInodesAndRemoveOld is about to go back and fix AlexInfo");
  2274. X        Status=lstat(AlexInfo, &StatBuf);
  2275. X        if (Status == 0) {
  2276. X            ClearParsedDirEntry(&Current);
  2277. X            (void) strcpy(Current.Name, ALEXINFO);
  2278. X            Current.Inode=InodeNext++;
  2279. X            FileLength = ftell(AIfile);              /* we are at the end */
  2280. X            Current.Size=FileLength;                 /* we know the real size now */
  2281. X            Current.Date=StatBuf.st_mtime;
  2282. X            Current.Type=AFILE;
  2283. X            Current.CacheStatus=1;
  2284. X            Current.SymLink[0]=0;
  2285. X            if ((AlexInfoLoc > 0) && (AlexInfoLoc <FileLength)) {
  2286. X                if (fseek(AIfile, AlexInfoLoc, 0)) {      /* we saw one go there */
  2287. X                    LogN("FixInodesAndRemoveOld fseek failed ", (int) AlexInfoLoc);
  2288. X                }
  2289. X            } else {
  2290. X                ToLog(DBERROR, "FixInodesAndRemoveOld ERROR BUG Bogus AlexInfoLoc %d\n ",
  2291. X                                                        (int) AlexInfoLoc);
  2292. X                Status=AFAIL;
  2293. X            }
  2294. X            if (Status == AOK) {
  2295. X                Status=OneLineOut(AIfile, &Current);   /* since size if fixed field this works */
  2296. X            }
  2297. X        } else {
  2298. X            Log2("FixInodesAndRemoveOld ERROR could not update size for ", AlexInfo);
  2299. X            Status=AFAIL;
  2300. X        }
  2301. X    } else {
  2302. X        if (AlexInfoLoc > 0) {
  2303. X            ToLog(DBERROR, "FixInodesAndRemoveOld ERROR %s has a .alex.info at %d\n", AlexInfo, AlexInfoLoc);
  2304. X        }
  2305. X    }
  2306. X
  2307. X    (void) AFCLOSE(AIfile);
  2308. X
  2309. X    LogT("FixInodesAndRemoveOld returning ", Status);
  2310. X    return(Status);
  2311. X}
  2312. X
  2313. X
  2314. X
  2315. X
  2316. X
  2317. X/*  returns 1 if we have no trouble with this name 
  2318. X */
  2319. Xint NotForbiddenName(Name)
  2320. Xchar *Name;
  2321. X{
  2322. X    return(!streql(Name, ".")      &&  !streql(Name, "..") && 
  2323. X           !streql(Name, ALEXINFO) &&  !streql(Name, ALEXDIR));
  2324. X}
  2325. X
  2326. X
  2327. X/*  WhereTo is either MAKELINKSTOALEX or MAKELINKSTOPARENT
  2328. X *    if TOPARENT then NumUp contains number of ../ to add.
  2329. X */
  2330. XModifyCurrentToLink(PtrCurrent, WhereTo, NumUp)
  2331. Xstruct ParsedDir *PtrCurrent;
  2332. Xint WhereTo, NumUp;
  2333. X{
  2334. X    int i;
  2335. X
  2336. X    PtrCurrent->Type=ALINK;
  2337. X
  2338. X    switch (WhereTo) {
  2339. X        case MAKELINKSTOALEX:   (void) strcpy(PtrCurrent->SymLink, ALEXPATH);
  2340. X                                (void) strcat(PtrCurrent->SymLink, "/");
  2341. X                                (void) strcat(PtrCurrent->SymLink, PtrCurrent->Name);
  2342. X                                break;
  2343. X
  2344. X        case MAKELINKSTOPARENT: PtrCurrent->SymLink[0]=0;
  2345. X                                for (i=0; i<NumUp; i++) {
  2346. X                                    (void) strcat(PtrCurrent->SymLink, "../");
  2347. X                                }
  2348. X                                (void) strcat(PtrCurrent->SymLink, PtrCurrent->Name);
  2349. X                                break;
  2350. X
  2351. X        default:                ToLog(DBERROR, "ModifyCurrentToLink got bogus argument %d", WhereTo);
  2352. X                                exit(-1);
  2353. X    }
  2354. X}
  2355. X
  2356. Xint ParentHasNewAlexDir(DirPath)
  2357. Xchar *DirPath;
  2358. X{
  2359. X    char ParentAlexDir[MAXPATH];
  2360. X
  2361. X    PathToDir(DirPath, ParentAlexDir);
  2362. X    (void) strcat(ParentAlexDir, SLASHALEXDIR);
  2363. X
  2364. X    if (SecsSinceWrite(ParentAlexDir) < SECSTILLRETRY) {
  2365. X        return(1);
  2366. X    } else {
  2367. X        return(0);
  2368. X    }
  2369. X}
  2370. X
  2371. Xchar *AlexTops[] =  {"ar", "arpa", "at", "au", "be", "br", "ca", "ch", "com", "de", "dk", "ec",
  2372. X                     "edu", "es", "fi", "fr", "gov", "gr", "hk", "ie", "il", "it", "jp",  "kr", 
  2373. X                     "mil", "net", "nl", "no", "nz", "org", "se", "sg", "tw", "uk", "za", NULL };
  2374. X
  2375. X/*  return 1 if Name is in above list */
  2376. Xint IsAnAlexTop(Name) 
  2377. Xchar *Name;
  2378. X{
  2379. X    int i;
  2380. X
  2381. X    for (i=0; AlexTops[i] != NULL; i++) {
  2382. X        if (streql(AlexTops[i], Name)) {
  2383. X            return(1);
  2384. X        } 
  2385. X    }
  2386. X    return(0);
  2387. X}
  2388. X
  2389. X/*  Input is *directory* to play with and HostPtr to host that is parent of this tree.
  2390. X *  If we don't have a HostPtr and there is no .alex.dir we just make a 
  2391. X *  .alex.info from the known hosts/domains.
  2392. X *
  2393. X *  We parse the .alex.dir returned from the ftp dir command once and create
  2394. X *  a .alex.info file which is in a standard easy to parse form.
  2395. X *
  2396. X *  .alex.dir | conversion | sort > .alex.info.tmp        (saving UpdateDate, NewestDate)
  2397. X *  FixInodesAndRemoveOld(Old, Tmp, UpdateDate, NewestDate) ==>  .alex.info.new
  2398. X *  mv .alex.info.new .alex.info 
  2399. X *
  2400. X */
  2401. Xextern int DirToInfo(DirPath, HostPtr, UidStr)
  2402. Xchar *DirPath;
  2403. Xstruct HostEntry *HostPtr;
  2404. Xchar *UidStr;
  2405. X{
  2406. X    FILE *ADfile, *AITmpFile;
  2407. X    char AlexDirPath[MAXPATH], DirPWS[MAXPATH];
  2408. X    char AlexInfo[MAXPATH], AlexInfoTmp[MAXPATH], AlexInfoOld[MAXPATH], AlexInfoNew[MAXPATH]; 
  2409. X    char line[MAXPATH];
  2410. X    char  Tokens[MAXTOKENS][MAXTOKENLEN];
  2411. X    int   Result, HaveNow, NumTokens, TypeOfDir;
  2412. X    int   NumLines, NumNotFound;  
  2413. X    struct ParsedDir Current;
  2414. X    struct timeb Now;
  2415. X    int Status, DPWSlen, NextHost, AddAnyErrorStatus;
  2416. X    unsigned int UpdateDate, NewestDate;
  2417. X    int MakeLinksType;
  2418. X    int FirstOfTwoPasses, TotalAlexTops, Done, NumUp, HaveAlexDir;
  2419. X#ifdef CAREFULATTOP
  2420. X    int AtHostTop;
  2421. X#endif
  2422. X
  2423. X    ToLog(DBFTP, "In DirToInfo %s\n", DirPath);
  2424. X
  2425. X    if (LiteStat(DirPath) != ADIR) {
  2426. X        ToLog(DBERROR, "DirToInfo ERROR BUG did not get a ADIR %s\n", DirPath);
  2427. X        return(AFAIL);
  2428. X    }
  2429. X
  2430. X    if ((HostPtr != NULL) && (HostPtr->Type == ADOMAIN)) {  /* ADOMAIN is useless here */
  2431. X        HostPtr=NULL;
  2432. X    }
  2433. X    InvalidateStatCache=1;
  2434. X
  2435. X    (void)  strcpy(AlexDirPath, DirPath);
  2436. X    (void)  strcat(AlexDirPath, SLASHALEXDIR);
  2437. X
  2438. X    (void)  strcpy(AlexInfo, DirPath);
  2439. X    (void)  strcat(AlexInfo, SLASHALEXINFO);
  2440. X
  2441. X    (void)  strcpy(DirPWS, &DirPath[CACHEDIRLEN]);       /* Dir-Path-With-Slash */
  2442. X    (void)  strcat(DirPWS, "/");
  2443. X    DPWSlen=strlen(DirPWS);
  2444. X
  2445. X    (void)  strcpy(AlexInfoTmp, AlexInfo);
  2446. X    (void)  strcat(AlexInfoTmp, ".tmp");
  2447. X
  2448. X    (void)  strcpy(AlexInfoNew, AlexInfo);
  2449. X    (void)  strcat(AlexInfoNew, ".new");
  2450. X
  2451. X
  2452. X    AITmpFile=AFOPEN(AlexInfoTmp, "w"); 
  2453. X    if (AITmpFile==NULL) {
  2454. X        error2("DirToInfo could not open", AlexInfoTmp);
  2455. X        return(AFAIL);
  2456. X    } else {
  2457. X        Log2("DirToInfo has done open for sort into ", AlexInfoTmp);
  2458. X    }
  2459. X
  2460. X    NewestDate=0;
  2461. X                                                      /* do this first since they are all . files */
  2462. X    Status=OutputExtras(AITmpFile, DirPath, UidStr, &NumUp, &NewestDate); 
  2463. X    if ((Status == MAKELINKSTOPARENT) || (Status == MAKELINKSTOALEX)) {
  2464. X        MakeLinksType=Status;
  2465. X        Status=AOK;
  2466. X    } else {
  2467. X        MakeLinksType=0;
  2468. X    }
  2469. X
  2470. X    if (Status == AOK) {
  2471. X        AddAnyErrorStatus=AddAnyErrorToStream(AITmpFile, DirPath);  
  2472. X    }
  2473. X    if ((Status != AOK) || (AddAnyErrorStatus == AFAIL)) {
  2474. X        ToLog(DBERROR, "DirToInfo ERROR BUG can not OutputExtras/AddAnyError to %s\n", DirPath);
  2475. X        AFCLOSE(AITmpFile);
  2476. X        LogT("DirToInfo returning ", Status);
  2477. X        return(Status);
  2478. X    }
  2479. X
  2480. X    NextHost=0;
  2481. X    Result= AOK;
  2482. X    UpdateDate=TimeInSeconds();    /* will use time on .alex.dir if exists */
  2483. X   
  2484. X    if (HostPtr == NULL) {
  2485. X        Log("DirToInfo found NULL HostPtr");                        /* skip many lines of code */
  2486. X    } else {
  2487. X#ifdef CAREFULATTOP
  2488. X        AtHostTop =  (HostPtr->PartsInHostName == (CountOccurrences(DirPWS, '/') -1));
  2489. X#endif
  2490. X        ADfile=AFOPEN(AlexDirPath,"r");
  2491. X        if (ADfile == NULL) {
  2492. X            HaveAlexDir=0;
  2493. X            Log2("DirToInfo could not open AlexDirPath", AlexDirPath); /* skip many lines of code */
  2494. X        } else {
  2495. X            HaveAlexDir=1;
  2496. X            UpdateDate=MTimeOfFile(AlexDirPath);
  2497. X            TypeOfDir=DetermineTypeOfDir(ADfile);
  2498. X            if (fseek(ADfile, (long) 0, 0)) {                           /* go back to start */
  2499. X                Log("DirToInfo ERROR fseek failed");
  2500. X                (void) AFCLOSE(ADfile);
  2501. X                (void) AFCLOSE(AITmpFile);
  2502. X                return(AFAIL);
  2503. X            }
  2504. X
  2505. X            NumLines=0;  
  2506. X            NumNotFound=0;  
  2507. X            HaveNow=0;
  2508. X            line[0]=0;
  2509. X            if (MakeLinksType == MAKELINKSTOALEX) {     /* only if name is "alex" */
  2510. X                FirstOfTwoPasses=1;
  2511. X            } else {
  2512. X                FirstOfTwoPasses=0;
  2513. X            }
  2514. X            TotalAlexTops=0;
  2515. X            Done=0;
  2516. X            while (!Done && (Result == AOK)) {
  2517. X                if (fgets(line, MAXPATH, ADfile) == NULL) {
  2518. X                    if (FirstOfTwoPasses) {
  2519. X                        if (TotalAlexTops < 10) {
  2520. X                            MakeLinksType = 0;       /* should be at least 10 of them */
  2521. X                        }
  2522. X                        NumLines=0;  
  2523. X                        NumNotFound=0;  
  2524. X                        FirstOfTwoPasses=0;          /* done with first pass */
  2525. X                        (void) rewind(ADfile);           
  2526. X                        continue;
  2527. X                    } else {
  2528. X                        Done=1;
  2529. X                        break;
  2530. X                    }
  2531. X                }
  2532. X
  2533. X                NumLines++;
  2534. X                if ((TypeOfDir == UNKNOWN) && (HasString(line, "not found"))) {
  2535. X                    NumNotFound++;
  2536. X                    continue;
  2537. X                }
  2538. X
  2539. X                NumTokens=LineToTokens(line, Tokens);
  2540. X
  2541. X                if (!IsRightType(Tokens, NumTokens, TypeOfDir)) {
  2542. X                    Log2("DirToInfo is ignoring this line ", line);
  2543. X                    continue;
  2544. X                }
  2545. X    
  2546. X                if (!HaveNow) {
  2547. X                    (void) GetRemoteNow(HostPtr, &Now);
  2548. X                    HaveNow=1;
  2549. X                }
  2550. X
  2551. X                ClearParsedDirEntry(&Current);
  2552. X                Status=TokensToParsedDir(Tokens, NumTokens, TypeOfDir, &Current, &Now, 
  2553. X                    DirPath, HostPtr->Path);
  2554. X
  2555. X                if (FirstOfTwoPasses) {
  2556. X                    if (IsAnAlexTop(Current.Name)) {
  2557. X                        TotalAlexTops++;
  2558. X                    }
  2559. X                } else if ((Status==AOK) && NotForbiddenName(Current.Name)){
  2560. X                    if (MakeLinksType != 0) {
  2561. X                        ModifyCurrentToLink(&Current, MakeLinksType, NumUp);
  2562. X                    }
  2563. X#ifndef AT_DIR
  2564. X                    NextHost=OutputHostsBefore(AITmpFile, NextHost, DirPWS, DPWSlen, Current.Name);
  2565. X#endif
  2566. X                    TotalFTPLS++;
  2567. X                    OneLineOut(AITmpFile, &Current);
  2568. X                    if ((NewestDate < Current.Date) && 
  2569. X                              ((Current.Type == AFILE)               || 
  2570. X#ifdef CAREFULATTOP
  2571. X                               (AtHostTop && (Current.Type == ADIR)) ||
  2572. X#endif
  2573. X                               (streql(Current.Name, ".")))) {
  2574. X                        NewestDate=Current.Date;
  2575. X                    }
  2576. X                }
  2577. X            }
  2578. X            if ((NumNotFound == 1) && (NumLines==1)) {    /* XXXX might be old if NotFound > 1 */
  2579. X                if (!ParentHasNewAlexDir(DirPath)) {
  2580. X                    Result=AOLD;
  2581. X                }
  2582. X            }
  2583. X            if (NumLines==0) {
  2584. X                Log2("ERROR Could not read from ", AlexDirPath);
  2585. X            }
  2586. X            (void) AFCLOSE(ADfile);
  2587. X        }                                                       /* end of big skip if null ADfile */
  2588. X    }                                                           /* end of big skip for hosts only */
  2589. X   
  2590. X#ifdef AT_DIR 
  2591. X    if ((HostPtr==NULL) || (ADfile == NULL))                   /* AT_DIR only sees hosts when no .alex.dir */
  2592. X#endif 
  2593. X    {
  2594. X     NextHost=OutputHostsBefore(AITmpFile, NextHost, DirPWS, DPWSlen, "~~~~~"); /* large ascii val */
  2595. X    }
  2596. X
  2597. X    SaveInodeNext();                                 /* we may have allocated some new ones */
  2598. X
  2599. X    Log("DirToInfo about to close tmpfile");
  2600. X    if (AFCLOSE(AITmpFile) < 0) {                     
  2601. X        ToLog(DBERROR, "DirToInfo ERROR close of tmpfile failed failed");
  2602. X        return(AFAIL);
  2603. X    }
  2604. X
  2605. X    if (Result != AOK) {
  2606. X        LogT("DirToInfo returning early with ", Result);
  2607. X        return(Result);
  2608. X    }
  2609. X
  2610. X    if (LiteStat(AlexInfo) == AFILE) {            /* if an old then we will use it but if not */
  2611. X        (void) strcpy(AlexInfoOld, AlexInfo);     /* careful now with two of same name        */
  2612. X    } else {
  2613. X        (void) strcpy(AlexInfoOld, "/dev/null");  /* then we will use /dev/null               */
  2614. X    }
  2615. X
  2616. X    Log2("DirToInfo     AlexInfoOld", AlexInfoOld);
  2617. X    LogT("DirToInfo    intermediate Result", Result);  /* must be AOK */
  2618. X
  2619. X    Result=SortFile(AlexInfoTmp);
  2620. X
  2621. X    if (Result == AOK) {
  2622. X        int PartsInHostName;
  2623. X
  2624. X        if (HostPtr == NULL) {
  2625. X            PartsInHostName = 0;
  2626. X        } else {
  2627. X            PartsInHostName = HostPtr->PartsInHostName;
  2628. X        }
  2629. X
  2630. X        LogN("DirToInfo PartsInHostName= ", PartsInHostName);
  2631. X
  2632. X        Status=FixInodesAndRemoveOld(AlexInfoOld, AlexInfoTmp, AlexInfoNew, UidStr, 
  2633. X               UpdateDate, NewestDate, TypeOfDir, PartsInHostName, AddAnyErrorStatus, HaveAlexDir);
  2634. X        if (Status != AOK) {
  2635. X            ToLog(DBERROR, "DirToInfo  ERROR  could not FixInodes %s\n", AlexInfo); 
  2636. X            (void) unlink(AlexInfoTmp);                         
  2637. X            Result=AFAIL;
  2638. X        } else {
  2639. X            Log("DirToInfo  think we have a good .alex.info.new"); 
  2640. X            Result=AOK; 
  2641. X
  2642. X            Status=unlink(AlexInfoTmp);                         
  2643. X            if (Status != AOK) {
  2644. X                ToLog(DBERROR, "DirToInfo  ERROR  could not unlink %s\n", AlexInfoTmp); 
  2645. X            }
  2646. X            if(rename(AlexInfoNew, AlexInfo)) {      /* last is   mv .alex.info.new .alex.info */
  2647. X                error2("DirToInfo ERROR could not rename .alex.info.new to ", AlexInfo);
  2648. X                Result=AFAIL;
  2649. X            }
  2650. X        }    
  2651. X    }
  2652. X
  2653. X    InvalidateStatCache=1;
  2654. X
  2655. X    ToLog(DBFTP, "DirToInfo is returning %s\n", ATypeToString(Result));
  2656. X    return(Result);
  2657. X}
  2658. X
  2659. X
  2660. X
  2661. END_OF_FILE
  2662.   if test 77292 -ne `wc -c <'alexsrvr/src/dirtoinfo.c'`; then
  2663.     echo shar: \"'alexsrvr/src/dirtoinfo.c'\" unpacked with wrong size!
  2664.   fi
  2665.   # end of 'alexsrvr/src/dirtoinfo.c'
  2666. fi
  2667. echo shar: End of archive 5 \(of 13\).
  2668. cp /dev/null ark5isdone
  2669. MISSING=""
  2670. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
  2671.     if test ! -f ark${I}isdone ; then
  2672.     MISSING="${MISSING} ${I}"
  2673.     fi
  2674. done
  2675. if test "${MISSING}" = "" ; then
  2676.     echo You have unpacked all 13 archives.
  2677.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2678. else
  2679.     echo You still must unpack the following archives:
  2680.     echo "        " ${MISSING}
  2681. fi
  2682. exit 0
  2683. exit 0 # Just in case...
  2684.