]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/fileutl.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: fileutl.cc,v 1.19 1999/02/08 07:30:50 jgg Exp $
4 /* ######################################################################
8 CopyFile - Buffered copy of a single file
9 GetLock - dpkg compatible lock file manipulation (fcntl)
11 This source is placed in the Public Domain, do with it what you will
12 It was originally written by Jason Gunthorpe.
14 ##################################################################### */
16 // Include Files /*{{{*/
18 #pragma implementation "apt-pkg/fileutl.h"
20 #include <apt-pkg/fileutl.h>
21 #include <apt-pkg/error.h>
25 #include <sys/fcntl.h>
26 #include <sys/types.h>
30 // CopyFile - Buffered copy of a file /*{{{*/
31 // ---------------------------------------------------------------------
32 /* The caller is expected to set things so that failure causes erasure */
33 bool CopyFile(FileFd
&From
,FileFd
&To
)
35 if (From
.IsOpen() == false || To
.IsOpen() == false)
38 // Buffered copy between fds
39 unsigned char *Buf
= new unsigned char[64000];
41 while ((Size
= read(From
.Fd(),Buf
,64000)) > 0)
43 if (To
.Write(Buf
,Size
) == false)
54 // GetLock - Gets a lock file /*{{{*/
55 // ---------------------------------------------------------------------
56 /* This will create an empty file of the given name and lock it. Once this
57 is done all other calls to GetLock in any other process will fail with
58 -1. The return result is the fd of the file, the call should call
59 close at some time. */
60 int GetLock(string File
,bool Errors
)
62 int FD
= open(File
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,0640);
66 _error
->Errno("open","Could not open lock file %s",File
.c_str());
70 // Aquire a write lock
73 fl
.l_whence
= SEEK_SET
;
76 if (fcntl(FD
,F_SETLK
,&fl
) == -1)
79 _error
->Errno("open","Could not get lock %s",File
.c_str());
87 // FileExists - Check if a file exists /*{{{*/
88 // ---------------------------------------------------------------------
90 bool FileExists(string File
)
93 if (stat(File
.c_str(),&Buf
) != 0)
98 // SafeGetCWD - This is a safer getcwd that returns a dynamic string /*{{{*/
99 // ---------------------------------------------------------------------
100 /* We return / on failure. */
103 // Stash the current dir.
106 if (getcwd(S
,sizeof(S
)-2) == 0)
108 unsigned int Len
= strlen(S
);
114 // flNotDir - Strip the directory from the filename /*{{{*/
115 // ---------------------------------------------------------------------
117 string
flNotDir(string File
)
119 string::size_type Res
= File
.rfind('/');
120 if (Res
== string::npos
)
123 return string(File
,Res
,Res
- File
.length());
126 // flNotFile - Strip the file from the directory name /*{{{*/
127 // ---------------------------------------------------------------------
129 string
flNotFile(string File
)
131 string::size_type Res
= File
.rfind('/');
132 if (Res
== string::npos
)
135 return string(File
,0,Res
);
138 // SetCloseExec - Set the close on exec flag /*{{{*/
139 // ---------------------------------------------------------------------
141 void SetCloseExec(int Fd
,bool Close
)
143 if (fcntl(Fd
,F_SETFD
,(Close
== false)?0:FD_CLOEXEC
) != 0)
145 cerr
<< "FATAL -> Could not set close on exec " << strerror(errno
) << endl
;
150 // SetNonBlock - Set the nonblocking flag /*{{{*/
151 // ---------------------------------------------------------------------
153 void SetNonBlock(int Fd
,bool Block
)
155 int Flags
= fcntl(Fd
,F_GETFL
) & (~O_NONBLOCK
);
156 if (fcntl(Fd
,F_SETFL
,Flags
| ((Block
== false)?0:O_NONBLOCK
)) != 0)
158 cerr
<< "FATAL -> Could not set non-blocking flag " << strerror(errno
) << endl
;
163 // WaitFd - Wait for a FD to become readable /*{{{*/
164 // ---------------------------------------------------------------------
165 /* This waits for a FD to become readable using select. It is usefull for
166 applications making use of non-blocking sockets. */
173 if (select(Fd
+1,&Set
,0,0,0) <= 0)
180 // FileFd::FileFd - Open a file /*{{{*/
181 // ---------------------------------------------------------------------
182 /* The most commonly used open mode combinations are given with Mode */
183 FileFd::FileFd(string FileName
,OpenMode Mode
, unsigned long Perms
)
189 iFd
= open(FileName
.c_str(),O_RDONLY
);
195 if (stat(FileName
.c_str(),&Buf
) == 0 && S_ISLNK(Buf
.st_mode
))
196 unlink(FileName
.c_str());
197 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,Perms
);
202 iFd
= open(FileName
.c_str(),O_RDWR
);
206 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
,Perms
);
211 _error
->Errno("open","Could not open file %s",FileName
.c_str());
214 this->FileName
= FileName
;
215 SetCloseExec(iFd
,true);
219 // FileFd::~File - Closes the file /*{{{*/
220 // ---------------------------------------------------------------------
221 /* If the proper modes are selected then we close the Fd and possibly
222 unlink the file on error. */
228 // FileFd::Read - Read a bit of the file /*{{{*/
229 // ---------------------------------------------------------------------
231 bool FileFd::Read(void *To
,unsigned long Size
)
233 if (read(iFd
,To
,Size
) != (signed)Size
)
236 return _error
->Errno("read","Read error");
242 // FileFd::Write - Write to the file /*{{{*/
243 // ---------------------------------------------------------------------
245 bool FileFd::Write(const void *From
,unsigned long Size
)
247 if (write(iFd
,From
,Size
) != (signed)Size
)
250 return _error
->Errno("write","Write error");
256 // FileFd::Seek - Seek in the file /*{{{*/
257 // ---------------------------------------------------------------------
259 bool FileFd::Seek(unsigned long To
)
261 if (lseek(iFd
,To
,SEEK_SET
) != (signed)To
)
264 return _error
->Error("Unable to seek to %u",To
);
270 // FileFd::Tell - Current seek position /*{{{*/
271 // ---------------------------------------------------------------------
273 unsigned long FileFd::Tell()
275 off_t Res
= lseek(iFd
,0,SEEK_CUR
);
276 if (Res
== (off_t
)-1)
277 _error
->Errno("lseek","Failed to determine the current file position");
281 // FileFd::Size - Return the size of the file /*{{{*/
282 // ---------------------------------------------------------------------
284 unsigned long FileFd::Size()
287 if (fstat(iFd
,&Buf
) != 0)
288 return _error
->Errno("fstat","Unable to determine the file size");
292 // FileFd::Close - Close the file if the close flag is set /*{{{*/
293 // ---------------------------------------------------------------------
298 if ((Flags
& AutoClose
) == AutoClose
)
299 if (iFd
>= 0 && close(iFd
) != 0)
300 Res
&= _error
->Errno("close","Problem closing the file");
303 if ((Flags
& Fail
) == Fail
&& (Flags
& DelOnFail
) == DelOnFail
&&
304 FileName
.empty() == false)
305 if (unlink(FileName
.c_str()) != 0)
306 Res
&= _error
->Warning("unlnk","Problem unlinking the file");