home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume19 / shape / part19 < prev    next >
Text File  |  1989-05-31  |  55KB  |  1,829 lines

  1. Subject:  v19i032:  A software configuration management system, Part19/33
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Axel Mahler <unido!coma!axel>
  7. Posting-number: Volume 19, Issue 32
  8. Archive-name: shape/part19
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 19 (of 33)."
  19. # Contents:  src/afs/afdelta.c src/shape/rule.c src/vc/doretrv.c
  20. # Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:11 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'src/afs/afdelta.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'src/afs/afdelta.c'\"
  24. else
  25. echo shar: Extracting \"'src/afs/afdelta.c'\" \(17045 characters\)
  26. sed "s/^X//" >'src/afs/afdelta.c' <<'END_OF_FILE'
  27. X/*
  28. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  29. X *  and U. Pralle
  30. X * 
  31. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  32. X * WARRANTY for any part of this software to work correctly or as described
  33. X * in the manuals. We do not accept any liability for any kind of damage
  34. X * caused by use of this software, such as loss of data, time, money, or 
  35. X * effort.
  36. X * 
  37. X * Permission is granted to use, copy, modify, or distribute any part of
  38. X * this software as long as this is done without asking for charge, and
  39. X * provided that this copyright notice is retained as part of the source
  40. X * files. You may charge a distribution fee for the physical act of
  41. X * transferring a copy, and you may at your option offer warranty
  42. X * protection in exchange for a fee.
  43. X * 
  44. X * Direct questions to: Tech. Univ. Berlin
  45. X *              Wilfried Koch
  46. X *              Sekr. FR 5-6 
  47. X *              Franklinstr. 28/29
  48. X *              D-1000 Berlin 10, West Germany
  49. X * 
  50. X *              Tel: +49-30-314-22972
  51. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  52. X */
  53. X/*
  54. X *    Shape/AFS
  55. X *
  56. X *    afdelta.c -- Delta processing
  57. X *
  58. X *    Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP
  59. X *                       andy@db0tui62.BITNET)
  60. X *
  61. X *    $Header: afdelta.c[1.4] Wed Feb 22 16:27:26 1989 andy@coma published $
  62. X *
  63. X *    EXPORT:
  64. X *    af_nodelta -- save entire file
  65. X *    af_dodelta -- save delta
  66. X *    af_undodelta -- rebuild file
  67. X *      af_rmdelta -- remove delta from delta chain
  68. X */
  69. X
  70. X#include <stdio.h>
  71. X
  72. X#include "typeconv.h"
  73. X#include "afsys.h"
  74. X#include "afs.h"
  75. X
  76. X/*====================================================================
  77. X *    af_nodelta
  78. X *
  79. X * Store the busy version (busykey) without building a delta.
  80. X * "nodelta" is necessary for saving the initial version (1.0)
  81. X * or for storing versions without delta technique.
  82. X *
  83. X *====================================================================*/
  84. X
  85. XEXPORT af_nodelta (busykey, savekey)
  86. X
  87. X     Af_key *busykey;
  88. X     Af_key *savekey;
  89. X{
  90. X  char    *malloc();
  91. X  FILE    *busyfile;
  92. X  
  93. X  VATTR(savekey).af_fsize = af_retfsize (busykey->af_ldes->af_busyfilename);
  94. X  VATTR(savekey).af_dsize = 0;
  95. X  VATTR(savekey).af_repr = AF_CHUNK;
  96. X  VATTR(savekey).af_data = 
  97. X    af_malloc (savekey->af_ldes, (unsigned) VATTR(savekey).af_fsize);
  98. X
  99. X  if ((busyfile = fopen (busykey->af_ldes->af_busyfilename, "r")) == (FILE *)0)
  100. X    FAIL ("nodelta", "fopen", AF_ESYSERR, ERROR);
  101. X
  102. X  if (fread (VATTR(savekey).af_data, sizeof (char), (Size_t) VATTR(savekey).af_fsize, busyfile) != VATTR(savekey).af_fsize)
  103. X    FAIL ("nodelta", "fread", AF_ESYSERR, ERROR);
  104. X
  105. X  (void) fclose (busyfile);
  106. X  savekey->af_ldes->af_datasize += VATTR(savekey).af_fsize;
  107. X  return (AF_OK);
  108. X} /* af_nodelta */
  109. X
  110. X
  111. X
  112. X/*====================================================================
  113. X *    af_dodelta
  114. X *
  115. X * Build a delta between a busy version (busykey) and its preceeding
  116. X * version (predkey) and store it as a new version (savekey).
  117. X * If no busykey is given ((Af_key *)0), build a null delta and store
  118. X * it as new version.
  119. X * The latter case is needed, if a version shall be stored with different
  120. X * attributes but unchanged contents. 
  121. X *
  122. X *====================================================================*/
  123. X
  124. XEXPORT af_dodelta (busykey, predkey, savekey)
  125. X
  126. X     Af_key *busykey;
  127. X     Af_key *predkey;
  128. X     Af_key *savekey;
  129. X{
  130. X  char    *delname, *malloc();
  131. X  FILE    *busyfile, *delfile;
  132. X  
  133. X  if (busykey != (Af_key *)0 )
  134. X    {
  135. X      /* read in busyfile for delta processing */
  136. X      VATTR(savekey).af_fsize = af_retfsize(busykey->af_ldes->af_busyfilename);
  137. X      
  138. X      VATTR(savekey).af_data =
  139. X    af_malloc (savekey->af_ldes, (unsigned) VATTR(savekey).af_fsize);
  140. X      if ((busyfile = fopen (busykey->af_ldes->af_busyfilename,"r"))
  141. X                                                            == (FILE *)0)
  142. X    FAIL ("dodelta", "fopen", AF_ESYSERR, ERROR);
  143. X
  144. X      if (fread (VATTR(savekey).af_data, sizeof (char), (Size_t) VATTR(savekey).af_fsize, busyfile) != VATTR(savekey).af_fsize)
  145. X    FAIL ("dodelta", "fread", AF_ESYSERR, ERROR);
  146. X
  147. X      (void) fclose (busyfile);
  148. X      savekey->af_ldes->af_datasize += VATTR(savekey).af_fsize;
  149. X      VATTR(savekey).af_dsize = 0;
  150. X      VATTR(savekey).af_repr = AF_CHUNK;
  151. X    }
  152. X  else
  153. X    /* produce null delta (new generation) */
  154. X    {
  155. X      VATTR(savekey).af_data = VATTR(predkey).af_data;
  156. X      VATTR(savekey).af_fsize = VATTR(predkey).af_fsize;
  157. X      VATTR(savekey).af_dsize = 0;
  158. X      VATTR(savekey).af_repr = AF_CHUNK;
  159. X      savekey->af_ldes->af_datasize += VATTR(savekey).af_fsize;
  160. X    }
  161. X
  162. X  /* if version opens a new branch, no delta processing is necessary */
  163. X  if ((predkey->af_ldes == (Af_revlist *)0) || 
  164. X      (VATTR(predkey).af_repr == AF_DELTA))
  165. X    { 
  166. X      VATTR(savekey).af_predgen = AF_NOVNUM;
  167. X      VATTR(savekey).af_predrev = AF_NOVNUM;
  168. X      return (AF_OK);
  169. X    }
  170. X
  171. X  /* else do delta processing */
  172. X
  173. X  /* create filename for delta */
  174. X  delname = af_gtmpname (CATTR(savekey).af_syspath, VATTR(savekey).af_name);
  175. X  af_regtmpfile (delname);
  176. X
  177. X  if (lcs (VATTR(savekey).af_data, VATTR(predkey).af_data,
  178. X      VATTR(savekey).af_fsize, VATTR(predkey).af_fsize, delname) == ERROR)
  179. X    FAIL ("dodelta", "", AF_EDELTA, ERROR);
  180. X
  181. X  /* update predversion */
  182. X  /* read deltafile */
  183. X  VATTR(predkey).af_dsize = af_retfsize (delname);
  184. X  if ((VATTR(predkey).af_dsize > VATTR(predkey).af_fsize) || 
  185. X                                      (busykey == (Af_key *)0 ))
  186. X    VATTR(predkey).af_data = af_malloc (predkey->af_ldes, (unsigned) VATTR(predkey).af_dsize);
  187. X
  188. X  if ((delfile = fopen (delname, "r")) == (FILE *)0)
  189. X    FAIL ("dodelta", "fopen", AF_ESYSERR, ERROR);
  190. X
  191. X  if ((fread (VATTR(predkey).af_data, sizeof (char), (Size_t) VATTR(predkey).af_dsize, delfile)) != VATTR(predkey).af_dsize)
  192. X    FAIL ("dodelta", "fread", AF_ESYSERR, ERROR);
  193. X  (void) fclose (delfile);
  194. X
  195. X  /* remove tmp-file */
  196. X  (void) af_unlink (delname);
  197. X  af_unregtmpfile (delname);
  198. X  
  199. X  /* update list descriptor (file is replaced by delta) */
  200. X  savekey->af_ldes->af_datasize -= VATTR(predkey).af_fsize;
  201. X  savekey->af_ldes->af_datasize += VATTR(predkey).af_dsize;
  202. X  VATTR(predkey).af_repr = AF_DELTA;
  203. X  VATTR(predkey).af_succgen = VATTR(savekey).af_gen;
  204. X  VATTR(predkey).af_succrev = VATTR(savekey).af_rev;
  205. X  
  206. X  return (AF_OK);
  207. X} /* af_dodelta */
  208. X
  209. X
  210. X
  211. X/*====================================================================
  212. X *    af_undodelta
  213. X *
  214. X * The version pointed to by deltakey is supposed to be a (at least)
  215. X * saved version represented by a chunk (AF_CHUNK) or a delta (AF_DELTA).
  216. X * Passing a busy version causes an error (AF_NOVERS).
  217. X * Filename has to be the name of an accessible UNIX-file,
  218. X * where the rebuilt version will be stored.
  219. X * The version pointed to by deltakey remains unchanged. 
  220. X *
  221. X *====================================================================*/
  222. X
  223. XEXPORT af_undodelta (deltakey, filename)
  224. X     Af_key *deltakey;
  225. X     char   *filename;
  226. X{
  227. X  Af_key *deltachain, *keyptr;
  228. X  char   *tmpname, *data, *malloc(), *realloc();
  229. X  int    i;
  230. X  off_t  fsize;
  231. X  FILE   *tmpfile;
  232. X
  233. X  /* this error should never occur */
  234. X  if (VATTR(deltakey).af_repr == AF_FILE)
  235. X    FAIL ("undodelta", "wrong kind of representation", AF_EINTERNAL, ERROR);
  236. X
  237. X  if ((deltachain = (Af_key *) malloc ((unsigned) (AF_SEGLEN * sizeof (Af_key)))) == (Af_key *)0)
  238. X    FAIL ("undodelta", "malloc", AF_ESYSERR, ERROR);
  239. X
  240. X  /* collect deltachain */
  241. X  i = 0;
  242. X  deltachain[0] = *deltakey;
  243. X  keyptr = deltakey;
  244. X  while (VATTR(keyptr).af_repr == AF_DELTA)
  245. X    {
  246. X      i++;
  247. X      if ((i & AF_SEGLEN) == AF_SEGLEN) /* if segment is full */
  248. X    if ((deltachain = (Af_key *) realloc ((char *) deltachain, (unsigned) ((i + AF_SEGLEN) * sizeof (Af_key)))) == (Af_key *)0)
  249. X      FAIL ("undodelta", "realloc", AF_ESYSERR, ERROR);
  250. X
  251. X      if (af_buildkey (deltakey->af_ldes, VATTR(keyptr).af_succgen,
  252. X               VATTR(keyptr).af_succrev, &(deltachain[i])) == ERROR)
  253. X    FAIL ("undodelta", "delta chain broken", AF_EINTERNAL, ERROR);
  254. X      keyptr = &(deltachain[i]);
  255. X    }
  256. X
  257. X  fsize = VATTR(keyptr).af_fsize;
  258. X  if ((data = malloc ((unsigned) VATTR(keyptr).af_fsize)) == (char *)0)
  259. X    FAIL ("undodelta", "malloc", AF_ESYSERR, ERROR);
  260. X  bcopy (VATTR(keyptr).af_data, data, (Size_t) fsize);
  261. X  /* first step is done */
  262. X  i--;
  263. X
  264. X  /* process delta chain */
  265. X  tmpname = af_gtmpname (CATTR(deltakey).af_syspath, VATTR(deltakey).af_name);
  266. X  af_regtmpfile (tmpname);
  267. X
  268. X  if (i < 0) /* no delta chain */
  269. X    {
  270. X      if ((tmpfile = fopen (tmpname, "w")) == (FILE *)0)
  271. X    FAIL ("undodelta", "fopen", AF_ESYSERR, ERROR);
  272. X      (void) fwrite (data, (Size_t) fsize, sizeof (char), tmpfile);
  273. X      (void) fclose (tmpfile);
  274. X    }
  275. X      
  276. X  /* else */
  277. X  for (i; i >= 0; i--)
  278. X    {
  279. X      keyptr = &(deltachain[i]);
  280. X      if (bsfd (data, VATTR(keyptr).af_data, fsize, VATTR(keyptr).af_dsize,
  281. X        tmpname) == ERROR)
  282. X    FAIL ("undodelta", "", AF_EDELTA, ERROR);
  283. X      if (i == 0) 
  284. X    continue;  /* increase performance */
  285. X      fsize = af_retfsize (tmpname);
  286. X      if ((data = realloc (data, (unsigned) (fsize * sizeof (char)))) == (char *)0)
  287. X    FAIL ("undodelta", "realloc", AF_ESYSERR, ERROR);
  288. X      if ((tmpfile = fopen (tmpname, "r")) == (FILE *)0)
  289. X    FAIL ("undodelta", "fopen", AF_ESYSERR, ERROR);
  290. X      (void) fread (data, (Size_t) fsize, sizeof (char), tmpfile);
  291. X      (void) fclose (tmpfile);
  292. X    }
  293. X  free ((char *) deltachain);
  294. X  free (data);
  295. X
  296. X  (void) af_unlink (filename);
  297. X  if (af_syslink (tmpname, filename) == ERROR)
  298. X    FAIL ("undodelta", "link", AF_ESYSERR, ERROR);
  299. X  (void) af_unlink (tmpname);
  300. X  af_unregtmpfile (tmpname);
  301. X
  302. X  return (AF_OK);
  303. X}
  304. X
  305. X/*====================================================================
  306. X *    af_rmdelta
  307. X *
  308. X *====================================================================*/
  309. X
  310. XEXPORT af_rmdelta (deltakey)
  311. X     Af_key *deltakey;
  312. X{
  313. X  register i;
  314. X  int      succsize, predsize;
  315. X  char     *succdata, *preddata, *malloc(), *realloc(), *tmpname;
  316. X  FILE     *tmpfile;
  317. X  Af_key   *deltachain, *keyptr, *predptr;
  318. X                    /* deltachain shall hold all keys from the physical
  319. X             * predecessor to the end of the physical line of 
  320. X             * descent (chunk). That is:
  321. X             * deltachain[0] = predecessor
  322. X             * deltachain[1] = deltakey
  323. X             * deltachain[2] = successor ...
  324. X             * ... deltachain[n] = chunk
  325. X             */
  326. X
  327. X  if ((deltachain = (Af_key *) malloc ((unsigned) (AF_SEGLEN * sizeof (Af_key)))) == (Af_key *)0)
  328. X    FAIL ("rmdelta", "malloc", AF_ESYSERR, ERROR);
  329. X
  330. X  /* update predecessor attributes of successor version */
  331. X  if ((VATTR(deltakey).af_succgen != AF_NOVNUM) && 
  332. X      (VATTR(deltakey).af_succrev != AF_NOVNUM))
  333. X    {
  334. X      (void) af_buildkey (deltakey->af_ldes, VATTR(deltakey).af_succgen, VATTR(deltakey).af_succrev, &(deltachain[2]));
  335. X      VATTR((&(deltachain[2]))).af_predgen = VATTR(deltakey).af_predgen;
  336. X      VATTR((&(deltachain[2]))).af_predrev = VATTR(deltakey).af_predrev;
  337. X    }
  338. X
  339. X  /* if deltakey points to the predecessor of the busy version,  */
  340. X  /* update busy version (should be optimized) */
  341. X  /* works only, if busy version is at position 0 */
  342. X  if ((deltakey->af_ldes->af_list[0].af_predgen == VATTR(deltakey).af_gen) &&
  343. X      (deltakey->af_ldes->af_list[0].af_predrev == VATTR(deltakey).af_rev))
  344. X    {
  345. X      deltakey->af_ldes->af_list[0].af_predgen = AF_NOVNUM;
  346. X      deltakey->af_ldes->af_list[0].af_predrev = AF_NOVNUM;
  347. X    }
  348. X  
  349. X  /* if deltakey points to first element in delta chain */
  350. X  /*    no delta processing is necessary */
  351. X  if ((VATTR(deltakey).af_predgen == AF_NOVNUM) && 
  352. X      (VATTR(deltakey).af_predrev == AF_NOVNUM))
  353. X    {
  354. X      return (AF_OK);
  355. X    }
  356. X
  357. X  /* else collect delta chain */
  358. X  (void) af_buildkey (deltakey->af_ldes, VATTR(deltakey).af_predgen,
  359. X           VATTR(deltakey).af_predrev, &(deltachain[0]));
  360. X  predptr = &(deltachain[0]);
  361. X  deltachain[1] = *deltakey;
  362. X  /* if deltakey points to chunk do nothing else */
  363. X  if ((VATTR(deltakey).af_succgen == AF_NOVNUM) && 
  364. X      (VATTR(deltakey).af_succrev == AF_NOVNUM))
  365. X    {
  366. X      i = 1;
  367. X    }
  368. X  else
  369. X    {
  370. X      i = 2;
  371. X      keyptr = &(deltachain[2]);
  372. X      while (VATTR(keyptr).af_repr == AF_DELTA)
  373. X    {
  374. X      i++;
  375. X      if ((i & AF_SEGLEN) == AF_SEGLEN) /* if segment is full */
  376. X        if ((deltachain = (Af_key *) realloc ((char *) deltachain, (unsigned) ((i+AF_SEGLEN) * sizeof(Af_key)))) == (Af_key *)0)
  377. X          FAIL ("rmdelta", "realloc", AF_ESYSERR, ERROR);
  378. X      
  379. X      (void) af_buildkey (deltakey->af_ldes, VATTR(keyptr).af_succgen,
  380. X               VATTR(keyptr).af_succrev, &(deltachain[i]));
  381. X      keyptr = &(deltachain[i]);
  382. X    }
  383. X    }
  384. X
  385. X  tmpname = af_gtmpname (CATTR(deltakey).af_syspath, VATTR(deltakey).af_name);
  386. X  af_regtmpfile (tmpname);
  387. X
  388. X  /* if deltakey points to chunk, only the predecessor version has to */
  389. X  /*    be rebuilt */
  390. X  if (i == 1)
  391. X    {
  392. X      /* generate chunk for predecessor */
  393. X      if (bsfd (VATTR(deltakey).af_data, VATTR(predptr).af_data,
  394. X        VATTR(deltakey).af_fsize, VATTR(predptr).af_dsize, tmpname)
  395. X      == ERROR)
  396. X    FAIL ("rmdelta", "", AF_EDELTA, ERROR);
  397. X
  398. X      VATTR(predptr).af_repr = AF_CHUNK;
  399. X      /* update sizes in revision list descriptor and in attribute buffer */
  400. X      deltakey->af_ldes->af_datasize -= VATTR(predptr).af_dsize;
  401. X      VATTR(predptr).af_dsize = 0;
  402. X      VATTR(predptr).af_fsize = af_retfsize (tmpname);
  403. X      deltakey->af_ldes->af_datasize += VATTR(predptr).af_fsize;
  404. X
  405. X      /* if VATTR(predptr).af_data points to memory allocated by an own
  406. X       * af_malloc (and not in af_readdata), this memory segment remains
  407. X       * "unfreed" (This is a BUG !).
  408. X       */
  409. X      if ((VATTR(predptr).af_data = af_malloc (predptr->af_ldes, (unsigned) (VATTR(predptr).af_fsize * sizeof(char)))) == (char *)0)
  410. X    FAIL ("rmdelta", "malloc", AF_ESYSERR, ERROR);
  411. X
  412. X      tmpfile = fopen (tmpname, "r");
  413. X      (void) fread (VATTR(predptr).af_data, (Size_t) VATTR(predptr).af_fsize, sizeof (char), tmpfile);
  414. X      (void) fclose (tmpfile);
  415. X      (void) af_unlink (tmpname);
  416. X      af_unregtmpfile (tmpname);
  417. X      VATTR(predptr).af_succgen = AF_NOVNUM;
  418. X      VATTR(predptr).af_succrev = AF_NOVNUM;
  419. X      return (AF_OK);
  420. X    }
  421. X      
  422. X  /* else process delta chain and build pred and succ version */
  423. X  succsize = VATTR(keyptr).af_fsize;
  424. X  if ((succdata = malloc ((unsigned) (VATTR(keyptr).af_fsize * sizeof (char)))) == (char *)0)
  425. X    FAIL ("rmdelta", "malloc", AF_ESYSERR, ERROR);
  426. X  bcopy (VATTR(keyptr).af_data, succdata, succsize);
  427. X  /* first step is done */
  428. X  i--;
  429. X
  430. X  /* first regenerate sucessor version and leave it in the buffer "succdata" */
  431. X  for (i; i >= 2; i--)
  432. X    {
  433. X      keyptr = &(deltachain[i]);
  434. X      if (bsfd (succdata, VATTR(keyptr).af_data, (long) succsize,
  435. X        VATTR(keyptr).af_dsize, tmpname) == ERROR)
  436. X    FAIL ("rmdelta", "", AF_EDELTA, ERROR);
  437. X
  438. X      succsize = af_retfsize (tmpname);
  439. X      if ((succdata = realloc (succdata, (unsigned) (succsize * sizeof(char)))) == (char *)0)
  440. X    FAIL ("rmdelta", "realloc", AF_ESYSERR, ERROR);
  441. X      tmpfile = fopen (tmpname, "r");
  442. X      (void) fread (succdata, (Size_t)succsize, sizeof (char), tmpfile);
  443. X      (void) fclose (tmpfile);
  444. X    }
  445. X  /* regenerate predecessor version in buffer "preddata" */
  446. X  if (bsfd (succdata, VATTR(deltakey).af_data, (long) succsize,
  447. X        VATTR(deltakey).af_dsize, tmpname) == ERROR)
  448. X    FAIL ("rmdelta", "", AF_EDELTA, ERROR);
  449. X
  450. X  predsize = af_retfsize (tmpname);
  451. X  if ((preddata = malloc ((unsigned) (predsize * sizeof (char)))) == (char *)0)
  452. X    FAIL ("rmdelta", "malloc", AF_ESYSERR, ERROR);
  453. X  tmpfile = fopen (tmpname, "r");
  454. X  (void) fread (preddata, predsize, sizeof (char), tmpfile);
  455. X  (void) fclose (tmpfile);
  456. X  if (bsfd (preddata, VATTR((&(deltachain[0]))).af_data, (long) predsize, VATTR((&(deltachain[0]))).af_dsize, tmpname) == ERROR)
  457. X    FAIL ("rmdelta", "", AF_EDELTA, ERROR);
  458. X  
  459. X  predsize = af_retfsize (tmpname);
  460. X  if ((preddata = realloc (preddata, (unsigned) (predsize * sizeof (char)))) == (char *)0)
  461. X    FAIL ("rmdelta", "realloc", AF_ESYSERR, ERROR);
  462. X  tmpfile = fopen (tmpname, "r");
  463. X  (void) fread (preddata, predsize, sizeof (char), tmpfile);
  464. X  (void) fclose (tmpfile);
  465. X  
  466. X  /* build new delta for predecessor version */
  467. X  if (lcs (succdata, preddata, (long) succsize, (long) predsize, tmpname) == ERROR)
  468. X    FAIL ("rmdelta", "", AF_EDELTA, ERROR);
  469. X
  470. X  /* update sizes in revision list descriptor and in attribute buffer */
  471. X  deltakey->af_ldes->af_datasize -= VATTR(predptr).af_dsize;
  472. X  VATTR(predptr).af_dsize = af_retfsize (tmpname);
  473. X  deltakey->af_ldes->af_datasize += VATTR(predptr).af_dsize;
  474. X
  475. X  /* if VATTR(predptr).af_data points to memory allocated by an own
  476. X   * af_malloc (and not in af_readdata), this memory segment remains
  477. X   * "unfreed" (This is a BUG !).
  478. X   */
  479. X  if ((VATTR(predptr).af_data = af_malloc (predptr->af_ldes, (unsigned) (VATTR(predptr).af_dsize*sizeof(char)))) == (char *)0)
  480. X    FAIL ("rmdelta", "malloc", AF_ESYSERR, ERROR);
  481. X  tmpfile = fopen (tmpname, "r");
  482. X  (void) fread (VATTR(predptr).af_data, (Size_t) VATTR(predptr).af_dsize, sizeof (char), tmpfile);
  483. X  (void) fclose (tmpfile);
  484. X  (void) af_unlink (tmpname);
  485. X  af_unregtmpfile (tmpname);
  486. X  free (succdata);
  487. X  free (preddata);
  488. X  VATTR(predptr).af_succgen = VATTR((&(deltachain[2]))).af_gen;
  489. X  VATTR(predptr).af_succrev = VATTR((&(deltachain[2]))).af_rev;
  490. X  free ((char *) deltachain);
  491. X  return (AF_OK);
  492. X}
  493. X
  494. END_OF_FILE
  495. if test 17045 -ne `wc -c <'src/afs/afdelta.c'`; then
  496.     echo shar: \"'src/afs/afdelta.c'\" unpacked with wrong size!
  497. fi
  498. # end of 'src/afs/afdelta.c'
  499. fi
  500. if test -f 'src/shape/rule.c' -a "${1}" != "-c" ; then 
  501.   echo shar: Will not clobber existing file \"'src/shape/rule.c'\"
  502. else
  503. echo shar: Extracting \"'src/shape/rule.c'\" \(17098 characters\)
  504. sed "s/^X//" >'src/shape/rule.c' <<'END_OF_FILE'
  505. X/*
  506. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  507. X *  and U. Pralle
  508. X * 
  509. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  510. X * WARRANTY for any part of this software to work correctly or as described
  511. X * in the manuals. We do not accept any liability for any kind of damage
  512. X * caused by use of this software, such as loss of data, time, money, or 
  513. X * effort.
  514. X * 
  515. X * Permission is granted to use, copy, modify, or distribute any part of
  516. X * this software as long as this is done without asking for charge, and
  517. X * provided that this copyright notice is retained as part of the source
  518. X * files. You may charge a distribution fee for the physical act of
  519. X * transferring a copy, and you may at your option offer warranty
  520. X * protection in exchange for a fee.
  521. X * 
  522. X * Direct questions to: Tech. Univ. Berlin
  523. X *              Wilfried Koch
  524. X *              Sekr. FR 5-6 
  525. X *              Franklinstr. 28/29
  526. X *              D-1000 Berlin 10, West Germany
  527. X * 
  528. X *              Tel: +49-30-314-22972
  529. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  530. X */
  531. X#ifndef lint
  532. Xstatic char *RCSid = "$Header: rule.c,v 3.0 89/01/24 11:36:35 wolfgang Stable $";
  533. X#endif
  534. X#ifndef lint
  535. Xstatic char *ConfFlg = CFFLGS;    /* should be defined from within Makefile */
  536. X#endif
  537. X/*
  538. X * $Log:    rule.c,v $
  539. X * Revision 3.0  89/01/24  11:36:35  wolfgang
  540. X * New System Generation
  541. X * 
  542. X * Revision 2.16  89/01/19  12:38:05  wolfgang
  543. X * check for .IGNORE added
  544. X * 
  545. X * Revision 2.15  89/01/03  13:13:00  wolfgang
  546. X * changes done for lint
  547. X * 
  548. X * Revision 2.14  88/12/21  15:11:59  wolfgang
  549. X * changes done for lint
  550. X * 
  551. X * Revision 2.13  88/12/19  13:24:06  wolfgang
  552. X * things for special targets .BPOOL & .NOBPOOL added.
  553. X * 
  554. X * Revision 2.12  88/12/12  13:16:40  wolfgang
  555. X * bug fixed (something for sun).
  556. X * 
  557. X * Revision 2.11  88/11/22  17:17:14  wolfgang
  558. X * changes done for sun & bugs fixed.
  559. X * 
  560. X * Revision 2.10  88/11/21  15:48:55  wolfgang
  561. X * return code of all malloc's checked
  562. X * 
  563. X * Revision 2.9  88/11/08  11:05:13  wolfgang
  564. X * This version is part of a release
  565. X * 
  566. X * Revision 2.8  88/09/16  12:59:29  wolfgang
  567. X * overload_stdrules() added.
  568. X * 
  569. X * Revision 2.7  88/09/14  10:52:06  wolfgang
  570. X * undone last changes
  571. X * 
  572. X * Revision 2.6  88/09/13  14:41:03  wolfgang
  573. X * Because of bad performance: get_src_name deleted.
  574. X * 
  575. X * Revision 2.5  88/09/09  11:57:33  wolfgang
  576. X * Performance improved. get_src_name has been called to often.
  577. X * 
  578. X * Revision 2.4  88/08/31  12:03:20  wolfgang
  579. X * Standard dependent added to depency list.
  580. X * 
  581. X * Revision 2.3  88/08/23  15:37:13  wolfgang
  582. X * ruledump() has been changed. In dependncy lines the first dependent
  583. X * is supressed if it is a name of a selection rule and we are generating
  584. X * a confid.
  585. X * 
  586. X * Revision 2.2  88/08/23  10:25:36  wolfgang
  587. X * Changed ruledump; now it can be used both to generate confid's
  588. X * and for the -d option.
  589. X * 
  590. X * Revision 2.1  88/08/19  10:17:50  wolfgang
  591. X * This version is part of a release
  592. X * 
  593. X */
  594. X
  595. X/* allow a:b   ?????? geht noch nicht ....
  596. X         a:c
  597. X     a:d  etc. if only one action is defined !!!!! */
  598. X
  599. X/* :: still not yet implememnted */
  600. X/* intermixing of implicit "." rules and normal targets is *not* allowed */
  601. X
  602. X#include "shape.h"
  603. X#include "rule.h"
  604. X
  605. Xextern int hashval();
  606. Xextern int errexit();
  607. Xextern char *expandmacro();
  608. Xextern char *get_src_name();
  609. Xextern struct rules *stdruletab[];
  610. Xextern int implicit_suffs[];
  611. Xextern Bool is_old_rule();
  612. Xstruct rules *ruletab[RULETABSIZE];
  613. Xchar *firsttarget;
  614. XBool oldrule;
  615. X
  616. Xint depnr;
  617. Xint targnr;
  618. Xint cmdnr;
  619. Xint heritnr;
  620. Xchar *targfield[MAXTARGS];
  621. Xchar *depfield[MAXDEPS];
  622. Xchar *cmdfield[MAXCMDS];
  623. Xchar *heritfield[MAXHERIT];
  624. X
  625. X
  626. Xruledef(string)
  627. X     char *string;
  628. X{
  629. Xint i = 0;
  630. Xint k = 0;
  631. Xchar klazu;
  632. Xchar *t;
  633. X
  634. Xtargnr = 0;
  635. Xdepnr = 0;
  636. Xcmdnr = 0;
  637. Xheritnr = 0;
  638. X
  639. Xif ((t = malloc( (unsigned) strlen(string) + 1)) == NIL)
  640. X  errexit(10,"malloc");
  641. X
  642. Xstring = expandmacro(string);
  643. X
  644. Xwhile(string[i] != ':')
  645. X  {
  646. X    while((string[i] != ' ') && (string[i] != '\t') && (string[i] != ':'))
  647. X      {
  648. X    t[k] = string[i];
  649. X    i++;
  650. X    k++;
  651. X      }
  652. X    t[k] = '\0';
  653. X    targnr++;
  654. X    if (targnr > MAXTARGS)
  655. X      errexit(27, "targets");
  656. X    if ((targfield[targnr] = malloc((unsigned) strlen(t) + 1)) == NIL)
  657. X      errexit(10,"malloc");
  658. X    (void) strcpy(targfield[targnr], t);
  659. X#ifdef DEBUG_RULE
  660. Xprintf("target no. %d = #%s#\n", targnr, targfield[targnr]);
  661. X#endif DEBUG_RULE
  662. X    k = 0;
  663. X    while((string[i] == ' ') || (string[i] == '\t'))
  664. X      i++;
  665. X  }
  666. Xif (string[i+1] == ':')
  667. X  {
  668. X    doublecolon = TRUE;
  669. X    i = i + 2;
  670. X  }
  671. Xelse
  672. X  i++;
  673. X
  674. Xwhile((string[i] != '\0') && (string[i] != ';') && (string[i] != ':'))
  675. X  {
  676. X    while((string[i] == ' ') || (string[i] == '\t') ||
  677. X      (string[i] == '\\'))
  678. X      {
  679. X    if ((string[i] == '\\') && (string[i+1] == '\n'))
  680. X      i = i+2;
  681. X    else
  682. X      i++;
  683. X      }
  684. X    while((string[i] != ' ') && (string[i] != '\t') &&
  685. X      (string[i] != ';') && (string[i] != '\0') &&
  686. X      (string[i] != ':') && (string[i] != '\\'))
  687. X      {
  688. X    t[k] = string[i];
  689. X    i++;
  690. X    k++;
  691. X      }
  692. X    t[k] = '\0';
  693. X    if (k != 0)
  694. X      {
  695. X    depnr++;
  696. X    if (depnr > MAXDEPS)
  697. X      errexit(27, "dependents");
  698. X    if ((depfield[depnr] = malloc((unsigned) strlen(t) + 1)) == NIL)
  699. X      errexit(10,"malloc");
  700. X    (void) strcpy(depfield[depnr],t);
  701. X#ifdef DEBUG_RULE
  702. Xprintf("dependent no. %d=#%s#\n", depnr , depfield[depnr]);
  703. X#endif DEBUG_RULE
  704. X      }
  705. X    k = 0;
  706. X  }
  707. X
  708. X
  709. Xwhile((string[i] == ' ') || (string[i] == '\t'))
  710. X  i++;
  711. X
  712. X/* heritage */
  713. X
  714. Xk = 0;
  715. Xif (string[i] == ':')
  716. X  {
  717. X    i++;
  718. X    while( (string[i] != '\0') )
  719. X      {
  720. X    while((string[i] == ' ') || (string[i] == '\t'))
  721. X      i++;
  722. X    if (string[i] != '+')
  723. X      errexit(26, &string[i]);
  724. X    if (string[i+1] == '(')
  725. X      klazu = ')';
  726. X    else
  727. X      {
  728. X        if (string[i+1] == '{')
  729. X          klazu = '}';
  730. X        else
  731. X          klazu = ' ';
  732. X      }
  733. X
  734. X    while (string[i] != klazu)
  735. X      {
  736. X        t[k] = string[i];
  737. X        i++;
  738. X        k++;
  739. X        if (string[i] == '\0')
  740. X          errexit(26,&string[i]);
  741. X      }
  742. X    t[k] = string[i];
  743. X    k++;
  744. X    i++;
  745. X    t[k] = '\0';
  746. X    heritnr++;
  747. X    if (heritnr > MAXHERIT)
  748. X      errexit(27, "iherits");
  749. X    if ((heritfield[heritnr] = malloc((unsigned) strlen(t) + 1)) == NIL)
  750. X      errexit(10,"malloc");
  751. X    (void) strcpy(heritfield[heritnr],t);
  752. X    k = 0;
  753. X      }
  754. X  }
  755. X
  756. X/* commands on ruledef line */
  757. Xif( string[i] == ';')
  758. X  {
  759. X    i++;
  760. X    while( (string[i] != '\0'))
  761. X      {
  762. X    t[k] = string[i];
  763. X    i++;
  764. X    k++;
  765. X      }
  766. X    t[k] = '\0';
  767. X    cmdnr++;
  768. X    if (cmdnr > MAXCMDS)
  769. X      errexit(27, "commands");
  770. X    if ((cmdfield[cmdnr] = malloc((unsigned) strlen(t) + 1)) == NIL)
  771. X      errexit(10,"malloc");
  772. X    if (t[strlen(t)-1] == '\n')
  773. X      t[strlen(t)-1] = '\0';
  774. X    (void) strcpy(cmdfield[cmdnr], t);
  775. X#ifdef DEBUG_RULE
  776. Xprintf("command[%d] = #%s#\n", cmdnr, cmdfield[cmdnr]);
  777. X#endif DEBUG_RULE
  778. X  }
  779. X}
  780. X
  781. Xrulecont(string)
  782. X     char *string;
  783. X{
  784. X/* only commands have been found */
  785. Xcmdnr++;
  786. Xif(cmdnr > MAXCMDS)
  787. X  errexit(27, "commands");
  788. Xif ((cmdfield[cmdnr] = malloc ((unsigned) strlen(string) + 1)) == NIL)
  789. X  errexit(10,"malloc");
  790. Xif (string[strlen(string)-1] == '\n')
  791. X  string[strlen(string)-1] = '\0';
  792. X(void) strcpy(cmdfield[cmdnr], string);
  793. X#ifdef DEBUG_RULE
  794. Xprintf("command[%d] = #%s#\n", cmdnr, cmdfield[cmdnr]);
  795. X#endif DEBUG_RULE
  796. X}
  797. X
  798. Xruleend()
  799. X{
  800. X  struct rules *current;
  801. X  struct cmds *curcmd;
  802. X  int i = 0;
  803. X  int j = 0;
  804. X  int jjj = 0;
  805. X  int kkk = 0;
  806. X  int xx = 0;
  807. X  int ss = 0;
  808. X  int minus = 0;
  809. X  Bool src_found = FALSE;
  810. X  int hasht = 0;
  811. X  char *p;
  812. X  char *srcname;
  813. X  Bool std_rule = FALSE;
  814. X  Bool found = FALSE;
  815. X  int targs = 0;
  816. X  
  817. X  if(targnr == 0)
  818. X    return;
  819. X
  820. X  if(!strcmp(targfield[1],".BPOOL"))
  821. X    bpoolflg = TRUE;
  822. X
  823. X  if(!strcmp(targfield[1],".NOBPOOL"))
  824. X    nobpoolflg = TRUE;
  825. X
  826. X  if(!strcmp(targfield[1],".IGNORE"))
  827. X    ignoreflg = TRUE;
  828. X  
  829. X  if ((is_old_rule(targfield[1])) && (strcmp(targfield[1],".SUFFIXES") != 0))
  830. X    {
  831. X      oldrule = TRUE;
  832. X      targs = targnr;
  833. X      for(i = 1; i <= targs; i++)
  834. X    {
  835. X      if (is_old_rule(targfield[i]))
  836. X        {
  837. X          if (targfield[i] != NIL)
  838. X        convertrule(i);
  839. X        }
  840. X          ruleend();
  841. X    }
  842. X      oldrule = FALSE;
  843. X      return;
  844. X    }
  845. X
  846. X  for(i = 1; i <= targnr; i++)
  847. X    {
  848. X      p = index(targfield[i],'%');
  849. X      if ((p != NIL) && ((*(p+1) == '\0') || (*(p+1) == '.')))
  850. X    {
  851. X      std_rule = TRUE;
  852. X      break;
  853. X    }
  854. X    }
  855. X
  856. X  for(i = 1; i <= targnr; i++)
  857. X    {
  858. X      found = FALSE;
  859. X      if(!std_rule)
  860. X    {
  861. X      hasht = hashval(targfield[i]);
  862. X#ifdef DEBUG_RULE
  863. Xprintf("targfield[i] = %s; i = %d\n", targfield[i], i);
  864. X#endif DEBUG_RULE
  865. X      if ( ruletab[hasht] == (struct rules *) NIL)
  866. X        {
  867. X          if((current = ruletab[hasht] = (struct rules *) malloc( sizeof(struct rules))) == (struct rules *)NIL)
  868. X        errexit(10,"malloc");
  869. X        }
  870. X      else
  871. X      {
  872. X        current = ruletab[hasht];
  873. X        if ((!strcmp(ruletab[hasht]->name, targfield[i])) &&
  874. X        (strcmp(ruletab[hasht]->name, ".SUFFIXES")) &&
  875. X        (current->doublecolon == FALSE) &&
  876. X        (doublecolon == FALSE) &&
  877. X        (ruletab[hasht]->cmdlist != (struct cmds *) NIL) &&
  878. X        (cmdfield[0] != NIL))
  879. X          errexit(1, targfield[i]);
  880. X
  881. X        if((!strcmp(current->name,targfield[i])) &&
  882. X           ((cmdfield[0] == NIL) ||
  883. X        (current->cmdlist == (struct cmds *) NIL)))
  884. X          {
  885. X        found = TRUE;
  886. X          }
  887. X
  888. X        while((current->nextrule != (struct rules *) NIL) && (!found))
  889. X          {
  890. X        if((strcmp(current->name,targfield[i]) == 0) &&
  891. X           ((cmdfield[0] == NIL) ||
  892. X            (current->cmdlist == (struct cmds *) NIL)))
  893. X          {
  894. X            found = TRUE;
  895. X            break;
  896. X          }
  897. X        else
  898. X          current = current->nextrule;
  899. X        if ((strcmp(current->name, targfield[i]) == 0) &&
  900. X            (strcmp(ruletab[hasht]->name, ".SUFFIXES") != 0) &&
  901. X            (ruletab[hasht]->cmdlist != (struct cmds *) NIL) &&
  902. X            (current->doublecolon == FALSE) &&
  903. X            (doublecolon == FALSE) &&
  904. X            (cmdfield[0] != NIL))
  905. X          errexit(1, targfield[i]);
  906. X        if ((strcmp(current->name, ".SUFFIXES")) == 0)
  907. X          {
  908. X            if (depnr == 0) /* delete suffix list */
  909. X              {
  910. X            current->deplist[0] = NIL;
  911. X              }
  912. X            else
  913. X              {
  914. X            while (current->deplist[jjj] != NIL)
  915. X              jjj++;
  916. X                for (kkk = 1; kkk <= depnr; kkk++)
  917. X              {
  918. X                if ((current->deplist[jjj + kkk - 1] =
  919. X                 malloc((unsigned) (strlen(depfield[kkk]) + 1))) == NIL)
  920. X                  errexit(10,"malloc");
  921. X                (void) strcpy(current->deplist[jjj + kkk - 1], depfield[kkk]);
  922. X              }
  923. X              }
  924. X          }
  925. X          }
  926. X        if (!found)
  927. X          {
  928. X        if((current = current->nextrule = (struct rules *) malloc( sizeof(struct rules))) == (struct rules *)NIL)
  929. X          errexit(10,"malloc");
  930. X          }
  931. X      }
  932. X    }
  933. X      else
  934. X    {
  935. X      if((current = stdruletab[lastrule] = (struct rules *) malloc( sizeof(struct rules))) == (struct rules *) NIL)
  936. X        errexit(10,"malloc");
  937. X      overload_stdrule();
  938. X      implicit_suffs[lastrule] = lastrule;
  939. X      lastrule++;
  940. X      implicit_suffs[lastrule] = -1;
  941. X      stdruletab[lastrule] = (struct rules *) NIL;
  942. X    }
  943. X      if (!found)
  944. X    {
  945. X      if((current->name = malloc( (unsigned) strlen( targfield[i] ) + 1)) == NIL)
  946. X        errexit(10,"malloc");
  947. X      (void) strcpy(current->name, targfield[i]);
  948. X    }
  949. X      current->done = FALSE;
  950. X      if (doublecolon)
  951. X    current->doublecolon = TRUE;
  952. X      else
  953. X    current->doublecolon = FALSE;
  954. X      if((i == 1) && (firsttarget == NIL) && (current->name[0] != '%') &&
  955. X     (current->name[0] != '.'))
  956. X     firsttarget = current->name;
  957. X      if(!found)
  958. X    {
  959. X      current->deplist[0] = NIL;
  960. X      current->cmdlist = (struct cmds *) NIL;
  961. X      current->nextrule = (struct rules *) NIL;
  962. X    }
  963. X      if ((depnr > 0) && (!found))
  964. X    {
  965. X      if ((current->firstdep = malloc((unsigned) (strlen(depfield[1]) + sizeof(char)))) == NIL)
  966. X        errexit(10,"malloc");
  967. X      (void) strcpy(current->firstdep, depfield[1]);
  968. X    }
  969. X      
  970. X      if (found)
  971. X    {
  972. X      for(xx = 0; current->deplist[xx] != NIL; xx++)
  973. X        ;
  974. X    }      
  975. X      minus = 0;
  976. X      for(j = xx+1; j <= xx+depnr; j++)
  977. X    {
  978. X      for(ss = 0; current->deplist[ss] != NIL; ss++)
  979. X        {
  980. X          if (!strcmp(current->deplist[ss],depfield[j-xx]))
  981. X        {
  982. X          src_found = TRUE;
  983. X          minus = 1;
  984. X          break;
  985. X        }
  986. X        }
  987. X      if(!src_found)
  988. X        {
  989. X          if ((current->deplist[j-1-minus] =
  990. X           malloc((unsigned) (strlen(depfield[j-xx]) + sizeof(char)))) == NIL)
  991. X        errexit(10,"malloc");
  992. X          (void) strcpy(current->deplist[j-1-minus], depfield[j-xx]);
  993. X        }
  994. X    }
  995. X      current->deplist[j-1] = NIL;
  996. X      src_found = FALSE;
  997. X    
  998. X      /* get standard dependent */
  999. X
  1000. X      if(current->name[0] != '%')
  1001. X    {
  1002. X      if((srcname = get_src_name(current->name)) != NIL)
  1003. X        {
  1004. X          for(ss = 0; ss <= j-2; ss++)
  1005. X        {
  1006. X          if(!strcmp(srcname,current->deplist[ss]))
  1007. X            {
  1008. X              src_found = TRUE;
  1009. X              break;
  1010. X            }
  1011. X        }
  1012. X          if (!src_found)
  1013. X        {
  1014. X          if((current->deplist[j-1] =
  1015. X              malloc((unsigned) (strlen(srcname) + 1))) == NIL)
  1016. X            errexit(10,"malloc");
  1017. X          (void) strcpy(current->deplist[j-1],srcname);
  1018. X          current->deplist[j] = NIL;
  1019. X        }
  1020. X          src_found = FALSE;
  1021. X        }
  1022. X    }
  1023. X
  1024. X      if (heritnr > 0)
  1025. X    {
  1026. X      for (j = 1; j <= heritnr; j++)
  1027. X        {
  1028. X          if((current->heritage[j-1] =
  1029. X          malloc((unsigned) (strlen(heritfield[j]) + sizeof(char)))) == NIL)
  1030. X        errexit(10,"malloc");
  1031. X          (void) strcpy(current->heritage[j-1], heritfield[j]);
  1032. X        }
  1033. X      current->heritage[j-1] = NIL;
  1034. X    }
  1035. X      else
  1036. X    current->heritage[0] = NIL;
  1037. X
  1038. X      if(std_rule)
  1039. X    {
  1040. X      for (j = 1; j <= targnr; j++)
  1041. X        {
  1042. X          if((current->targetlist[j-1] =
  1043. X          malloc((unsigned) (strlen(targfield[j]) + 1))) == NIL)
  1044. X        errexit(10,"malloc");
  1045. X          (void) strcpy(current->targetlist[j-1],targfield[j]);
  1046. X        }
  1047. X      current->targetlist[j-1] = NIL;
  1048. X    }
  1049. X      if (cmdnr > 0)
  1050. X    {
  1051. X      if ((curcmd = current->cmdlist = (struct cmds *) malloc( sizeof( struct cmds))) == (struct cmds *) NIL)
  1052. X        errexit(10,"malloc");
  1053. X      for (j = 1; j <= cmdnr; j++)
  1054. X        {
  1055. X          if((curcmd->command = malloc( (unsigned) strlen (cmdfield[j]) + 1)) == NIL)
  1056. X        errexit(10,"malloc");
  1057. X          (void) strcpy(curcmd->command, cmdfield[j]);
  1058. X          if (j != cmdnr)
  1059. X        {
  1060. X          if((curcmd = curcmd->nextcmd = (struct cmds *) malloc( sizeof( struct cmds))) == (struct cmds *) NIL)
  1061. X            errexit(10,"malloc");
  1062. X        }
  1063. X          else
  1064. X        curcmd->nextcmd = (struct cmds *) NIL;
  1065. X        }
  1066. X    }
  1067. X    }
  1068. X
  1069. Xdoublecolon = FALSE;
  1070. X
  1071. Xif (!oldrule)
  1072. X  {
  1073. X    targnr = 0;
  1074. X    targfield[1] = NIL;
  1075. X    depnr =  0;
  1076. X    depfield[1] = NIL;
  1077. X    cmdnr = 0;
  1078. X    cmdfield[1] = NIL;
  1079. X    heritnr = 0;
  1080. X    heritfield[1] = NIL;
  1081. X  }
  1082. X} /* end ruleend */
  1083. X
  1084. Xconvertrule(i)
  1085. X     int i;
  1086. X{
  1087. X  char *p;
  1088. X  p = rindex(targfield[i],'.');
  1089. X  *p = '\0';
  1090. X  p++;
  1091. X  if ((depfield[1] = malloc((unsigned) (strlen(targfield[i]) + 3))) == NIL)
  1092. X    errexit(10,"malloc");
  1093. X  (void) strcpy(depfield[1],"%");
  1094. X  (void) strcat(depfield[1],targfield[i]);
  1095. X  if((targfield[1] = malloc((unsigned) (strlen(p) + 3))) == NIL)
  1096. X    errexit(10,"malloc");
  1097. X  (void) strcpy(targfield[1],"%.");
  1098. X  (void) strcat(targfield[1],p);
  1099. X  targnr = 1;
  1100. X  depnr = 1;
  1101. X}
  1102. X
  1103. Xruledump(fd)
  1104. X     FILE *fd;
  1105. X{
  1106. Xstruct rules *cur;
  1107. Xstruct cmds *ccmd;
  1108. Xint i;
  1109. Xint k = 0;
  1110. Xfor(i = 0; i< RULETABSIZE; i++)
  1111. X  {
  1112. X    if (ruletab[i] != (struct rules *) NIL)
  1113. X      {
  1114. X    k = 0;
  1115. X    cur = ruletab[i];
  1116. X    while( cur != (struct rules *) NIL)
  1117. X      {
  1118. X        if(fd == stdout)
  1119. X          fprintf(fd,"%s\n", cur->name);
  1120. X        else
  1121. X          fprintf(fd,"%s", cur->name);
  1122. X
  1123. X        if (fd == stdout)
  1124. X          fprintf(fd," depends on:");
  1125. X        else
  1126. X          fprintf(fd,":");
  1127. X
  1128. X        while (cur->deplist[k] != NIL)
  1129. X          {
  1130. X        if (fd != stdout)
  1131. X          {
  1132. X            if(!is_selrule_name(cur->deplist[k]))
  1133. X              fprintf(fd," %s",cur->deplist[k]);
  1134. X            k++;
  1135. X          }
  1136. X        else
  1137. X          {
  1138. X            fprintf(fd," %s",cur->deplist[k]);
  1139. X            k++;
  1140. X          }
  1141. X          }
  1142. X        fprintf(fd,"\n");
  1143. X
  1144. X        ccmd = cur->cmdlist;
  1145. X
  1146. X        if(fd == stdout)
  1147. X          fprintf(fd," commands:\n");
  1148. X          
  1149. X        while (ccmd != (struct cmds *) NIL)
  1150. X          {
  1151. X        fprintf(fd,"%s\n", ccmd->command);
  1152. X        ccmd = ccmd->nextcmd;
  1153. X          }
  1154. X        fprintf(fd,"\n");
  1155. X        cur = cur->nextrule;
  1156. X      }
  1157. X      }
  1158. X  }
  1159. X
  1160. X
  1161. Xfor(i = 0; i < lastrule; i++)
  1162. X  {
  1163. X    k = 0;
  1164. X    cur = stdruletab[i];
  1165. X
  1166. X    if(fd == stdout)
  1167. X      fprintf(fd,"%s\n", cur->name);
  1168. X    else
  1169. X      fprintf(fd,"%s", cur->name);
  1170. X
  1171. X    if (fd == stdout)
  1172. X      fprintf(fd," depends on:");
  1173. X    else
  1174. X      fprintf(fd," :");
  1175. X
  1176. X    while (cur->deplist[k] != NIL)
  1177. X      {
  1178. X    fprintf(fd," %s",cur->deplist[k]);
  1179. X    k++;
  1180. X      }
  1181. X
  1182. X    if (fd == stdout)
  1183. X      fprintf(fd,"\n");
  1184. X
  1185. X    k = 0;
  1186. X    
  1187. X    if (fd == stdout)
  1188. X      fprintf(fd," inherits:");
  1189. X    else
  1190. X      fprintf(fd," :");
  1191. X
  1192. X    while (cur->heritage[k] != NIL)
  1193. X      {
  1194. X    fprintf(fd," %s", cur->heritage[k]);
  1195. X    k++;
  1196. X      }
  1197. X    fprintf(fd,"\n");
  1198. X
  1199. X    ccmd = cur->cmdlist;
  1200. X    
  1201. X    if (fd == stdout)
  1202. X      fprintf(fd," commands:\n");
  1203. X
  1204. X    while (ccmd != (struct cmds *) NIL)
  1205. X      {
  1206. X    fprintf(fd,"%s\n", ccmd->command);
  1207. X    ccmd = ccmd->nextcmd;
  1208. X    if (ccmd->command == NIL)
  1209. X      break;
  1210. X      }
  1211. X    fprintf(fd,"\n");
  1212. X  }
  1213. X
  1214. X(void) fflush(fd);
  1215. X
  1216. X} /* end ruledump */
  1217. X
  1218. X
  1219. Xadjust_stdrules(suffs)
  1220. X     /*ARGSUSED*/
  1221. X     char *suffs;
  1222. X{
  1223. X
  1224. X;
  1225. X}
  1226. X      
  1227. XBool is_old_rule(string)
  1228. X     char *string;
  1229. X{
  1230. X  char *p1,*p2;
  1231. X  if (index(string,'/') != NIL)
  1232. X    return(FALSE);
  1233. X  if (((p1 = index(string,'.')) != NIL) &&
  1234. X      ((p2 = index(string+2,'.')) != NIL) &&
  1235. X      (p1 < p2))
  1236. X    return(TRUE);
  1237. X  else
  1238. X    return(FALSE);
  1239. X}
  1240. X      
  1241. X   
  1242. Xoverload_stdrule()
  1243. X{
  1244. X  int i;
  1245. X  
  1246. X  for(i = 0; i < lastrule; i++)
  1247. X    {
  1248. X      if((strcmp(stdruletab[implicit_suffs[i]]->name,targfield[1]) == 0) &&
  1249. X     (strcmp(stdruletab[implicit_suffs[i]]->deplist[0], depfield[1]) == 0))
  1250. X    {
  1251. X      implicit_suffs[i] = lastrule;
  1252. X      return;
  1253. X    }
  1254. X    }
  1255. X}
  1256. X    
  1257. X    
  1258. X    
  1259. Xinit_ruletab()
  1260. X{
  1261. X  bzero((char *) ruletab, 257 * sizeof(struct rules *));
  1262. X}
  1263. X
  1264. END_OF_FILE
  1265. if test 17098 -ne `wc -c <'src/shape/rule.c'`; then
  1266.     echo shar: \"'src/shape/rule.c'\" unpacked with wrong size!
  1267. fi
  1268. # end of 'src/shape/rule.c'
  1269. fi
  1270. if test -f 'src/vc/doretrv.c' -a "${1}" != "-c" ; then 
  1271.   echo shar: Will not clobber existing file \"'src/vc/doretrv.c'\"
  1272. else
  1273. echo shar: Extracting \"'src/vc/doretrv.c'\" \(17013 characters\)
  1274. sed "s/^X//" >'src/vc/doretrv.c' <<'END_OF_FILE'
  1275. X/*
  1276. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  1277. X *  and U. Pralle
  1278. X * 
  1279. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  1280. X * WARRANTY for any part of this software to work correctly or as described
  1281. X * in the manuals. We do not accept any liability for any kind of damage
  1282. X * caused by use of this software, such as loss of data, time, money, or 
  1283. X * effort.
  1284. X * 
  1285. X * Permission is granted to use, copy, modify, or distribute any part of
  1286. X * this software as long as this is done without asking for charge, and
  1287. X * provided that this copyright notice is retained as part of the source
  1288. X * files. You may charge a distribution fee for the physical act of
  1289. X * transferring a copy, and you may at your option offer warranty
  1290. X * protection in exchange for a fee.
  1291. X * 
  1292. X * Direct questions to: Tech. Univ. Berlin
  1293. X *              Wilfried Koch
  1294. X *              Sekr. FR 5-6 
  1295. X *              Franklinstr. 28/29
  1296. X *              D-1000 Berlin 10, West Germany
  1297. X * 
  1298. X *              Tel: +49-30-314-22972
  1299. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  1300. X */
  1301. X#ifndef lint
  1302. Xstatic char *AFSid = "$Header: doretrv.c[3.12] Thu Feb 23 18:13:27 1989 axel@coma published $";
  1303. X#ifdef CFFLGS
  1304. Xstatic char *ConfFlg = CFFLGS;
  1305. X    /* should be defined from within Makefile */
  1306. X#endif
  1307. X#endif
  1308. X/*
  1309. X * Log for /u/shape/dist-tape/src/vc/doretrv.c[3.6]
  1310. X *     Thu Feb 23 18:13:27 1989 axel@coma published $
  1311. X *  --- empty log message ---
  1312. X *  doretrv.c[3.8] Thu Feb 23 18:13:27 1989 axel@coma published $
  1313. X *  --- empty log message ---
  1314. X *  doretrv.c[3.9] Thu Feb 23 18:13:27 1989 axel@coma save $
  1315. X *  --- empty log message ---
  1316. X *  doretrv.c[3.10] Thu Feb 23 18:13:27 1989 axel@coma save $
  1317. X *  --- empty log message ---
  1318. X *  doretrv.c[3.11] Thu Feb 23 18:13:27 1989 axel@coma published $
  1319. X *  --- empty log message ---
  1320. X *  doretrv.c[3.12] Thu Feb 23 18:13:27 1989 axel@coma published $
  1321. X *  --- empty log message ---
  1322. X */
  1323. X
  1324. X#include <sys/file.h>
  1325. X#include <pwd.h>
  1326. X#include <stdio.h>
  1327. X#include <strings.h>
  1328. X#include "afs.h"
  1329. X#include "retrv.h"
  1330. X#include "project.h"
  1331. X#include "locks.h"
  1332. X
  1333. Xextern struct Transaction ThisTransaction;
  1334. Xextern unsigned int options;
  1335. X
  1336. X#ifndef ERROR
  1337. X#define ERROR -1
  1338. X#endif
  1339. X
  1340. XRetrieveAFile (fname, vdesc, proj, destpath)
  1341. X     char *fname, *destpath;
  1342. X     struct Vdesc *vdesc;
  1343. X     Project *proj; {
  1344. X /*
  1345. X  *  NOTE: use of variant attribute in af_getkey is not yet functional.
  1346. X  *        The parameter, however, is necessary to occupy the slot.
  1347. X  *        Implementation of variant selection may make it necessary
  1348. X  *        to add another parameter to this procedure.
  1349. X  */
  1350. X       char spath[MAXNAMLEN], origpath[MAXNAMLEN], name[MAXNAMLEN], *afname,
  1351. X       *aftype, *afvariant = NULL, messg[80], vsymname[80], *lbuf, *busyloc,
  1352. X       tname[MAXNAMLEN], *getattr(), *vnum(), *mktemp(), *malloc(),
  1353. X       destname[256], lockdir[256], lockfn[256], *intent, *getintent(),
  1354. X       *lockerid();
  1355. X       FILE *vfil, *bfile, *tfil;
  1356. X       Af_attrs reqattrs, fattrs;
  1357. X       Af_set hits;
  1358. X       Af_key busy, tkey, tmpkey, *busykey, *thiskey = &tkey;
  1359. X       Af_user *locker;
  1360. X       int nudattr = 0, nhits, nbytes;
  1361. X       unsigned int pstat = 0;
  1362. X       register int i;
  1363. X
  1364. X       if (!fname) return;
  1365. X       af_initattrs (&reqattrs);
  1366. X       busykey = &busy;
  1367. X       getsyspath (fname, proj, spath, origpath, name);
  1368. X       afname = af_afname (name);
  1369. X       aftype = af_aftype (name);
  1370. X       /* start fill out the warrant -- first 3 items may differ */
  1371. X       (void)strcpy (reqattrs.af_name, afname);
  1372. X       (void)strcpy (reqattrs.af_type, aftype);
  1373. X       (void)strcpy (reqattrs.af_syspath, spath);
  1374. X
  1375. X       /* ... the following settings will remain constant */
  1376. X       if (options & VSPECSET) {
  1377. X     if (vdesc->v_vno) {
  1378. X       reqattrs.af_gen = gen(vdesc->v_vno);
  1379. X       reqattrs.af_rev = rev(vdesc->v_vno);
  1380. X     }
  1381. X     else {
  1382. X       (void)sprintf (vsymname, "%s=%s", SYMNAME, vdesc->v_spec);
  1383. X       reqattrs.af_udattrs[nudattr] = vsymname;
  1384. X       nudattr++;
  1385. X     }
  1386. X       }
  1387. X       if (options & ATTRDEF) {
  1388. X     reqattrs.af_udattrs[nudattr] = 
  1389. X       getattr (vdesc->v_attrf, proj, aftype, REWIND);
  1390. X     if (reqattrs.af_udattrs[nudattr]) nudattr++;
  1391. X     while (reqattrs.af_udattrs[nudattr] = getattr (vdesc->v_attrf, 
  1392. X                              proj, aftype, NEXT))
  1393. X       nudattr++;
  1394. X       }
  1395. X       if ((options & GENSET) && (!(options & VSPECSET))) {
  1396. X     reqattrs.af_gen = vdesc->v_genno;
  1397. X       }
  1398. X       if (options & AUNSET) {
  1399. X     (void)strcpy (reqattrs.af_author.af_username, vdesc->v_aunam);
  1400. X     (void)strcpy (reqattrs.af_author.af_userhost, vdesc->v_auhost);
  1401. X       }
  1402. X       if (options & STATSET) {
  1403. X     reqattrs.af_state = vdesc->v_state;
  1404. X       }
  1405. X       /* descriptive attributes are filled in now. 
  1406. X    * lets try to find something 
  1407. X    */
  1408. X       if (fail(af_find(&reqattrs, &hits))) {
  1409. X     af_perror (fname);
  1410. X     abort_this(TRUE);
  1411. X       }
  1412. X       Register ((char *)&hits, AFSET);
  1413. X       
  1414. X       /* Now lets see what kind of deed needs to be done */
  1415. X       nhits = af_nrofkeys (&hits);
  1416. X       if (nhits == 0) {
  1417. X     (void)sprintf (messg, "No appropriate version of %s.", fname);
  1418. X     logmsg (messg);
  1419. X     (void)sprintf (messg, NORESTORE, fname);
  1420. X     logmsg (messg);
  1421. X     abort_this(FALSE);
  1422. X       }
  1423. X       if (nhits == 1) {
  1424. X     if (af_setgkey (&hits, 0, &tkey) == ERROR) {
  1425. X       af_perror ("af_setgkey");
  1426. X       abort_this (TRUE);
  1427. X     }
  1428. X       }
  1429. X       else if (nhits > 1) {
  1430. X     if (fail(af_sortset(&hits, AF_ATTSTIME))) {
  1431. X       af_perror ("af_sortset");
  1432. X       abort_this (TRUE);
  1433. X     }
  1434. X     if (!(options & DATESET)) {
  1435. X       if (af_setgkey (&hits, nhits-1, &tkey) == ERROR) {
  1436. X         af_perror ("af_setgkey");
  1437. X         abort_this (TRUE);
  1438. X       }
  1439. X     }
  1440. X     else { /* some cutoff-date was specified */
  1441. X       /* Don't consider busy version here */
  1442. X       af_setgkey (&hits, 0, &tmpkey);
  1443. X       if (af_rstate (&tmpkey) == AF_BUSY) {
  1444. X         af_setrmkey (&hits, &tmpkey);
  1445. X         nhits--;
  1446. X       }
  1447. X       for (i = nhits; i > 0; i--) {
  1448. X         if (af_setgkey (&hits, i-1, &tkey) == ERROR) {
  1449. X           af_perror ("af_setgkey");
  1450. X           abort_this (TRUE);
  1451. X         }
  1452. X         if (fail(af_gattrs(thiskey, &fattrs))) {
  1453. X           af_perror ("af_gattrs");
  1454. X           abort_this (FALSE);
  1455. X         }
  1456. X         if (fattrs.af_stime >= vdesc->v_time) {
  1457. X           af_setrmkey (&hits, thiskey);
  1458. X           udafree (&fattrs);
  1459. X         }
  1460. X         else {
  1461. X           udafree (&fattrs);
  1462. X           break;
  1463. X         }
  1464. X       } /* end loop */
  1465. X       if ((nhits = af_nrofkeys (&hits)) == 0) {
  1466. X         (void)sprintf (messg, "No appropriate version of %s.", fname);
  1467. X         logmsg (messg);
  1468. X         abort_this (FALSE);
  1469. X       }
  1470. X     } /* end of else (some cut-off date) */
  1471. X     if ((options & XACT) && (nhits > 1)) {
  1472. X       (void)sprintf (messg, "No exact hit for %s. (got %d)", fname, nhits);
  1473. X       logmsg (messg);
  1474. X       (void)sprintf (messg, NORESTORE, fname);
  1475. X       logmsg (messg);
  1476. X       abort_this (FALSE);
  1477. X     }
  1478. X       }
  1479. X       else {
  1480. X     (void)sprintf (messg, "%d is an unreasonble number of hits.", nhits);
  1481. X     logerr (messg);
  1482. X     abort_this (TRUE);
  1483. X       }
  1484. X
  1485. X       if (fail(af_gattrs(thiskey, &fattrs))) {
  1486. X     af_perror ("af_gattrs");
  1487. X     abort_this (FALSE);
  1488. X       }
  1489. X       Register ((char *)&fattrs, AFATTRS);
  1490. X       /* at this point we do have a single af_key and 'thiskey' points 
  1491. X    * at it. now decide what 
  1492. X    * to do with it. fattrs contains its attributes.
  1493. X    */
  1494. X       switch (options & (TYPEOUT | COPY | LOCKIT)) {
  1495. X       case TYPEOUT:
  1496. X     if (!(vfil = af_open (thiskey, "r"))) {
  1497. X       af_perror ("af_open");
  1498. X       abort_this (TRUE);
  1499. X     }
  1500. X     mkvstring (messg, thiskey);
  1501. X     logdiag (messg);
  1502. X     lbuf = malloc ((unsigned)fattrs.af_size);
  1503. X     nbytes=fread (lbuf, sizeof (*lbuf), (Size_t)fattrs.af_size, vfil);
  1504. X     WriteXPand (lbuf, nbytes, stdout, thiskey);
  1505. X     free (lbuf);
  1506. X     af_close (vfil);
  1507. X     UnRegister ((char *)&hits, AFSET);
  1508. X     af_dropset (&hits);
  1509. X     UnRegister ((char *)&fattrs, AFATTRS);
  1510. X     udafree (&fattrs);
  1511. X     return;
  1512. X     break;
  1513. X       case COPY:
  1514. X     /* This option creates a plain UNIX file from the specified
  1515. X      * AFS file. The created copy is - in general - an object without
  1516. X      * history. If, however, the copy happens to go into the 
  1517. X      * history-directory (the one containing the archive) it will
  1518. X      * 'automatically' be considered the busy-version.
  1519. X      * If - in this case - a copy replaces a formerly locked busy-version,
  1520. X      * the lock will be released.
  1521. X      */
  1522. X     busyloc = destpath ? destpath : ".";
  1523. X     (void)sprintf (destname, "%s%s%s", destpath ? busyloc : "", 
  1524. X          destpath ? "/" : "", name);
  1525. X     if ((tfil = fopen (destname, "r")) == NULL) {
  1526. X       /* take this as test for presence */
  1527. X       if (access (busyloc, W_OK) == 0) { /* may we create ? */
  1528. X         pstat |= DOIT; /* No scruples if no busyvers current */
  1529. X       }
  1530. X       else {
  1531. X         (void)sprintf (messg, "write permission for directory %s denied.",
  1532. X              busyloc);
  1533. X         logerr (messg);
  1534. X         pstat |= DENIED;
  1535. X       }
  1536. X     }
  1537. X     else { /* file exists */
  1538. X       (void)fclose (tfil);
  1539. X       if (access (destname, W_OK) < 0) {
  1540. X         if (access (busyloc, W_OK) == 0) {
  1541. X           (void)sprintf (messg, "%s write-protected, re-create it ?",
  1542. X            destname);
  1543. X           if (options & QUIETPLEASE) {
  1544. X         pstat |= (options & FORCE) ? (RECREATE | DOIT) : DENIED;
  1545. X           }
  1546. X           else {
  1547. X         if (ask_confirm (messg, "no")) {
  1548. X           pstat |= DENIED;
  1549. X         }
  1550. X         else {
  1551. X           pstat |= (RECREATE | DOIT);
  1552. X         }
  1553. X           }
  1554. X         }
  1555. X         else { 
  1556. X           (void)sprintf (messg, "no write permission for %s", destname);
  1557. X           logmsg (messg);
  1558. X           pstat |= DENIED;
  1559. X         }
  1560. X       }
  1561. X       else { /* write access on destfile */
  1562. X         if (strcmp (busyloc, ".")) {
  1563. X           (void)sprintf (messg, "%s exists and is writable. Overwrite it ?",
  1564. X              destname);
  1565. X           if (options & QUIETPLEASE) {
  1566. X         pstat |= (options & FORCE) ? DOIT : 0;
  1567. X           }
  1568. X           else {
  1569. X         if (!ask_confirm (messg, "no")) {
  1570. X           pstat |= DOIT;
  1571. X         }
  1572. X           }
  1573. X         }
  1574. X         else { /* current dir! - test for lock */
  1575. X           if (fail (af_getkey (spath, afname, aftype, AF_BUSYVERS,
  1576. X                    AF_BUSYVERS, afvariant, &busy)))
  1577. X         { /* No busy-key -- no lock, this is impossible here */
  1578. X           pstat |= DOIT;
  1579. X         }
  1580. X           else {
  1581. X         if (lockeruid (vc_testlock_g(&busy)) == getuid ()) {
  1582. X           (void)sprintf (messg, "Give up lock on %s and overwrite it ?",
  1583. X                destname);
  1584. X           if (options & QUIETPLEASE) {
  1585. X             pstat |= (options & FORCE) ? DOIT : 0;
  1586. X           }
  1587. X           else {
  1588. X             if (!ask_confirm (messg, "no")) {
  1589. X               pstat |= DOIT;
  1590. X               (void)vc_unlock_g(&busy);
  1591. X             }
  1592. X             else {
  1593. X               pstat |= DENIED;
  1594. X             }
  1595. X           }
  1596. X         }
  1597. X         else {
  1598. X           pstat |= DOIT;
  1599. X         }
  1600. X           }
  1601. X         }
  1602. X       }
  1603. X     }
  1604. X     if (pstat & DOIT) {
  1605. X       if ((vfil=af_open(thiskey, "r")) == NULL) {
  1606. X         af_perror ("af_open");
  1607. X         abort_this (TRUE);
  1608. X       } 
  1609. X       (void)sprintf (tname, "%s%s%s", destpath ? destpath : "",
  1610. X            destpath ? "/" : "", mktemp("retrvXXXXXX"));
  1611. X       if ((bfile = fopen (tname, "w")) == NULL) {
  1612. X         (void)sprintf (messg, "cannot create tmp-file (%s) for writing.",
  1613. X              tname);
  1614. X         logerr (messg);
  1615. X         abort_this (TRUE);
  1616. X       }
  1617. X       Register (tname, TYPEF);
  1618. X       (void)sprintf (messg, "%s%s%s[%s] -> %s", spath[0] ? spath : "",
  1619. X            spath[0] ? "/" : "", name, vnum (thiskey), destname);
  1620. X       logdiag (messg);
  1621. X       lbuf = malloc ((unsigned)fattrs.af_size);
  1622. X       nbytes=fread (lbuf, sizeof (*lbuf), (Size_t)fattrs.af_size, vfil);
  1623. X       WriteXPand (lbuf, nbytes, bfile, thiskey);
  1624. X       free (lbuf);
  1625. X       (void)fclose (bfile); (void)fclose (vfil);
  1626. X       (void)unlink (destname);
  1627. X       if (link (tname, destname) < 0) {
  1628. X         perror (destname);
  1629. X         abort_this (TRUE);
  1630. X       }
  1631. X       (void)chmod (destname, 0444); 
  1632. X       UnRegister (tname, TYPEF);
  1633. X       (void)unlink (tname);
  1634. X     }
  1635. X     else {
  1636. X       (void)sprintf (messg, "%s not retrieved", fname);
  1637. X       logmsg (messg);
  1638. X     }
  1639. X     UnRegister ((char *)&hits, AFSET);
  1640. X     af_dropset (&hits);
  1641. X     UnRegister ((char *)&fattrs, AFATTRS);
  1642. X     udafree (&fattrs);
  1643. X     return;
  1644. X     break;
  1645. X       case LOCKIT:
  1646. X     /*
  1647. X      *  Before a version is retrieved, set-busy, and locked, the
  1648. X      *  following preconditions must be fulfilled:
  1649. X      *  - the retrieve must go to the directory containing the 
  1650. X      *    archive directory. -> current directory
  1651. X      *  - the retrieved version must not be locked by anybody but
  1652. X      *    the calling user.
  1653. X      *  - the current directory must grant write access to the 
  1654. X      *    calling user.
  1655. X      *  - if some busy-version would be overwritten by the retrieve,
  1656. X      *    the user is asked if she wants that
  1657. X      */
  1658. X     if ((destpath) && (destpath[0])) {
  1659. X       (void)sprintf (messg, "can't checkout (with lock) to %s.", destpath);
  1660. X       logmsg (messg);
  1661. X       abort_this (FALSE);
  1662. X     }
  1663. X     (void)sprintf (lockfn, "%s%s%s", spath[0] ? spath : "", 
  1664. X          spath[0] ? "/" : "", name);
  1665. X     (void)sprintf (lockdir, "%s", spath[0] ? spath : ".");
  1666. X     /*
  1667. X      *  The following checks are based on the permission information
  1668. X      *  stored in the archive files. It is unclear how
  1669. X      *  to properly handle vanilla filesystem related inquiries.
  1670. X      */
  1671. X     if (fail (af_getkey (spath, afname, aftype, AF_LASTVERS,
  1672. X                  AF_LASTVERS, afvariant, &busy))) {
  1673. X       /* well, this case seems to be impossible. If we get here, */
  1674. X       /* at least _*some*_ version should be present */
  1675. X
  1676. X       af_perror ("RetrieveAFile -- no version in sight.");
  1677. X       abort_this (TRUE);
  1678. X     }
  1679. X     else { /* there is a version */
  1680. X       if (((lockeruid (locker = af_testlock (&busy, AF_GLOBALLOCK))) 
  1681. X        == getuid ()) || !(locked (locker))) {
  1682. X#ifdef AFACCOK
  1683. X         if (af_access (spath[0] ? spath : ".", afname, 
  1684. X                aftype, W_OK) == 0) {
  1685. X#else
  1686. X         if (access (fname, W_OK) == 0) {
  1687. X#endif
  1688. X           (void)sprintf (messg, "Writable %s exists, overwrite it ?", lockfn);
  1689. X           if (options & QUIETPLEASE) {
  1690. X         pstat |= (options & FORCE) ? DOIT : DENIED;
  1691. X           }
  1692. X           else {
  1693. X         pstat |= (ask_confirm (messg, "no")) ? DENIED : DOIT;
  1694. X           }
  1695. X         }
  1696. X         else if (access (lockdir, W_OK) == 0) {
  1697. X           if (access (lockfn, F_OK) == 0) {
  1698. X         (void)sprintf (messg, 
  1699. X              "Write access on %s denied. Overwrite it anyway ?",
  1700. X              lockfn);
  1701. X         if (options & QUIETPLEASE) {
  1702. X           pstat |= (options & FORCE) ? DOIT : DENIED;
  1703. X         }
  1704. X         else {
  1705. X           pstat |= (ask_confirm (messg, "no")) ? DENIED : DOIT;
  1706. X         }
  1707. X           }
  1708. X           else pstat |= DOIT;
  1709. X         }
  1710. X         else { /* no write access on current dir */
  1711. X           (void)sprintf (messg, "Can't create in %s.", lockdir);
  1712. X           abort_this (TRUE);
  1713. X         }
  1714. X         if (!locked(locker)) {
  1715. X           if (!vc_lock_g(&busy, getuid())) {
  1716. X         af_perror ("af_lock");
  1717. X         abort_this (TRUE);
  1718. X           }
  1719. X         }
  1720. X       }
  1721. X       else { /* busy version locked by someone else */
  1722. X         pstat |= DENIED;
  1723. X         (void)sprintf (messg, "%s already locked by %s.", lockfn, 
  1724. X              lockerid(locker));
  1725. X         logmsg (messg);
  1726. X       }
  1727. X     } 
  1728. X     /* now all the checks are done. set retrieved version busy and 
  1729. X      * create it in lockdir.
  1730. X      */
  1731. X     if ((pstat & DOIT) && (!(pstat & DENIED))) {
  1732. X       if (! ((options & QUIETPLEASE) || (options & FORCE)))
  1733. X         intent = getintent ("Describe intended changes ?", (char *)NULL);
  1734. X       else intent = (char *)NULL;
  1735. X       /* setbusy sets just the attributes. data must be moved manually */
  1736. X       if ((vfil=af_open(thiskey, "r")) == NULL) {
  1737. X         af_perror ("af_open");
  1738. X         abort_this (TRUE);
  1739. X       } 
  1740. X       (void)sprintf (tname, "%s/%s", lockdir, mktemp("retrvXXXXXX"));
  1741. X       if ((bfile = fopen (tname, "w")) == NULL) {
  1742. X         (void)sprintf (messg, "cannot create tmp-file (%s) for writing.",
  1743. X            tname);
  1744. X         logerr (messg);
  1745. X         af_close (vfil);
  1746. X         abort_this (TRUE);
  1747. X       }
  1748. X       Register (tname, TYPEF);
  1749. X       (void)sprintf (messg, "%s%s%s[%s] -> %s%s%s", spath[0] ? spath : "", 
  1750. X            spath[0] ? "/" : "", name,
  1751. X            vnum (thiskey), spath[0] ? spath : "", 
  1752. X            spath[0] ? "/" : "",
  1753. X            name);
  1754. X       logdiag (messg);
  1755. X
  1756. X       /* there's no attribute citation for locked busy versions .... */
  1757. X       lbuf = malloc ((unsigned)fattrs.af_size);
  1758. X       nbytes=fread (lbuf, sizeof (*lbuf), (Size_t)fattrs.af_size, vfil);
  1759. X       if (fwrite (lbuf, sizeof (*lbuf), nbytes, bfile) != nbytes) {
  1760. X         logerr ("fatal: couldn't write busy file.");
  1761. X         abort_this (TRUE);
  1762. X       }
  1763. X       free (lbuf);
  1764. X       (void)fclose (bfile);
  1765. X       (void)chmod (tname, 0644);
  1766. X       af_close (vfil);
  1767. X       /* if no busyversion was present, busykey contains garbage */
  1768. X       /* this might be responsible for trouble here */
  1769. X       (void)unlink (fname);
  1770. X       (void)link (tname, fname);
  1771. X       ThisTransaction.tr_done = TRUE;
  1772. X       UnRegister (tname, TYPEF);
  1773. X       (void)unlink (tname);
  1774. X       if (af_crkey (spath, afname, aftype, busykey) < 0) {
  1775. X         af_perror ("af_crkey");
  1776. X         abort_this (TRUE);
  1777. X       }
  1778. X       if (fail(af_setbusy(busykey, thiskey))) {
  1779. X         af_perror ("af_setbusy");
  1780. X         abort_this (TRUE); /* check out what happens in abort_this */
  1781. X       }
  1782. X       (void)vc_lock_g(busykey, getuid());
  1783. X       if (intent) {
  1784. X         char *intattr;
  1785. X         intattr = malloc ((unsigned)(strlen (intent)+strlen (INTENT)+ 1));
  1786. X         (void)sprintf (intattr, "%s%s", INTENT, intent);
  1787. X         if (fail(af_sudattr (busykey, AF_REPLACE, intattr)))
  1788. X           af_sudattr (busykey, AF_ADD, intattr);
  1789. X         free (intattr);
  1790. X       }
  1791. X     }
  1792. X     else { /* denied or not doit */
  1793. X       (void)sprintf (messg, NORESTORE, ThisTransaction.tr_fname);
  1794. X       logmsg (messg);
  1795. X     }
  1796. X     UnRegister ((char *)&fattrs, AFATTRS);
  1797. X     udafree (&fattrs);
  1798. X     UnRegister ((char *)&hits, AFSET);
  1799. X     af_dropset (&hits);
  1800. X     break;
  1801. X       default:
  1802. X     logerr ("fatal: illegal action switch in doretrv.c");
  1803. X     break;
  1804. X       }
  1805. X     }
  1806. END_OF_FILE
  1807. if test 17013 -ne `wc -c <'src/vc/doretrv.c'`; then
  1808.     echo shar: \"'src/vc/doretrv.c'\" unpacked with wrong size!
  1809. fi
  1810. # end of 'src/vc/doretrv.c'
  1811. fi
  1812. echo shar: End of archive 19 \(of 33\).
  1813. cp /dev/null ark19isdone
  1814. MISSING=""
  1815. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
  1816.     if test ! -f ark${I}isdone ; then
  1817.     MISSING="${MISSING} ${I}"
  1818.     fi
  1819. done
  1820. if test "${MISSING}" = "" ; then
  1821.     echo You have unpacked all 33 archives.
  1822.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1823. else
  1824.     echo You still need to unpack the following archives:
  1825.     echo "        " ${MISSING}
  1826. fi
  1827. ##  End of shell archive.
  1828. exit 0
  1829.