]> git.saurik.com Git - apt.git/blob - apt-pkg/contrib/fileutl.cc
Fixed glibc2.1 compile
[apt.git] / apt-pkg / contrib / fileutl.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: fileutl.cc,v 1.19 1999/02/08 07:30:50 jgg Exp $
4 /* ######################################################################
5
6 File Utilities
7
8 CopyFile - Buffered copy of a single file
9 GetLock - dpkg compatible lock file manipulation (fcntl)
10
11 This source is placed in the Public Domain, do with it what you will
12 It was originally written by Jason Gunthorpe.
13
14 ##################################################################### */
15 /*}}}*/
16 // Include Files /*{{{*/
17 #ifdef __GNUG__
18 #pragma implementation "apt-pkg/fileutl.h"
19 #endif
20 #include <apt-pkg/fileutl.h>
21 #include <apt-pkg/error.h>
22
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <sys/fcntl.h>
26 #include <sys/types.h>
27 #include <errno.h>
28 /*}}}*/
29
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)
34 {
35 if (From.IsOpen() == false || To.IsOpen() == false)
36 return false;
37
38 // Buffered copy between fds
39 unsigned char *Buf = new unsigned char[64000];
40 long Size;
41 while ((Size = read(From.Fd(),Buf,64000)) > 0)
42 {
43 if (To.Write(Buf,Size) == false)
44 {
45 delete [] Buf;
46 return false;
47 }
48 }
49
50 delete [] Buf;
51 return true;
52 }
53 /*}}}*/
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)
61 {
62 int FD = open(File.c_str(),O_RDWR | O_CREAT | O_TRUNC,0640);
63 if (FD < 0)
64 {
65 if (Errors == true)
66 _error->Errno("open","Could not open lock file %s",File.c_str());
67 return -1;
68 }
69
70 // Aquire a write lock
71 struct flock fl;
72 fl.l_type = F_WRLCK;
73 fl.l_whence = SEEK_SET;
74 fl.l_start = 0;
75 fl.l_len = 0;
76 if (fcntl(FD,F_SETLK,&fl) == -1)
77 {
78 if (Errors == true)
79 _error->Errno("open","Could not get lock %s",File.c_str());
80 close(FD);
81 return -1;
82 }
83
84 return FD;
85 }
86 /*}}}*/
87 // FileExists - Check if a file exists /*{{{*/
88 // ---------------------------------------------------------------------
89 /* */
90 bool FileExists(string File)
91 {
92 struct stat Buf;
93 if (stat(File.c_str(),&Buf) != 0)
94 return false;
95 return true;
96 }
97 /*}}}*/
98 // SafeGetCWD - This is a safer getcwd that returns a dynamic string /*{{{*/
99 // ---------------------------------------------------------------------
100 /* We return / on failure. */
101 string SafeGetCWD()
102 {
103 // Stash the current dir.
104 char S[300];
105 S[0] = 0;
106 if (getcwd(S,sizeof(S)-2) == 0)
107 return "/";
108 unsigned int Len = strlen(S);
109 S[Len] = '/';
110 S[Len+1] = 0;
111 return S;
112 }
113 /*}}}*/
114 // flNotDir - Strip the directory from the filename /*{{{*/
115 // ---------------------------------------------------------------------
116 /* */
117 string flNotDir(string File)
118 {
119 string::size_type Res = File.rfind('/');
120 if (Res == string::npos)
121 return File;
122 Res++;
123 return string(File,Res,Res - File.length());
124 }
125 /*}}}*/
126 // flNotFile - Strip the file from the directory name /*{{{*/
127 // ---------------------------------------------------------------------
128 /* */
129 string flNotFile(string File)
130 {
131 string::size_type Res = File.rfind('/');
132 if (Res == string::npos)
133 return File;
134 Res++;
135 return string(File,0,Res);
136 }
137 /*}}}*/
138 // SetCloseExec - Set the close on exec flag /*{{{*/
139 // ---------------------------------------------------------------------
140 /* */
141 void SetCloseExec(int Fd,bool Close)
142 {
143 if (fcntl(Fd,F_SETFD,(Close == false)?0:FD_CLOEXEC) != 0)
144 {
145 cerr << "FATAL -> Could not set close on exec " << strerror(errno) << endl;
146 exit(100);
147 }
148 }
149 /*}}}*/
150 // SetNonBlock - Set the nonblocking flag /*{{{*/
151 // ---------------------------------------------------------------------
152 /* */
153 void SetNonBlock(int Fd,bool Block)
154 {
155 int Flags = fcntl(Fd,F_GETFL) & (~O_NONBLOCK);
156 if (fcntl(Fd,F_SETFL,Flags | ((Block == false)?0:O_NONBLOCK)) != 0)
157 {
158 cerr << "FATAL -> Could not set non-blocking flag " << strerror(errno) << endl;
159 exit(100);
160 }
161 }
162 /*}}}*/
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. */
167 bool WaitFd(int Fd)
168 {
169 fd_set Set;
170 FD_ZERO(&Set);
171 FD_SET(Fd,&Set);
172
173 if (select(Fd+1,&Set,0,0,0) <= 0)
174 return false;
175
176 return true;
177 }
178 /*}}}*/
179
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)
184 {
185 Flags = AutoClose;
186 switch (Mode)
187 {
188 case ReadOnly:
189 iFd = open(FileName.c_str(),O_RDONLY);
190 break;
191
192 case WriteEmpty:
193 {
194 struct stat Buf;
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);
198 break;
199 }
200
201 case WriteExists:
202 iFd = open(FileName.c_str(),O_RDWR);
203 break;
204
205 case WriteAny:
206 iFd = open(FileName.c_str(),O_RDWR | O_CREAT,Perms);
207 break;
208 }
209
210 if (iFd < 0)
211 _error->Errno("open","Could not open file %s",FileName.c_str());
212 else
213 {
214 this->FileName = FileName;
215 SetCloseExec(iFd,true);
216 }
217 }
218 /*}}}*/
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. */
223 FileFd::~FileFd()
224 {
225 Close();
226 }
227 /*}}}*/
228 // FileFd::Read - Read a bit of the file /*{{{*/
229 // ---------------------------------------------------------------------
230 /* */
231 bool FileFd::Read(void *To,unsigned long Size)
232 {
233 if (read(iFd,To,Size) != (signed)Size)
234 {
235 Flags |= Fail;
236 return _error->Errno("read","Read error");
237 }
238
239 return true;
240 }
241 /*}}}*/
242 // FileFd::Write - Write to the file /*{{{*/
243 // ---------------------------------------------------------------------
244 /* */
245 bool FileFd::Write(const void *From,unsigned long Size)
246 {
247 if (write(iFd,From,Size) != (signed)Size)
248 {
249 Flags |= Fail;
250 return _error->Errno("write","Write error");
251 }
252
253 return true;
254 }
255 /*}}}*/
256 // FileFd::Seek - Seek in the file /*{{{*/
257 // ---------------------------------------------------------------------
258 /* */
259 bool FileFd::Seek(unsigned long To)
260 {
261 if (lseek(iFd,To,SEEK_SET) != (signed)To)
262 {
263 Flags |= Fail;
264 return _error->Error("Unable to seek to %u",To);
265 }
266
267 return true;
268 }
269 /*}}}*/
270 // FileFd::Tell - Current seek position /*{{{*/
271 // ---------------------------------------------------------------------
272 /* */
273 unsigned long FileFd::Tell()
274 {
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");
278 return Res;
279 }
280 /*}}}*/
281 // FileFd::Size - Return the size of the file /*{{{*/
282 // ---------------------------------------------------------------------
283 /* */
284 unsigned long FileFd::Size()
285 {
286 struct stat Buf;
287 if (fstat(iFd,&Buf) != 0)
288 return _error->Errno("fstat","Unable to determine the file size");
289 return Buf.st_size;
290 }
291 /*}}}*/
292 // FileFd::Close - Close the file if the close flag is set /*{{{*/
293 // ---------------------------------------------------------------------
294 /* */
295 bool FileFd::Close()
296 {
297 bool Res = true;
298 if ((Flags & AutoClose) == AutoClose)
299 if (iFd >= 0 && close(iFd) != 0)
300 Res &= _error->Errno("close","Problem closing the file");
301 iFd = -1;
302
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");
307 return Res;
308 }
309 /*}}}*/