home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Magazine / wwwoffle-2.1.tar.gz / wwwoffle-2.1 / spool.c < prev    next >
C/C++ Source or Header  |  1998-02-11  |  23KB  |  1,038 lines

  1. /***************************************
  2.   $Header: /home/amb/wwwoffle/RCS/spool.c 2.23 1998/02/11 17:33:45 amb Exp $
  3.  
  4.   WWWOFFLE - World Wide Web Offline Explorer - Version 2.1.
  5.   Handle all of the spooling of files in the spool directory.
  6.   ******************/ /******************
  7.   Written by Andrew M. Bishop
  8.  
  9.   This file Copyright 1996,97,98 Andrew M. Bishop
  10.   It may be distributed under the GNU Public License, version 2, or
  11.   any higher version.  See section COPYING of the GNU Public license
  12.   for conditions under which this file may be redistributed.
  13.   ***************************************/
  14.  
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19.  
  20. #include <time.h>
  21. #include <utime.h>
  22. #include <sys/stat.h>
  23. #include <dirent.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <errno.h>
  27. #include <ctype.h>
  28.  
  29. #include "wwwoffle.h"
  30. #include "misc.h"
  31. #include "errors.h"
  32. #include "config.h"
  33.  
  34.  
  35. /*++++++++++++++++++++++++++++++++++++++
  36.   Open a file in the outgoing directory to write into / read from.
  37.  
  38.   int OpenOutgoingSpoolFile Returns a file descriptor, or -1 on failure.
  39.  
  40.   int rw Set to true to read, else false.
  41.   ++++++++++++++++++++++++++++++++++++++*/
  42.  
  43. int OpenOutgoingSpoolFile(int rw)
  44. {
  45.  struct stat buf;
  46.  int fd=-1;
  47.  
  48.  /* Create the outgoing directory if needed and change to it */
  49.  
  50.  if(lstat("outgoing",&buf))
  51.    {
  52.     PrintMessage(Inform,"Directory 'outgoing' does not exist [%!s]; creating one.");
  53.     if(mkdir("outgoing",0755))
  54.       {PrintMessage(Warning,"Cannot create directory 'outgoing' [%!s].");return(-1);}
  55.    }
  56.  else
  57.     if(!S_ISDIR(buf.st_mode))
  58.       {PrintMessage(Warning,"The file 'outgoing' is not a directory.");return(-1);}
  59.  
  60.  if(chdir("outgoing"))
  61.    {PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return(-1);}
  62.  
  63.  /* Open the outgoing file */
  64.  
  65.  if(rw)
  66.    {
  67.     struct dirent* ent;
  68.     DIR *dir=opendir(".");
  69.  
  70.     if(!dir)
  71.       {PrintMessage(Warning,"Cannot open current directory 'outgoing' [%!s].");chdir("..");return(-1);}
  72.  
  73.     ent=readdir(dir);  /* skip .  */
  74.     if(!ent)
  75.       {PrintMessage(Warning,"Cannot read current directory 'outgoing' [%!s].");closedir(dir);chdir("..");return(-1);}
  76.     ent=readdir(dir);  /* skip .. */
  77.  
  78.     while((ent=readdir(dir)))
  79.        if(*ent->d_name=='O')
  80.          {
  81.           if((fd=open(ent->d_name,O_RDONLY))==-1)
  82.              PrintMessage(Inform,"Cannot open file 'outgoing/%s' [%!s]; race condition?",ent->d_name);
  83.           else
  84.              if(unlink(ent->d_name))
  85.                {
  86.                 PrintMessage(Inform,"Cannot unlink file 'outgoing/%s' [%!s]; race condition?",ent->d_name);
  87.                 close(fd); fd=-1;
  88.                }
  89.              else
  90.                {
  91.                 *ent->d_name='U';
  92.                 unlink(ent->d_name);
  93.                 break;
  94.                }
  95.          }
  96.     closedir(dir);
  97.    }
  98.  else
  99.    {
  100.     char name[16];
  101.  
  102.     sprintf(name,"tmp.%d",getpid());
  103.  
  104.     fd=open(name,O_WRONLY|O_CREAT|O_EXCL,0644);
  105.     if(fd==-1)
  106.        PrintMessage(Inform,"Cannot open file 'outgoing/%s' [%!s]",name);
  107.    }
  108.  
  109.  chdir("..");
  110.  
  111.  return(fd);
  112. }
  113.  
  114.  
  115. /*++++++++++++++++++++++++++++++++++++++
  116.   Close an outgoing spool file and rename it to the hashed name.
  117.  
  118.   int fd The file descriptor to close.
  119.  
  120.   URL *Url The URL to close.
  121.   ++++++++++++++++++++++++++++++++++++++*/
  122.  
  123. void CloseOutgoingSpoolFile(int fd,URL *Url)
  124. {
  125.  char oldname[16],*newname;
  126.  int ufd;
  127.  
  128.  close(fd);
  129.  
  130.  if(chdir("outgoing"))
  131.    {PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return;}
  132.  
  133.  sprintf(oldname,"tmp.%d",getpid());
  134.  
  135.  newname=URLToFileName(Url);
  136.  *newname='U';
  137.  
  138.  unlink(newname);
  139.  ufd=open(newname,O_WRONLY|O_CREAT|O_EXCL,0644);
  140.  if(ufd!=-1)
  141.    {
  142.     write_string(ufd,Url->name);
  143.     close(ufd);
  144.    }
  145.  
  146.  *newname='O';
  147.  if(rename(oldname,newname))
  148.    {PrintMessage(Warning,"Cannot rename 'outgoing/%s' to 'outgoing/%s' [%!s].",oldname,newname);unlink(oldname);}
  149.  
  150.  chdir("..");
  151.  
  152.  free(newname);
  153. }
  154.  
  155.  
  156. /*++++++++++++++++++++++++++++++++++++++
  157.   Check if a specified URL exists in the outgoing directory.
  158.  
  159.   int ExistsOutgoingSpoolFile Returns a boolean.
  160.  
  161.   URL *Url The URL to check for.
  162.   ++++++++++++++++++++++++++++++++++++++*/
  163.  
  164. int ExistsOutgoingSpoolFile(URL *Url)
  165. {
  166.  struct stat buf;
  167.  char *name;
  168.  int exists=0;
  169.  
  170.  if(chdir("outgoing"))
  171.    {PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return(0);}
  172.  
  173.  /* Stat the outgoing file */
  174.  
  175.  name=URLToFileName(Url);
  176.  *name='O';
  177.  
  178.  exists=!stat(name,&buf);
  179.  
  180.  chdir("..");
  181.  
  182.  free(name);
  183.  
  184.  return(exists);
  185. }
  186.  
  187.  
  188. /*++++++++++++++++++++++++++++++++++++++
  189.   Create a hash value from the request for a specified URL in the outgoing directory.
  190.  
  191.   int HashOutgoingSpoolFile Returns a hash string or NULL in error.
  192.  
  193.   URL *Url The URL to create the hash for.
  194.   ++++++++++++++++++++++++++++++++++++++*/
  195.  
  196. char *HashOutgoingSpoolFile(URL *Url)
  197. {
  198.  char *name,*req,*hash;
  199.  int fd,r;
  200.  
  201.  if(chdir("outgoing"))
  202.    {PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return(NULL);}
  203.  
  204.  /* Read the outgoing file */
  205.  
  206.  name=URLToFileName(Url);
  207.  *name='O';
  208.  
  209.  fd=open(name,O_RDONLY);
  210.  if(fd==-1)
  211.    {PrintMessage(Warning,"Cannot open outgoing request to create hash [%!s].");free(name);chdir("..");return(NULL);}
  212.  
  213.  req=(char*)malloc(256+1);
  214.  
  215.  r=read(fd,req,256);
  216.  if(r==256)
  217.    {
  218.     int rr=0;
  219.     do
  220.       {
  221.        r+=rr;
  222.        req=(char*)realloc(req,r+256+1);
  223.       }
  224.     while((rr=read(fd,&req[r],256))>0);
  225.    }
  226.  else if(r==-1)
  227.    {PrintMessage(Warning,"Cannot read from outgoing request to create hash [%!s].");close(fd);free(name);free(req);chdir("..");return(NULL);}
  228.  
  229.  req[r]=0;
  230.  
  231.  close(fd);
  232.  
  233.  hash=MakeHash(req);
  234.  
  235.  chdir("..");
  236.  
  237.  free(name);
  238.  free(req);
  239.  
  240.  return(hash);
  241. }
  242.  
  243.  
  244. /*++++++++++++++++++++++++++++++++++++++
  245.   Delete a specified URL request from the outgoing requests.
  246.  
  247.   char *DeleteOutgoingSpoolFile Returns NULL if OK else error message.
  248.  
  249.   URL *Url The URL to delete.
  250.   ++++++++++++++++++++++++++++++++++++++*/
  251.  
  252. char *DeleteOutgoingSpoolFile(URL *Url)
  253. {
  254.  char *err=NULL;
  255.  
  256.  if(chdir("outgoing"))
  257.    {err=PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return(err);}
  258.  
  259.  /* Delete the file for the request or all of them. */
  260.  
  261.  if(Url)
  262.    {
  263.     char *name;
  264.  
  265.     name=URLToFileName(Url);
  266.     *name='O';
  267.  
  268.     if(unlink(name))
  269.        err=PrintMessage(Warning,"Cannot unlink outgoing request 'outgoing/%s' [%!s].",name);
  270.  
  271.     *name='U';
  272.     unlink(name);
  273.  
  274.     free(name);
  275.    }
  276.  else
  277.    {
  278.     struct dirent* ent;
  279.     DIR *dir=opendir(".");
  280.  
  281.     if(!dir)
  282.       {err=PrintMessage(Warning,"Cannot open current directory 'outgoing' [%!s].");chdir("..");return(err);}
  283.  
  284.     ent=readdir(dir);  /* skip .  */
  285.     if(!ent)
  286.       {err=PrintMessage(Warning,"Cannot read current directory 'outgoing' [%!s].");closedir(dir);chdir("..");return(err);}
  287.     ent=readdir(dir);  /* skip .. */
  288.  
  289.     while((ent=readdir(dir)))
  290.       {
  291.        if(unlink(ent->d_name))
  292.           err=PrintMessage(Warning,"Cannot unlink outgoing request 'outgoing/%s' [%!s].",ent->d_name);
  293.       }
  294.  
  295.     closedir(dir);
  296.    }
  297.  
  298.  chdir("..");
  299.  
  300.  return(err);
  301. }
  302.  
  303.  
  304. /*++++++++++++++++++++++++++++++++++++++
  305.   Open a file in a spool subdirectory to write into / read from.
  306.  
  307.   int OpenWebpageSpoolFile Returns a file descriptor.
  308.  
  309.   int rw Set to 1 to read, 0 to write.
  310.  
  311.   URL *Url The URL to open.
  312.   ++++++++++++++++++++++++++++++++++++++*/
  313.  
  314. int OpenWebpageSpoolFile(int rw,URL *Url)
  315. {
  316.  struct stat buf;
  317.  char *file;
  318.  int fd=-1;
  319.  
  320.  /* Create the spool directory if needed and change to it. */
  321.  
  322.  if(lstat(Url->proto,&buf))
  323.    {
  324.     PrintMessage(Inform,"Directory '%s' does not exist [%!s]; creating one.",Url->proto);
  325.     if(mkdir(Url->proto,0755))
  326.       {PrintMessage(Warning,"Cannot create directory '%s' [%!s].",Url->proto);return(-1);}
  327.    }
  328.  else
  329.     if(!S_ISDIR(buf.st_mode))
  330.       {PrintMessage(Warning,"The file '%s' is not a directory.",Url->proto);return(-1);}
  331.  
  332.  if(chdir(Url->proto))
  333.    {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return(-1);}
  334.  
  335.  if(lstat(Url->host,&buf))
  336.    {
  337.     PrintMessage(Inform,"Directory '%s/%s' does not exist [%!s]; creating one.",Url->proto,Url->host);
  338.     if(mkdir(Url->host,0755))
  339.       {PrintMessage(Warning,"Cannot create directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return(-1);}
  340.    }
  341.  else
  342.     if(!S_ISDIR(buf.st_mode))
  343.       {PrintMessage(Warning,"The file '%s/%s' is not a directory.",Url->proto,Url->host);chdir("..");return(-1);}
  344.  
  345.  if(chdir(Url->host))
  346.    {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return(-1);}
  347.  
  348.  /* Open the file for the web page. */
  349.  
  350.  file=URLToFileName(Url);
  351.  
  352.  *file='D';
  353.  if(rw)
  354.     fd=open(file,O_RDONLY);
  355.  else
  356.     fd=open(file,O_RDWR|O_CREAT,0644);
  357.  
  358.  if(!rw && fd!=-1)
  359.    {
  360.     int ufd;
  361.  
  362.     *file='U';
  363.     ufd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
  364.  
  365.     if(ufd!=-1)
  366.       {
  367.        write_string(ufd,Url->name);
  368.        close(ufd);
  369.       }
  370.     else
  371.       {
  372.        close(fd);
  373.        fd=-1;
  374.       }
  375.    }
  376.  
  377.  /* Change the modification time on the directory. */
  378.  
  379.  if(!rw && fd!=-1)
  380.     utime(".",NULL);
  381.  
  382.  chdir("..");
  383.  
  384.  if(!rw && fd!=-1)
  385.     utime(".",NULL);
  386.  
  387.  chdir("..");
  388.  
  389.  free(file);
  390.  
  391.  return(fd);
  392. }
  393.  
  394.  
  395. /*++++++++++++++++++++++++++++++++++++++
  396.   Delete a file in a spool subdirectory.
  397.  
  398.   char *DeleteWebpageSpoolFile Return NULL if OK else error message.
  399.  
  400.   URL *Url The URL to delete.
  401.  
  402.   int all If set then delete all pages from this host.
  403.   ++++++++++++++++++++++++++++++++++++++*/
  404.  
  405. char *DeleteWebpageSpoolFile(URL *Url,int all)
  406. {
  407.  char *err=NULL;
  408.  
  409.  if(chdir(Url->proto))
  410.    {err=PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return(err);}
  411.  
  412.  if(chdir(Url->host))
  413.    {err=PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return(err);}
  414.  
  415.  /* Delete the file for the web page. */
  416.  
  417.  if(all)
  418.    {
  419.     struct dirent* ent;
  420.     DIR *dir=opendir(".");
  421.  
  422.     if(!dir)
  423.       {err=PrintMessage(Warning,"Cannot open current directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("../..");return(err);}
  424.  
  425.     ent=readdir(dir);  /* skip .  */
  426.     if(!ent)
  427.       {err=PrintMessage(Warning,"Cannot read current directory '%s/%s' [%!s].",Url->proto,Url->host);closedir(dir);chdir("../..");return(err);}
  428.     ent=readdir(dir);  /* skip .. */
  429.  
  430.     while((ent=readdir(dir)))
  431.       {
  432.        if(unlink(ent->d_name))
  433.           err=PrintMessage(Warning,"Cannot unlink cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,ent->d_name);
  434.       }
  435.  
  436.     closedir(dir);
  437.  
  438.     chdir("..");
  439.  
  440.     if(rmdir(Url->host))
  441.       err=PrintMessage(Warning,"Cannot delete what should be an empty directory '%s/%s' [%!s].",Url->proto,Url->host);
  442.  
  443.     chdir("..");
  444.    }
  445.  else
  446.    {
  447.     char *file=URLToFileName(Url);
  448.     struct stat buf;
  449.     int didstat=1;
  450.  
  451.     if(stat(".",&buf))
  452.        PrintMessage(Warning,"Cannot stat directory '%s/%s' [%!s].",Url->proto,Url->host);
  453.     else
  454.        didstat=1;
  455.  
  456.     *file='D';
  457.     if(unlink(file))
  458.        err=PrintMessage(Warning,"Cannot unlink cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
  459.  
  460.     *file='U';
  461.     unlink(file);
  462.  
  463.     free(file);
  464.  
  465.     if(didstat)
  466.       {
  467.        struct utimbuf utbuf;
  468.  
  469.        utbuf.actime=time(NULL);
  470.        utbuf.modtime=buf.st_mtime;
  471.        utime(".",&utbuf);
  472.       }
  473.  
  474.     chdir("../..");
  475.    }
  476.  
  477.  return(err);
  478. }
  479.  
  480.  
  481. /*++++++++++++++++++++++++++++++++++++++
  482.   Touch a file in a spool subdirectory.
  483.  
  484.   URL *Url The URL to touch.
  485.   ++++++++++++++++++++++++++++++++++++++*/
  486.  
  487. void TouchWebpageSpoolFile(URL *Url)
  488. {
  489.  char *file;
  490.  
  491.  if(chdir(Url->proto))
  492.    {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
  493.  
  494.  if(chdir(Url->host))
  495.    {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return;}
  496.  
  497.  /* Touch the file for the web page. */
  498.  
  499.  file=URLToFileName(Url);
  500.  
  501.  *file='D';
  502.  utime(file,NULL);
  503.  
  504.  chdir("../..");
  505.  
  506.  free(file);
  507. }
  508.  
  509.  
  510. /*++++++++++++++++++++++++++++++++++++++
  511.   Touch a file in a spool subdirectory.
  512.  
  513.   int ExistsWebpageSpoolFile Return a true value if the page exists.
  514.  
  515.   URL *Url The URL to touch.
  516.   ++++++++++++++++++++++++++++++++++++++*/
  517.  
  518. int ExistsWebpageSpoolFile(URL *Url)
  519. {
  520.  struct stat buf;
  521.  char *file;
  522.  int exists=0;
  523.  
  524.  if(chdir(Url->proto))
  525.     return(0);
  526.  
  527.  if(chdir(Url->host))
  528.    {chdir("..");return(0);}
  529.  
  530.  /* Stat the file for the web page. */
  531.  
  532.  file=URLToFileName(Url);
  533.  *file='D';
  534.  
  535.  exists=!stat(file,&buf);
  536.  
  537.  chdir("../..");
  538.  
  539.  free(file);
  540.  
  541.  return(exists);
  542. }
  543.  
  544.  
  545. /*++++++++++++++++++++++++++++++++++++++
  546.   Create a backup copy of a file in a spool subdirectory.
  547.  
  548.   URL *Url The URL to make a copy of.
  549.  
  550.   int fd The file descriptor of the original file.
  551.   ++++++++++++++++++++++++++++++++++++++*/
  552.  
  553. void CreateBackupWebpageSpoolFile(URL *Url,int fd)
  554. {
  555.  struct stat buf;
  556.  char *file;
  557.  int bfd=-1;
  558.  
  559.  /* Create the spool directory if needed and change to it. */
  560.  
  561.  if(chdir(Url->proto))
  562.    {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
  563.  
  564.  if(chdir(Url->host))
  565.    {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return;}
  566.  
  567.  /* Open the file for the web page. */
  568.  
  569.  file=URLToFileName(Url);
  570.  
  571.  *file='D';
  572.  strcat(file,"~");
  573.  
  574.  if(!stat(file,&buf))
  575.     PrintMessage(Inform,"Backup already exists for '%s' [%!s].",Url->name);
  576.  else
  577.    {
  578.     bfd=open(file,O_WRONLY|O_CREAT,0644);
  579.  
  580.     if(bfd==-1)
  581.        PrintMessage(Warning,"Cannot create backup spool file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
  582.     else
  583.       {
  584.        int n;
  585.        char data[256];
  586.  
  587.        while((n=read(fd,data,256))>0)
  588.           write(bfd,data,n);
  589.  
  590.        if(n==-1)
  591.           PrintMessage(Warning,"Error copying to backup spool file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
  592.  
  593.        lseek(fd,0,SEEK_SET);
  594.  
  595.        close(bfd);
  596.  
  597.        if(fstat(fd,&buf))
  598.           PrintMessage(Warning,"Cannot get the date to set for the backup spool file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
  599.        else
  600.          {
  601.           struct utimbuf utbuf;
  602.  
  603.           utbuf.actime=buf.st_atime;
  604.           utbuf.modtime=buf.st_mtime;
  605.           utime(file,&utbuf);
  606.          }
  607.       }
  608.    }
  609.  
  610.  chdir("../..");
  611.  
  612.  free(file);
  613. }
  614.  
  615.  
  616. /*++++++++++++++++++++++++++++++++++++++
  617.   Restore the backup copy of a file in a spool subdirectory.
  618.  
  619.   URL *Url The URL to restore.
  620.   ++++++++++++++++++++++++++++++++++++++*/
  621.  
  622. void RestoreBackupWebpageSpoolFile(URL *Url)
  623. {
  624.  struct stat buf;
  625.  struct utimbuf utbuf;
  626.  char *file;
  627.  int ifd=-1,ofd=-1;
  628.  
  629.  /* Create the spool directory if needed and change to it. */
  630.  
  631.  if(chdir(Url->proto))
  632.    {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
  633.  
  634.  if(chdir(Url->host))
  635.    {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return;}
  636.  
  637.  /* Open the file for the web page. */
  638.  
  639.  file=URLToFileName(Url);
  640.  
  641.  *file='D';
  642.  strcat(file,"~");
  643.  
  644.  if(!stat(file,&buf))
  645.    {
  646.     ifd=open(file,O_RDONLY);
  647.  
  648.     if(ifd==-1)
  649.        PrintMessage(Warning,"Cannot open spool file '%s/%s/%s' to restore from [%!s].",Url->proto,Url->host,file);
  650.     else
  651.       {
  652.        if(unlink(file))
  653.           PrintMessage(Warning,"Cannot unlink backup cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
  654.  
  655.        file[strlen(file)-1]=0;
  656.  
  657.        ofd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
  658.  
  659.        if(ofd==-1)
  660.           PrintMessage(Warning,"Cannot open spool file '%s/%s/%s' to restore to [%!s].",Url->proto,Url->host,file);
  661.        else
  662.          {
  663.           int n;
  664.           char data[256];
  665.  
  666.           while((n=read(ifd,data,256))>0)
  667.              write(ofd,data,n);
  668.  
  669.           if(n==-1)
  670.              PrintMessage(Warning,"Error copying from backup cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
  671.  
  672.           close(ofd);
  673.  
  674.           utbuf.actime=buf.st_atime;
  675.           utbuf.modtime=buf.st_mtime;
  676.           utime(file,&utbuf);
  677.          }
  678.  
  679.        close(ifd);
  680.       }
  681.    }
  682.  
  683.  chdir("../..");
  684.  
  685.  free(file);
  686. }
  687.  
  688.  
  689. /*++++++++++++++++++++++++++++++++++++++
  690.   Delete a file in a spool subdirectory.
  691.  
  692.   URL *Url The URL to delete.
  693.   ++++++++++++++++++++++++++++++++++++++*/
  694.  
  695. void DeleteBackupWebpageSpoolFile(URL *Url)
  696. {
  697.  char *file;
  698.  
  699.  if(chdir(Url->proto))
  700.    {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
  701.  
  702.  if(chdir(Url->host))
  703.    {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return;}
  704.  
  705.  /* Delete the file for the backup web page. */
  706.  
  707.  file=URLToFileName(Url);
  708.  
  709.  *file='D';
  710.  strcat(file,"~");
  711.  
  712.  if(unlink(file))
  713.     PrintMessage(Warning,"Cannot unlink backup cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
  714.  
  715.  chdir("../..");
  716.  
  717.  free(file);
  718. }
  719.  
  720.  
  721. /*++++++++++++++++++++++++++++++++++++++
  722.   Delete a specified URL from the lasttime directory.
  723.  
  724.   char *DeleteLastTimeSpoolFile Returns NULL if OK else error message.
  725.  
  726.   URL *Url The URL to delete or NULL for all of them.
  727.   ++++++++++++++++++++++++++++++++++++++*/
  728.  
  729. char *DeleteLastTimeSpoolFile(URL *Url)
  730. {
  731.  struct stat buf;
  732.  char *err=NULL;
  733.  char *name;
  734.  
  735.  /* Create the outgoing directory if needed and change to it */
  736.  
  737.  if(!Url)
  738.     if(lstat("lasttime",&buf))
  739.       {
  740.        PrintMessage(Inform,"Directory 'lasttime' does not exist [%!s]; creating one.");
  741.        if(mkdir("lasttime",0755))
  742.          {err=PrintMessage(Warning,"Cannot create directory 'lasttime' [%!s].");return(err);}
  743.       }
  744.     else
  745.        if(!S_ISDIR(buf.st_mode))
  746.          {err=PrintMessage(Warning,"The file 'lasttime' is not a directory.");return(err);}
  747.  
  748.  if(chdir("lasttime"))
  749.    {err=PrintMessage(Warning,"Cannot change to directory 'lasttime' [%!s].");return(err);}
  750.  
  751.  /* Delete the file for the request or all of them. */
  752.  
  753.  if(Url)
  754.    {
  755.     name=URLToFileName(Url);
  756.     *name='D';
  757.  
  758.     if(unlink(name))
  759.        err=PrintMessage(Warning,"Cannot unlink lasttime request 'lasttime/%s' [%!s].",name);
  760.  
  761.     *name='U';
  762.     unlink(name);
  763.  
  764.     free(name);
  765.    }
  766.  else
  767.    {
  768.     struct dirent* ent;
  769.     DIR *dir;
  770.  
  771.     dir=opendir(".");
  772.  
  773.     if(!dir)
  774.       {err=PrintMessage(Warning,"Cannot open current directory 'lasttime' [%!s].");chdir("..");return(err);}
  775.  
  776.     ent=readdir(dir);  /* skip .  */
  777.     if(!ent)
  778.       {err=PrintMessage(Warning,"Cannot read current directory 'lasttime' [%!s].");closedir(dir);chdir("..");return(err);}
  779.     ent=readdir(dir);  /* skip .. */
  780.  
  781.     while((ent=readdir(dir)))
  782.       {
  783.        if(unlink(ent->d_name))
  784.           PrintMessage(Warning,"Cannot unlink last time page 'lasttime/%s' [%!s].",ent->d_name);
  785.       }
  786.  
  787.     closedir(dir);
  788.    }
  789.  
  790.  chdir("..");
  791.  
  792.  return(err);
  793. }
  794.  
  795.  
  796. /*++++++++++++++++++++++++++++++++++++++
  797.   Create a file in the lasttime directory.
  798.  
  799.   int CreateLastTimeSpoolFile Returns 1 if the file already exists.
  800.  
  801.   URL *Url The URL to create.
  802.   ++++++++++++++++++++++++++++++++++++++*/
  803.  
  804. int CreateLastTimeSpoolFile(URL *Url)
  805. {
  806.  struct stat buf;
  807.  char *file;
  808.  int exists=0;
  809.  
  810.  /* Change to the last time directory */
  811.  
  812.  if(chdir("lasttime"))
  813.    {PrintMessage(Warning,"Cannot change to directory 'lasttime' [%!s].");return(0);}
  814.  
  815.  /* Create the file. */
  816.  
  817.  file=URLToFileName(Url);
  818.  
  819.  *file='D';
  820.  
  821.  if(stat(file,&buf)==-1)
  822.    {
  823.     int fd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
  824.  
  825.     if(fd==-1)
  826.       {PrintMessage(Warning,"Cannot create file 'lasttime/%s' [%!s].",file);}
  827.     else
  828.       {
  829.        int ufd;
  830.  
  831.        *file='U';
  832.        ufd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
  833.  
  834.        if(ufd!=-1)
  835.          {
  836.           write_string(ufd,Url->name);
  837.           close(ufd);
  838.          }
  839.  
  840.        close(fd);
  841.       }
  842.    }
  843.  else
  844.     exists=1;
  845.  
  846.  chdir("..");
  847.  
  848.  free(file);
  849.  
  850.  return(exists);
  851. }
  852.  
  853.  
  854. /*++++++++++++++++++++++++++++++++++++++
  855.   Open a file in the monitor directory to write into.
  856.  
  857.   int OpenMonitorSpoolFile Returns a file descriptor, or -1 on failure.
  858.  
  859.   URL *Url The URL of the file to monitor.
  860.   ++++++++++++++++++++++++++++++++++++++*/
  861.  
  862. int OpenMonitorSpoolFile(URL *Url)
  863. {
  864.  struct stat buf;
  865.  int fd=-1;
  866.  char *file;
  867.  
  868.  /* Create the monitor directory if needed and change to it */
  869.  
  870.  if(lstat("monitor",&buf))
  871.    {
  872.     PrintMessage(Inform,"Directory 'monitor' does not exist [%!s]; creating one.");
  873.     if(mkdir("monitor",0755))
  874.       {PrintMessage(Warning,"Cannot create directory 'monitor' [%!s].");return(-1);}
  875.    }
  876.  else
  877.     if(!S_ISDIR(buf.st_mode))
  878.       {PrintMessage(Warning,"The file 'monitor' is not a directory.");return(-1);}
  879.  
  880.  if(chdir("monitor"))
  881.    {PrintMessage(Warning,"Cannot change to directory 'monitor' [%!s].");return(-1);}
  882.  
  883.  /* Open the monitor file */
  884.  
  885.  file=URLToFileName(Url);
  886.  
  887.  *file='O';
  888.  
  889.  fd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
  890.  
  891.  if(fd==-1)
  892.    {PrintMessage(Warning,"Cannot create file 'monitor/%s' [%!s].",file);}
  893.  else
  894.    {
  895.     int ufd;
  896.  
  897.     *file='U';
  898.     ufd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
  899.  
  900.     if(ufd!=-1)
  901.       {
  902.        write_string(ufd,Url->name);
  903.        close(ufd);
  904.       }
  905.     else
  906.       {
  907.        close(fd);
  908.        fd=-1;
  909.       }
  910.    }
  911.  
  912.  chdir("..");
  913.  
  914.  free(file);
  915.  
  916.  return(fd);
  917. }
  918.  
  919.  
  920. /*++++++++++++++++++++++++++++++++++++++
  921.   Delete a specified URL from the monitor directory.
  922.  
  923.   char *DeleteMonitorSpoolFile Returns NULL if OK else error message.
  924.  
  925.   URL *Url The URL to delete.
  926.   ++++++++++++++++++++++++++++++++++++++*/
  927.  
  928. char *DeleteMonitorSpoolFile(URL *Url)
  929. {
  930.  char *err=NULL;
  931.  char *name;
  932.  
  933.  if(chdir("monitor"))
  934.    {err=PrintMessage(Warning,"Cannot change to directory 'monitor' [%!s].");return(err);}
  935.  
  936.  /* Delete the file for the request. */
  937.  
  938.  name=URLToFileName(Url);
  939.  *name='O';
  940.  
  941.  if(unlink(name))
  942.     err=PrintMessage(Warning,"Cannot unlink monitor request 'monitor/%s' [%!s].",name);
  943.  
  944.  *name='U';
  945.  unlink(name);
  946.  
  947.  free(name);
  948.  
  949.  chdir("..");
  950.  
  951.  return(err);
  952. }
  953.  
  954.  
  955. /*++++++++++++++++++++++++++++++++++++++
  956.   Convert a filename to a URL.
  957.  
  958.   char *FileNameToURL Returns the URL.
  959.  
  960.   char *file The file name.
  961.   ++++++++++++++++++++++++++++++++++++++*/
  962.  
  963. char *FileNameToURL(char *file)
  964. {
  965.  char *path,*copy;
  966.  int ufd,r;
  967.  
  968.  if(file[0] && file[0]!='D' && file[0]!='O')
  969.     return(NULL);
  970.  
  971.  copy=(char*)malloc(strlen(file)+1);
  972.  strcpy(copy,file);
  973.  
  974.  path=(char*)malloc(256+1);
  975.  
  976.  *copy='U';
  977.  
  978.  ufd=open(copy,O_RDONLY);
  979.  
  980.  if(ufd==-1)
  981.    {
  982.     free(copy);
  983.     free(path);
  984.     return(NULL);
  985.    }
  986.  
  987.  r=read(ufd,path,256);
  988.  
  989.  if(r==256)
  990.    {
  991.     int rr=0;
  992.     do
  993.       {
  994.        r+=rr;
  995.        path=(char*)realloc(path,r+256+1);
  996.       }
  997.     while((rr=read(ufd,&path[r],256))>0);
  998.    }
  999.  else if(r==-1)
  1000.    {
  1001.     close(ufd);
  1002.     free(copy);
  1003.     free(path);
  1004.     return(NULL);
  1005.    }
  1006.  
  1007.  path[r]=0;
  1008.  
  1009.  close(ufd);
  1010.  
  1011.  free(copy);
  1012.  
  1013.  return(path);
  1014. }
  1015.  
  1016.  
  1017. /*++++++++++++++++++++++++++++++++++++++
  1018.   Convert a URL to a filename
  1019.  
  1020.   char *URLToFileName Returns the filename.
  1021.  
  1022.   URL *Url The URL to convert to a filename.
  1023.   ++++++++++++++++++++++++++++++++++++++*/
  1024.  
  1025. char *URLToFileName(URL *Url)
  1026. {
  1027.  char *hash;
  1028.  char *file;
  1029.  
  1030.  hash=MakeHash(Url->name);
  1031.  
  1032.  file=(char*)malloc(strlen(hash)+3);
  1033.  
  1034.  sprintf(file,"X%s",hash);
  1035.  
  1036.  return(file);
  1037. }
  1038.