home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume12 / cake / part02 / file.c < prev   
Encoding:
C/C++ Source or Header  |  1987-10-14  |  11.9 KB  |  638 lines

  1. /*
  2. **    File system interface module.
  3. */
  4.  
  5. static    char
  6. rcs_id[] = "$Header: /mip/zs/src/sys/cake/RCS/file.c,v 1.14 86/07/19 12:23:08 zs Exp $";
  7.  
  8. #include    "cake.h"
  9. #include    <errno.h>
  10. #include    <sys/dir.h>
  11. #include    <sys/stat.h>
  12. #ifndef        ATT
  13. #include    <sys/time.h>
  14. #endif
  15.  
  16. typedef    struct    timeval        Tval;
  17. typedef    struct    timezone    Tzone;
  18. typedef    struct    stat        Stat;
  19. typedef    struct    direct        Dirent;
  20.  
  21. extern    int    errno;
  22.  
  23. static    char    dir_name[30] = "/tmp/CakeXXXXXX";
  24.  
  25. /*
  26. **    Create the directory to be used for all temporary storage.
  27. */
  28.  
  29. dir_start()
  30. {
  31.     reg    bool    successful;
  32.  
  33.     mktemp(dir_name);
  34.  
  35. #ifdef    ATT
  36.     {
  37.         extern    int    cake_proc();
  38.         extern    Wait    cake_wait();
  39.         reg    int    pid;
  40.         Wait        code;
  41.  
  42.         sprintf(scratchbuf, "mkdir %s", dir_name);
  43.         pid = cake_proc(new_name(scratchbuf), Exec, (char *) NULL,
  44.             (Node *) NULL, (int (*)()) NULL, (List *) NULL);
  45.         code = cake_wait(pid);
  46.         successful = code.w_status == 0;
  47.     }
  48. #else
  49.     successful = mkdir(dir_name, 0700) == 0;
  50. #endif
  51.  
  52.     if (! successful)
  53.     {
  54.         sprintf(scratchbuf, "cake system error, mkdir %s", dir_name);
  55.         perror(scratchbuf);
  56.         exit_cake(FALSE);
  57.     }
  58.  
  59. #ifdef    ATT
  60.     if (chmod(dir_name, 0700) != 0)
  61.     {
  62.         sprintf(scratchbuf, "cake system error, chmod 700 %s", dir_name);
  63.         perror(scratchbuf);
  64.         exit_cake(FALSE);
  65.     }
  66. #endif
  67. }
  68.  
  69. /*
  70. **    Clean up /tmp when we are finished
  71. */
  72.  
  73. dir_finish()
  74. {
  75. #ifndef    LEAVE_DIR
  76. #ifdef    ATT
  77.     extern    int    cake_proc();
  78.     extern    Wait    cake_wait();
  79.     reg    int    pid;
  80.     Wait        code;
  81.  
  82.     sprintf(scratchbuf, "/bin/rm -fr %s", dir_name);
  83.     pid = cake_proc(new_name(scratchbuf), Exec, (char *) NULL,
  84.         (Node *) NULL, (int (*)()) NULL, (List *) NULL);
  85.     code = cake_wait(pid);
  86.     if (code.w_status != 0)
  87.     {
  88.         fprintf(stderr, "cake system error: cannot remove %s\n", dir_name);
  89.         return;
  90.     }
  91. #else
  92.     char        buf[1024];
  93.     reg    DIR    *dirp;
  94.     reg    Dirent    *dp;
  95.     reg    int    nameoffset;
  96.  
  97.     if ((dirp = opendir(dir_name)) == NULL)
  98.     {
  99.         sprintf(scratchbuf, "cake system error, opendir %s", dir_name);
  100.         perror(scratchbuf);
  101.         return;
  102.     }
  103.  
  104.     strcpy(buf, dir_name);
  105.     strcat(buf, "/");
  106.     nameoffset = strlen(buf);
  107.  
  108.     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
  109.         if (strdiff(dp->d_name, ".") && strdiff(dp->d_name, ".."))
  110.         {
  111.             buf[nameoffset] = '\0';
  112.             strcat(buf, dp->d_name);
  113.             cdebug("dir_finish unlink %s\n", buf);
  114.             if (unlink(buf) != 0)
  115.             {
  116.                 sprintf(scratchbuf, "cake system error, unlink %s", buf);
  117.                 perror(scratchbuf);
  118.             }
  119.         }
  120.  
  121.     closedir(dirp);
  122.  
  123.     cdebug("rmdir %s\n", dir_name);
  124.     if (rmdir(dir_name) != 0)
  125.     {
  126.         sprintf(scratchbuf, "cake system error, rmdir %s", dir_name);
  127.         perror(scratchbuf);
  128.     }
  129. #endif
  130. #endif
  131. }
  132.  
  133. /*
  134. **    Get a new filename in our private directory.
  135. **    These files are used to store shell scripts
  136. **    and the output of actions.
  137. **
  138. **    These names MUST be different from those generated
  139. **    by get_savename, so they have different prefixes.
  140. */
  141.  
  142. char *
  143. get_newname()
  144. {
  145.     char        buf[100];
  146.     static    int    count = 0;
  147.  
  148.     ++count;
  149.     sprintf(buf, "%s/gen_%d", dir_name, count);
  150.     return new_name(buf);
  151. }
  152.  
  153. /*
  154. **    Save a nonvolatile file for later comparison.
  155. **    Any slashes in the filename are replaced by colons
  156. **    to avoid reference to nonexistent directories.
  157. */
  158.  
  159. save_novol(node)
  160. reg    Node    *node;
  161. {
  162.     char        buf[MAXSIZE];
  163.     reg    FILE    *ifp, *ofp;
  164.     reg    int    c;
  165.  
  166.     if (nflag)
  167.     {
  168.         node->n_stime = node->n_rtime;
  169.         return;
  170.     }
  171.  
  172.     put_trail("save_novol", "start");
  173.     cdebug("saving %s\n", node->n_name);
  174.     node->n_stime = node->n_rtime;
  175.  
  176.     get_savename(node->n_name, buf);
  177.     if ((ifp = fopen(node->n_name, "r")) == NULL)
  178.     {
  179.         if (errno == ENOENT)
  180.         {
  181.             cdebug("%s does not exist, considered volatile\n", node->n_name);
  182.             reset_node(node, nf_NONVOL);
  183.             put_trail("save_novol", "finish");
  184.             return;
  185.         }
  186.  
  187.         sprintf(scratchbuf, "cake system error, fopen (r) %s", node->n_name);
  188.         perror(scratchbuf);
  189.         printf("cake: considering %s volatile\n", node->n_name);
  190.         reset_node(node, nf_NONVOL);
  191.         put_trail("save_novol", "finish");
  192.         return;
  193.     }
  194.  
  195.     if ((ofp = fopen(buf, "w")) == NULL)
  196.     {
  197.         sprintf(scratchbuf, "cake system error, fopen (w) %s", buf);
  198.         perror(scratchbuf);
  199.         printf("cake: considering %s volatile\n", node->n_name);
  200.         reset_node(node, nf_NONVOL);
  201.         put_trail("save_novol", "finish");
  202.         return;
  203.     }
  204.  
  205.     while ((c = getc(ifp)) != EOF)
  206.         putc(c, ofp);
  207.     
  208.     fclose(ifp);
  209.     fclose(ofp);
  210.     put_trail("save_novol", "finish");
  211. }
  212.  
  213. /*
  214. **    See if the given file has been changed since saved.
  215. */
  216.  
  217. bool
  218. diff_novol(node)
  219. reg    Node    *node;
  220. {
  221.     char        buf[MAXSIZE];
  222.     reg    FILE    *i1fp, *i2fp;
  223.     reg    int    c;
  224.     reg    bool    diff;
  225.  
  226.     if (nflag)
  227.         return FALSE;
  228.  
  229.     put_trail("diff_novol", "start");
  230.     cdebug("comparing saved copy of %s: ", node->n_name);
  231.  
  232.     get_savename(node->n_name, buf);
  233.     if ((i1fp = fopen(node->n_name, "r")) == NULL)
  234.     {
  235.         sprintf(scratchbuf, "cake system error, fopen (r) %s", node->n_name);
  236.         perror(scratchbuf);
  237.         printf("cake: considering %s different\n", node->n_name);
  238.         reset_node(node, nf_NONVOL);
  239.         put_trail("diff_novol", "finish");
  240.         return TRUE;;
  241.     }
  242.  
  243.     if ((i2fp = fopen(buf, "r")) == NULL)
  244.     {
  245.         sprintf(scratchbuf, "cake system error, fopen (r) %s", buf);
  246.         perror(scratchbuf);
  247.         printf("cake: considering %s different\n", node->n_name);
  248.         reset_node(node, nf_NONVOL);
  249.         put_trail("diff_novol", "finish");
  250.         return TRUE;;
  251.     }
  252.  
  253.     diff = FALSE;
  254.     while ((c = getc(i1fp)) != EOF)
  255.         if (getc(i2fp) != c)
  256.         {
  257.             diff = TRUE;
  258.             break;
  259.         }
  260.     
  261.     if (getc(i2fp) != EOF)
  262.         diff = TRUE;
  263.     
  264.     fclose(i1fp);
  265.     fclose(i2fp);
  266.     cdebug("diff_novol unlink %s\n", buf);
  267.     if (unlink(buf) != 0)
  268.     {
  269.         sprintf(scratchbuf, "cake system error, unlink %s", buf);
  270.         perror(scratchbuf);
  271.         put_trail("diff_novol", "finish");
  272.         return TRUE;
  273.     }
  274.  
  275.     cdebug("%s\n", diff? "different": "same");
  276.     put_trail("diff_novol", "finish");
  277.     return diff;
  278. }
  279.  
  280. /*
  281. **    Get the the name of the saved copy of the given file.
  282. */
  283.  
  284. get_savename(name, buf)
  285. reg    char    *name;
  286. reg    char    buf[];
  287. {
  288.     extern    char    *noslash();
  289.  
  290.     strcpy(buf, dir_name);
  291.     strcat(buf, "/save_");
  292.     strcat(buf, noslash(name));
  293. }
  294.  
  295. /*
  296. **    Remove any slashes from a filename.
  297. */
  298.  
  299. char *
  300. noslash(name)
  301. reg    char    *name;
  302. {
  303.     char        buf[MAXSIZE];
  304.     reg    int    i;
  305.     reg    char    *s;
  306.  
  307.     i = 0;
  308.     for (s = name; *s != '\0'; s++)
  309.         if (*s == '/')
  310.             buf[i++] = ':';
  311.         else
  312.             buf[i++] = *s;
  313.     
  314.     buf[i] = '\0';
  315.     return new_name(buf);
  316. }
  317.  
  318. /*
  319. **    Perform a stat on the given file. The only relevant info
  320. **    is the return code, indicating whether the file exists or not
  321. **    and its last modify (or status change) date. Note that if a
  322. **    file does not exist, it is by definition volatile. An aside
  323. **    considers all directories precious.
  324. */
  325.  
  326. node_stat(node)
  327. reg    Node    *node;
  328. {
  329.     extern    int    stat();
  330.     Stat        statbuf;
  331.  
  332.     if (node->n_name != (char *) NULL && stat(node->n_name, &statbuf) == 0)
  333.     {
  334.         set_node(node, nf_EXIST);
  335.         if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
  336.             set_node(node, nf_PRECIOUS);
  337.  
  338.         node->n_rtime = cflag? statbuf.st_ctime: statbuf.st_mtime;
  339.     }
  340.     else
  341.     {
  342.         reset_node(node, nf_EXIST);
  343.         reset_node(node, nf_NONVOL);
  344.         node->n_rtime = GENESIS;
  345.     }
  346. }
  347.  
  348. /*
  349. **    Restore the previous stat of a nonvol file,
  350. **    both in the filesystem and in cake's memory.
  351. **    However, make sure that it will not need to be
  352. **    remade again and again to discover this anew
  353. **    while its ancestors remain the same.
  354. */
  355.  
  356. node_resetstat(node)
  357. reg    Node    *node;
  358. {
  359.     node_stat(node);
  360.     if (off_node(node, nf_EXIST))
  361.         return;
  362.  
  363.     cake_utimes(node, max(node->n_stime, node->n_utime));
  364.     node->n_utime = node->n_rtime;
  365. }
  366.  
  367. /*
  368. **    Set up the stat of a file as the latest ancestor's,
  369. **    both in the filesystem and in cake's memory.
  370. */
  371.  
  372. node_setstat(node)
  373. reg    Node    *node;
  374. {
  375.     extern    time_t    get_youngest();
  376.     reg    time_t    youngest;
  377.  
  378.     node_stat(node);
  379.     if (off_node(node, nf_EXIST))
  380.         return;
  381.  
  382.     youngest = get_youngest(node, FALSE);
  383.     if (youngest != node->n_utime && youngest != GENESIS)
  384.     {
  385.         fprintf(stderr, "cake internal error: youngest is mismatched for %s\n",
  386.             node->n_name);
  387.         exit_cake(TRUE);
  388.     }
  389.  
  390.     cake_utimes(node, node->n_utime);
  391. }
  392.  
  393. /*
  394. **    Return the time, converting formats.
  395. */
  396.  
  397. time_t
  398. cake_gettime()
  399. {
  400. #ifdef    ATT
  401.     extern    long    time();
  402.     long        val;
  403.  
  404.     if (time(&val) == -1)
  405.     {
  406.         sprintf(scratchbuf, "cake system error, time");
  407.         perror(scratchbuf);
  408.         exit_cake(FALSE);
  409.     }
  410.  
  411.     return (time_t) val;
  412. #else
  413.     Tzone        tzone;
  414.     Tval        tval;
  415.  
  416.     if (gettimeofday(&tval, &tzone) != 0)
  417.     {
  418.         sprintf(scratchbuf, "cake system error, gettimeofday");
  419.         perror(scratchbuf);
  420.         exit_cake(FALSE);
  421.     }
  422.  
  423.     return (time_t) tval.tv_sec;
  424. #endif
  425. }
  426.  
  427. /*
  428. **    Issue the system call utimes after expanding its arguments
  429. **    from time_t to Tval. If the time given is GENESIS, use the
  430. **    current time instead.
  431. */
  432.  
  433. #ifdef    ATT
  434. typedef    struct    utimbuf
  435. {
  436.     time_t    actime;
  437.     time_t    modtime;
  438. } Utimbuf;
  439. #endif
  440.  
  441. cake_utimes(node, newtime)
  442. reg    Node    *node;
  443. time_t        newtime;
  444. {
  445. #ifdef    ATT
  446.     extern    int    utime();
  447. #else
  448.     extern    int    utimes();
  449. #endif
  450.     extern    int    stat();
  451.     Stat        statbuf;
  452. #ifdef    ATT
  453.     Utimbuf        timbuf;
  454.     long        vals[2];
  455. #else
  456.     Tzone        tzone;
  457.     Tval        tvals[2];
  458. #endif
  459.  
  460.     cdebug("resetting time for %s to %d, %s",
  461.         node->n_name, newtime, ctime(&newtime));
  462.  
  463. #ifdef    ATT
  464.     if (time(&vals[0]) == -1)
  465.     {
  466.         sprintf(scratchbuf, "cake system error, time");
  467.         perror(scratchbuf);
  468.         exit_cake(FALSE);
  469.     }
  470. #else
  471.     if (gettimeofday(&tvals[0], &tzone) != 0)
  472.     {
  473.         sprintf(scratchbuf, "cake system error, gettimeofday");
  474.         perror(scratchbuf);
  475.         exit_cake(FALSE);
  476.     }
  477. #endif
  478.  
  479.     if (newtime == GENESIS)
  480.     {
  481.         cdebug("reinterpreting GENESIS\n");
  482. #ifdef    ATT
  483.         if (time(&vals[1]) == -1)
  484.         {
  485.             sprintf(scratchbuf, "cake system error, time");
  486.             perror(scratchbuf);
  487.             exit_cake(FALSE);
  488.         }
  489. #else
  490.         if (gettimeofday(&tvals[1], &tzone) != 0)
  491.         {
  492.             sprintf(scratchbuf, "cake system error, gettimeofday");
  493.             perror(scratchbuf);
  494.             exit_cake(FALSE);
  495.         }
  496. #endif
  497.     }
  498.     else
  499.     {
  500. #ifdef    ATT
  501.         vals[1] = (long) newtime;
  502. #else
  503.         tvals[1].tv_sec  = newtime;
  504.         tvals[1].tv_usec = 0;
  505. #endif
  506.     }
  507.  
  508. #ifdef    ATT
  509.     timbuf.actime  = vals[0];
  510.     timbuf.modtime = vals[1];
  511.     node->n_rtime  = vals[1];
  512. #else
  513.     node->n_rtime  = (time_t) tvals[1].tv_sec;
  514. #endif
  515.  
  516.     if (nflag)
  517.         return;
  518.  
  519. #ifdef    ATT
  520.     if (utime(node->n_name, &timbuf) != 0)
  521. #else
  522.     if (utimes(node->n_name, tvals) != 0)
  523. #endif
  524.     {
  525.         sprintf(scratchbuf, "cake system error, utime(s) %s", node->n_name);
  526.         perror(scratchbuf);
  527.         fprintf(stderr, "cake: continuing\n");
  528.     }
  529.  
  530. #ifdef    CAKEDEBUG
  531.     if (cakedebug)
  532.     {
  533.         if (stat(node->n_name, &statbuf) != 0)
  534.             printf("cannot verify utimes\n");
  535.         else
  536.         {
  537.             print_time("accessed", statbuf.st_atime);
  538.             print_time("modified", statbuf.st_mtime);
  539.             print_time("changed ", statbuf.st_ctime);
  540.         }
  541.     }
  542. #endif
  543. }
  544.  
  545. /*
  546. **    See if the given file exists.
  547. */
  548.  
  549. bool
  550. exist(name)
  551. reg    char    *name;
  552. {
  553.     Stat    statbuf;
  554.  
  555.     if (stat(name, &statbuf) == 0)
  556.         return TRUE;
  557.     else
  558.         return FALSE;
  559. }
  560.  
  561. /*
  562. **    Remove the given file.
  563. */
  564.  
  565. cake_remove(name)
  566. reg    char    *name;
  567. {
  568. #ifdef    CAREFUL
  569.     if (! Xflag)
  570.     {
  571.         extern    int    getpid();
  572.         extern    int    cake_proc();
  573.         extern    Wait    cake_wait();
  574.         extern    char    *noslash();
  575.         reg    int    pid, cakepid;
  576.         Stat        statbuf;
  577.         Wait        code;
  578.         char        buf[80];
  579.  
  580. #ifndef    ATT
  581.         if (lstat(name, &statbuf) != 0)
  582.         {
  583.             sprintf(scratchbuf, "cake system error, lstat %s", name);
  584.             perror(scratchbuf);
  585.             fprintf(stderr, "cake: continuing\n");
  586.             return;
  587.         }
  588.  
  589.         if ((statbuf.st_mode & S_IFMT) == S_IFLNK)
  590.         {
  591.             printf("removing the symbolic link %s\n", name);
  592.             cdebug("cake_remove unlink %s\n", name);
  593.             if (unlink(name) != 0)
  594.             {
  595.                 sprintf(scratchbuf, "cake system error, unlink %s", name);
  596.                 perror(scratchbuf);
  597.                 fprintf(stderr, "cake: continuing\n");
  598.             }
  599.  
  600.             return;
  601.         }
  602. #endif
  603.  
  604.         cakepid = getpid();
  605.         printf("moving %s to /tmp\n", name);
  606.         sprintf(buf, "mv %s /tmp/%s.%d", name, noslash(name), cakepid);
  607.         pid = cake_proc(buf, Exec, (char *) NULL, (Node *) NULL,
  608.             (int (*)()) NULL, (List *) NULL);
  609.         code = cake_wait(pid);
  610.         if (code.w_status != 0)
  611.         {
  612.             fprintf(stderr, "cake system error: '%s' failed\n", buf);
  613.             fprintf(stderr, "cake: continuing\n");
  614.             return;
  615.         }
  616.  
  617.         sprintf(buf, "/tmp/%s.%d", noslash(name), cakepid);
  618.         if (chmod(buf, 0600) != 0)
  619.         {
  620.             sprintf(scratchbuf, "cake system error, chmod %s", buf);
  621.             perror(scratchbuf);
  622.             fprintf(stderr, "cake: continuing\n");
  623.             return;
  624.         }
  625.  
  626.         return;
  627.     }
  628. #endif
  629.  
  630.     cdebug("cake_remove unlink %s\n", name);
  631.     if (unlink(name) != 0)
  632.     {
  633.         sprintf(scratchbuf, "cake system error, unlink %s", name);
  634.         perror(scratchbuf);
  635.         fprintf(stderr, "cake: continuing\n");
  636.     }
  637. }
  638.