#include <apt-pkg/strutl.h>
#include <apt-pkg/error.h>
#include <apt-pkg/md5.h>
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/hashsum_template.h>
+#include <ctype.h>
+#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
-#include <utime.h>
+#include <sys/time.h>
#include <unistd.h>
-#include <iostream>
#include "multicompress.h"
#include <apti18n.h>
/* Open all the temp files now so we can report any errors. File is
made unreable to prevent people from touching it during creating. */
for (Files *I = Outputs; I != 0; I = I->Next)
- I->TmpFile.Open(I->Output + ".new",FileFd::WriteEmpty,0600);
+ I->TmpFile.Open(I->Output + ".new", FileFd::WriteOnly | FileFd::Create | FileFd::Empty, FileFd::Extension, 0600);
if (_error->PendingError() == true)
return;
_exit(0);
};
- /* Tidy up the temp files, we open them in the constructor so as to
- get proper error reporting. Close them now. */
- for (Files *I = Outputs; I != 0; I = I->Next)
- I->TmpFile.Close();
-
close(Pipe[0]);
Input = fdopen(Pipe[1],"w");
if (Input == 0)
else
{
// Update the mtime if necessary
- if (UpdateMTime > 0 &&
+ if (UpdateMTime > 0 &&
(Now - St.st_mtime > (signed)UpdateMTime || St.st_mtime > Now))
{
- struct utimbuf Buf;
- Buf.actime = Buf.modtime = Now;
- utime(I->Output.c_str(),&Buf);
+ utimes(I->Output.c_str(), NULL);
Changed = true;
- }
+ }
}
// Force the file permissions
// MultiCompress::OpenOld - Open an old file /*{{{*/
// ---------------------------------------------------------------------
/* This opens one of the original output files, possibly decompressing it. */
-bool MultiCompress::OpenOld(int &Fd,pid_t &Proc)
+bool MultiCompress::OpenOld(FileFd &Fd)
{
Files *Best = Outputs;
for (Files *I = Outputs; I != 0; I = I->Next)
Best = I;
// Open the file
- FileFd F(Best->Output,FileFd::ReadOnly);
- if (_error->PendingError() == true)
- return false;
-
- // Decompress the file so we can read it
- if (ExecCompressor(Best->CompressProg,&Proc,F.Fd(),Fd,false) == false)
- return false;
-
- return true;
+ return Fd.Open(Best->Output, FileFd::ReadOnly, FileFd::Extension);
}
/*}}}*/
-// MultiCompress::CloseOld - Close the old file /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool MultiCompress::CloseOld(int Fd,pid_t Proc)
-{
- close(Fd);
- if (Proc != -1)
- if (ExecWait(Proc,_("decompressor"),false) == false)
- return false;
- return true;
-}
- /*}}}*/
// MultiCompress::Child - The writer child /*{{{*/
// ---------------------------------------------------------------------
/* The child process forks a bunch of compression children and takes
is new then the temp files are renamed, otherwise they are erased. */
bool MultiCompress::Child(int const &FD)
{
- // Start the compression children.
- for (Files *I = Outputs; I != 0; I = I->Next)
- {
- if (ExecCompressor(I->CompressProg,&(I->CompressProc),I->TmpFile.Fd(),
- I->Fd,true) == false)
- return false;
- }
-
/* Okay, now we just feed data from FD to all the other FDs. Also
stash a hash of the data to use later. */
SetNonBlock(FD,false);
FileSize += Res;
for (Files *I = Outputs; I != 0; I = I->Next)
{
- if (write(I->Fd,Buffer,Res) != Res)
+ if (I->TmpFile.Write(Buffer, Res) == false)
{
_error->Errno("write",_("IO to subprocess/file failed"));
break;
}
}
}
-
- // Close all the writers
- for (Files *I = Outputs; I != 0; I = I->Next)
- close(I->Fd);
-
- // Wait for the compressors to exit
- for (Files *I = Outputs; I != 0; I = I->Next)
- {
- if (I->CompressProc != -1)
- ExecWait(I->CompressProc, I->CompressProg.Binary.c_str(), false);
- }
-
+
if (_error->PendingError() == true)
return false;
// Check the MD5 of the lowest cost entity.
while (Missing == false)
{
- int CompFd = -1;
- pid_t Proc = -1;
- if (OpenOld(CompFd,Proc) == false)
+ FileFd CompFd;
+ if (OpenOld(CompFd) == false)
{
_error->Discard();
break;
}
-
+
// Compute the hash
MD5Summation OldMD5;
unsigned long long NewFileSize = 0;
while (1)
{
- int Res = read(CompFd,Buffer,sizeof(Buffer));
+ unsigned long long Res = 0;
+ if (CompFd.Read(Buffer,sizeof(Buffer), &Res) == false)
+ return _error->Errno("read",_("Failed to read while computing MD5"));
if (Res == 0)
break;
- if (Res < 0)
- return _error->Errno("read",_("Failed to read while computing MD5"));
NewFileSize += Res;
OldMD5.Add(Buffer,Res);
}
-
- // Tidy the compressor
- if (CloseOld(CompFd,Proc) == false)
- return false;
+ CompFd.Close();
// Check the hash
if (OldMD5.Result() == MD5.Result() &&
for (Files *I = Outputs; I != 0; I = I->Next)
{
// Set the correct file modes
- fchmod(I->TmpFile.Fd(),Permissions);
+ chmod(I->TmpFile.Name().c_str(),Permissions);
if (rename(I->TmpFile.Name().c_str(),I->Output.c_str()) != 0)
_error->Errno("rename",_("Failed to rename %s to %s"),