// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: fileutl.cc,v 1.36 2001/03/03 22:36:20 tausq Exp $
+// $Id: fileutl.cc,v 1.42 2002/09/14 05:29:22 jgg Exp $
/* ######################################################################
File Utilities
GetLock - dpkg compatible lock file manipulation (fcntl)
This source is placed in the Public Domain, do with it what you will
- It was originally written by Jason Gunthorpe.
+ It was originally written by Jason Gunthorpe <jgg@debian.org>.
##################################################################### */
/*}}}*/
#include <apt-pkg/fileutl.h>
#include <apt-pkg/error.h>
#include <apt-pkg/sptr.h>
+#include <apt-pkg/configuration.h>
#include <apti18n.h>
+#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
+#include <set>
/*}}}*/
+using namespace std;
+
// CopyFile - Buffered copy of a file /*{{{*/
// ---------------------------------------------------------------------
/* The caller is expected to set things so that failure causes erasure */
/*}}}*/
// flNotFile - Strip the file from the directory name /*{{{*/
// ---------------------------------------------------------------------
-/* */
+/* Result ends in a / */
string flNotFile(string File)
{
string::size_type Res = File.rfind('/');
if (Res == string::npos)
- return File;
+ return "./";
Res++;
return string(File,0,Res);
}
/* 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()
+pid_t ExecFork()
{
// Fork off the process
pid_t Process = fork();
signal(SIGWINCH,SIG_DFL);
signal(SIGCONT,SIG_DFL);
signal(SIGTSTP,SIG_DFL);
-
+
+ set<int> KeepFDs;
+ Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds");
+ if (Opts != 0 && Opts->Child != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+ int fd = atoi(Opts->Value.c_str());
+ KeepFDs.insert(fd);
+ }
+ }
+
// Close all of our FDs - just in case
for (int K = 3; K != 40; K++)
- fcntl(K,F_SETFD,FD_CLOEXEC);
+ {
+ if(KeepFDs.find(K) == KeepFDs.end())
+ fcntl(K,F_SETFD,FD_CLOEXEC);
+ }
}
return Process;
/*}}}*/
// ExecWait - Fancy waitpid /*{{{*/
// ---------------------------------------------------------------------
-/* Waits for the given sub process. If Reap is set the no errors are
+/* Waits for the given sub process. If Reap is set then no errors are
generated. Otherwise a failed subprocess will generate a proper descriptive
message */
-bool ExecWait(int Pid,const char *Name,bool Reap)
+bool ExecWait(pid_t Pid,const char *Name,bool Reap)
{
if (Pid <= 1)
return true;
if (Reap == true)
return false;
- return _error->Error(_("Waited, for %s but it wasn't there"),Name);
+ return _error->Error(_("Waited for %s but it wasn't there"),Name);
}
break;
case WriteTemp:
- unlink(Filename.c_str());
- iFd = open(FileName.c_str(),O_RDWR | O_CREATE | O_EXCL,Perms);
+ unlink(FileName.c_str());
+ iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
break;
}
// ---------------------------------------------------------------------
/* We are carefull to handle interruption by a signal while reading
gracefully. */
-bool FileFd::Read(void *To,unsigned long Size,bool AllowEof)
+bool FileFd::Read(void *To,unsigned long Size,unsigned long *Actual)
{
int Res;
errno = 0;
+ if (Actual != 0)
+ *Actual = 0;
+
do
{
Res = read(iFd,To,Size);
To = (char *)To + Res;
Size -= Res;
+ if (Actual != 0)
+ *Actual += Res;
}
while (Res > 0 && Size > 0);
return true;
// Eof handling
- if (AllowEof == true)
+ if (Actual != 0)
{
Flags |= HitEof;
return true;