]> git.saurik.com Git - apt.git/blob - apt-pkg/contrib/fileutl.cc
Package Record parser
[apt.git] / apt-pkg / contrib / fileutl.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: fileutl.cc,v 1.6 1998/07/19 04:42:12 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 */
32 bool 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. */
59 int 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 /* */
89 bool 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. */
100 string 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 /*}}}*/
110
111 // FileFd::FileFd - Open a file /*{{{*/
112 // ---------------------------------------------------------------------
113 /* The most commonly used open mode combinations are given with Mode */
114 FileFd::FileFd(string FileName,OpenMode Mode, unsigned long Perms)
115 {
116 Flags = AutoClose;
117 switch (Mode)
118 {
119 case ReadOnly:
120 iFd = open(FileName.c_str(),O_RDONLY);
121 break;
122
123 case WriteEmpty:
124 unlink(FileName.c_str());
125 iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
126 break;
127
128 case WriteExists:
129 iFd = open(FileName.c_str(),O_RDWR);
130 break;
131
132 // Dont use this in public directories
133 case LockEmpty:
134 iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_TRUNC,Perms);
135 break;
136 }
137
138 if (iFd < 0)
139 _error->Errno("open","Could not open file %s",FileName.c_str());
140 else
141 this->FileName = FileName;
142 }
143 /*}}}*/
144 // FileFd::~File - Closes the file /*{{{*/
145 // ---------------------------------------------------------------------
146 /* If the proper modes are selected then we close the Fd and possibly
147 unlink the file on error. */
148 FileFd::~FileFd()
149 {
150 Close();
151 }
152 /*}}}*/
153 // FileFd::Read - Read a bit of the file /*{{{*/
154 // ---------------------------------------------------------------------
155 /* */
156 bool FileFd::Read(void *To,unsigned long Size)
157 {
158 if (read(iFd,To,Size) != (signed)Size)
159 {
160 Flags |= Fail;
161 return _error->Errno("read","Read error");
162 }
163
164 return true;
165 }
166 /*}}}*/
167 // FileFd::Write - Write to the file /*{{{*/
168 // ---------------------------------------------------------------------
169 /* */
170 bool FileFd::Write(void *From,unsigned long Size)
171 {
172 if (write(iFd,From,Size) != (signed)Size)
173 {
174 Flags |= Fail;
175 return _error->Errno("write","Write error");
176 }
177
178 return true;
179 }
180 /*}}}*/
181 // FileFd::Seek - Seek in the file /*{{{*/
182 // ---------------------------------------------------------------------
183 /* */
184 bool FileFd::Seek(unsigned long To)
185 {
186 if (lseek(iFd,To,SEEK_SET) != (signed)To)
187 {
188 Flags |= Fail;
189 return _error->Error("Unable to seek to %u",To);
190 }
191
192 return true;
193 }
194 /*}}}*/
195 // FileFd::Size - Return the size of the file /*{{{*/
196 // ---------------------------------------------------------------------
197 /* */
198 unsigned long FileFd::Size()
199 {
200 struct stat Buf;
201 if (fstat(iFd,&Buf) != 0)
202 return _error->Errno("fstat","Unable to determine the file size");
203 return Buf.st_size;
204 }
205 /*}}}*/
206 // FileFd::Close - Close the file if the close flag is set /*{{{*/
207 // ---------------------------------------------------------------------
208 /* */
209 bool FileFd::Close()
210 {
211 bool Res = true;
212 if ((Flags & AutoClose) == AutoClose)
213 if (iFd >= 0 && close(iFd) != 0)
214 Res &= _error->Errno("close","Problem closing the file");
215 iFd = -1;
216
217 if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail &&
218 FileName.empty() == false)
219 if (unlink(FileName.c_str()) != 0)
220 Res &= _error->Warning("unlnk","Problem unlinking the file");
221 return Res;
222 }
223 /*}}}*/