X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/65a1e968442361247b646dc61843f841235114e0..c1e78ee5a2697afc0902d1be294d71de93090909:/apt-pkg/contrib/fileutl.cc diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index f34d839e3..43717da16 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: fileutl.cc,v 1.19 1999/02/08 07:30:50 jgg Exp $ +// $Id: fileutl.cc,v 1.27 1999/04/20 05:02:09 jgg Exp $ /* ###################################################################### File Utilities @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include /*}}}*/ @@ -37,14 +39,21 @@ bool CopyFile(FileFd &From,FileFd &To) // Buffered copy between fds unsigned char *Buf = new unsigned char[64000]; - long Size; - while ((Size = read(From.Fd(),Buf,64000)) > 0) + unsigned long Size = From.Size(); + while (Size != 0) { - if (To.Write(Buf,Size) == false) + unsigned long ToRead = Size; + if (Size > 64000) + ToRead = 64000; + + if (From.Read(Buf,ToRead) == false || + To.Write(Buf,ToRead) == false) { delete [] Buf; return false; } + + Size -= ToRead; } delete [] Buf; @@ -75,6 +84,11 @@ int GetLock(string File,bool Errors) fl.l_len = 0; if (fcntl(FD,F_SETLK,&fl) == -1) { + if (errno == ENOLCK) + { + _error->Warning("Not using locking for nfs mounted lock file %s",File.c_str()); + return true; + } if (Errors == true) _error->Errno("open","Could not get lock %s",File.c_str()); close(FD); @@ -163,19 +177,78 @@ void SetNonBlock(int Fd,bool Block) // WaitFd - Wait for a FD to become readable /*{{{*/ // --------------------------------------------------------------------- /* This waits for a FD to become readable using select. It is usefull for - applications making use of non-blocking sockets. */ -bool WaitFd(int Fd) + applications making use of non-blocking sockets. The timeout is + in seconds. */ +bool WaitFd(int Fd,bool write,unsigned long timeout) { fd_set Set; + struct timeval tv; FD_ZERO(&Set); FD_SET(Fd,&Set); - - if (select(Fd+1,&Set,0,0,0) <= 0) - return false; - + tv.tv_sec = timeout; + tv.tv_usec = 0; + if (write == true) + { + int Res; + do + { + Res = select(Fd+1,0,&Set,0,(timeout != 0?&tv:0)); + } + while (Res < 0 && errno == EINTR); + + if (Res <= 0) + return false; + } + else + { + int Res; + do + { + Res = select(Fd+1,&Set,0,0,(timeout != 0?&tv:0)); + } + while (Res < 0 && errno == EINTR); + + if (Res <= 0) + return false; + } + return true; } /*}}}*/ +// ExecFork - Magical fork that sanitizes the context before execing /*{{{*/ +// --------------------------------------------------------------------- +/* This is used if you want to cleanse the environment for the forked + child, it fixes up the important signals and nukes all of the fds, + otherwise acts like normal fork. */ +int ExecFork() +{ + // Fork off the process + pid_t Process = fork(); + if (Process < 0) + { + cerr << "FATAL -> Failed to fork." << endl; + exit(100); + } + + // Spawn the subprocess + if (Process == 0) + { + // Setup the signals + signal(SIGPIPE,SIG_DFL); + signal(SIGQUIT,SIG_DFL); + signal(SIGINT,SIG_DFL); + signal(SIGWINCH,SIG_DFL); + signal(SIGCONT,SIG_DFL); + signal(SIGTSTP,SIG_DFL); + + // Close all of our FDs - just in case + for (int K = 3; K != 40; K++) + fcntl(K,F_SETFD,FD_CLOEXEC); + } + + return Process; +} + /*}}}*/ // FileFd::FileFd - Open a file /*{{{*/ // --------------------------------------------------------------------- @@ -227,16 +300,33 @@ FileFd::~FileFd() /*}}}*/ // FileFd::Read - Read a bit of the file /*{{{*/ // --------------------------------------------------------------------- -/* */ +/* We are carefull to handle interruption by a signal while reading + gracefully. */ bool FileFd::Read(void *To,unsigned long Size) { - if (read(iFd,To,Size) != (signed)Size) + int Res; + errno = 0; + do { - Flags |= Fail; - return _error->Errno("read","Read error"); - } + Res = read(iFd,To,Size); + if (Res < 0 && errno == EINTR) + continue; + if (Res < 0) + { + Flags |= Fail; + return _error->Errno("read","Read error"); + } - return true; + To = (char *)To + Res; + Size -= Res; + } + while (Res > 0 && Size > 0); + + if (Size == 0) + return true; + + Flags |= Fail; + return _error->Error("read, still have %u to read but none left",Size); } /*}}}*/ // FileFd::Write - Write to the file /*{{{*/ @@ -244,13 +334,29 @@ bool FileFd::Read(void *To,unsigned long Size) /* */ bool FileFd::Write(const void *From,unsigned long Size) { - if (write(iFd,From,Size) != (signed)Size) + int Res; + errno = 0; + do { - Flags |= Fail; - return _error->Errno("write","Write error"); + Res = write(iFd,From,Size); + if (Res < 0 && errno == EINTR) + continue; + if (Res < 0) + { + Flags |= Fail; + return _error->Errno("write","Write error"); + } + + From = (char *)From + Res; + Size -= Res; } + while (Res > 0 && Size > 0); - return true; + if (Size == 0) + return true; + + Flags |= Fail; + return _error->Error("write, still have %u to write but couldn't",Size); } /*}}}*/ // FileFd::Seek - Seek in the file /*{{{*/ @@ -264,6 +370,20 @@ bool FileFd::Seek(unsigned long To) return _error->Error("Unable to seek to %u",To); } + return true; +} + /*}}}*/ +// FileFd::Truncate - Truncate the file /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool FileFd::Truncate(unsigned long To) +{ + if (ftruncate(iFd,To) != 0) + { + Flags |= Fail; + return _error->Error("Unable to truncate to %u",To); + } + return true; } /*}}}*/