Fixed up the docs a bit
[ntk/apt.git] / apt-pkg / contrib / fileutl.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
8b89e57f 3// $Id: fileutl.cc,v 1.13 1998/10/26 07:11:49 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 /*}}}*/
3b5421b4
AL
122// SetCloseExec - Set the close on exec flag /*{{{*/
123// ---------------------------------------------------------------------
124/* */
125void SetCloseExec(int Fd,bool Close)
126{
127 if (fcntl(Fd,F_SETFD,(Close == false)?0:FD_CLOEXEC) != 0)
128 {
129 cerr << "FATAL -> Could not set close on exec " << strerror(errno) << endl;
130 exit(100);
131 }
132}
133 /*}}}*/
134// SetNonBlock - Set the nonblocking flag /*{{{*/
135// ---------------------------------------------------------------------
136/* */
137void SetNonBlock(int Fd,bool Block)
138{
0a8a80e5
AL
139 int Flags = fcntl(Fd,F_GETFL) & (~O_NONBLOCK);
140 if (fcntl(Fd,F_SETFL,Flags | ((Block == false)?0:O_NONBLOCK)) != 0)
3b5421b4
AL
141 {
142 cerr << "FATAL -> Could not set non-blocking flag " << strerror(errno) << endl;
143 exit(100);
144 }
145}
146 /*}}}*/
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. */
151bool WaitFd(int Fd)
152{
153 fd_set Set;
154 FD_ZERO(&Set);
155 FD_SET(Fd,&Set);
0a8a80e5 156
3b5421b4
AL
157 if (select(Fd+1,&Set,0,0,0) <= 0)
158 return false;
0a8a80e5 159
3b5421b4
AL
160 return true;
161}
162 /*}}}*/
578bfd0a 163
8e06abb2 164// FileFd::FileFd - Open a file /*{{{*/
578bfd0a
AL
165// ---------------------------------------------------------------------
166/* The most commonly used open mode combinations are given with Mode */
8e06abb2 167FileFd::FileFd(string FileName,OpenMode Mode, unsigned long Perms)
578bfd0a 168{
1164783d 169 Flags = AutoClose;
578bfd0a
AL
170 switch (Mode)
171 {
172 case ReadOnly:
173 iFd = open(FileName.c_str(),O_RDONLY);
174 break;
175
176 case WriteEmpty:
177 unlink(FileName.c_str());
178 iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
179 break;
180
181 case WriteExists:
182 iFd = open(FileName.c_str(),O_RDWR);
183 break;
0a8e3465
AL
184
185 case WriteAny:
186 iFd = open(FileName.c_str(),O_RDWR | O_CREAT,Perms);
187 break;
8e06abb2
AL
188
189 // Dont use this in public directories
190 case LockEmpty:
191 iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_TRUNC,Perms);
192 break;
578bfd0a
AL
193 }
194
195 if (iFd < 0)
196 _error->Errno("open","Could not open file %s",FileName.c_str());
197 else
4b4fd143 198 {
578bfd0a 199 this->FileName = FileName;
4b4fd143
AL
200 SetCloseExec(iFd,true);
201 }
578bfd0a
AL
202}
203 /*}}}*/
8e06abb2 204// FileFd::~File - Closes the file /*{{{*/
578bfd0a
AL
205// ---------------------------------------------------------------------
206/* If the proper modes are selected then we close the Fd and possibly
207 unlink the file on error. */
8e06abb2 208FileFd::~FileFd()
578bfd0a
AL
209{
210 Close();
211}
212 /*}}}*/
8e06abb2 213// FileFd::Read - Read a bit of the file /*{{{*/
578bfd0a
AL
214// ---------------------------------------------------------------------
215/* */
8e06abb2 216bool FileFd::Read(void *To,unsigned long Size)
578bfd0a
AL
217{
218 if (read(iFd,To,Size) != (signed)Size)
219 {
220 Flags |= Fail;
221 return _error->Errno("read","Read error");
222 }
223
224 return true;
225}
226 /*}}}*/
8e06abb2 227// FileFd::Write - Write to the file /*{{{*/
578bfd0a
AL
228// ---------------------------------------------------------------------
229/* */
8e06abb2 230bool FileFd::Write(void *From,unsigned long Size)
578bfd0a
AL
231{
232 if (write(iFd,From,Size) != (signed)Size)
233 {
234 Flags |= Fail;
235 return _error->Errno("write","Write error");
236 }
237
238 return true;
239}
240 /*}}}*/
8e06abb2 241// FileFd::Seek - Seek in the file /*{{{*/
578bfd0a
AL
242// ---------------------------------------------------------------------
243/* */
8e06abb2 244bool FileFd::Seek(unsigned long To)
578bfd0a
AL
245{
246 if (lseek(iFd,To,SEEK_SET) != (signed)To)
247 {
248 Flags |= Fail;
249 return _error->Error("Unable to seek to %u",To);
250 }
251
252 return true;
253}
254 /*}}}*/
8e06abb2 255// FileFd::Size - Return the size of the file /*{{{*/
578bfd0a
AL
256// ---------------------------------------------------------------------
257/* */
8e06abb2 258unsigned long FileFd::Size()
578bfd0a
AL
259{
260 struct stat Buf;
261 if (fstat(iFd,&Buf) != 0)
262 return _error->Errno("fstat","Unable to determine the file size");
263 return Buf.st_size;
264}
265 /*}}}*/
8e06abb2 266// FileFd::Close - Close the file if the close flag is set /*{{{*/
578bfd0a
AL
267// ---------------------------------------------------------------------
268/* */
8e06abb2 269bool FileFd::Close()
578bfd0a
AL
270{
271 bool Res = true;
272 if ((Flags & AutoClose) == AutoClose)
1164783d 273 if (iFd >= 0 && close(iFd) != 0)
578bfd0a 274 Res &= _error->Errno("close","Problem closing the file");
1164783d
AL
275 iFd = -1;
276
578bfd0a
AL
277 if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail &&
278 FileName.empty() == false)
279 if (unlink(FileName.c_str()) != 0)
280 Res &= _error->Warning("unlnk","Problem unlinking the file");
281 return Res;
282}
283 /*}}}*/