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