spool.c
上传用户:seven77cht
上传日期:2007-01-04
资源大小:486k
文件大小:33k
- /***************************************
- $Header: /home/amb/wwwoffle/RCS/spool.c 2.50 1999/11/27 16:02:28 amb Exp $
- WWWOFFLE - World Wide Web Offline Explorer - Version 2.5c.
- Handle all of the spooling of files in the spool directory.
- ******************/ /******************
- Written by Andrew M. Bishop
- This file Copyright 1996,97,98,99 Andrew M. Bishop
- It may be distributed under the GNU Public License, version 2, or
- any higher version. See section COPYING of the GNU Public license
- for conditions under which this file may be redistributed.
- ***************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <utime.h>
- #include <sys/stat.h>
- #include <dirent.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <ctype.h>
- #include "wwwoffle.h"
- #include "misc.h"
- #include "errors.h"
- #include "config.h"
- /*+ Need this for Win32 to use binary mode +*/
- #ifndef O_BINARY
- #define O_BINARY 0
- #endif
- /*++++++++++++++++++++++++++++++++++++++
- Open a file in the outgoing directory to write into / read from.
- int OpenOutgoingSpoolFile Returns a file descriptor, or -1 on failure.
- int rw Set to true to read, else false.
- ++++++++++++++++++++++++++++++++++++++*/
- int OpenOutgoingSpoolFile(int rw)
- {
- struct stat buf;
- int fd=-1;
- char name[16];
- sprintf(name,"tmp.%ld",(long)getpid());
- /* Create the outgoing directory if needed and change to it */
- if(lstat("outgoing",&buf))
- {
- PrintMessage(Inform,"Directory 'outgoing' does not exist [%!s]; creating one.");
- if(mkdir("outgoing",DirPerm))
- {PrintMessage(Warning,"Cannot create directory 'outgoing' [%!s].");return(-1);}
- }
- else
- if(!S_ISDIR(buf.st_mode))
- {PrintMessage(Warning,"The file 'outgoing' is not a directory.");return(-1);}
- if(chdir("outgoing"))
- {PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return(-1);}
- /* Open the outgoing file */
- if(rw)
- {
- struct dirent* ent;
- DIR *dir=opendir(".");
- if(!dir)
- {PrintMessage(Warning,"Cannot open current directory 'outgoing' [%!s].");chdir("..");return(-1);}
- ent=readdir(dir); /* skip . */
- if(!ent)
- {PrintMessage(Warning,"Cannot read current directory 'outgoing' [%!s].");closedir(dir);chdir("..");return(-1);}
- ent=readdir(dir); /* skip .. */
- while((ent=readdir(dir)))
- if(*ent->d_name=='O')
- {
- if(rename(ent->d_name,name))
- PrintMessage(Inform,"Cannot rename file 'outgoing/%s' to 'outgoing/%s' [%!s]; race condition?",ent->d_name,name);
- else
- {
- fd=open(name,O_RDONLY|O_BINARY);
- if(fd==-1)
- PrintMessage(Inform,"Cannot open file 'outgoing/%s' [%!s]; race condition?",name);
- else
- {
- *ent->d_name='U';
- unlink(ent->d_name);
- unlink(name);
- break;
- }
- }
- }
- closedir(dir);
- }
- else
- {
- fd=open(name,O_WRONLY|O_CREAT|O_EXCL|O_BINARY,FilePerm);
- if(fd==-1)
- PrintMessage(Warning,"Cannot open file 'outgoing/%s' [%!s]",name);
- }
- /* Change dir back and tidy up. */
- chdir("..");
- return(fd);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Close an outgoing spool file and rename it to the hashed name.
- int fd The file descriptor to close.
- URL *Url The URL to close.
- ++++++++++++++++++++++++++++++++++++++*/
- void CloseOutgoingSpoolFile(int fd,URL *Url)
- {
- char oldname[16],*newname;
- int ufd;
- close(fd);
- /* Change to the outgoing directory. */
- if(chdir("outgoing"))
- {PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return;}
- /* Create and rename the file */
- sprintf(oldname,"tmp.%ld",(long)getpid());
- newname=URLToFileName(Url);
- *newname='U';
- unlink(newname);
- ufd=open(newname,O_WRONLY|O_CREAT|O_EXCL|O_BINARY,FilePerm);
- if(ufd!=-1)
- {
- write_string(ufd,Url->file);
- close(ufd);
- }
- *newname='O';
- if(rename(oldname,newname))
- {PrintMessage(Warning,"Cannot rename 'outgoing/%s' to 'outgoing/%s' [%!s].",oldname,newname);unlink(oldname);}
- /* Change dir back and tidy up. */
- chdir("..");
- free(newname);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Check if a specified URL exists in the outgoing directory.
- int ExistsOutgoingSpoolFile Returns a boolean.
- URL *Url The URL to check for.
- ++++++++++++++++++++++++++++++++++++++*/
- int ExistsOutgoingSpoolFile(URL *Url)
- {
- struct stat buf;
- char *name;
- int exists=0;
- if(chdir("outgoing"))
- {PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return(0);}
- /* Stat the outgoing file */
- name=URLToFileName(Url);
- *name='O';
- exists=!stat(name,&buf);
- /* Change dir back and tidy up. */
- chdir("..");
- free(name);
- return(exists);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a hash value from the request for a specified URL in the outgoing directory.
- int HashOutgoingSpoolFile Returns a hash string or NULL in error.
- URL *Url The URL to create the hash for.
- ++++++++++++++++++++++++++++++++++++++*/
- char *HashOutgoingSpoolFile(URL *Url)
- {
- char *name,*req,*hash;
- int fd,r;
- if(chdir("outgoing"))
- {PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return(NULL);}
- /* Read the outgoing file */
- name=URLToFileName(Url);
- *name='O';
- fd=open(name,O_RDONLY|O_BINARY);
- if(fd==-1)
- {PrintMessage(Warning,"Cannot open outgoing request to create hash [%!s].");free(name);chdir("..");return(NULL);}
- req=(char*)malloc(256+1);
- r=read(fd,req,256);
- if(r==256)
- {
- int rr=0;
- do
- {
- r+=rr;
- req=(char*)realloc(req,r+256+1);
- }
- while((rr=read(fd,&req[r],256))>0);
- }
- else if(r==-1)
- {PrintMessage(Warning,"Cannot read from outgoing request to create hash [%!s].");close(fd);free(name);free(req);chdir("..");return(NULL);}
- req[r]=0;
- close(fd);
- hash=MakeHash(req);
- /* Change dir back and tidy up. */
- chdir("..");
- free(name);
- free(req);
- return(hash);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Delete a specified URL request from the outgoing requests.
- char *DeleteOutgoingSpoolFile Returns NULL if OK else error message.
- URL *Url The URL to delete or NULL for all of them.
- ++++++++++++++++++++++++++++++++++++++*/
- char *DeleteOutgoingSpoolFile(URL *Url)
- {
- char *err=NULL;
- /* Change to the outgoing directory. */
- if(chdir("outgoing"))
- {err=PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return(err);}
- /* Delete the file for the request or all of them. */
- if(Url)
- {
- char *name;
- name=URLToFileName(Url);
- *name='O';
- if(unlink(name))
- err=PrintMessage(Warning,"Cannot unlink outgoing request 'outgoing/%s' [%!s].",name);
- *name='U';
- unlink(name);
- free(name);
- }
- else
- {
- struct dirent* ent;
- DIR *dir=opendir(".");
- if(!dir)
- {err=PrintMessage(Warning,"Cannot open current directory 'outgoing' [%!s].");chdir("..");return(err);}
- ent=readdir(dir); /* skip . */
- if(!ent)
- {err=PrintMessage(Warning,"Cannot read current directory 'outgoing' [%!s].");closedir(dir);chdir("..");return(err);}
- ent=readdir(dir); /* skip .. */
- while((ent=readdir(dir)))
- {
- if(unlink(ent->d_name))
- err=PrintMessage(Warning,"Cannot unlink outgoing request 'outgoing/%s' [%!s].",ent->d_name);
- }
- closedir(dir);
- }
- /* Change dir back and tidy up. */
- chdir("..");
- return(err);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Open a file in a spool subdirectory to write into / read from.
- int OpenWebpageSpoolFile Returns a file descriptor.
- int rw Set to 1 to read, 0 to write.
- URL *Url The URL to open.
- ++++++++++++++++++++++++++++++++++++++*/
- int OpenWebpageSpoolFile(int rw,URL *Url)
- {
- struct stat buf;
- char *file;
- int fd=-1;
- /* Create the spool directory if needed and change to it. */
- if(lstat(Url->proto,&buf))
- {
- PrintMessage(Inform,"Directory '%s' does not exist [%!s]; creating one.",Url->proto);
- if(mkdir(Url->proto,DirPerm))
- {PrintMessage(Warning,"Cannot create directory '%s' [%!s].",Url->proto);return(-1);}
- }
- else
- if(!S_ISDIR(buf.st_mode))
- {PrintMessage(Warning,"The file '%s' is not a directory.",Url->proto);return(-1);}
- if(chdir(Url->proto))
- {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return(-1);}
- if(lstat(Url->dir,&buf))
- {
- PrintMessage(Inform,"Directory '%s/%s' does not exist [%!s]; creating one.",Url->proto,Url->dir);
- if(mkdir(Url->dir,DirPerm))
- {PrintMessage(Warning,"Cannot create directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("..");return(-1);}
- }
- else
- if(!S_ISDIR(buf.st_mode))
- {PrintMessage(Warning,"The file '%s/%s' is not a directory.",Url->proto,Url->dir);chdir("..");return(-1);}
- if(chdir(Url->dir))
- {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("..");return(-1);}
- /* Open the file for the web page. */
- file=URLToFileName(Url);
- *file='D';
- if(rw)
- fd=open(file,O_RDONLY|O_BINARY);
- else
- fd=open(file,O_RDWR|O_CREAT|O_BINARY,FilePerm);
- if(!rw && fd!=-1)
- {
- int ufd;
- *file='U';
- ufd=open(file,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,FilePerm);
- if(ufd!=-1)
- {
- write_string(ufd,Url->file);
- close(ufd);
- }
- else
- {
- close(fd);
- fd=-1;
- }
- }
- /* Change the modification time on the directory. */
- if(!rw && fd!=-1)
- utime(".",NULL);
- chdir("..");
- if(!rw && fd!=-1)
- utime(".",NULL);
- /* Change dir back and tidy up. */
- chdir("..");
- free(file);
- return(fd);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Delete a file in a spool subdirectory.
- char *DeleteWebpageSpoolFile Return NULL if OK else error message.
- URL *Url The URL to delete.
- int all If set then delete all pages from this host.
- ++++++++++++++++++++++++++++++++++++++*/
- char *DeleteWebpageSpoolFile(URL *Url,int all)
- {
- char *err=NULL;
- /* Change to the spool directory. */
- if(chdir(Url->proto))
- {err=PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return(err);}
- if(chdir(Url->dir))
- {err=PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("..");return(err);}
- /* Delete the file for the web page. */
- if(all)
- {
- struct dirent* ent;
- DIR *dir=opendir(".");
- if(!dir)
- {err=PrintMessage(Warning,"Cannot open current directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("../..");return(err);}
- ent=readdir(dir); /* skip . */
- if(!ent)
- {err=PrintMessage(Warning,"Cannot read current directory '%s/%s' [%!s].",Url->proto,Url->dir);closedir(dir);chdir("../..");return(err);}
- ent=readdir(dir); /* skip .. */
- while((ent=readdir(dir)))
- {
- if(*ent->d_name=='D')
- {
- char *delurl;
- if((delurl=FileNameToURL(ent->d_name)))
- {
- URL *delUrl=SplitURL(delurl);
- chdir("../..");
- if(ExistsLastTimeSpoolFile(delUrl))
- DeleteLastTimeSpoolFile(delUrl);
- chdir(Url->proto);
- chdir(Url->dir);
- free(delurl);
- FreeURL(delUrl);
- }
- }
- if(unlink(ent->d_name))
- err=PrintMessage(Warning,"Cannot unlink cached file '%s/%s/%s' [%!s].",Url->proto,Url->dir,ent->d_name);
- }
- closedir(dir);
- chdir("..");
- if(rmdir(Url->dir))
- err=PrintMessage(Warning,"Cannot delete what should be an empty directory '%s/%s' [%!s].",Url->proto,Url->dir);
- chdir("..");
- }
- else
- {
- char *file=URLToFileName(Url);
- struct stat buf;
- int didstat=1;
- if(stat(".",&buf))
- PrintMessage(Warning,"Cannot stat directory '%s/%s' [%!s].",Url->proto,Url->dir);
- else
- didstat=1;
- *file='D';
- if(unlink(file))
- err=PrintMessage(Warning,"Cannot unlink cached file '%s/%s/%s' [%!s].",Url->proto,Url->dir,file);
- *file='U';
- unlink(file);
- free(file);
- if(didstat)
- {
- struct utimbuf utbuf;
- utbuf.actime=time(NULL);
- utbuf.modtime=buf.st_mtime;
- utime(".",&utbuf);
- }
- chdir("../..");
- if(ExistsLastTimeSpoolFile(Url))
- DeleteLastTimeSpoolFile(Url);
- }
- return(err);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Touch a file in a spool subdirectory.
- URL *Url The URL to touch.
- time_t when The time to set the access time to.
- ++++++++++++++++++++++++++++++++++++++*/
- void TouchWebpageSpoolFile(URL *Url,time_t when)
- {
- char *file;
- /* Change to the spool directory. */
- if(chdir(Url->proto))
- {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
- if(chdir(Url->dir))
- {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("..");return;}
- /* Touch the file for the web page. */
- file=URLToFileName(Url);
- *file='D';
- if(when)
- {
- struct stat buf;
- if(stat(file,&buf))
- utime(file,NULL);
- else
- {
- struct utimbuf ubuf;
- ubuf.actime=when;
- ubuf.modtime=buf.st_mtime;
- utime(file,&ubuf);
- }
- }
- else
- utime(file,NULL);
- /* Change dir back and tidy up. */
- chdir("../..");
- free(file);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Check if a file in a spool subdirectory exists.
- time_t ExistsWebpageSpoolFile Return a the time the page was last accessed if the page exists.
- URL *Url The URL to check for.
- ++++++++++++++++++++++++++++++++++++++*/
- time_t ExistsWebpageSpoolFile(URL *Url)
- {
- struct stat buf;
- char *file;
- /* Change to the spool directory. */
- if(chdir(Url->proto))
- return(0);
- if(chdir(Url->dir))
- {chdir("..");return(0);}
- /* Stat the file for the web page. */
- file=URLToFileName(Url);
- *file='D';
- if(stat(file,&buf))
- buf.st_atime=0;
- /* Change dir back and tidy up. */
- chdir("../..");
- free(file);
- return(buf.st_atime);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a backup copy of a file in a spool subdirectory.
- URL *Url The URL to make a copy of.
- ++++++++++++++++++++++++++++++++++++++*/
- void CreateBackupWebpageSpoolFile(URL *Url)
- {
- struct stat buf;
- char *bakfile,*orgfile;
- /* Change to the spool directory. */
- if(chdir(Url->proto))
- {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
- if(chdir(Url->dir))
- {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("..");return;}
- /* Create the filenames and rename the files. */
- orgfile=URLToFileName(Url);
- bakfile=(char*)malloc(strlen(orgfile)+2);
- strcpy(bakfile,orgfile);
- *bakfile=*orgfile='D';
- strcat(bakfile,"~");
- if(!stat(bakfile,&buf))
- PrintMessage(Inform,"Backup already exists for '%s'.",Url->name);
- else
- {
- if(rename(orgfile,bakfile))
- PrintMessage(Warning,"Cannot rename backup cached file '%s/%s/%s' to %s [%!s].",Url->proto,Url->dir,bakfile,orgfile);
- *bakfile=*orgfile='U';
- rename(orgfile,bakfile);
- }
- /* Change dir back and tidy up. */
- chdir("../..");
- free(bakfile);
- free(orgfile);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Restore the backup copy of a file in a spool subdirectory.
- URL *Url The URL to restore.
- ++++++++++++++++++++++++++++++++++++++*/
- void RestoreBackupWebpageSpoolFile(URL *Url)
- {
- struct stat buf;
- char *bakfile,*orgfile;
- /* Change to the spool directory. */
- if(chdir(Url->proto))
- {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
- if(chdir(Url->dir))
- {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("..");return;}
- /* Create the filenames and rename the files. */
- orgfile=URLToFileName(Url);
- bakfile=(char*)malloc(strlen(orgfile)+2);
- strcpy(bakfile,orgfile);
- *bakfile=*orgfile='D';
- strcat(bakfile,"~");
- if(!stat(bakfile,&buf))
- {
- if(rename(bakfile,orgfile))
- PrintMessage(Warning,"Cannot rename backup cached file '%s/%s/%s' to %s [%!s].",Url->proto,Url->dir,bakfile,orgfile);
- *bakfile=*orgfile='U';
- rename(bakfile,orgfile);
- }
- /* Change dir back and tidy up. */
- chdir("../..");
- free(bakfile);
- free(orgfile);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Delete a file in a spool subdirectory.
- URL *Url The URL to delete.
- ++++++++++++++++++++++++++++++++++++++*/
- void DeleteBackupWebpageSpoolFile(URL *Url)
- {
- char *bakfile;
- /* Change to the spool directory. */
- if(chdir(Url->proto))
- {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
- if(chdir(Url->dir))
- {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("..");return;}
- /* Delete the file for the backup web page. */
- bakfile=URLToFileName(Url);
- *bakfile='D';
- strcat(bakfile,"~");
- if(unlink(bakfile))
- PrintMessage(Warning,"Cannot unlink backup cached file '%s/%s/%s' [%!s].",Url->proto,Url->dir,bakfile);
- *bakfile='U';
- unlink(bakfile);
- /* Change dir back and tidy up. */
- chdir("../..");
- free(bakfile);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a lock file in a spool subdirectory.
- URL *Url The URL to lock.
- ++++++++++++++++++++++++++++++++++++++*/
- void CreateLockWebpageSpoolFile(URL *Url)
- {
- struct stat buf;
- char *lokfile,*orgfile;
- /* Change to the spool directory. */
- if(chdir(Url->proto))
- {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
- if(chdir(Url->dir))
- {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("..");return;}
- /* Create the lock file for the web page. */
- orgfile=URLToFileName(Url);
- lokfile=(char*)malloc(strlen(orgfile)+2);
- strcpy(lokfile,orgfile);
- *lokfile='L';
- *orgfile='D';
- if(!stat(lokfile,&buf))
- PrintMessage(Inform,"Lock file already exists for '%s'.",Url->name);
- else
- {
- if(link(orgfile,lokfile))
- PrintMessage(Warning,"Cannot make a lock file for '%s/%s/%s' [%!s].",Url->proto,Url->dir,orgfile);
- }
- /* Change dir back and tidy up. */
- chdir("../..");
- free(lokfile);
- free(orgfile);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Check for the existance of a lock file in a spool subdirectory.
- int ExistsLockWebpageSpoolFile Return a true value if the lock file exists.
- URL *Url The URL to check for the lock file for.
- ++++++++++++++++++++++++++++++++++++++*/
- int ExistsLockWebpageSpoolFile(URL *Url)
- {
- struct stat buf;
- char *file;
- int exists=0;
- if(chdir(Url->proto))
- return(0);
- if(chdir(Url->dir))
- {chdir("..");return(0);}
- /* Stat the file for the web page. */
- file=URLToFileName(Url);
- *file='L';
- exists=!stat(file,&buf);
- /* Change dir back and tidy up. */
- chdir("../..");
- free(file);
- return(exists);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Delete a lock file in a spool subdirectory.
- URL *Url The URL with the lock to delete.
- ++++++++++++++++++++++++++++++++++++++*/
- void DeleteLockWebpageSpoolFile(URL *Url)
- {
- char *lokfile;
- /* Change to the spool directory */
- if(chdir(Url->proto))
- {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
- if(chdir(Url->dir))
- {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->dir);chdir("..");return;}
- /* Delete the file for the backup web page. */
- lokfile=URLToFileName(Url);
- *lokfile='L';
- if(unlink(lokfile))
- PrintMessage(Inform,"Cannot unlink lock file '%s/%s/%s' [%!s].",Url->proto,Url->dir,lokfile);
- /* Change dir back and tidy up. */
- chdir("../..");
- free(lokfile);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a file in the lasttime directory.
- int CreateLastTimeSpoolFile Returns 1 if the file already exists.
- URL *Url The URL to create.
- ++++++++++++++++++++++++++++++++++++++*/
- int CreateLastTimeSpoolFile(URL *Url)
- {
- struct stat buf;
- char *file;
- int exists=0;
- if(NoLasttimeIndex)
- return(1);
- /* Change to the last time directory */
- if(chdir("lasttime"))
- {PrintMessage(Warning,"Cannot change to directory 'lasttime' [%!s].");return(0);}
- /* Create the file. */
- file=URLToFileName(Url);
- *file='D';
- if(stat(file,&buf)==-1)
- {
- char *name=(char*)malloc(strlen(Url->proto)+strlen(Url->dir)+strlen(file)+8);
- sprintf(name,"../%s/%s/%s",Url->proto,Url->dir,file);
- if(link(name,file))
- {PrintMessage(Warning,"Cannot create file 'lasttime/%s' [%!s].",file);}
- else
- {
- *file='U';
- sprintf(name,"../%s/%s/%s",Url->proto,Url->dir,file);
- if(link(name,file))
- {PrintMessage(Warning,"Cannot create file 'lasttime/%s' [%!s].",file);}
- }
- free(name);
- }
- else
- exists=1;
- /* Change dir back and tidy up. */
- chdir("..");
- free(file);
- return(exists);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Determine if a particular URL exists in the last time spool directory.
- int ExistsLastTimeSpoolFile Returns 1 if the URL exists.
- URL *Url The URL to look for.
- ++++++++++++++++++++++++++++++++++++++*/
- int ExistsLastTimeSpoolFile(URL *Url)
- {
- struct stat buf;
- int i,retval=0;
- char *name=URLToFileName(Url);
- *name='D';
- for(i=0;i<=NUM_PREVTIME_DIR;i++)
- {
- char lasttime[40];
- if(i)
- sprintf(lasttime,"prevtime%d/%s",i,name);
- else
- sprintf(lasttime,"lasttime/%s",name);
- if(!stat(lasttime,&buf))
- {retval=1;break;}
- }
- free(name);
- return(retval);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Delete a specified URL from the lasttime directory.
- char *DeleteLastTimeSpoolFile Returns NULL if OK else error message.
- URL *Url The URL to delete or NULL for all of them.
- ++++++++++++++++++++++++++++++++++++++*/
- char *DeleteLastTimeSpoolFile(URL *Url)
- {
- struct stat buf;
- char *err=NULL;
- int i;
- char *name=URLToFileName(Url);
- for(i=0;i<=NUM_PREVTIME_DIR;i++)
- {
- char lasttime[16];
- if(i)
- sprintf(lasttime,"prevtime%d",i);
- else
- strcpy(lasttime,"lasttime");
- /* Change to the last time directory */
- if(chdir(lasttime))
- {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",lasttime);}
- else
- {
- *name='D';
- if(!stat(name,&buf))
- {
- if(unlink(name))
- err=PrintMessage(Warning,"Cannot unlink lasttime request '%s/%s' [%!s].",lasttime,name);
- *name='U';
- unlink(name);
- }
- chdir("..");
- }
- }
- free(name);
- return(err);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Cycle the URLs from the lasttime directory down to the prevtime directories.
- ++++++++++++++++++++++++++++++++++++++*/
- void CycleLastTimeSpoolFile(void)
- {
- char lasttime[16],prevlasttime[16];
- struct stat buf;
- int i;
- /* Cycle the directories */
- for(i=NUM_PREVTIME_DIR;i>=0;i--)
- {
- if(i)
- sprintf(lasttime,"prevtime%d",i);
- else
- strcpy(lasttime,"lasttime");
- /* Create it if it does not exist. */
- if(lstat(lasttime,&buf))
- {
- PrintMessage(Inform,"Directory '%s' does not exist [%!s]; creating one.",lasttime);
- if(mkdir(lasttime,DirPerm))
- PrintMessage(Warning,"Cannot create directory '%s' [%!s].",lasttime);
- }
- else
- if(!S_ISDIR(buf.st_mode))
- PrintMessage(Warning,"The file '%s' is not a directory.",lasttime);
- /* Delete the contents of the oldest one, rename the newer ones. */
- if(i==NUM_PREVTIME_DIR)
- {
- DIR *dir;
- struct dirent* ent;
- if(chdir(lasttime))
- {PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",lasttime);continue;}
- dir=opendir(".");
- if(!dir)
- {PrintMessage(Warning,"Cannot open current directory '%s' [%!s].",lasttime);chdir("..");continue;}
- ent=readdir(dir); /* skip . */
- if(!ent)
- {PrintMessage(Warning,"Cannot read current directory '%s' [%!s].",lasttime);closedir(dir);chdir("..");continue;}
- ent=readdir(dir); /* skip .. */
- while((ent=readdir(dir)))
- if(unlink(ent->d_name))
- PrintMessage(Warning,"Cannot unlink previous time page '%s/%s' [%!s].",lasttime,ent->d_name);
- closedir(dir);
- chdir("..");
- if(rmdir(lasttime))
- PrintMessage(Warning,"Cannot unlink previous time directory '%s' [%!s].",lasttime);
- }
- else
- if(rename(lasttime,prevlasttime))
- PrintMessage(Warning,"Cannot rename previous time directory '%s' to '%s' [%!s].",lasttime,prevlasttime);
- strcpy(prevlasttime,lasttime);
- }
- if(mkdir("lasttime",DirPerm))
- PrintMessage(Warning,"Cannot create directory 'lasttime' [%!s].");
- }
- /*++++++++++++++++++++++++++++++++++++++
- Open a file in the monitor directory to write into.
- int CreateMonitorSpoolFile Returns a file descriptor, or -1 on failure.
- URL *Url The URL of the file to monitor.
- char MofY[13] A mask indicating the months of the year allowed.
- char DofM[32] A mask indicating the days of the month allowed.
- char DofW[8] A mask indicating the days of the week allowed.
- char HofD[25] A mask indicating the hours of the day allowed.
- ++++++++++++++++++++++++++++++++++++++*/
- int CreateMonitorSpoolFile(URL *Url,char MofY[13],char DofM[32],char DofW[8],char HofD[25])
- {
- struct stat buf;
- int fd=-1;
- char *file;
- /* Create the monitor directory if needed and change to it */
- if(lstat("monitor",&buf))
- {
- PrintMessage(Inform,"Directory 'monitor' does not exist [%!s]; creating one.");
- if(mkdir("monitor",DirPerm))
- {PrintMessage(Warning,"Cannot create directory 'monitor' [%!s].");return(-1);}
- }
- else
- if(!S_ISDIR(buf.st_mode))
- {PrintMessage(Warning,"The file 'monitor' is not a directory.");return(-1);}
- if(chdir("monitor"))
- {PrintMessage(Warning,"Cannot change to directory 'monitor' [%!s].");return(-1);}
- /* Open the monitor file */
- file=URLToFileName(Url);
- *file='O';
- fd=open(file,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,FilePerm);
- if(fd==-1)
- {PrintMessage(Warning,"Cannot create file 'monitor/%s' [%!s].",file);}
- else
- {
- int ufd,mfd;
- *file='U';
- ufd=open(file,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,FilePerm);
- if(ufd!=-1)
- {
- write_string(ufd,Url->file);
- close(ufd);
- }
- else
- {
- close(fd);
- fd=-1;
- }
- *file='M';
- mfd=open(file,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,FilePerm);
- if(mfd!=-1)
- {
- write_formatted(mfd,"%sn",MofY);
- write_formatted(mfd,"%sn",DofM);
- write_formatted(mfd,"%sn",DofW);
- write_formatted(mfd,"%sn",HofD);
- close(mfd);
- }
- else
- {
- close(fd);
- fd=-1;
- }
- }
- /* Change dir back and tidy up. */
- chdir("..");
- free(file);
- return(fd);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read a file containing the time to be monitored.
- long ReadMonitorTimesSpoolFile Returns the timestamp of the file.
- URL *Url The URL to read from.
- char MofY[13] Returns a mask indicating the months of the year allowed.
- char DofM[32] Returns a mask indicating the days of the month allowed.
- char DofW[8] Returns a mask indicating the days of the week allowed.
- char HofD[25] Returns a mask indicating the hours of the day allowed.
- ++++++++++++++++++++++++++++++++++++++*/
- long ReadMonitorTimesSpoolFile(URL *Url,char MofY[13],char DofM[32],char DofW[8],char HofD[25])
- {
- time_t atime,mtime;
- struct stat buf;
- int mfd;
- char *file;
- strcpy(MofY,"111111111111");
- strcpy(DofM,"1111111111111111111111111111111");
- strcpy(DofW,"1111111");
- strcpy(HofD,"100000000000000000000000");
- /* Change to the monitor directory. */
- if(chdir("monitor"))
- {PrintMessage(Warning,"Cannot change to directory 'monitor' [%!s].");return(0);}
- file=URLToFileName(Url);
- /* Check for 'O*' file. */
- *file='O';
- if(lstat(file,&buf))
- atime=0,mtime=time(NULL);
- else
- atime=buf.st_atime,mtime=buf.st_mtime;
- /* Check for 'M*' file for the old format. */
- *file='M';
- if(lstat(file,&buf) || buf.st_size<8)
- {
- int interval=7;
- mfd=open(file,O_RDONLY|O_BINARY);
- if(mfd)
- {
- char str[8];
- if(read(mfd,str,8)>0)
- interval=atoi(str);
- if(interval<0)
- interval=0;
- close(mfd);
- }
- strcpy(MofY,"111111111111");
- if(interval==7)
- {
- strcpy(DofM,"1111111111111111111111111111111");
- strcpy(DofW,"0000000"); DofW[(4+mtime/(3600*24))%7]='1';
- }
- else
- {
- int i;
- if(interval)
- {strcpy(DofM,"0000000000000000000000000000000"); for(i=0;i<31;i+=interval) DofM[i]='1';}
- else
- strcpy(DofM,"1111111111111111111111111111111");
- strcpy(DofW,"1111111");
- }
- if(interval)
- {strcpy(HofD,"000000000000000000000000"); HofD[(mtime/3600)%24]='1';}
- else
- strcpy(HofD,"111111111111111111111111");
- chdir("..");
- return(atime);
- }
- /* Assume that the file is in the new format. */
- mfd=open(file,O_RDONLY|O_BINARY);
- if(mfd)
- {
- char line[80];
- line[78]=0;
- if(read(mfd,line,80)!=78 ||
- sscanf(line,"%12s %31s %7s %24s",MofY,DofM,DofW,HofD)!=4 ||
- strlen(MofY)!=12 || strlen(DofM)!=31 || strlen(DofW)!=7 || strlen(HofD)!=24)
- {
- strcpy(MofY,"111111111111");
- strcpy(DofM,"1111111111111111111111111111111");
- strcpy(DofW,"1111111");
- strcpy(HofD,"100000000000000000000000");
- }
- close(mfd);
- }
- chdir("..");
- return(atime);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Delete a specified URL from the monitor directory.
- char *DeleteMonitorSpoolFile Returns NULL if OK else error message.
- URL *Url The URL to delete or NULL for all of them.
- ++++++++++++++++++++++++++++++++++++++*/
- char *DeleteMonitorSpoolFile(URL *Url)
- {
- char *err=NULL;
- char *name;
- /* Change to the monitor directory. */
- if(chdir("monitor"))
- {err=PrintMessage(Warning,"Cannot change to directory 'monitor' [%!s].");return(err);}
- /* Delete the file for the request. */
- if(Url)
- {
- name=URLToFileName(Url);
- *name='O';
- if(unlink(name))
- err=PrintMessage(Warning,"Cannot unlink monitor request 'monitor/%s' [%!s].",name);
- *name='U';
- unlink(name);
- *name='M';
- unlink(name);
- free(name);
- }
- else
- {
- struct dirent* ent;
- DIR *dir=opendir(".");
- if(!dir)
- {err=PrintMessage(Warning,"Cannot open current directory 'monitor' [%!s].");chdir("..");return(err);}
- ent=readdir(dir); /* skip . */
- if(!ent)
- {err=PrintMessage(Warning,"Cannot read current directory 'monitor' [%!s].");closedir(dir);chdir("..");return(err);}
- ent=readdir(dir); /* skip .. */
- while((ent=readdir(dir)))
- {
- if(unlink(ent->d_name))
- err=PrintMessage(Warning,"Cannot unlink outgoing request 'monitor/%s' [%!s].",ent->d_name);
- }
- closedir(dir);
- }
- /* Change dir back and tidy up. */
- chdir("..");
- return(err);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a temporary spool file.
- int CreateTempSpoolFile Returns the file descriptor.
- ++++++++++++++++++++++++++++++++++++++*/
- int CreateTempSpoolFile(void)
- {
- char name[16];
- struct stat buf;
- int fd;
- /* Create the outgoing directory if needed and change to it */
- if(lstat("temp",&buf))
- {
- PrintMessage(Inform,"Directory 'temp' does not exist [%!s]; creating one.");
- if(mkdir("temp",DirPerm))
- {PrintMessage(Warning,"Cannot create directory 'temp' [%!s].");return(-1);}
- }
- else
- if(!S_ISDIR(buf.st_mode))
- {PrintMessage(Warning,"The file 'temp' is not a directory.");return(-1);}
- /* Open the file */
- sprintf(name,"temp/tmp.%ld",(long)getpid());
- fd=open(name,O_RDWR|O_CREAT|O_TRUNC|O_BINARY,FilePerm);
- if(fd==-1)
- PrintMessage(Warning,"Cannot create temporary file '%s' [%!s].",name);
- return(fd);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Close and delete the temporary spool file.
- int fd The file descriptor.
- ++++++++++++++++++++++++++++++++++++++*/
- void CloseTempSpoolFile(int fd)
- {
- char name[16];
- sprintf(name,"temp/tmp.%ld",(long)getpid());
- if(unlink(name)==-1)
- PrintMessage(Warning,"Cannot unlink temporary file '%s' [%!s].",name);
- close(fd);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Convert a filename to a URL.
- char *FileNameToURL Returns the URL.
- char *file The file name.
- ++++++++++++++++++++++++++++++++++++++*/
- char *FileNameToURL(char *file)
- {
- char *path,*copy;
- int ufd,r;
- if(!file || !*file)
- return(NULL);
- copy=(char*)malloc(strlen(file)+1);
- strcpy(copy,file);
- path=(char*)malloc(256+1);
- *copy='U';
- ufd=open(copy,O_RDONLY|O_BINARY);
- if(ufd==-1)
- {
- free(copy);
- free(path);
- return(NULL);
- }
- r=read(ufd,path,256);
- if(r==256)
- {
- int rr=0;
- do
- {
- r+=rr;
- path=(char*)realloc(path,r+256+1);
- }
- while((rr=read(ufd,&path[r],256))>0);
- }
- else if(r==-1)
- {
- close(ufd);
- free(copy);
- free(path);
- return(NULL);
- }
- path[r]=0;
- close(ufd);
- free(copy);
- return(path);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Convert a URL to a filename
- char *URLToFileName Returns the filename.
- URL *Url The URL to convert to a filename.
- ++++++++++++++++++++++++++++++++++++++*/
- char *URLToFileName(URL *Url)
- {
- char *hash;
- char *file;
- hash=MakeHash(Url->file);
- file=(char*)malloc(strlen(hash)+3);
- sprintf(file,"X%s",hash);
- return(file);
- }