]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/fileutl.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: fileutl.cc,v 1.24 1999/03/17 03:25:25 jgg Exp $
4 /* ######################################################################
8 CopyFile - Buffered copy of a single file
9 GetLock - dpkg compatible lock file manipulation (fcntl)
11 This source is placed in the Public Domain, do with it what you will
12 It was originally written by Jason Gunthorpe.
14 ##################################################################### */
16 // Include Files /*{{{*/
18 #pragma implementation "apt-pkg/fileutl.h"
20 #include <apt-pkg/fileutl.h>
21 #include <apt-pkg/error.h>
25 #include <sys/fcntl.h>
26 #include <sys/types.h>
31 // CopyFile - Buffered copy of a file /*{{{*/
32 // ---------------------------------------------------------------------
33 /* The caller is expected to set things so that failure causes erasure */
34 bool CopyFile(FileFd
&From
,FileFd
&To
)
36 if (From
.IsOpen() == false || To
.IsOpen() == false)
39 // Buffered copy between fds
40 unsigned char *Buf
= new unsigned char[64000];
41 unsigned long Size
= From
.Size();
44 unsigned long ToRead
= Size
;
48 if (From
.Read(Buf
,ToRead
) == false ||
49 To
.Write(Buf
,ToRead
) == false)
62 // GetLock - Gets a lock file /*{{{*/
63 // ---------------------------------------------------------------------
64 /* This will create an empty file of the given name and lock it. Once this
65 is done all other calls to GetLock in any other process will fail with
66 -1. The return result is the fd of the file, the call should call
67 close at some time. */
68 int GetLock(string File
,bool Errors
)
70 int FD
= open(File
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,0640);
74 _error
->Errno("open","Could not open lock file %s",File
.c_str());
78 // Aquire a write lock
81 fl
.l_whence
= SEEK_SET
;
84 if (fcntl(FD
,F_SETLK
,&fl
) == -1)
87 _error
->Errno("open","Could not get lock %s",File
.c_str());
95 // FileExists - Check if a file exists /*{{{*/
96 // ---------------------------------------------------------------------
98 bool FileExists(string File
)
101 if (stat(File
.c_str(),&Buf
) != 0)
106 // SafeGetCWD - This is a safer getcwd that returns a dynamic string /*{{{*/
107 // ---------------------------------------------------------------------
108 /* We return / on failure. */
111 // Stash the current dir.
114 if (getcwd(S
,sizeof(S
)-2) == 0)
116 unsigned int Len
= strlen(S
);
122 // flNotDir - Strip the directory from the filename /*{{{*/
123 // ---------------------------------------------------------------------
125 string
flNotDir(string File
)
127 string::size_type Res
= File
.rfind('/');
128 if (Res
== string::npos
)
131 return string(File
,Res
,Res
- File
.length());
134 // flNotFile - Strip the file from the directory name /*{{{*/
135 // ---------------------------------------------------------------------
137 string
flNotFile(string File
)
139 string::size_type Res
= File
.rfind('/');
140 if (Res
== string::npos
)
143 return string(File
,0,Res
);
146 // SetCloseExec - Set the close on exec flag /*{{{*/
147 // ---------------------------------------------------------------------
149 void SetCloseExec(int Fd
,bool Close
)
151 if (fcntl(Fd
,F_SETFD
,(Close
== false)?0:FD_CLOEXEC
) != 0)
153 cerr
<< "FATAL -> Could not set close on exec " << strerror(errno
) << endl
;
158 // SetNonBlock - Set the nonblocking flag /*{{{*/
159 // ---------------------------------------------------------------------
161 void SetNonBlock(int Fd
,bool Block
)
163 int Flags
= fcntl(Fd
,F_GETFL
) & (~O_NONBLOCK
);
164 if (fcntl(Fd
,F_SETFL
,Flags
| ((Block
== false)?0:O_NONBLOCK
)) != 0)
166 cerr
<< "FATAL -> Could not set non-blocking flag " << strerror(errno
) << endl
;
171 // WaitFd - Wait for a FD to become readable /*{{{*/
172 // ---------------------------------------------------------------------
173 /* This waits for a FD to become readable using select. It is usefull for
174 applications making use of non-blocking sockets. The timeout is
176 bool WaitFd(int Fd
,bool write
,unsigned long timeout
)
189 Res
= select(Fd
+1,0,&Set
,0,(timeout
!= 0?&tv
:0));
191 while (Res
< 0 && errno
== EINTR
);
201 Res
= select(Fd
+1,&Set
,0,0,(timeout
!= 0?&tv
:0));
203 while (Res
< 0 && errno
== EINTR
);
213 // FileFd::FileFd - Open a file /*{{{*/
214 // ---------------------------------------------------------------------
215 /* The most commonly used open mode combinations are given with Mode */
216 FileFd::FileFd(string FileName
,OpenMode Mode
, unsigned long Perms
)
222 iFd
= open(FileName
.c_str(),O_RDONLY
);
228 if (stat(FileName
.c_str(),&Buf
) == 0 && S_ISLNK(Buf
.st_mode
))
229 unlink(FileName
.c_str());
230 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,Perms
);
235 iFd
= open(FileName
.c_str(),O_RDWR
);
239 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
,Perms
);
244 _error
->Errno("open","Could not open file %s",FileName
.c_str());
247 this->FileName
= FileName
;
248 SetCloseExec(iFd
,true);
252 // FileFd::~File - Closes the file /*{{{*/
253 // ---------------------------------------------------------------------
254 /* If the proper modes are selected then we close the Fd and possibly
255 unlink the file on error. */
261 // FileFd::Read - Read a bit of the file /*{{{*/
262 // ---------------------------------------------------------------------
263 /* We are carefull to handle interruption by a signal while reading
265 bool FileFd::Read(void *To
,unsigned long Size
)
271 Res
= read(iFd
,To
,Size
);
272 if (Res
< 0 && errno
== EINTR
)
277 return _error
->Errno("read","Read error");
280 To
= (char *)To
+ Res
;
283 while (Res
> 0 && Size
> 0);
289 return _error
->Error("read, still have %u to read but none left",Size
);
292 // FileFd::Write - Write to the file /*{{{*/
293 // ---------------------------------------------------------------------
295 bool FileFd::Write(const void *From
,unsigned long Size
)
301 Res
= write(iFd
,From
,Size
);
302 if (Res
< 0 && errno
== EINTR
)
307 return _error
->Errno("write","Write error");
310 From
= (char *)From
+ Res
;
313 while (Res
> 0 && Size
> 0);
319 return _error
->Error("write, still have %u to write but couldn't",Size
);
322 // FileFd::Seek - Seek in the file /*{{{*/
323 // ---------------------------------------------------------------------
325 bool FileFd::Seek(unsigned long To
)
327 if (lseek(iFd
,To
,SEEK_SET
) != (signed)To
)
330 return _error
->Error("Unable to seek to %u",To
);
336 // FileFd::Truncate - Truncate the file /*{{{*/
337 // ---------------------------------------------------------------------
339 bool FileFd::Truncate(unsigned long To
)
341 if (ftruncate(iFd
,To
) != 0)
344 return _error
->Error("Unable to truncate to %u",To
);
350 // FileFd::Tell - Current seek position /*{{{*/
351 // ---------------------------------------------------------------------
353 unsigned long FileFd::Tell()
355 off_t Res
= lseek(iFd
,0,SEEK_CUR
);
356 if (Res
== (off_t
)-1)
357 _error
->Errno("lseek","Failed to determine the current file position");
361 // FileFd::Size - Return the size of the file /*{{{*/
362 // ---------------------------------------------------------------------
364 unsigned long FileFd::Size()
367 if (fstat(iFd
,&Buf
) != 0)
368 return _error
->Errno("fstat","Unable to determine the file size");
372 // FileFd::Close - Close the file if the close flag is set /*{{{*/
373 // ---------------------------------------------------------------------
378 if ((Flags
& AutoClose
) == AutoClose
)
379 if (iFd
>= 0 && close(iFd
) != 0)
380 Res
&= _error
->Errno("close","Problem closing the file");
383 if ((Flags
& Fail
) == Fail
&& (Flags
& DelOnFail
) == DelOnFail
&&
384 FileName
.empty() == false)
385 if (unlink(FileName
.c_str()) != 0)
386 Res
&= _error
->Warning("unlnk","Problem unlinking the file");