]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/fileutl.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: fileutl.cc,v 1.26 1999/03/21 07:24:14 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)
88 _error
->Warning("Not using locking for nfs mounted lock file %s",File
.c_str());
92 _error
->Errno("open","Could not get lock %s",File
.c_str());
100 // FileExists - Check if a file exists /*{{{*/
101 // ---------------------------------------------------------------------
103 bool FileExists(string File
)
106 if (stat(File
.c_str(),&Buf
) != 0)
111 // SafeGetCWD - This is a safer getcwd that returns a dynamic string /*{{{*/
112 // ---------------------------------------------------------------------
113 /* We return / on failure. */
116 // Stash the current dir.
119 if (getcwd(S
,sizeof(S
)-2) == 0)
121 unsigned int Len
= strlen(S
);
127 // flNotDir - Strip the directory from the filename /*{{{*/
128 // ---------------------------------------------------------------------
130 string
flNotDir(string File
)
132 string::size_type Res
= File
.rfind('/');
133 if (Res
== string::npos
)
136 return string(File
,Res
,Res
- File
.length());
139 // flNotFile - Strip the file from the directory name /*{{{*/
140 // ---------------------------------------------------------------------
142 string
flNotFile(string File
)
144 string::size_type Res
= File
.rfind('/');
145 if (Res
== string::npos
)
148 return string(File
,0,Res
);
151 // SetCloseExec - Set the close on exec flag /*{{{*/
152 // ---------------------------------------------------------------------
154 void SetCloseExec(int Fd
,bool Close
)
156 if (fcntl(Fd
,F_SETFD
,(Close
== false)?0:FD_CLOEXEC
) != 0)
158 cerr
<< "FATAL -> Could not set close on exec " << strerror(errno
) << endl
;
163 // SetNonBlock - Set the nonblocking flag /*{{{*/
164 // ---------------------------------------------------------------------
166 void SetNonBlock(int Fd
,bool Block
)
168 int Flags
= fcntl(Fd
,F_GETFL
) & (~O_NONBLOCK
);
169 if (fcntl(Fd
,F_SETFL
,Flags
| ((Block
== false)?0:O_NONBLOCK
)) != 0)
171 cerr
<< "FATAL -> Could not set non-blocking flag " << strerror(errno
) << endl
;
176 // WaitFd - Wait for a FD to become readable /*{{{*/
177 // ---------------------------------------------------------------------
178 /* This waits for a FD to become readable using select. It is usefull for
179 applications making use of non-blocking sockets. The timeout is
181 bool WaitFd(int Fd
,bool write
,unsigned long timeout
)
194 Res
= select(Fd
+1,0,&Set
,0,(timeout
!= 0?&tv
:0));
196 while (Res
< 0 && errno
== EINTR
);
206 Res
= select(Fd
+1,&Set
,0,0,(timeout
!= 0?&tv
:0));
208 while (Res
< 0 && errno
== EINTR
);
218 // FileFd::FileFd - Open a file /*{{{*/
219 // ---------------------------------------------------------------------
220 /* The most commonly used open mode combinations are given with Mode */
221 FileFd::FileFd(string FileName
,OpenMode Mode
, unsigned long Perms
)
227 iFd
= open(FileName
.c_str(),O_RDONLY
);
233 if (stat(FileName
.c_str(),&Buf
) == 0 && S_ISLNK(Buf
.st_mode
))
234 unlink(FileName
.c_str());
235 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
| O_TRUNC
,Perms
);
240 iFd
= open(FileName
.c_str(),O_RDWR
);
244 iFd
= open(FileName
.c_str(),O_RDWR
| O_CREAT
,Perms
);
249 _error
->Errno("open","Could not open file %s",FileName
.c_str());
252 this->FileName
= FileName
;
253 SetCloseExec(iFd
,true);
257 // FileFd::~File - Closes the file /*{{{*/
258 // ---------------------------------------------------------------------
259 /* If the proper modes are selected then we close the Fd and possibly
260 unlink the file on error. */
266 // FileFd::Read - Read a bit of the file /*{{{*/
267 // ---------------------------------------------------------------------
268 /* We are carefull to handle interruption by a signal while reading
270 bool FileFd::Read(void *To
,unsigned long Size
)
276 Res
= read(iFd
,To
,Size
);
277 if (Res
< 0 && errno
== EINTR
)
282 return _error
->Errno("read","Read error");
285 To
= (char *)To
+ Res
;
288 while (Res
> 0 && Size
> 0);
294 return _error
->Error("read, still have %u to read but none left",Size
);
297 // FileFd::Write - Write to the file /*{{{*/
298 // ---------------------------------------------------------------------
300 bool FileFd::Write(const void *From
,unsigned long Size
)
306 Res
= write(iFd
,From
,Size
);
307 if (Res
< 0 && errno
== EINTR
)
312 return _error
->Errno("write","Write error");
315 From
= (char *)From
+ Res
;
318 while (Res
> 0 && Size
> 0);
324 return _error
->Error("write, still have %u to write but couldn't",Size
);
327 // FileFd::Seek - Seek in the file /*{{{*/
328 // ---------------------------------------------------------------------
330 bool FileFd::Seek(unsigned long To
)
332 if (lseek(iFd
,To
,SEEK_SET
) != (signed)To
)
335 return _error
->Error("Unable to seek to %u",To
);
341 // FileFd::Truncate - Truncate the file /*{{{*/
342 // ---------------------------------------------------------------------
344 bool FileFd::Truncate(unsigned long To
)
346 if (ftruncate(iFd
,To
) != 0)
349 return _error
->Error("Unable to truncate to %u",To
);
355 // FileFd::Tell - Current seek position /*{{{*/
356 // ---------------------------------------------------------------------
358 unsigned long FileFd::Tell()
360 off_t Res
= lseek(iFd
,0,SEEK_CUR
);
361 if (Res
== (off_t
)-1)
362 _error
->Errno("lseek","Failed to determine the current file position");
366 // FileFd::Size - Return the size of the file /*{{{*/
367 // ---------------------------------------------------------------------
369 unsigned long FileFd::Size()
372 if (fstat(iFd
,&Buf
) != 0)
373 return _error
->Errno("fstat","Unable to determine the file size");
377 // FileFd::Close - Close the file if the close flag is set /*{{{*/
378 // ---------------------------------------------------------------------
383 if ((Flags
& AutoClose
) == AutoClose
)
384 if (iFd
>= 0 && close(iFd
) != 0)
385 Res
&= _error
->Errno("close","Problem closing the file");
388 if ((Flags
& Fail
) == Fail
&& (Flags
& DelOnFail
) == DelOnFail
&&
389 FileName
.empty() == false)
390 if (unlink(FileName
.c_str()) != 0)
391 Res
&= _error
->Warning("unlnk","Problem unlinking the file");