118 lines
3.2 KiB
C++
118 lines
3.2 KiB
C++
// -*- mode: cpp; mode: fold -*-
|
|
// Description /*{{{*/
|
|
/* ######################################################################
|
|
|
|
Directory Stream
|
|
|
|
This class provides a simple basic extractor that can be used for
|
|
a number of purposes.
|
|
|
|
##################################################################### */
|
|
/*}}}*/
|
|
// Include Files /*{{{*/
|
|
#include <config.h>
|
|
|
|
#include <apt-pkg/dirstream.h>
|
|
#include <apt-pkg/error.h>
|
|
|
|
#include <cerrno>
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
#include <apti18n.h>
|
|
/*}}}*/
|
|
|
|
// DirStream::DoItem - Process an item /*{{{*/
|
|
// ---------------------------------------------------------------------
|
|
/* This is a very simple extractor, it does not deal with things like
|
|
overwriting directories with files and so on. */
|
|
bool pkgDirStream::DoItem(Item &Itm,int &Fd)
|
|
{
|
|
switch (Itm.Type)
|
|
{
|
|
case Item::File:
|
|
{
|
|
/* Open the output file, NDELAY is used to prevent this from
|
|
blowing up on device special files.. */
|
|
int iFd = open(Itm.Name,O_NDELAY|O_WRONLY|O_CREAT|O_TRUNC|O_APPEND,
|
|
Itm.Mode);
|
|
if (iFd < 0)
|
|
return _error->Errno("open",_("Failed to write file %s"),
|
|
Itm.Name);
|
|
|
|
// fchmod deals with umask and fchown sets the ownership
|
|
if (fchmod(iFd,Itm.Mode) != 0)
|
|
{
|
|
close(iFd);
|
|
return _error->Errno("fchmod",_("Failed to write file %s"), Itm.Name);
|
|
}
|
|
if (fchown(iFd,Itm.UID,Itm.GID) != 0 && errno != EPERM)
|
|
{
|
|
close(iFd);
|
|
return _error->Errno("fchown",_("Failed to write file %s"), Itm.Name);
|
|
}
|
|
Fd = iFd;
|
|
return true;
|
|
}
|
|
|
|
case Item::HardLink:
|
|
case Item::SymbolicLink:
|
|
case Item::CharDevice:
|
|
case Item::BlockDevice:
|
|
case Item::Directory:
|
|
{
|
|
struct stat Buf;
|
|
// check if the dir is already there, if so return true
|
|
if (stat(Itm.Name,&Buf) == 0)
|
|
{
|
|
if(S_ISDIR(Buf.st_mode))
|
|
return true;
|
|
// something else is there already, return false
|
|
return false;
|
|
}
|
|
// nothing here, create the dir
|
|
if(mkdir(Itm.Name,Itm.Mode) < 0)
|
|
return false;
|
|
return true;
|
|
}
|
|
case Item::FIFO:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
/*}}}*/
|
|
// DirStream::FinishedFile - Finished processing a file /*{{{*/
|
|
// ---------------------------------------------------------------------
|
|
/* */
|
|
bool pkgDirStream::FinishedFile(Item &Itm,int Fd)
|
|
{
|
|
if (Fd < 0)
|
|
return true;
|
|
|
|
/* Set the modification times. The only way it can fail is if someone
|
|
has futzed with our file, which is intolerable :> */
|
|
struct timeval times[2];
|
|
times[0].tv_sec = times[1].tv_sec = Itm.MTime;
|
|
times[0].tv_usec = times[1].tv_usec = 0;
|
|
if (utimes(Itm.Name, times) != 0)
|
|
_error->Errno("utimes", "Failed to set modification time for %s",Itm.Name);
|
|
|
|
if (close(Fd) != 0)
|
|
return _error->Errno("close",_("Failed to close file %s"),Itm.Name);
|
|
return true;
|
|
}
|
|
/*}}}*/
|
|
// DirStream::Fail - Failed processing a file /*{{{*/
|
|
// ---------------------------------------------------------------------
|
|
/* */
|
|
bool pkgDirStream::Fail(Item &/*Itm*/, int Fd)
|
|
{
|
|
if (Fd < 0)
|
|
return true;
|
|
|
|
close(Fd);
|
|
return false;
|
|
}
|
|
/*}}}*/
|