1 // -*- mode: cpp; mode: fold -*-
3 // $Id: fileutl.cc,v 1.42 2002/09/14 05:29:22 jgg Exp $
4 /* ######################################################################
8 CopyFile - Buffered copy of a single file
9 GetLock - dpkg compatible lock file manipulation (fcntl)
11 Most of this source is placed in the Public Domain, do with it what
13 It was originally written by Jason Gunthorpe <jgg@debian.org>.
14 FileFd gzip support added by Martin Pitt <martin.pitt@canonical.com>
16 The exception is RunScripts() it is under the GPLv2
18 ##################################################################### */
20 // Include Files /*{{{*/
21 #include <apt-pkg/fileutl.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/error.h>
24 #include <apt-pkg/sptr.h>
25 #include <apt-pkg/configuration.h>
37 #include <sys/types.h>
47 #ifdef WORDS_BIGENDIAN
54 // RunScripts - Run a set of scripts from a configuration subtree /*{{{*/
55 // ---------------------------------------------------------------------
57 bool RunScripts(const char *Cnf
)
59 Configuration::Item
const *Opts
= _config
->Tree(Cnf
);
60 if (Opts
== 0 || Opts
->Child
== 0)
64 // Fork for running the system calls
65 pid_t Child
= ExecFork();
70 if (chdir("/tmp/") != 0)
73 unsigned int Count
= 1;
74 for (; Opts
!= 0; Opts
= Opts
->Next
, Count
++)
76 if (Opts
->Value
.empty() == true)
79 if (system(Opts
->Value
.c_str()) != 0)
87 while (waitpid(Child
,&Status
,0) != Child
)
91 return _error
->Errno("waitpid","Couldn't wait for subprocess");
94 // Restore sig int/quit
95 signal(SIGQUIT
,SIG_DFL
);
96 signal(SIGINT
,SIG_DFL
);
98 // Check for an error code.
99 if (WIFEXITED(Status
) == 0 || WEXITSTATUS(Status
) != 0)
101 unsigned int Count
= WEXITSTATUS(Status
);
105 for (; Opts
!= 0 && Count
!= 1; Opts
= Opts
->Next
, Count
--);
106 _error
->Error("Problem executing scripts %s '%s'",Cnf
,Opts
->Value
.c_str());
109 return _error
->Error("Sub-process returned an error code");
116 // CopyFile - Buffered copy of a file /*{{{*/
117 // ---------------------------------------------------------------------
118 /* The caller is expected to set things so that failure causes erasure */
119 bool CopyFile(FileFd
&From
,FileFd
&To
)
121 if (From
.IsOpen() == false || To
.IsOpen() == false)
124 // Buffered copy between fds
125 SPtrArray
<unsigned char> Buf
= new unsigned char[64000];
126 unsigned long Size
= From
.Size();
129 unsigned long ToRead
= Size
;
133 if (From
.Read(Buf
,ToRead
) == false ||
134 To
.Write(Buf
,ToRead
) == false)
143 // GetLock - Gets a lock file /*{{{*/
144 // ---------------------------------------------------------------------
145 /* This will create an empty file of the given name and lock it. Once this
146 is done all other calls to GetLock in any other process will fail with
147 -1. The return result is the fd of the file, the call should call
148 close at some time. */
149 int GetLock(string File
,bool Errors
)
151 // GetLock() is used in aptitude on directories with public-write access
152 // Use O_NOFOLLOW here to prevent symlink traversal attacks
153 int FD
= open(File
.c_str(),O_RDWR
| O_CREAT
| O_NOFOLLOW
,0640);
156 // Read only .. cant have locking problems there.
159 _error
->Warning(_("Not using locking for read only lock file %s"),File
.c_str());
160 return dup(0); // Need something for the caller to close
164 _error
->Errno("open",_("Could not open lock file %s"),File
.c_str());
166 // Feh.. We do this to distinguish the lock vs open case..
170 SetCloseExec(FD
,true);
172 // Aquire a write lock
175 fl
.l_whence
= SEEK_SET
;
178 if (fcntl(FD
,F_SETLK
,&fl
) == -1)
182 _error
->Warning(_("Not using locking for nfs mounted lock file %s"),File
.c_str());
183 return dup(0); // Need something for the caller to close
186 _error
->Errno("open",_("Could not get lock %s"),File
.c_str());
197 // FileExists - Check if a file exists /*{{{*/
198 // ---------------------------------------------------------------------
200 bool FileExists(string File
)
203 if (stat(File
.c_str(),&Buf
) != 0)
208 // DirectoryExists - Check if a directory exists and is really one /*{{{*/
209 // ---------------------------------------------------------------------
211 bool DirectoryExists(string
const &Path
)
214 if (stat(Path
.c_str(),&Buf
) != 0)
216 return ((Buf
.st_mode
& S_IFDIR
) != 0);
219 // CreateDirectory - poor man's mkdir -p guarded by a parent directory /*{{{*/
220 // ---------------------------------------------------------------------
221 /* This method will create all directories needed for path in good old
222 mkdir -p style but refuses to do this if Parent is not a prefix of
223 this Path. Example: /var/cache/ and /var/cache/apt/archives are given,
224 so it will create apt/archives if /var/cache exists - on the other
225 hand if the parent is /var/lib the creation will fail as this path
226 is not a parent of the path to be generated. */
227 bool CreateDirectory(string
const &Parent
, string
const &Path
)
229 if (Parent
.empty() == true || Path
.empty() == true)
232 if (DirectoryExists(Path
) == true)
235 if (DirectoryExists(Parent
) == false)
238 // we are not going to create directories "into the blue"
239 if (Path
.find(Parent
, 0) != 0)
242 vector
<string
> const dirs
= VectorizeString(Path
.substr(Parent
.size()), '/');
243 string progress
= Parent
;
244 for (vector
<string
>::const_iterator d
= dirs
.begin(); d
!= dirs
.end(); ++d
)
246 if (d
->empty() == true)
249 progress
.append("/").append(*d
);
250 if (DirectoryExists(progress
) == true)
253 if (mkdir(progress
.c_str(), 0755) != 0)
259 // CreateAPTDirectoryIfNeeded - ensure that the given directory exists /*{{{*/
260 // ---------------------------------------------------------------------
261 /* a small wrapper around CreateDirectory to check if it exists and to
262 remove the trailing "/apt/" from the parent directory if needed */
263 bool CreateAPTDirectoryIfNeeded(string
const &Parent
, string
const &Path
)
265 if (DirectoryExists(Path
) == true)
268 size_t const len
= Parent
.size();
269 if (len
> 5 && Parent
.find("/apt/", len
- 6, 5) == len
- 5)
271 if (CreateDirectory(Parent
.substr(0,len
-5), Path
) == true)
274 else if (CreateDirectory(Parent
, Path
) == true)
280 // GetListOfFilesInDir - returns a vector of files in the given dir /*{{{*/
281 // ---------------------------------------------------------------------
282 /* If an extension is given only files with this extension are included
283 in the returned vector, otherwise every "normal" file is included. */
284 std::vector
<string
> GetListOfFilesInDir(string
const &Dir
, string
const &Ext
,
285 bool const &SortList
, bool const &AllowNoExt
)
287 std::vector
<string
> ext
;
289 if (Ext
.empty() == false)
291 if (AllowNoExt
== true && ext
.empty() == false)
293 return GetListOfFilesInDir(Dir
, ext
, SortList
);
295 std::vector
<string
> GetListOfFilesInDir(string
const &Dir
, std::vector
<string
> const &Ext
,
296 bool const &SortList
)
298 // Attention debuggers: need to be set with the environment config file!
299 bool const Debug
= _config
->FindB("Debug::GetListOfFilesInDir", false);
302 std::clog
<< "Accept in " << Dir
<< " only files with the following " << Ext
.size() << " extensions:" << std::endl
;
303 if (Ext
.empty() == true)
304 std::clog
<< "\tNO extension" << std::endl
;
306 for (std::vector
<string
>::const_iterator e
= Ext
.begin();
308 std::clog
<< '\t' << (e
->empty() == true ? "NO" : *e
) << " extension" << std::endl
;
311 std::vector
<string
> List
;
312 Configuration::MatchAgainstConfig
SilentIgnore("Dir::Ignore-Files-Silently");
313 DIR *D
= opendir(Dir
.c_str());
316 _error
->Errno("opendir",_("Unable to read %s"),Dir
.c_str());
320 for (struct dirent
*Ent
= readdir(D
); Ent
!= 0; Ent
= readdir(D
))
322 // skip "hidden" files
323 if (Ent
->d_name
[0] == '.')
326 // check for accepted extension:
327 // no extension given -> periods are bad as hell!
328 // extensions given -> "" extension allows no extension
329 if (Ext
.empty() == false)
331 string d_ext
= flExtension(Ent
->d_name
);
332 if (d_ext
== Ent
->d_name
) // no extension
334 if (std::find(Ext
.begin(), Ext
.end(), "") == Ext
.end())
337 std::clog
<< "Bad file: " << Ent
->d_name
<< " → no extension" << std::endl
;
338 if (SilentIgnore
.Match(Ent
->d_name
) == false)
339 _error
->Notice("Ignoring file '%s' in directory '%s' as it has no filename extension", Ent
->d_name
, Dir
.c_str());
343 else if (std::find(Ext
.begin(), Ext
.end(), d_ext
) == Ext
.end())
346 std::clog
<< "Bad file: " << Ent
->d_name
<< " → bad extension »" << flExtension(Ent
->d_name
) << "«" << std::endl
;
347 if (SilentIgnore
.Match(Ent
->d_name
) == false)
348 _error
->Notice("Ignoring file '%s' in directory '%s' as it has an invalid filename extension", Ent
->d_name
, Dir
.c_str());
353 // Skip bad filenames ala run-parts
354 const char *C
= Ent
->d_name
;
356 if (isalpha(*C
) == 0 && isdigit(*C
) == 0
357 && *C
!= '_' && *C
!= '-') {
358 // no required extension -> dot is a bad character
359 if (*C
== '.' && Ext
.empty() == false)
364 // we don't reach the end of the name -> bad character included
368 std::clog
<< "Bad file: " << Ent
->d_name
<< " → bad character »"
369 << *C
<< "« in filename (period allowed: " << (Ext
.empty() ? "no" : "yes") << ")" << std::endl
;
373 // skip filenames which end with a period. These are never valid
377 std::clog
<< "Bad file: " << Ent
->d_name
<< " → Period as last character" << std::endl
;
381 // Make sure it is a file and not something else
382 string
const File
= flCombine(Dir
,Ent
->d_name
);
384 if (stat(File
.c_str(),&St
) != 0 || S_ISREG(St
.st_mode
) == 0)
387 std::clog
<< "Bad file: " << Ent
->d_name
<< " → stat says not a good file" << std::endl
;
392 std::clog
<< "Accept file: " << Ent
->d_name
<< " in " << Dir
<< std::endl
;
393 List
.push_back(File
);
397 if (SortList
== true)
398 std::sort(List
.begin(),List
.end());
402 // SafeGetCWD - This is a safer getcwd that returns a dynamic string /*{{{*/
403 // ---------------------------------------------------------------------
404 /* We return / on failure. */
407 // Stash the current dir.
410 if (getcwd(S
,sizeof(S
)-2) == 0)
412 unsigned int Len
= strlen(S
);
418 // flNotDir - Strip the directory from the filename /*{{{*/
419 // ---------------------------------------------------------------------
421 string
flNotDir(string File
)
423 string::size_type Res
= File
.rfind('/');
424 if (Res
== string::npos
)
427 return string(File
,Res
,Res
- File
.length());
430 // flNotFile - Strip the file from the directory name /*{{{*/
431 // ---------------------------------------------------------------------
432 /* Result ends in a / */
433 string
flNotFile(string File
)
435 string::size_type Res
= File
.rfind('/');
436 if (Res
== string::npos
)
439 return string(File
,0,Res
);
442 // flExtension - Return the extension for the file /*{{{*/
443 // ---------------------------------------------------------------------
445 string
flExtension(string File
)
447 string::size_type Res
= File
.rfind('.');
448 if (Res
== string::npos
)
451 return string(File
,Res
,Res
- File
.length());
454 // flNoLink - If file is a symlink then deref it /*{{{*/
455 // ---------------------------------------------------------------------
456 /* If the name is not a link then the returned path is the input. */
457 string
flNoLink(string File
)
460 if (lstat(File
.c_str(),&St
) != 0 || S_ISLNK(St
.st_mode
) == 0)
462 if (stat(File
.c_str(),&St
) != 0)
465 /* Loop resolving the link. There is no need to limit the number of
466 loops because the stat call above ensures that the symlink is not
474 if ((Res
= readlink(NFile
.c_str(),Buffer
,sizeof(Buffer
))) <= 0 ||
475 (unsigned)Res
>= sizeof(Buffer
))
478 // Append or replace the previous path
480 if (Buffer
[0] == '/')
483 NFile
= flNotFile(NFile
) + Buffer
;
485 // See if we are done
486 if (lstat(NFile
.c_str(),&St
) != 0)
488 if (S_ISLNK(St
.st_mode
) == 0)
493 // flCombine - Combine a file and a directory /*{{{*/
494 // ---------------------------------------------------------------------
495 /* If the file is an absolute path then it is just returned, otherwise
496 the directory is pre-pended to it. */
497 string
flCombine(string Dir
,string File
)
499 if (File
.empty() == true)
502 if (File
[0] == '/' || Dir
.empty() == true)
504 if (File
.length() >= 2 && File
[0] == '.' && File
[1] == '/')
506 if (Dir
[Dir
.length()-1] == '/')
508 return Dir
+ '/' + File
;
511 // SetCloseExec - Set the close on exec flag /*{{{*/
512 // ---------------------------------------------------------------------
514 void SetCloseExec(int Fd
,bool Close
)
516 if (fcntl(Fd
,F_SETFD
,(Close
== false)?0:FD_CLOEXEC
) != 0)
518 cerr
<< "FATAL -> Could not set close on exec " << strerror(errno
) << endl
;
523 // SetNonBlock - Set the nonblocking flag /*{{{*/
524 // ---------------------------------------------------------------------
526 void SetNonBlock(int Fd
,bool Block
)
528 int Flags
= fcntl(Fd
,F_GETFL
) & (~O_NONBLOCK
);
529 if (fcntl(Fd
,F_SETFL
,Flags
| ((Block
== false)?0:O_NONBLOCK
)) != 0)
531 cerr
<< "FATAL -> Could not set non-blocking flag " << strerror(errno
) << endl
;
536 // WaitFd - Wait for a FD to become readable /*{{{*/
537 // ---------------------------------------------------------------------
538 /* This waits for a FD to become readable using select. It is useful for
539 applications making use of non-blocking sockets. The timeout is
541 bool WaitFd(int Fd
,bool write
,unsigned long timeout
)
554 Res
= select(Fd
+1,0,&Set
,0,(timeout
!= 0?&tv
:0));
556 while (Res
< 0 && errno
== EINTR
);
566 Res
= select(Fd
+1,&Set
,0,0,(timeout
!= 0?&tv
:0));
568 while (Res
< 0 && errno
== EINTR
);
577 // ExecFork - Magical fork that sanitizes the context before execing /*{{{*/
578 // ---------------------------------------------------------------------
579 /* This is used if you want to cleanse the environment for the forked
580 child, it fixes up the important signals and nukes all of the fds,
581 otherwise acts like normal fork. */
584 // Fork off the process
585 pid_t Process
= fork();
588 cerr
<< "FATAL -> Failed to fork." << endl
;
592 // Spawn the subprocess
596 signal(SIGPIPE
,SIG_DFL
);
597 signal(SIGQUIT
,SIG_DFL
);
598 signal(SIGINT
,SIG_DFL
);
599 signal(SIGWINCH
,SIG_DFL
);
600 signal(SIGCONT
,SIG_DFL
);
601 signal(SIGTSTP
,SIG_DFL
);
604 Configuration::Item
const *Opts
= _config
->Tree("APT::Keep-Fds");
605 if (Opts
!= 0 && Opts
->Child
!= 0)
608 for (; Opts
!= 0; Opts
= Opts
->Next
)
610 if (Opts
->Value
.empty() == true)
612 int fd
= atoi(Opts
->Value
.c_str());
617 // Close all of our FDs - just in case
618 for (int K
= 3; K
!= 40; K
++)
620 if(KeepFDs
.find(K
) == KeepFDs
.end())
621 fcntl(K
,F_SETFD
,FD_CLOEXEC
);
628 // ExecWait - Fancy waitpid /*{{{*/
629 // ---------------------------------------------------------------------
630 /* Waits for the given sub process. If Reap is set then no errors are
631 generated. Otherwise a failed subprocess will generate a proper descriptive
633 bool ExecWait(pid_t Pid
,const char *Name
,bool Reap
)
638 // Wait and collect the error code
640 while (waitpid(Pid
,&Status
,0) != Pid
)
648 return _error
->Error(_("Waited for %s but it wasn't there"),Name
);
652 // Check for an error code.
653 if (WIFEXITED(Status
) == 0 || WEXITSTATUS(Status
) != 0)
657 if (WIFSIGNALED(Status
) != 0)
659 if( WTERMSIG(Status
) == SIGSEGV
)
660 return _error
->Error(_("Sub-process %s received a segmentation fault."),Name
);
662 return _error
->Error(_("Sub-process %s received signal %u."),Name
, WTERMSIG(Status
));
665 if (WIFEXITED(Status
) != 0)
666 return _error
->Error(_("Sub-process %s returned an error code (%u)"),Name
,WEXITSTATUS(Status
));
668 return _error
->Error(_("Sub-process %s exited unexpectedly"),Name
);
675 // FileFd::Open - Open a file /*{{{*/
676 // ---------------------------------------------------------------------
677 /* The most commonly used open mode combinations are given with Mode */
678 bool FileFd::Open(string FileName
,OpenMode Mode
, unsigned long Perms
)
685 iFd
= open(FileName
.c_str(),O_RDONLY
);
689 iFd
= open(FileName
.c_str(),O_RDONLY
);
691 gz
= gzdopen (iFd
, "r");
702 char *name
= strdup((FileName
+ ".XXXXXX").c_str());
703 TemporaryFileName
= string(mktemp(name
));
704 iFd
= open(TemporaryFileName
.c_str(),O_RDWR
| O_CREAT
| O_EXCL
,Perms
);
712 if (lstat(FileName
.c_str(),&Buf
) == 0 && S_ISLNK(Buf
.st_mode
))
713 unlink(FileName
.c_str());
714 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,Perms
);
719 iFd
= open(FileName
.c_str(),O_RDWR
);
723 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
,Perms
);
727 unlink(FileName
.c_str());
728 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_EXCL
,Perms
);
733 return _error
->Errno("open",_("Could not open file %s"),FileName
.c_str());
735 this->FileName
= FileName
;
736 SetCloseExec(iFd
,true);
740 bool FileFd::OpenDescriptor(int Fd
, OpenMode Mode
, bool AutoClose
)
743 Flags
= (AutoClose
) ? FileFd::AutoClose
: 0;
745 if (Mode
== ReadOnlyGzip
) {
746 gz
= gzdopen (iFd
, "r");
750 return _error
->Errno("gzdopen",_("Could not open file descriptor %d"),
758 // FileFd::~File - Closes the file /*{{{*/
759 // ---------------------------------------------------------------------
760 /* If the proper modes are selected then we close the Fd and possibly
761 unlink the file on error. */
767 // FileFd::Read - Read a bit of the file /*{{{*/
768 // ---------------------------------------------------------------------
769 /* We are carefull to handle interruption by a signal while reading
771 bool FileFd::Read(void *To
,unsigned long Size
,unsigned long *Actual
)
781 Res
= gzread(gz
,To
,Size
);
783 Res
= read(iFd
,To
,Size
);
784 if (Res
< 0 && errno
== EINTR
)
789 return _error
->Errno("read",_("Read error"));
792 To
= (char *)To
+ Res
;
797 while (Res
> 0 && Size
> 0);
810 return _error
->Error(_("read, still have %lu to read but none left"),Size
);
813 // FileFd::Write - Write to the file /*{{{*/
814 // ---------------------------------------------------------------------
816 bool FileFd::Write(const void *From
,unsigned long Size
)
823 Res
= gzwrite(gz
,From
,Size
);
825 Res
= write(iFd
,From
,Size
);
826 if (Res
< 0 && errno
== EINTR
)
831 return _error
->Errno("write",_("Write error"));
834 From
= (char *)From
+ Res
;
837 while (Res
> 0 && Size
> 0);
843 return _error
->Error(_("write, still have %lu to write but couldn't"),Size
);
846 // FileFd::Seek - Seek in the file /*{{{*/
847 // ---------------------------------------------------------------------
849 bool FileFd::Seek(unsigned long To
)
853 res
= gzseek(gz
,To
,SEEK_SET
);
855 res
= lseek(iFd
,To
,SEEK_SET
);
856 if (res
!= (signed)To
)
859 return _error
->Error("Unable to seek to %lu",To
);
865 // FileFd::Skip - Seek in the file /*{{{*/
866 // ---------------------------------------------------------------------
868 bool FileFd::Skip(unsigned long Over
)
872 res
= gzseek(gz
,Over
,SEEK_CUR
);
874 res
= lseek(iFd
,Over
,SEEK_CUR
);
878 return _error
->Error("Unable to seek ahead %lu",Over
);
884 // FileFd::Truncate - Truncate the file /*{{{*/
885 // ---------------------------------------------------------------------
887 bool FileFd::Truncate(unsigned long To
)
892 return _error
->Error("Truncating gzipped files is not implemented (%s)", FileName
.c_str());
894 if (ftruncate(iFd
,To
) != 0)
897 return _error
->Error("Unable to truncate to %lu",To
);
903 // FileFd::Tell - Current seek position /*{{{*/
904 // ---------------------------------------------------------------------
906 unsigned long FileFd::Tell()
912 Res
= lseek(iFd
,0,SEEK_CUR
);
913 if (Res
== (off_t
)-1)
914 _error
->Errno("lseek","Failed to determine the current file position");
918 // FileFd::FileSize - Return the size of the file /*{{{*/
919 // ---------------------------------------------------------------------
921 unsigned long FileFd::FileSize()
925 if (fstat(iFd
,&Buf
) != 0)
926 return _error
->Errno("fstat","Unable to determine the file size");
930 // FileFd::Size - Return the size of the content in the file /*{{{*/
931 // ---------------------------------------------------------------------
933 unsigned long FileFd::Size()
935 unsigned long size
= FileSize();
937 // only check gzsize if we are actually a gzip file, just checking for
938 // "gz" is not sufficient as uncompressed files will be opened with
939 // gzopen in "direct" mode as well
940 if (gz
&& !gzdirect(gz
) && size
> 0)
942 /* unfortunately zlib.h doesn't provide a gzsize(), so we have to do
943 * this ourselves; the original (uncompressed) file size is the last 32
944 * bits of the file */
945 off_t orig_pos
= lseek(iFd
, 0, SEEK_CUR
);
946 if (lseek(iFd
, -4, SEEK_END
) < 0)
947 return _error
->Errno("lseek","Unable to seek to end of gzipped file");
949 if (read(iFd
, &size
, 4) != 4)
950 return _error
->Errno("read","Unable to read original size of gzipped file");
952 #ifdef WORDS_BIGENDIAN
953 uint32_t tmp_size
= size
;
954 uint8_t const * const p
= (uint8_t const * const) &tmp_size
;
955 tmp_size
= (p
[3] << 24) | (p
[2] << 16) | (p
[1] << 8) | p
[0];
959 if (lseek(iFd
, orig_pos
, SEEK_SET
) < 0)
960 return _error
->Errno("lseek","Unable to seek in gzipped file");
967 // FileFd::Close - Close the file if the close flag is set /*{{{*/
968 // ---------------------------------------------------------------------
973 if ((Flags
& AutoClose
) == AutoClose
)
976 int const e
= gzclose(gz
);
977 // gzdopen() on empty files always fails with "buffer error" here, ignore that
978 if (e
!= 0 && e
!= Z_BUF_ERROR
)
979 Res
&= _error
->Errno("close",_("Problem closing the gzip file %s"), FileName
.c_str());
981 if (iFd
> 0 && close(iFd
) != 0)
982 Res
&= _error
->Errno("close",_("Problem closing the file %s"), FileName
.c_str());
985 if ((Flags
& Replace
) == Replace
&& iFd
>= 0) {
986 if (rename(TemporaryFileName
.c_str(), FileName
.c_str()) != 0)
987 Res
&= _error
->Errno("rename",_("Problem renaming the file %s to %s"), TemporaryFileName
.c_str(), FileName
.c_str());
989 FileName
= TemporaryFileName
; // for the unlink() below.
995 if ((Flags
& Fail
) == Fail
&& (Flags
& DelOnFail
) == DelOnFail
&&
996 FileName
.empty() == false)
997 if (unlink(FileName
.c_str()) != 0)
998 Res
&= _error
->WarningE("unlnk",_("Problem unlinking the file %s"), FileName
.c_str());
1004 // FileFd::Sync - Sync the file /*{{{*/
1005 // ---------------------------------------------------------------------
1009 #ifdef _POSIX_SYNCHRONIZED_IO
1010 if (fsync(iFd
) != 0)
1011 return _error
->Errno("sync",_("Problem syncing the file"));