/* * File: io.c * * Author: Ulli Horlacher (framstag@rus.uni-stuttgart.de) * * History: * * 1995-08-11 Framstag initial version * 1996-04-23 Framstag added file copying function * 1996-05-02 Framstag corrected file creating bug in fcopy() * 1996-06-24 Framstag enhanced fcopy() to copy to stdout * 1997-02-02 Framstag improved reliability for fcopy() with NFS * 1997-02-24 Framstag sprintf() -> snprintf() * 1997-05-05 Framstag better IRIX support (blksize) * 1997-12-09 Framstag added whereis() * 2001-01-10 Framstag added rfopen() * 2001-02-04 Framstag added mktmpdir() and rmtmpdir() * 2001-02-16 Framstag fixed cleanup loop * * Socket read and write routines and file copy function of the * sendfile package. * * Copyright © 1995-2001 Ulli Horlacher * This file is covered by the GNU General Public License */ #include "config.h" /* various #defines */ #include #include #include #include #include #include #include #include #include #include "io.h" /* (socket) read/write */ #include "net.h" /* the network routines */ #include "string.h" /* extended string functions */ #include "message.h" /* information, warning and error messages */ #ifdef NEXT #include #endif #if defined(SOLARIS2) #ifndef fileno int fileno(FILE *); #endif #endif /* * readn - read n bytes from network socket * * INPUT: fd - socket file descriptor * ptr - empty string * nbytes - number of bytes to read * * RETURN: number of actual read bytes * * this function is derived from example code from * "Unix Networking Programming" by W. R. Stevens */ int readn(int fd, char *ptr, int nbytes) { int nleft, nread; nleft=nbytes; while (nleft>0) { nread=read(fd, ptr, nleft); if (nread<0) return(nread); else if (nread==0) break; nleft-=nread; ptr+=nread; } return(nbytes-nleft); } /* * writen - write n bytes to network socket * * INPUT: fd - socket file descriptor * ptr - string to send * nbytes - number of bytes to send * * RETURN: number of actual written bytes * * this function is derived from example code from * "Unix Networking Programming" by W. R. Stevens */ int writen(int fd, char *ptr, int nbytes) { int nleft, nwritten; nleft=nbytes; while (nleft>0) { nwritten=write(fd, ptr, nleft); if (nwritten<0) return(nwritten); nleft-=nwritten; ptr+=nwritten; } return(nbytes-nleft); } /* * fcopy - copy a file (copy to stdout if there is no destination filename) * * INPUT: from - source file * to - destination file * mode - file protection mode * * RETURN: 0 if ok, -1 on failure * */ int fcopy(const char *from, const char *to, mode_t mode) { int fdin, fdout; /* file descriptor in/out */ int rbytes, /* read bytes */ wbytes; /* written bytes */ char tmp[MAXLEN], /* temporary string */ *buf; /* copy buffer */ struct stat finfo; /* information about a file */ off_t fsize, /* original file size */ wtotal, /* total read bytes */ blksize; /* file system block size */ wtotal=0; /* get the original file size */ if (stat(from,&finfo)<0) { snprintf(MAXS(tmp),"cannot access '%s'",from); message("",'E',tmp); return(-1); } fsize=finfo.st_size; /* open source file */ fdin=open(from,O_RDONLY,0); if (fdin<0) { snprintf(MAXS(tmp),"error opening '%s'",from); message("",'E',tmp); return(-1); } /* destination file specified? */ if (*to) { /* open destination file */ fdout=creat(to,mode); if (fdout<0) { snprintf(MAXS(tmp),"error creating '%s'",to); message("",'E',tmp); close(fdin); return(-1); } /* get file system block size for copy operation */ stat(to,&finfo); #ifdef HAVE_ST_BLKSIZE blksize=finfo.st_blksize; #else blksize=1024; #endif /* ANSI C can not dynamicly allocate with buf[blksize] */ buf=(char *)malloc(blksize); if (!buf) message("",'F',"out of memory"); /* read until EOF */ while ((rbytes=read(fdin,buf,blksize)) > 0) { /* write to destination file */ wbytes=write(fdout,buf,rbytes); if (wbytes!=rbytes) { /* write error */ close(fdin); close(fdout); free(buf); snprintf(MAXS(tmp),"error writing '%s'",to); message("",'E',tmp); return(-1); } wtotal+=wbytes; } close(fdout); } else /* copy to stdout */ { /* get file system block size for copy operation */ stat(from,&finfo); #ifdef HAVE_ST_BLKSIZE blksize=finfo.st_blksize; #else blksize=1024; #endif /* ANSI C can not dynamicly allocate with buf[blksize] */ buf=(char *)malloc(blksize); if (!buf) message("",'F',"out of memory"); /* read until EOF */ while ((rbytes=read(fdin,buf,blksize)) > 0) { /* write to stdout */ wbytes=write(fileno(stdout),buf,rbytes); wtotal+=wbytes; } } close(fdin); free(buf); /* read error? */ if (rbytes<0) { snprintf(MAXS(tmp),"error reading '%s'",from); message("",'E',tmp); return(-1); } /* count mismatch or read/write errors? */ if (fsize!=wtotal) { errno=0; snprintf(MAXS(tmp),"wrong byte count for '%s'",from); message("",'E',tmp); return(-1); } return(0); } /* * whereis - where is a program in the path * * INPUT: prg - program to look for * * RETURN: NULL if not found else path to file */ char *whereis(char *prg) { int len; static char filepath[MAXLEN]; /* file with path */ char *path; /* $PATH */ char *cp; /* when file contains a / test directly */ if (strchr(prg,'/')) { if (access(prg,X_OK)==0) return(prg); else return(NULL); } len=strlen(prg); path=getenv("PATH"); if (!path || !strchr(path,'/')) return(NULL); while (*path==':') path++; while (*path) { snprintf(filepath,MAXLEN-2-len,"%s",path); if ((cp=strchr(filepath,':'))) *cp=0; strcat(filepath,"/"); strcat(filepath,prg); if (access(filepath,X_OK)==0) return(filepath); if ((cp=strchr(path,':'))) path=cp+1; else return(NULL); } return(NULL); } /* * rfopen - open a regular file * * INPUT: file - file name (with path) * mode - fopen mode * * RETURN: same like fopen(), but NULL if file is not a regular file */ FILE *rfopen(const char *file, const char *mode) { struct stat finfo; /* information about a file */ /* what kind of file ist it and do we have access at all? */ if (stat(file,&finfo)<0) { /* no such file ==> open it! (mode can be "w" or "a+") */ if (errno==ENOENT) return(fopen(file,mode)); else /* other error */ return(NULL); } else { /* regular file? */ if (finfo.st_mode&S_IFREG) { return(fopen(file,mode)); } else { errno=EIO; return(NULL); } } } /* * mktmpdir - create a new temporary directory * * INPUT: verbose - flag * * RETURN: full path of the temporary directory * * ENVIRONMENT: SF_TMPDIR, TMPDIR */ char *mktmpdir(int verbose) { char *cp; /* a simple string pointer */ char tmp[MAXLEN]; /* temporary string */ static char tmpdir[FLEN]; /* directory for temporary files */ /* get tmpdir base */ if ((cp=getenv("SF_TMPDIR"))) snprintf(tmpdir,FLEN-30,"%s",cp); else if ((cp=getenv("TMPDIR"))) snprintf(tmpdir,FLEN-30,"%s",cp); else strcpy(tmpdir,"/tmp"); snprintf(tmp,30,"/sf_%u.tmp",(unsigned int)(time(NULL)*getpid())); strcat(tmpdir,tmp); if (mkdir(tmpdir,S_IRWXU)<0 || chmod(tmpdir,S_IRWXU)<0) { snprintf(MAXS(tmp),"cannot create tmpdir %s",tmpdir); message("",'F',tmp); } if (verbose) { snprintf(MAXS(tmp),"directory for temporary files is: %s",tmpdir); message("",'I',tmp); } return(tmpdir); } /* * rmtmpdir - delete the temporary directory * * INPUT: full path of the temporary directory */ void rmtmpdir(char *tmpdir) { char cwd[FLEN]; /* current directory */ char tmp[MAXLEN]; /* temporary string */ struct dirent *dire; /* directory entry */ DIR *dp; /* directory pointer */ if (!tmpdir || !*tmpdir) return; if (!getcwd(MAXS(cwd))) strcpy(cwd,"/tmp"); if (chdir(tmpdir) < 0) return; /* open dir */ if (!(dp=opendir(tmpdir))) { snprintf(MAXS(tmp),"cleanup: cannot open %s",tmpdir); message("",'X',tmp); } while ((dire=readdir(dp))) { /* skip . and .. */ if (strcmp(dire->d_name,".")==0 || strcmp(dire->d_name,"..")==0) continue; /* delete file */ if (unlink(dire->d_name) < 0) { snprintf(MAXS(tmp),"cannot remove %s/%s",tmpdir); message("",'X',tmp); } } chdir(cwd); if (rmdir(tmpdir) < 0) { snprintf(MAXS(tmp),"cannot remove %s",tmpdir); message("",'X',tmp); } } /* int main(int argc, char *argv[]) { char *filepath; filepath=whereis(argv[1]); if (filepath) { printf("%s\n",filepath); exit(0); } exit(1); } */