]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/fileutl.cc
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 // ---------------------------------------------------------------------
199 /* Beware: Directories are also files! */
200 bool FileExists(string File
)
203 if (stat(File
.c_str(),&Buf
) != 0)
208 // RealFileExists - Check if a file exists and if it is really a file /*{{{*/
209 // ---------------------------------------------------------------------
211 bool RealFileExists(string File
)
214 if (stat(File
.c_str(),&Buf
) != 0)
216 return ((Buf
.st_mode
& S_IFREG
) != 0);
219 // DirectoryExists - Check if a directory exists and is really one /*{{{*/
220 // ---------------------------------------------------------------------
222 bool DirectoryExists(string
const &Path
)
225 if (stat(Path
.c_str(),&Buf
) != 0)
227 return ((Buf
.st_mode
& S_IFDIR
) != 0);
230 // CreateDirectory - poor man's mkdir -p guarded by a parent directory /*{{{*/
231 // ---------------------------------------------------------------------
232 /* This method will create all directories needed for path in good old
233 mkdir -p style but refuses to do this if Parent is not a prefix of
234 this Path. Example: /var/cache/ and /var/cache/apt/archives are given,
235 so it will create apt/archives if /var/cache exists - on the other
236 hand if the parent is /var/lib the creation will fail as this path
237 is not a parent of the path to be generated. */
238 bool CreateDirectory(string
const &Parent
, string
const &Path
)
240 if (Parent
.empty() == true || Path
.empty() == true)
243 if (DirectoryExists(Path
) == true)
246 if (DirectoryExists(Parent
) == false)
249 // we are not going to create directories "into the blue"
250 if (Path
.find(Parent
, 0) != 0)
253 vector
<string
> const dirs
= VectorizeString(Path
.substr(Parent
.size()), '/');
254 string progress
= Parent
;
255 for (vector
<string
>::const_iterator d
= dirs
.begin(); d
!= dirs
.end(); ++d
)
257 if (d
->empty() == true)
260 progress
.append("/").append(*d
);
261 if (DirectoryExists(progress
) == true)
264 if (mkdir(progress
.c_str(), 0755) != 0)
270 // CreateAPTDirectoryIfNeeded - ensure that the given directory exists /*{{{*/
271 // ---------------------------------------------------------------------
272 /* a small wrapper around CreateDirectory to check if it exists and to
273 remove the trailing "/apt/" from the parent directory if needed */
274 bool CreateAPTDirectoryIfNeeded(string
const &Parent
, string
const &Path
)
276 if (DirectoryExists(Path
) == true)
279 size_t const len
= Parent
.size();
280 if (len
> 5 && Parent
.find("/apt/", len
- 6, 5) == len
- 5)
282 if (CreateDirectory(Parent
.substr(0,len
-5), Path
) == true)
285 else if (CreateDirectory(Parent
, Path
) == true)
291 // GetListOfFilesInDir - returns a vector of files in the given dir /*{{{*/
292 // ---------------------------------------------------------------------
293 /* If an extension is given only files with this extension are included
294 in the returned vector, otherwise every "normal" file is included. */
295 std::vector
<string
> GetListOfFilesInDir(string
const &Dir
, string
const &Ext
,
296 bool const &SortList
, bool const &AllowNoExt
)
298 std::vector
<string
> ext
;
300 if (Ext
.empty() == false)
302 if (AllowNoExt
== true && ext
.empty() == false)
304 return GetListOfFilesInDir(Dir
, ext
, SortList
);
306 std::vector
<string
> GetListOfFilesInDir(string
const &Dir
, std::vector
<string
> const &Ext
,
307 bool const &SortList
)
309 // Attention debuggers: need to be set with the environment config file!
310 bool const Debug
= _config
->FindB("Debug::GetListOfFilesInDir", false);
313 std::clog
<< "Accept in " << Dir
<< " only files with the following " << Ext
.size() << " extensions:" << std::endl
;
314 if (Ext
.empty() == true)
315 std::clog
<< "\tNO extension" << std::endl
;
317 for (std::vector
<string
>::const_iterator e
= Ext
.begin();
319 std::clog
<< '\t' << (e
->empty() == true ? "NO" : *e
) << " extension" << std::endl
;
322 std::vector
<string
> List
;
324 if (DirectoryExists(Dir
.c_str()) == false)
326 _error
->Error(_("List of files can't be created as '%s' is not a directory"), Dir
.c_str());
330 Configuration::MatchAgainstConfig
SilentIgnore("Dir::Ignore-Files-Silently");
331 DIR *D
= opendir(Dir
.c_str());
334 _error
->Errno("opendir",_("Unable to read %s"),Dir
.c_str());
338 for (struct dirent
*Ent
= readdir(D
); Ent
!= 0; Ent
= readdir(D
))
340 // skip "hidden" files
341 if (Ent
->d_name
[0] == '.')
344 // Make sure it is a file and not something else
345 string
const File
= flCombine(Dir
,Ent
->d_name
);
346 #ifdef _DIRENT_HAVE_D_TYPE
347 if (Ent
->d_type
!= DT_REG
)
350 if (RealFileExists(File
.c_str()) == false)
352 if (SilentIgnore
.Match(Ent
->d_name
) == false)
353 _error
->Notice(_("Ignoring '%s' in directory '%s' as it is not a regular file"), Ent
->d_name
, Dir
.c_str());
358 // check for accepted extension:
359 // no extension given -> periods are bad as hell!
360 // extensions given -> "" extension allows no extension
361 if (Ext
.empty() == false)
363 string d_ext
= flExtension(Ent
->d_name
);
364 if (d_ext
== Ent
->d_name
) // no extension
366 if (std::find(Ext
.begin(), Ext
.end(), "") == Ext
.end())
369 std::clog
<< "Bad file: " << Ent
->d_name
<< " → no extension" << std::endl
;
370 if (SilentIgnore
.Match(Ent
->d_name
) == false)
371 _error
->Notice(_("Ignoring file '%s' in directory '%s' as it has no filename extension"), Ent
->d_name
, Dir
.c_str());
375 else if (std::find(Ext
.begin(), Ext
.end(), d_ext
) == Ext
.end())
378 std::clog
<< "Bad file: " << Ent
->d_name
<< " → bad extension »" << flExtension(Ent
->d_name
) << "«" << std::endl
;
379 if (SilentIgnore
.Match(Ent
->d_name
) == false)
380 _error
->Notice(_("Ignoring file '%s' in directory '%s' as it has an invalid filename extension"), Ent
->d_name
, Dir
.c_str());
385 // Skip bad filenames ala run-parts
386 const char *C
= Ent
->d_name
;
388 if (isalpha(*C
) == 0 && isdigit(*C
) == 0
389 && *C
!= '_' && *C
!= '-') {
390 // no required extension -> dot is a bad character
391 if (*C
== '.' && Ext
.empty() == false)
396 // we don't reach the end of the name -> bad character included
400 std::clog
<< "Bad file: " << Ent
->d_name
<< " → bad character »"
401 << *C
<< "« in filename (period allowed: " << (Ext
.empty() ? "no" : "yes") << ")" << std::endl
;
405 // skip filenames which end with a period. These are never valid
409 std::clog
<< "Bad file: " << Ent
->d_name
<< " → Period as last character" << std::endl
;
414 std::clog
<< "Accept file: " << Ent
->d_name
<< " in " << Dir
<< std::endl
;
415 List
.push_back(File
);
419 if (SortList
== true)
420 std::sort(List
.begin(),List
.end());
424 // SafeGetCWD - This is a safer getcwd that returns a dynamic string /*{{{*/
425 // ---------------------------------------------------------------------
426 /* We return / on failure. */
429 // Stash the current dir.
432 if (getcwd(S
,sizeof(S
)-2) == 0)
434 unsigned int Len
= strlen(S
);
440 // flNotDir - Strip the directory from the filename /*{{{*/
441 // ---------------------------------------------------------------------
443 string
flNotDir(string File
)
445 string::size_type Res
= File
.rfind('/');
446 if (Res
== string::npos
)
449 return string(File
,Res
,Res
- File
.length());
452 // flNotFile - Strip the file from the directory name /*{{{*/
453 // ---------------------------------------------------------------------
454 /* Result ends in a / */
455 string
flNotFile(string File
)
457 string::size_type Res
= File
.rfind('/');
458 if (Res
== string::npos
)
461 return string(File
,0,Res
);
464 // flExtension - Return the extension for the file /*{{{*/
465 // ---------------------------------------------------------------------
467 string
flExtension(string File
)
469 string::size_type Res
= File
.rfind('.');
470 if (Res
== string::npos
)
473 return string(File
,Res
,Res
- File
.length());
476 // flNoLink - If file is a symlink then deref it /*{{{*/
477 // ---------------------------------------------------------------------
478 /* If the name is not a link then the returned path is the input. */
479 string
flNoLink(string File
)
482 if (lstat(File
.c_str(),&St
) != 0 || S_ISLNK(St
.st_mode
) == 0)
484 if (stat(File
.c_str(),&St
) != 0)
487 /* Loop resolving the link. There is no need to limit the number of
488 loops because the stat call above ensures that the symlink is not
496 if ((Res
= readlink(NFile
.c_str(),Buffer
,sizeof(Buffer
))) <= 0 ||
497 (unsigned)Res
>= sizeof(Buffer
))
500 // Append or replace the previous path
502 if (Buffer
[0] == '/')
505 NFile
= flNotFile(NFile
) + Buffer
;
507 // See if we are done
508 if (lstat(NFile
.c_str(),&St
) != 0)
510 if (S_ISLNK(St
.st_mode
) == 0)
515 // flCombine - Combine a file and a directory /*{{{*/
516 // ---------------------------------------------------------------------
517 /* If the file is an absolute path then it is just returned, otherwise
518 the directory is pre-pended to it. */
519 string
flCombine(string Dir
,string File
)
521 if (File
.empty() == true)
524 if (File
[0] == '/' || Dir
.empty() == true)
526 if (File
.length() >= 2 && File
[0] == '.' && File
[1] == '/')
528 if (Dir
[Dir
.length()-1] == '/')
530 return Dir
+ '/' + File
;
533 // SetCloseExec - Set the close on exec flag /*{{{*/
534 // ---------------------------------------------------------------------
536 void SetCloseExec(int Fd
,bool Close
)
538 if (fcntl(Fd
,F_SETFD
,(Close
== false)?0:FD_CLOEXEC
) != 0)
540 cerr
<< "FATAL -> Could not set close on exec " << strerror(errno
) << endl
;
545 // SetNonBlock - Set the nonblocking flag /*{{{*/
546 // ---------------------------------------------------------------------
548 void SetNonBlock(int Fd
,bool Block
)
550 int Flags
= fcntl(Fd
,F_GETFL
) & (~O_NONBLOCK
);
551 if (fcntl(Fd
,F_SETFL
,Flags
| ((Block
== false)?0:O_NONBLOCK
)) != 0)
553 cerr
<< "FATAL -> Could not set non-blocking flag " << strerror(errno
) << endl
;
558 // WaitFd - Wait for a FD to become readable /*{{{*/
559 // ---------------------------------------------------------------------
560 /* This waits for a FD to become readable using select. It is useful for
561 applications making use of non-blocking sockets. The timeout is
563 bool WaitFd(int Fd
,bool write
,unsigned long timeout
)
576 Res
= select(Fd
+1,0,&Set
,0,(timeout
!= 0?&tv
:0));
578 while (Res
< 0 && errno
== EINTR
);
588 Res
= select(Fd
+1,&Set
,0,0,(timeout
!= 0?&tv
:0));
590 while (Res
< 0 && errno
== EINTR
);
599 // ExecFork - Magical fork that sanitizes the context before execing /*{{{*/
600 // ---------------------------------------------------------------------
601 /* This is used if you want to cleanse the environment for the forked
602 child, it fixes up the important signals and nukes all of the fds,
603 otherwise acts like normal fork. */
606 // Fork off the process
607 pid_t Process
= fork();
610 cerr
<< "FATAL -> Failed to fork." << endl
;
614 // Spawn the subprocess
618 signal(SIGPIPE
,SIG_DFL
);
619 signal(SIGQUIT
,SIG_DFL
);
620 signal(SIGINT
,SIG_DFL
);
621 signal(SIGWINCH
,SIG_DFL
);
622 signal(SIGCONT
,SIG_DFL
);
623 signal(SIGTSTP
,SIG_DFL
);
626 Configuration::Item
const *Opts
= _config
->Tree("APT::Keep-Fds");
627 if (Opts
!= 0 && Opts
->Child
!= 0)
630 for (; Opts
!= 0; Opts
= Opts
->Next
)
632 if (Opts
->Value
.empty() == true)
634 int fd
= atoi(Opts
->Value
.c_str());
639 // Close all of our FDs - just in case
640 for (int K
= 3; K
!= 40; K
++)
642 if(KeepFDs
.find(K
) == KeepFDs
.end())
643 fcntl(K
,F_SETFD
,FD_CLOEXEC
);
650 // ExecWait - Fancy waitpid /*{{{*/
651 // ---------------------------------------------------------------------
652 /* Waits for the given sub process. If Reap is set then no errors are
653 generated. Otherwise a failed subprocess will generate a proper descriptive
655 bool ExecWait(pid_t Pid
,const char *Name
,bool Reap
)
660 // Wait and collect the error code
662 while (waitpid(Pid
,&Status
,0) != Pid
)
670 return _error
->Error(_("Waited for %s but it wasn't there"),Name
);
674 // Check for an error code.
675 if (WIFEXITED(Status
) == 0 || WEXITSTATUS(Status
) != 0)
679 if (WIFSIGNALED(Status
) != 0)
681 if( WTERMSIG(Status
) == SIGSEGV
)
682 return _error
->Error(_("Sub-process %s received a segmentation fault."),Name
);
684 return _error
->Error(_("Sub-process %s received signal %u."),Name
, WTERMSIG(Status
));
687 if (WIFEXITED(Status
) != 0)
688 return _error
->Error(_("Sub-process %s returned an error code (%u)"),Name
,WEXITSTATUS(Status
));
690 return _error
->Error(_("Sub-process %s exited unexpectedly"),Name
);
697 // FileFd::Open - Open a file /*{{{*/
698 // ---------------------------------------------------------------------
699 /* The most commonly used open mode combinations are given with Mode */
700 bool FileFd::Open(string FileName
,OpenMode Mode
, unsigned long Perms
)
707 iFd
= open(FileName
.c_str(),O_RDONLY
);
711 iFd
= open(FileName
.c_str(),O_RDONLY
);
713 gz
= gzdopen (iFd
, "r");
724 char *name
= strdup((FileName
+ ".XXXXXX").c_str());
725 TemporaryFileName
= string(mktemp(name
));
726 iFd
= open(TemporaryFileName
.c_str(),O_RDWR
| O_CREAT
| O_EXCL
,Perms
);
734 if (lstat(FileName
.c_str(),&Buf
) == 0 && S_ISLNK(Buf
.st_mode
))
735 unlink(FileName
.c_str());
736 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,Perms
);
741 iFd
= open(FileName
.c_str(),O_RDWR
);
745 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
,Perms
);
749 unlink(FileName
.c_str());
750 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_EXCL
,Perms
);
755 return _error
->Errno("open",_("Could not open file %s"),FileName
.c_str());
757 this->FileName
= FileName
;
758 SetCloseExec(iFd
,true);
762 bool FileFd::OpenDescriptor(int Fd
, OpenMode Mode
, bool AutoClose
)
765 Flags
= (AutoClose
) ? FileFd::AutoClose
: 0;
767 if (Mode
== ReadOnlyGzip
) {
768 gz
= gzdopen (iFd
, "r");
772 return _error
->Errno("gzdopen",_("Could not open file descriptor %d"),
780 // FileFd::~File - Closes the file /*{{{*/
781 // ---------------------------------------------------------------------
782 /* If the proper modes are selected then we close the Fd and possibly
783 unlink the file on error. */
789 // FileFd::Read - Read a bit of the file /*{{{*/
790 // ---------------------------------------------------------------------
791 /* We are carefull to handle interruption by a signal while reading
793 bool FileFd::Read(void *To
,unsigned long Size
,unsigned long *Actual
)
803 Res
= gzread(gz
,To
,Size
);
805 Res
= read(iFd
,To
,Size
);
806 if (Res
< 0 && errno
== EINTR
)
811 return _error
->Errno("read",_("Read error"));
814 To
= (char *)To
+ Res
;
819 while (Res
> 0 && Size
> 0);
832 return _error
->Error(_("read, still have %lu to read but none left"),Size
);
835 // FileFd::Write - Write to the file /*{{{*/
836 // ---------------------------------------------------------------------
838 bool FileFd::Write(const void *From
,unsigned long Size
)
845 Res
= gzwrite(gz
,From
,Size
);
847 Res
= write(iFd
,From
,Size
);
848 if (Res
< 0 && errno
== EINTR
)
853 return _error
->Errno("write",_("Write error"));
856 From
= (char *)From
+ Res
;
859 while (Res
> 0 && Size
> 0);
865 return _error
->Error(_("write, still have %lu to write but couldn't"),Size
);
868 // FileFd::Seek - Seek in the file /*{{{*/
869 // ---------------------------------------------------------------------
871 bool FileFd::Seek(unsigned long To
)
875 res
= gzseek(gz
,To
,SEEK_SET
);
877 res
= lseek(iFd
,To
,SEEK_SET
);
878 if (res
!= (signed)To
)
881 return _error
->Error("Unable to seek to %lu",To
);
887 // FileFd::Skip - Seek in the file /*{{{*/
888 // ---------------------------------------------------------------------
890 bool FileFd::Skip(unsigned long Over
)
894 res
= gzseek(gz
,Over
,SEEK_CUR
);
896 res
= lseek(iFd
,Over
,SEEK_CUR
);
900 return _error
->Error("Unable to seek ahead %lu",Over
);
906 // FileFd::Truncate - Truncate the file /*{{{*/
907 // ---------------------------------------------------------------------
909 bool FileFd::Truncate(unsigned long To
)
914 return _error
->Error("Truncating gzipped files is not implemented (%s)", FileName
.c_str());
916 if (ftruncate(iFd
,To
) != 0)
919 return _error
->Error("Unable to truncate to %lu",To
);
925 // FileFd::Tell - Current seek position /*{{{*/
926 // ---------------------------------------------------------------------
928 unsigned long FileFd::Tell()
934 Res
= lseek(iFd
,0,SEEK_CUR
);
935 if (Res
== (off_t
)-1)
936 _error
->Errno("lseek","Failed to determine the current file position");
940 // FileFd::FileSize - Return the size of the file /*{{{*/
941 // ---------------------------------------------------------------------
943 unsigned long FileFd::FileSize()
947 if (fstat(iFd
,&Buf
) != 0)
948 return _error
->Errno("fstat","Unable to determine the file size");
952 // FileFd::Size - Return the size of the content in the file /*{{{*/
953 // ---------------------------------------------------------------------
955 unsigned long FileFd::Size()
957 unsigned long size
= FileSize();
959 // only check gzsize if we are actually a gzip file, just checking for
960 // "gz" is not sufficient as uncompressed files will be opened with
961 // gzopen in "direct" mode as well
962 if (gz
&& !gzdirect(gz
) && size
> 0)
964 /* unfortunately zlib.h doesn't provide a gzsize(), so we have to do
965 * this ourselves; the original (uncompressed) file size is the last 32
966 * bits of the file */
967 off_t orig_pos
= lseek(iFd
, 0, SEEK_CUR
);
968 if (lseek(iFd
, -4, SEEK_END
) < 0)
969 return _error
->Errno("lseek","Unable to seek to end of gzipped file");
971 if (read(iFd
, &size
, 4) != 4)
972 return _error
->Errno("read","Unable to read original size of gzipped file");
974 #ifdef WORDS_BIGENDIAN
975 uint32_t tmp_size
= size
;
976 uint8_t const * const p
= (uint8_t const * const) &tmp_size
;
977 tmp_size
= (p
[3] << 24) | (p
[2] << 16) | (p
[1] << 8) | p
[0];
981 if (lseek(iFd
, orig_pos
, SEEK_SET
) < 0)
982 return _error
->Errno("lseek","Unable to seek in gzipped file");
989 // FileFd::Close - Close the file if the close flag is set /*{{{*/
990 // ---------------------------------------------------------------------
995 if ((Flags
& AutoClose
) == AutoClose
)
998 int const e
= gzclose(gz
);
999 // gzdopen() on empty files always fails with "buffer error" here, ignore that
1000 if (e
!= 0 && e
!= Z_BUF_ERROR
)
1001 Res
&= _error
->Errno("close",_("Problem closing the gzip file %s"), FileName
.c_str());
1003 if (iFd
> 0 && close(iFd
) != 0)
1004 Res
&= _error
->Errno("close",_("Problem closing the file %s"), FileName
.c_str());
1007 if ((Flags
& Replace
) == Replace
&& iFd
>= 0) {
1008 if (rename(TemporaryFileName
.c_str(), FileName
.c_str()) != 0)
1009 Res
&= _error
->Errno("rename",_("Problem renaming the file %s to %s"), TemporaryFileName
.c_str(), FileName
.c_str());
1011 FileName
= TemporaryFileName
; // for the unlink() below.
1017 if ((Flags
& Fail
) == Fail
&& (Flags
& DelOnFail
) == DelOnFail
&&
1018 FileName
.empty() == false)
1019 if (unlink(FileName
.c_str()) != 0)
1020 Res
&= _error
->WarningE("unlnk",_("Problem unlinking the file %s"), FileName
.c_str());
1026 // FileFd::Sync - Sync the file /*{{{*/
1027 // ---------------------------------------------------------------------
1031 #ifdef _POSIX_SYNCHRONIZED_IO
1032 if (fsync(iFd
) != 0)
1033 return _error
->Errno("sync",_("Problem syncing the file"));