]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/fileutl.cc
Minor fixes
[apt.git] / apt-pkg / contrib / fileutl.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
65a1e968 3// $Id: fileutl.cc,v 1.19 1999/02/08 07:30:50 jgg Exp $
578bfd0a
AL
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 /*{{{*/
6c139d6e 17#ifdef __GNUG__
094a497d 18#pragma implementation "apt-pkg/fileutl.h"
6c139d6e 19#endif
094a497d
AL
20#include <apt-pkg/fileutl.h>
21#include <apt-pkg/error.h>
578bfd0a
AL
22
23#include <unistd.h>
24#include <sys/stat.h>
25#include <sys/fcntl.h>
26#include <sys/types.h>
65a1e968 27#include <errno.h>
578bfd0a
AL
28 /*}}}*/
29
30// CopyFile - Buffered copy of a file /*{{{*/
31// ---------------------------------------------------------------------
32/* The caller is expected to set things so that failure causes erasure */
8b89e57f 33bool CopyFile(FileFd &From,FileFd &To)
578bfd0a
AL
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. */
60int 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;
c71bc556
AL
72 fl.l_type = F_WRLCK;
73 fl.l_whence = SEEK_SET;
74 fl.l_start = 0;
75 fl.l_len = 0;
578bfd0a
AL
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/* */
90bool 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. */
101string SafeGetCWD()
102{
103 // Stash the current dir.
104 char S[300];
105 S[0] = 0;
7f25bdff 106 if (getcwd(S,sizeof(S)-2) == 0)
578bfd0a 107 return "/";
7f25bdff
AL
108 unsigned int Len = strlen(S);
109 S[Len] = '/';
110 S[Len+1] = 0;
578bfd0a
AL
111 return S;
112}
113 /*}}}*/
8ce4327b
AL
114// flNotDir - Strip the directory from the filename /*{{{*/
115// ---------------------------------------------------------------------
116/* */
117string 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 /*}}}*/
d38b7b3d
AL
126// flNotFile - Strip the file from the directory name /*{{{*/
127// ---------------------------------------------------------------------
128/* */
129string 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 /*}}}*/
3b5421b4
AL
138// SetCloseExec - Set the close on exec flag /*{{{*/
139// ---------------------------------------------------------------------
140/* */
141void 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/* */
153void SetNonBlock(int Fd,bool Block)
154{
0a8a80e5
AL
155 int Flags = fcntl(Fd,F_GETFL) & (~O_NONBLOCK);
156 if (fcntl(Fd,F_SETFL,Flags | ((Block == false)?0:O_NONBLOCK)) != 0)
3b5421b4
AL
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. */
167bool WaitFd(int Fd)
168{
169 fd_set Set;
170 FD_ZERO(&Set);
171 FD_SET(Fd,&Set);
0a8a80e5 172
3b5421b4
AL
173 if (select(Fd+1,&Set,0,0,0) <= 0)
174 return false;
0a8a80e5 175
3b5421b4
AL
176 return true;
177}
178 /*}}}*/
578bfd0a 179
8e06abb2 180// FileFd::FileFd - Open a file /*{{{*/
578bfd0a
AL
181// ---------------------------------------------------------------------
182/* The most commonly used open mode combinations are given with Mode */
8e06abb2 183FileFd::FileFd(string FileName,OpenMode Mode, unsigned long Perms)
578bfd0a 184{
1164783d 185 Flags = AutoClose;
578bfd0a
AL
186 switch (Mode)
187 {
188 case ReadOnly:
189 iFd = open(FileName.c_str(),O_RDONLY);
190 break;
191
192 case WriteEmpty:
50b513a1
AL
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 }
578bfd0a
AL
200
201 case WriteExists:
202 iFd = open(FileName.c_str(),O_RDWR);
203 break;
0a8e3465
AL
204
205 case WriteAny:
206 iFd = open(FileName.c_str(),O_RDWR | O_CREAT,Perms);
d38b7b3d 207 break;
578bfd0a
AL
208 }
209
210 if (iFd < 0)
211 _error->Errno("open","Could not open file %s",FileName.c_str());
212 else
4b4fd143 213 {
578bfd0a 214 this->FileName = FileName;
4b4fd143
AL
215 SetCloseExec(iFd,true);
216 }
578bfd0a
AL
217}
218 /*}}}*/
8e06abb2 219// FileFd::~File - Closes the file /*{{{*/
578bfd0a
AL
220// ---------------------------------------------------------------------
221/* If the proper modes are selected then we close the Fd and possibly
222 unlink the file on error. */
8e06abb2 223FileFd::~FileFd()
578bfd0a
AL
224{
225 Close();
226}
227 /*}}}*/
8e06abb2 228// FileFd::Read - Read a bit of the file /*{{{*/
578bfd0a
AL
229// ---------------------------------------------------------------------
230/* */
8e06abb2 231bool FileFd::Read(void *To,unsigned long Size)
578bfd0a
AL
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 /*}}}*/
8e06abb2 242// FileFd::Write - Write to the file /*{{{*/
578bfd0a
AL
243// ---------------------------------------------------------------------
244/* */
a05599f1 245bool FileFd::Write(const void *From,unsigned long Size)
578bfd0a
AL
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 /*}}}*/
8e06abb2 256// FileFd::Seek - Seek in the file /*{{{*/
578bfd0a
AL
257// ---------------------------------------------------------------------
258/* */
8e06abb2 259bool FileFd::Seek(unsigned long To)
578bfd0a
AL
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 /*}}}*/
7f25bdff
AL
270// FileFd::Tell - Current seek position /*{{{*/
271// ---------------------------------------------------------------------
272/* */
273unsigned 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 /*}}}*/
8e06abb2 281// FileFd::Size - Return the size of the file /*{{{*/
578bfd0a
AL
282// ---------------------------------------------------------------------
283/* */
8e06abb2 284unsigned long FileFd::Size()
578bfd0a
AL
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 /*}}}*/
8e06abb2 292// FileFd::Close - Close the file if the close flag is set /*{{{*/
578bfd0a
AL
293// ---------------------------------------------------------------------
294/* */
8e06abb2 295bool FileFd::Close()
578bfd0a
AL
296{
297 bool Res = true;
298 if ((Flags & AutoClose) == AutoClose)
1164783d 299 if (iFd >= 0 && close(iFd) != 0)
578bfd0a 300 Res &= _error->Errno("close","Problem closing the file");
1164783d
AL
301 iFd = -1;
302
578bfd0a
AL
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 /*}}}*/