Base revisions
[ntk/apt.git] / apt-pkg / contrib / fileutl.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: fileutl.cc,v 1.1 1998/07/02 02:58:13 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 #include <fileutl.h>
18 #include <pkglib/error.h>
19
20 #include <unistd.h>
21 #include <sys/stat.h>
22 #include <sys/fcntl.h>
23 #include <sys/types.h>
24 /*}}}*/
25
26 // CopyFile - Buffered copy of a file /*{{{*/
27 // ---------------------------------------------------------------------
28 /* The caller is expected to set things so that failure causes erasure */
29 bool CopyFile(File From,File To)
30 {
31 if (From.IsOpen() == false || To.IsOpen() == false)
32 return false;
33
34 // Buffered copy between fds
35 unsigned char *Buf = new unsigned char[64000];
36 long Size;
37 while ((Size = read(From.Fd(),Buf,64000)) > 0)
38 {
39 if (To.Write(Buf,Size) == false)
40 {
41 delete [] Buf;
42 return false;
43 }
44 }
45
46 delete [] Buf;
47 return true;
48 }
49 /*}}}*/
50 // GetLock - Gets a lock file /*{{{*/
51 // ---------------------------------------------------------------------
52 /* This will create an empty file of the given name and lock it. Once this
53 is done all other calls to GetLock in any other process will fail with
54 -1. The return result is the fd of the file, the call should call
55 close at some time. */
56 int GetLock(string File,bool Errors)
57 {
58 int FD = open(File.c_str(),O_RDWR | O_CREAT | O_TRUNC,0640);
59 if (FD < 0)
60 {
61 if (Errors == true)
62 _error->Errno("open","Could not open lock file %s",File.c_str());
63 return -1;
64 }
65
66 // Aquire a write lock
67 struct flock fl;
68 fl.l_type= F_WRLCK;
69 fl.l_whence= SEEK_SET;
70 fl.l_start= 0;
71 fl.l_len= 1;
72 if (fcntl(FD,F_SETLK,&fl) == -1)
73 {
74 if (Errors == true)
75 _error->Errno("open","Could not get lock %s",File.c_str());
76 close(FD);
77 return -1;
78 }
79
80 return FD;
81 }
82 /*}}}*/
83 // FileExists - Check if a file exists /*{{{*/
84 // ---------------------------------------------------------------------
85 /* */
86 bool FileExists(string File)
87 {
88 struct stat Buf;
89 if (stat(File.c_str(),&Buf) != 0)
90 return false;
91 return true;
92 }
93 /*}}}*/
94 // SafeGetCWD - This is a safer getcwd that returns a dynamic string /*{{{*/
95 // ---------------------------------------------------------------------
96 /* We return / on failure. */
97 string SafeGetCWD()
98 {
99 // Stash the current dir.
100 char S[300];
101 S[0] = 0;
102 if (getcwd(S,sizeof(S)) == 0)
103 return "/";
104 return S;
105 }
106 /*}}}*/
107
108 // File::File - Open a file /*{{{*/
109 // ---------------------------------------------------------------------
110 /* The most commonly used open mode combinations are given with Mode */
111 File::File(string FileName,OpenMode Mode, unsigned long Perms)
112 {
113 Flags = 0;
114 switch (Mode)
115 {
116 case ReadOnly:
117 iFd = open(FileName.c_str(),O_RDONLY);
118 break;
119
120 case WriteEmpty:
121 unlink(FileName.c_str());
122 iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
123 break;
124
125 case WriteExists:
126 iFd = open(FileName.c_str(),O_RDWR);
127 break;
128 }
129
130 if (iFd < 0)
131 _error->Errno("open","Could not open file %s",FileName.c_str());
132 else
133 this->FileName = FileName;
134 }
135 /*}}}*/
136 // File::~File - Closes the file /*{{{*/
137 // ---------------------------------------------------------------------
138 /* If the proper modes are selected then we close the Fd and possibly
139 unlink the file on error. */
140 File::~File()
141 {
142 Close();
143 }
144 /*}}}*/
145 // File::Read - Read a bit of the file /*{{{*/
146 // ---------------------------------------------------------------------
147 /* */
148 bool File::Read(void *To,unsigned long Size)
149 {
150 if (read(iFd,To,Size) != (signed)Size)
151 {
152 Flags |= Fail;
153 return _error->Errno("read","Read error");
154 }
155
156 return true;
157 }
158 /*}}}*/
159 // File::Write - Write to the file /*{{{*/
160 // ---------------------------------------------------------------------
161 /* */
162 bool File::Write(void *From,unsigned long Size)
163 {
164 if (write(iFd,From,Size) != (signed)Size)
165 {
166 Flags |= Fail;
167 return _error->Errno("write","Write error");
168 }
169
170 return true;
171 }
172 /*}}}*/
173 // File::Seek - Seek in the file /*{{{*/
174 // ---------------------------------------------------------------------
175 /* */
176 bool File::Seek(unsigned long To)
177 {
178 if (lseek(iFd,To,SEEK_SET) != (signed)To)
179 {
180 Flags |= Fail;
181 return _error->Error("Unable to seek to %u",To);
182 }
183
184 return true;
185 }
186 /*}}}*/
187 // File::Size - Return the size of the file /*{{{*/
188 // ---------------------------------------------------------------------
189 /* */
190 unsigned long File::Size()
191 {
192 struct stat Buf;
193 if (fstat(iFd,&Buf) != 0)
194 return _error->Errno("fstat","Unable to determine the file size");
195 return Buf.st_size;
196 }
197 /*}}}*/
198 // File::Close - Close the file if the close flag is set /*{{{*/
199 // ---------------------------------------------------------------------
200 /* */
201 bool File::Close()
202 {
203 bool Res = true;
204 if ((Flags & AutoClose) == AutoClose)
205 if (close(iFd) != 0)
206 Res &= _error->Errno("close","Problem closing the file");
207
208 if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail &&
209 FileName.empty() == false)
210 if (unlink(FileName.c_str()) != 0)
211 Res &= _error->Warning("unlnk","Problem unlinking the file");
212 return Res;
213 }
214 /*}}}*/