]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/fileutl.cc
Small linker changes
[apt.git] / apt-pkg / contrib / fileutl.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
50b513a1 3// $Id: fileutl.cc,v 1.16 1998/11/27 04:20:52 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>
27 /*}}}*/
28
29// CopyFile - Buffered copy of a file /*{{{*/
30// ---------------------------------------------------------------------
31/* The caller is expected to set things so that failure causes erasure */
8b89e57f 32bool CopyFile(FileFd &From,FileFd &To)
578bfd0a
AL
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)) == 0)
106 return "/";
107 return S;
108}
109 /*}}}*/
8ce4327b
AL
110// flNotDir - Strip the directory from the filename /*{{{*/
111// ---------------------------------------------------------------------
112/* */
113string flNotDir(string File)
114{
115 string::size_type Res = File.rfind('/');
116 if (Res == string::npos)
117 return File;
118 Res++;
119 return string(File,Res,Res - File.length());
120}
121 /*}}}*/
d38b7b3d
AL
122// flNotFile - Strip the file from the directory name /*{{{*/
123// ---------------------------------------------------------------------
124/* */
125string flNotFile(string File)
126{
127 string::size_type Res = File.rfind('/');
128 if (Res == string::npos)
129 return File;
130 Res++;
131 return string(File,0,Res);
132}
133 /*}}}*/
3b5421b4
AL
134// SetCloseExec - Set the close on exec flag /*{{{*/
135// ---------------------------------------------------------------------
136/* */
137void SetCloseExec(int Fd,bool Close)
138{
139 if (fcntl(Fd,F_SETFD,(Close == false)?0:FD_CLOEXEC) != 0)
140 {
141 cerr << "FATAL -> Could not set close on exec " << strerror(errno) << endl;
142 exit(100);
143 }
144}
145 /*}}}*/
146// SetNonBlock - Set the nonblocking flag /*{{{*/
147// ---------------------------------------------------------------------
148/* */
149void SetNonBlock(int Fd,bool Block)
150{
0a8a80e5
AL
151 int Flags = fcntl(Fd,F_GETFL) & (~O_NONBLOCK);
152 if (fcntl(Fd,F_SETFL,Flags | ((Block == false)?0:O_NONBLOCK)) != 0)
3b5421b4
AL
153 {
154 cerr << "FATAL -> Could not set non-blocking flag " << strerror(errno) << endl;
155 exit(100);
156 }
157}
158 /*}}}*/
159// WaitFd - Wait for a FD to become readable /*{{{*/
160// ---------------------------------------------------------------------
161/* This waits for a FD to become readable using select. It is usefull for
162 applications making use of non-blocking sockets. */
163bool WaitFd(int Fd)
164{
165 fd_set Set;
166 FD_ZERO(&Set);
167 FD_SET(Fd,&Set);
0a8a80e5 168
3b5421b4
AL
169 if (select(Fd+1,&Set,0,0,0) <= 0)
170 return false;
0a8a80e5 171
3b5421b4
AL
172 return true;
173}
174 /*}}}*/
578bfd0a 175
8e06abb2 176// FileFd::FileFd - Open a file /*{{{*/
578bfd0a
AL
177// ---------------------------------------------------------------------
178/* The most commonly used open mode combinations are given with Mode */
8e06abb2 179FileFd::FileFd(string FileName,OpenMode Mode, unsigned long Perms)
578bfd0a 180{
1164783d 181 Flags = AutoClose;
578bfd0a
AL
182 switch (Mode)
183 {
184 case ReadOnly:
185 iFd = open(FileName.c_str(),O_RDONLY);
186 break;
187
188 case WriteEmpty:
50b513a1
AL
189 {
190 struct stat Buf;
191 if (stat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode))
192 unlink(FileName.c_str());
193 iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_TRUNC,Perms);
194 break;
195 }
578bfd0a
AL
196
197 case WriteExists:
198 iFd = open(FileName.c_str(),O_RDWR);
199 break;
0a8e3465
AL
200
201 case WriteAny:
202 iFd = open(FileName.c_str(),O_RDWR | O_CREAT,Perms);
d38b7b3d 203 break;
578bfd0a
AL
204 }
205
206 if (iFd < 0)
207 _error->Errno("open","Could not open file %s",FileName.c_str());
208 else
4b4fd143 209 {
578bfd0a 210 this->FileName = FileName;
4b4fd143
AL
211 SetCloseExec(iFd,true);
212 }
578bfd0a
AL
213}
214 /*}}}*/
8e06abb2 215// FileFd::~File - Closes the file /*{{{*/
578bfd0a
AL
216// ---------------------------------------------------------------------
217/* If the proper modes are selected then we close the Fd and possibly
218 unlink the file on error. */
8e06abb2 219FileFd::~FileFd()
578bfd0a
AL
220{
221 Close();
222}
223 /*}}}*/
8e06abb2 224// FileFd::Read - Read a bit of the file /*{{{*/
578bfd0a
AL
225// ---------------------------------------------------------------------
226/* */
8e06abb2 227bool FileFd::Read(void *To,unsigned long Size)
578bfd0a
AL
228{
229 if (read(iFd,To,Size) != (signed)Size)
230 {
231 Flags |= Fail;
232 return _error->Errno("read","Read error");
233 }
234
235 return true;
236}
237 /*}}}*/
8e06abb2 238// FileFd::Write - Write to the file /*{{{*/
578bfd0a
AL
239// ---------------------------------------------------------------------
240/* */
a05599f1 241bool FileFd::Write(const void *From,unsigned long Size)
578bfd0a
AL
242{
243 if (write(iFd,From,Size) != (signed)Size)
244 {
245 Flags |= Fail;
246 return _error->Errno("write","Write error");
247 }
248
249 return true;
250}
251 /*}}}*/
8e06abb2 252// FileFd::Seek - Seek in the file /*{{{*/
578bfd0a
AL
253// ---------------------------------------------------------------------
254/* */
8e06abb2 255bool FileFd::Seek(unsigned long To)
578bfd0a
AL
256{
257 if (lseek(iFd,To,SEEK_SET) != (signed)To)
258 {
259 Flags |= Fail;
260 return _error->Error("Unable to seek to %u",To);
261 }
262
263 return true;
264}
265 /*}}}*/
8e06abb2 266// FileFd::Size - Return the size of the file /*{{{*/
578bfd0a
AL
267// ---------------------------------------------------------------------
268/* */
8e06abb2 269unsigned long FileFd::Size()
578bfd0a
AL
270{
271 struct stat Buf;
272 if (fstat(iFd,&Buf) != 0)
273 return _error->Errno("fstat","Unable to determine the file size");
274 return Buf.st_size;
275}
276 /*}}}*/
8e06abb2 277// FileFd::Close - Close the file if the close flag is set /*{{{*/
578bfd0a
AL
278// ---------------------------------------------------------------------
279/* */
8e06abb2 280bool FileFd::Close()
578bfd0a
AL
281{
282 bool Res = true;
283 if ((Flags & AutoClose) == AutoClose)
1164783d 284 if (iFd >= 0 && close(iFd) != 0)
578bfd0a 285 Res &= _error->Errno("close","Problem closing the file");
1164783d
AL
286 iFd = -1;
287
578bfd0a
AL
288 if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail &&
289 FileName.empty() == false)
290 if (unlink(FileName.c_str()) != 0)
291 Res &= _error->Warning("unlnk","Problem unlinking the file");
292 return Res;
293}
294 /*}}}*/