]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/fileutl.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: fileutl.cc,v 1.17 1999/01/18 06:20:08 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>
29 // CopyFile - Buffered copy of a file /*{{{*/
30 // ---------------------------------------------------------------------
31 /* The caller is expected to set things so that failure causes erasure */
32 bool CopyFile(FileFd
&From
,FileFd
&To
)
34 if (From
.IsOpen() == false || To
.IsOpen() == false)
37 // Buffered copy between fds
38 unsigned char *Buf
= new unsigned char[64000];
40 while ((Size
= read(From
.Fd(),Buf
,64000)) > 0)
42 if (To
.Write(Buf
,Size
) == false)
53 // GetLock - Gets a lock file /*{{{*/
54 // ---------------------------------------------------------------------
55 /* This will create an empty file of the given name and lock it. Once this
56 is done all other calls to GetLock in any other process will fail with
57 -1. The return result is the fd of the file, the call should call
58 close at some time. */
59 int GetLock(string File
,bool Errors
)
61 int FD
= open(File
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,0640);
65 _error
->Errno("open","Could not open lock file %s",File
.c_str());
69 // Aquire a write lock
72 fl
.l_whence
= SEEK_SET
;
75 if (fcntl(FD
,F_SETLK
,&fl
) == -1)
78 _error
->Errno("open","Could not get lock %s",File
.c_str());
86 // FileExists - Check if a file exists /*{{{*/
87 // ---------------------------------------------------------------------
89 bool FileExists(string File
)
92 if (stat(File
.c_str(),&Buf
) != 0)
97 // SafeGetCWD - This is a safer getcwd that returns a dynamic string /*{{{*/
98 // ---------------------------------------------------------------------
99 /* We return / on failure. */
102 // Stash the current dir.
105 if (getcwd(S
,sizeof(S
)-2) == 0)
107 unsigned int Len
= strlen(S
);
113 // flNotDir - Strip the directory from the filename /*{{{*/
114 // ---------------------------------------------------------------------
116 string
flNotDir(string File
)
118 string::size_type Res
= File
.rfind('/');
119 if (Res
== string::npos
)
122 return string(File
,Res
,Res
- File
.length());
125 // flNotFile - Strip the file from the directory name /*{{{*/
126 // ---------------------------------------------------------------------
128 string
flNotFile(string File
)
130 string::size_type Res
= File
.rfind('/');
131 if (Res
== string::npos
)
134 return string(File
,0,Res
);
137 // SetCloseExec - Set the close on exec flag /*{{{*/
138 // ---------------------------------------------------------------------
140 void SetCloseExec(int Fd
,bool Close
)
142 if (fcntl(Fd
,F_SETFD
,(Close
== false)?0:FD_CLOEXEC
) != 0)
144 cerr
<< "FATAL -> Could not set close on exec " << strerror(errno
) << endl
;
149 // SetNonBlock - Set the nonblocking flag /*{{{*/
150 // ---------------------------------------------------------------------
152 void SetNonBlock(int Fd
,bool Block
)
154 int Flags
= fcntl(Fd
,F_GETFL
) & (~O_NONBLOCK
);
155 if (fcntl(Fd
,F_SETFL
,Flags
| ((Block
== false)?0:O_NONBLOCK
)) != 0)
157 cerr
<< "FATAL -> Could not set non-blocking flag " << strerror(errno
) << endl
;
162 // WaitFd - Wait for a FD to become readable /*{{{*/
163 // ---------------------------------------------------------------------
164 /* This waits for a FD to become readable using select. It is usefull for
165 applications making use of non-blocking sockets. */
172 if (select(Fd
+1,&Set
,0,0,0) <= 0)
179 // FileFd::FileFd - Open a file /*{{{*/
180 // ---------------------------------------------------------------------
181 /* The most commonly used open mode combinations are given with Mode */
182 FileFd::FileFd(string FileName
,OpenMode Mode
, unsigned long Perms
)
188 iFd
= open(FileName
.c_str(),O_RDONLY
);
194 if (stat(FileName
.c_str(),&Buf
) == 0 && S_ISLNK(Buf
.st_mode
))
195 unlink(FileName
.c_str());
196 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,Perms
);
201 iFd
= open(FileName
.c_str(),O_RDWR
);
205 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
,Perms
);
210 _error
->Errno("open","Could not open file %s",FileName
.c_str());
213 this->FileName
= FileName
;
214 SetCloseExec(iFd
,true);
218 // FileFd::~File - Closes the file /*{{{*/
219 // ---------------------------------------------------------------------
220 /* If the proper modes are selected then we close the Fd and possibly
221 unlink the file on error. */
227 // FileFd::Read - Read a bit of the file /*{{{*/
228 // ---------------------------------------------------------------------
230 bool FileFd::Read(void *To
,unsigned long Size
)
232 if (read(iFd
,To
,Size
) != (signed)Size
)
235 return _error
->Errno("read","Read error");
241 // FileFd::Write - Write to the file /*{{{*/
242 // ---------------------------------------------------------------------
244 bool FileFd::Write(const void *From
,unsigned long Size
)
246 if (write(iFd
,From
,Size
) != (signed)Size
)
249 return _error
->Errno("write","Write error");
255 // FileFd::Seek - Seek in the file /*{{{*/
256 // ---------------------------------------------------------------------
258 bool FileFd::Seek(unsigned long To
)
260 if (lseek(iFd
,To
,SEEK_SET
) != (signed)To
)
263 return _error
->Error("Unable to seek to %u",To
);
269 // FileFd::Tell - Current seek position /*{{{*/
270 // ---------------------------------------------------------------------
272 unsigned long FileFd::Tell()
274 off_t Res
= lseek(iFd
,0,SEEK_CUR
);
275 if (Res
== (off_t
)-1)
276 _error
->Errno("lseek","Failed to determine the current file position");
280 // FileFd::Size - Return the size of the file /*{{{*/
281 // ---------------------------------------------------------------------
283 unsigned long FileFd::Size()
286 if (fstat(iFd
,&Buf
) != 0)
287 return _error
->Errno("fstat","Unable to determine the file size");
291 // FileFd::Close - Close the file if the close flag is set /*{{{*/
292 // ---------------------------------------------------------------------
297 if ((Flags
& AutoClose
) == AutoClose
)
298 if (iFd
>= 0 && close(iFd
) != 0)
299 Res
&= _error
->Errno("close","Problem closing the file");
302 if ((Flags
& Fail
) == Fail
&& (Flags
& DelOnFail
) == DelOnFail
&&
303 FileName
.empty() == false)
304 if (unlink(FileName
.c_str()) != 0)
305 Res
&= _error
->Warning("unlnk","Problem unlinking the file");