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 >
Wrap
C/C++ Source or Header
|
1998-02-11
|
23KB
|
1,038 lines
/***************************************
$Header: /home/amb/wwwoffle/RCS/spool.c 2.23 1998/02/11 17:33:45 amb Exp $
WWWOFFLE - World Wide Web Offline Explorer - Version 2.1.
Handle all of the spooling of files in the spool directory.
******************/ /******************
Written by Andrew M. Bishop
This file Copyright 1996,97,98 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"
/*++++++++++++++++++++++++++++++++++++++
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;
/* 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",0755))
{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((fd=open(ent->d_name,O_RDONLY))==-1)
PrintMessage(Inform,"Cannot open file 'outgoing/%s' [%!s]; race condition?",ent->d_name);
else
if(unlink(ent->d_name))
{
PrintMessage(Inform,"Cannot unlink file 'outgoing/%s' [%!s]; race condition?",ent->d_name);
close(fd); fd=-1;
}
else
{
*ent->d_name='U';
unlink(ent->d_name);
break;
}
}
closedir(dir);
}
else
{
char name[16];
sprintf(name,"tmp.%d",getpid());
fd=open(name,O_WRONLY|O_CREAT|O_EXCL,0644);
if(fd==-1)
PrintMessage(Inform,"Cannot open file 'outgoing/%s' [%!s]",name);
}
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);
if(chdir("outgoing"))
{PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s].");return;}
sprintf(oldname,"tmp.%d",getpid());
newname=URLToFileName(Url);
*newname='U';
unlink(newname);
ufd=open(newname,O_WRONLY|O_CREAT|O_EXCL,0644);
if(ufd!=-1)
{
write_string(ufd,Url->name);
close(ufd);
}
*newname='O';
if(rename(oldname,newname))
{PrintMessage(Warning,"Cannot rename 'outgoing/%s' to 'outgoing/%s' [%!s].",oldname,newname);unlink(oldname);}
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);
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);
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);
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.
++++++++++++++++++++++++++++++++++++++*/
char *DeleteOutgoingSpoolFile(URL *Url)
{
char *err=NULL;
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);
}
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,0755))
{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->host,&buf))
{
PrintMessage(Inform,"Directory '%s/%s' does not exist [%!s]; creating one.",Url->proto,Url->host);
if(mkdir(Url->host,0755))
{PrintMessage(Warning,"Cannot create directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return(-1);}
}
else
if(!S_ISDIR(buf.st_mode))
{PrintMessage(Warning,"The file '%s/%s' is not a directory.",Url->proto,Url->host);chdir("..");return(-1);}
if(chdir(Url->host))
{PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return(-1);}
/* Open the file for the web page. */
file=URLToFileName(Url);
*file='D';
if(rw)
fd=open(file,O_RDONLY);
else
fd=open(file,O_RDWR|O_CREAT,0644);
if(!rw && fd!=-1)
{
int ufd;
*file='U';
ufd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
if(ufd!=-1)
{
write_string(ufd,Url->name);
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);
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;
if(chdir(Url->proto))
{err=PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return(err);}
if(chdir(Url->host))
{err=PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);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->host);chdir("../..");return(err);}
ent=readdir(dir); /* skip . */
if(!ent)
{err=PrintMessage(Warning,"Cannot read current directory '%s/%s' [%!s].",Url->proto,Url->host);closedir(dir);chdir("../..");return(err);}
ent=readdir(dir); /* skip .. */
while((ent=readdir(dir)))
{
if(unlink(ent->d_name))
err=PrintMessage(Warning,"Cannot unlink cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,ent->d_name);
}
closedir(dir);
chdir("..");
if(rmdir(Url->host))
err=PrintMessage(Warning,"Cannot delete what should be an empty directory '%s/%s' [%!s].",Url->proto,Url->host);
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->host);
else
didstat=1;
*file='D';
if(unlink(file))
err=PrintMessage(Warning,"Cannot unlink cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
*file='U';
unlink(file);
free(file);
if(didstat)
{
struct utimbuf utbuf;
utbuf.actime=time(NULL);
utbuf.modtime=buf.st_mtime;
utime(".",&utbuf);
}
chdir("../..");
}
return(err);
}
/*++++++++++++++++++++++++++++++++++++++
Touch a file in a spool subdirectory.
URL *Url The URL to touch.
++++++++++++++++++++++++++++++++++++++*/
void TouchWebpageSpoolFile(URL *Url)
{
char *file;
if(chdir(Url->proto))
{PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
if(chdir(Url->host))
{PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return;}
/* Touch the file for the web page. */
file=URLToFileName(Url);
*file='D';
utime(file,NULL);
chdir("../..");
free(file);
}
/*++++++++++++++++++++++++++++++++++++++
Touch a file in a spool subdirectory.
int ExistsWebpageSpoolFile Return a true value if the page exists.
URL *Url The URL to touch.
++++++++++++++++++++++++++++++++++++++*/
int ExistsWebpageSpoolFile(URL *Url)
{
struct stat buf;
char *file;
int exists=0;
if(chdir(Url->proto))
return(0);
if(chdir(Url->host))
{chdir("..");return(0);}
/* Stat the file for the web page. */
file=URLToFileName(Url);
*file='D';
exists=!stat(file,&buf);
chdir("../..");
free(file);
return(exists);
}
/*++++++++++++++++++++++++++++++++++++++
Create a backup copy of a file in a spool subdirectory.
URL *Url The URL to make a copy of.
int fd The file descriptor of the original file.
++++++++++++++++++++++++++++++++++++++*/
void CreateBackupWebpageSpoolFile(URL *Url,int fd)
{
struct stat buf;
char *file;
int bfd=-1;
/* Create the spool directory if needed and change to it. */
if(chdir(Url->proto))
{PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
if(chdir(Url->host))
{PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return;}
/* Open the file for the web page. */
file=URLToFileName(Url);
*file='D';
strcat(file,"~");
if(!stat(file,&buf))
PrintMessage(Inform,"Backup already exists for '%s' [%!s].",Url->name);
else
{
bfd=open(file,O_WRONLY|O_CREAT,0644);
if(bfd==-1)
PrintMessage(Warning,"Cannot create backup spool file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
else
{
int n;
char data[256];
while((n=read(fd,data,256))>0)
write(bfd,data,n);
if(n==-1)
PrintMessage(Warning,"Error copying to backup spool file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
lseek(fd,0,SEEK_SET);
close(bfd);
if(fstat(fd,&buf))
PrintMessage(Warning,"Cannot get the date to set for the backup spool file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
else
{
struct utimbuf utbuf;
utbuf.actime=buf.st_atime;
utbuf.modtime=buf.st_mtime;
utime(file,&utbuf);
}
}
}
chdir("../..");
free(file);
}
/*++++++++++++++++++++++++++++++++++++++
Restore the backup copy of a file in a spool subdirectory.
URL *Url The URL to restore.
++++++++++++++++++++++++++++++++++++++*/
void RestoreBackupWebpageSpoolFile(URL *Url)
{
struct stat buf;
struct utimbuf utbuf;
char *file;
int ifd=-1,ofd=-1;
/* Create the spool directory if needed and change to it. */
if(chdir(Url->proto))
{PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
if(chdir(Url->host))
{PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return;}
/* Open the file for the web page. */
file=URLToFileName(Url);
*file='D';
strcat(file,"~");
if(!stat(file,&buf))
{
ifd=open(file,O_RDONLY);
if(ifd==-1)
PrintMessage(Warning,"Cannot open spool file '%s/%s/%s' to restore from [%!s].",Url->proto,Url->host,file);
else
{
if(unlink(file))
PrintMessage(Warning,"Cannot unlink backup cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
file[strlen(file)-1]=0;
ofd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
if(ofd==-1)
PrintMessage(Warning,"Cannot open spool file '%s/%s/%s' to restore to [%!s].",Url->proto,Url->host,file);
else
{
int n;
char data[256];
while((n=read(ifd,data,256))>0)
write(ofd,data,n);
if(n==-1)
PrintMessage(Warning,"Error copying from backup cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
close(ofd);
utbuf.actime=buf.st_atime;
utbuf.modtime=buf.st_mtime;
utime(file,&utbuf);
}
close(ifd);
}
}
chdir("../..");
free(file);
}
/*++++++++++++++++++++++++++++++++++++++
Delete a file in a spool subdirectory.
URL *Url The URL to delete.
++++++++++++++++++++++++++++++++++++++*/
void DeleteBackupWebpageSpoolFile(URL *Url)
{
char *file;
if(chdir(Url->proto))
{PrintMessage(Warning,"Cannot change to directory '%s' [%!s].",Url->proto);return;}
if(chdir(Url->host))
{PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s].",Url->proto,Url->host);chdir("..");return;}
/* Delete the file for the backup web page. */
file=URLToFileName(Url);
*file='D';
strcat(file,"~");
if(unlink(file))
PrintMessage(Warning,"Cannot unlink backup cached file '%s/%s/%s' [%!s].",Url->proto,Url->host,file);
chdir("../..");
free(file);
}
/*++++++++++++++++++++++++++++++++++++++
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;
char *name;
/* Create the outgoing directory if needed and change to it */
if(!Url)
if(lstat("lasttime",&buf))
{
PrintMessage(Inform,"Directory 'lasttime' does not exist [%!s]; creating one.");
if(mkdir("lasttime",0755))
{err=PrintMessage(Warning,"Cannot create directory 'lasttime' [%!s].");return(err);}
}
else
if(!S_ISDIR(buf.st_mode))
{err=PrintMessage(Warning,"The file 'lasttime' is not a directory.");return(err);}
if(chdir("lasttime"))
{err=PrintMessage(Warning,"Cannot change to directory 'lasttime' [%!s].");return(err);}
/* Delete the file for the request or all of them. */
if(Url)
{
name=URLToFileName(Url);
*name='D';
if(unlink(name))
err=PrintMessage(Warning,"Cannot unlink lasttime request 'lasttime/%s' [%!s].",name);
*name='U';
unlink(name);
free(name);
}
else
{
struct dirent* ent;
DIR *dir;
dir=opendir(".");
if(!dir)
{err=PrintMessage(Warning,"Cannot open current directory 'lasttime' [%!s].");chdir("..");return(err);}
ent=readdir(dir); /* skip . */
if(!ent)
{err=PrintMessage(Warning,"Cannot read current directory 'lasttime' [%!s].");closedir(dir);chdir("..");return(err);}
ent=readdir(dir); /* skip .. */
while((ent=readdir(dir)))
{
if(unlink(ent->d_name))
PrintMessage(Warning,"Cannot unlink last time page 'lasttime/%s' [%!s].",ent->d_name);
}
closedir(dir);
}
chdir("..");
return(err);
}
/*++++++++++++++++++++++++++++++++++++++
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;
/* 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)
{
int fd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
if(fd==-1)
{PrintMessage(Warning,"Cannot create file 'lasttime/%s' [%!s].",file);}
else
{
int ufd;
*file='U';
ufd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
if(ufd!=-1)
{
write_string(ufd,Url->name);
close(ufd);
}
close(fd);
}
}
else
exists=1;
chdir("..");
free(file);
return(exists);
}
/*++++++++++++++++++++++++++++++++++++++
Open a file in the monitor directory to write into.
int OpenMonitorSpoolFile Returns a file descriptor, or -1 on failure.
URL *Url The URL of the file to monitor.
++++++++++++++++++++++++++++++++++++++*/
int OpenMonitorSpoolFile(URL *Url)
{
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",0755))
{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,0644);
if(fd==-1)
{PrintMessage(Warning,"Cannot create file 'monitor/%s' [%!s].",file);}
else
{
int ufd;
*file='U';
ufd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0644);
if(ufd!=-1)
{
write_string(ufd,Url->name);
close(ufd);
}
else
{
close(fd);
fd=-1;
}
}
chdir("..");
free(file);
return(fd);
}
/*++++++++++++++++++++++++++++++++++++++
Delete a specified URL from the monitor directory.
char *DeleteMonitorSpoolFile Returns NULL if OK else error message.
URL *Url The URL to delete.
++++++++++++++++++++++++++++++++++++++*/
char *DeleteMonitorSpoolFile(URL *Url)
{
char *err=NULL;
char *name;
if(chdir("monitor"))
{err=PrintMessage(Warning,"Cannot change to directory 'monitor' [%!s].");return(err);}
/* Delete the file for the request. */
name=URLToFileName(Url);
*name='O';
if(unlink(name))
err=PrintMessage(Warning,"Cannot unlink monitor request 'monitor/%s' [%!s].",name);
*name='U';
unlink(name);
free(name);
chdir("..");
return(err);
}
/*++++++++++++++++++++++++++++++++++++++
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[0] && file[0]!='D' && file[0]!='O')
return(NULL);
copy=(char*)malloc(strlen(file)+1);
strcpy(copy,file);
path=(char*)malloc(256+1);
*copy='U';
ufd=open(copy,O_RDONLY);
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->name);
file=(char*)malloc(strlen(hash)+3);
sprintf(file,"X%s",hash);
return(file);
}