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