]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/fileutl.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: fileutl.cc,v 1.9 1998/10/20 02:39:28 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
)) == 0)
110 // flNotDir - Strip the directory from the filename /*{{{*/
111 // ---------------------------------------------------------------------
113 string
flNotDir(string File
)
115 string::size_type Res
= File
.rfind('/');
116 if (Res
== string::npos
)
119 return string(File
,Res
,Res
- File
.length());
122 // SetCloseExec - Set the close on exec flag /*{{{*/
123 // ---------------------------------------------------------------------
125 void SetCloseExec(int Fd
,bool Close
)
127 if (fcntl(Fd
,F_SETFD
,(Close
== false)?0:FD_CLOEXEC
) != 0)
129 cerr
<< "FATAL -> Could not set close on exec " << strerror(errno
) << endl
;
134 // SetNonBlock - Set the nonblocking flag /*{{{*/
135 // ---------------------------------------------------------------------
137 void SetNonBlock(int Fd
,bool Block
)
139 int Flags
= fcntl(Fd
,F_GETFL
);
140 if (fcntl(Fd
,F_SETFL
,(Block
== false)?0:O_NONBLOCK
) != 0)
142 cerr
<< "FATAL -> Could not set non-blocking flag " << strerror(errno
) << endl
;
147 // WaitFd - Wait for a FD to become readable /*{{{*/
148 // ---------------------------------------------------------------------
149 /* This waits for a FD to become readable using select. It is usefull for
150 applications making use of non-blocking sockets. */
156 if (select(Fd
+1,&Set
,0,0,0) <= 0)
162 // FileFd::FileFd - Open a file /*{{{*/
163 // ---------------------------------------------------------------------
164 /* The most commonly used open mode combinations are given with Mode */
165 FileFd::FileFd(string FileName
,OpenMode Mode
, unsigned long Perms
)
171 iFd
= open(FileName
.c_str(),O_RDONLY
);
175 unlink(FileName
.c_str());
176 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_EXCL
,Perms
);
180 iFd
= open(FileName
.c_str(),O_RDWR
);
184 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
,Perms
);
187 // Dont use this in public directories
189 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,Perms
);
194 _error
->Errno("open","Could not open file %s",FileName
.c_str());
196 this->FileName
= FileName
;
197 SetCloseExec(iFd
,true);
200 // FileFd::~File - Closes the file /*{{{*/
201 // ---------------------------------------------------------------------
202 /* If the proper modes are selected then we close the Fd and possibly
203 unlink the file on error. */
209 // FileFd::Read - Read a bit of the file /*{{{*/
210 // ---------------------------------------------------------------------
212 bool FileFd::Read(void *To
,unsigned long Size
)
214 if (read(iFd
,To
,Size
) != (signed)Size
)
217 return _error
->Errno("read","Read error");
223 // FileFd::Write - Write to the file /*{{{*/
224 // ---------------------------------------------------------------------
226 bool FileFd::Write(void *From
,unsigned long Size
)
228 if (write(iFd
,From
,Size
) != (signed)Size
)
231 return _error
->Errno("write","Write error");
237 // FileFd::Seek - Seek in the file /*{{{*/
238 // ---------------------------------------------------------------------
240 bool FileFd::Seek(unsigned long To
)
242 if (lseek(iFd
,To
,SEEK_SET
) != (signed)To
)
245 return _error
->Error("Unable to seek to %u",To
);
251 // FileFd::Size - Return the size of the file /*{{{*/
252 // ---------------------------------------------------------------------
254 unsigned long FileFd::Size()
257 if (fstat(iFd
,&Buf
) != 0)
258 return _error
->Errno("fstat","Unable to determine the file size");
262 // FileFd::Close - Close the file if the close flag is set /*{{{*/
263 // ---------------------------------------------------------------------
268 if ((Flags
& AutoClose
) == AutoClose
)
269 if (iFd
>= 0 && close(iFd
) != 0)
270 Res
&= _error
->Errno("close","Problem closing the file");
273 if ((Flags
& Fail
) == Fail
&& (Flags
& DelOnFail
) == DelOnFail
&&
274 FileName
.empty() == false)
275 if (unlink(FileName
.c_str()) != 0)
276 Res
&= _error
->Warning("unlnk","Problem unlinking the file");