2 * Copyright (c) 2001, Robert Collins.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
12 * Written by Robert Collins <rbtcollins@hotmail.com>
18 #include "filemanip.h"
26 #include "io_stream_file.h"
27 #include "IOStreamProvider.h"
28 #include "LogSingleton.h"
30 /* completely private iostream registration class */
31 class FileProvider
: public IOStreamProvider
34 int exists (const std::string
& path
) const
35 {return io_stream_file::exists(path
);}
36 int remove (const std::string
& path
) const
37 {return io_stream_file::remove(path
);}
38 int mklink (const std::string
& a
, const std::string
& b
, io_stream_link_t c
) const
39 {return io_stream_file::mklink(a
,b
,c
);}
40 io_stream
*open (const std::string
& a
,const std::string
& b
, mode_t m
) const
41 {return new io_stream_file (a
, b
, m
);}
43 int move (const std::string
& a
,const std::string
& b
) const
44 {return io_stream_file::move (a
, b
);}
45 int mkdir_p (path_type_t isadir
, const std::string
& path
, mode_t mode
) const
47 return ::mkdir_p (isadir
== PATH_TO_DIR
? 1 : 0, path
.c_str(), mode
);
50 FileProvider() // no creating this
52 io_stream::registerProvider (theInstance
, "file://");
54 FileProvider(FileProvider
const &); // no copying
55 FileProvider
&operator=(FileProvider
const &); // no assignment
57 static FileProvider theInstance
;
59 FileProvider
FileProvider::theInstance
= FileProvider();
62 io_stream_file::w_str ()
66 wname
= new wchar_t [fname
.size () + 7];
68 mklongpath (wname
, fname
.c_str (), fname
.size () + 7);
73 io_stream_file::io_stream_file (const std::string
& name
, const std::string
& mode
, mode_t perms
) : fp(), lasterr (0), fname(name
), wname (NULL
)
80 fp
= nt_wfopen (w_str (), mode
.c_str (), perms
);
86 io_stream_file::~io_stream_file ()
95 io_stream_file::exists (const std::string
& path
)
98 size_t len
= 2 * path
.size () + 7;
100 mklongpath (wname
, path
.c_str (), len
);
101 attr
= GetFileAttributesW (wname
);
102 return attr
!= INVALID_FILE_ATTRIBUTES
103 && !(attr
& (FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_DEVICE
));
107 io_stream_file::remove (const std::string
& path
)
111 size_t len
= path
.size () + 7;
113 mklongpath (wpath
, path
.c_str (), len
);
115 unsigned long w
= GetFileAttributesW (wpath
);
116 if (w
== INVALID_FILE_ATTRIBUTES
)
118 if (w
& FILE_ATTRIBUTE_DIRECTORY
)
120 len
= wcslen (wpath
);
127 swprintf (tmp
+ len
, L
"old-%d", i
);
129 while (GetFileAttributesW (tmp
) != INVALID_FILE_ATTRIBUTES
);
130 Log (LOG_TIMESTAMP
) << "warning: moving directory \"" << path
.c_str()
131 << "\" out of the way." << endLog
;
132 MoveFileW (wpath
, tmp
);
134 SetFileAttributesW (wpath
, w
& ~FILE_ATTRIBUTE_READONLY
);
135 return !DeleteFileW (wpath
);
139 io_stream_file::mklink (const std::string
& from
, const std::string
& to
,
140 io_stream_link_t linktype
)
142 if (!from
.size() || !to
.size())
146 case IO_STREAM_SYMLINK
:
147 return mkcygsymlink (from
.c_str(), to
.c_str());
148 case IO_STREAM_HARDLINK
:
158 io_stream_file::read (void *buffer
, size_t len
)
162 if (len
&& fp
&& !feof (fp
))
165 size_t fret
= fread (buffer
, 1, len
, fp
);
166 if (fret
< len
&& ferror (fp
))
172 ret
= (ssize_t
) fret
;
178 io_stream_file::write (const void *buffer
, size_t len
)
185 size_t fret
= fwrite (buffer
, 1, len
, fp
);
186 if (fret
< len
&& ferror (fp
))
192 ret
= (ssize_t
) fret
;
198 io_stream_file::peek (void *buffer
, size_t len
)
202 off_t pos
= ftello (fp
);
203 ssize_t rv
= read (buffer
, len
);
204 fseeko (fp
, pos
, SEEK_SET
);
211 io_stream_file::tell ()
220 io_stream_file::seek (off_t where
, io_stream_seek_t whence
)
223 return fseeko (fp
, where
, (int) whence
);
230 io_stream_file::error ()
238 io_stream_file::set_mtime (time_t mtime
)
244 long long ftimev
= mtime
* NSPERSEC
+ FACTOR
;
246 ftime
.dwHighDateTime
= ftimev
>> 32;
247 ftime
.dwLowDateTime
= ftimev
;
249 h
= CreateFileW (w_str(), GENERIC_WRITE
,
250 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
,
251 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_BACKUP_SEMANTICS
, 0);
252 if (h
!= INVALID_HANDLE_VALUE
)
254 SetFileTime (h
, 0, 0, &ftime
);
262 io_stream_file::move (const std::string
& from
, const std::string
& to
)
264 if (!from
.size()|| !to
.size())
266 return rename (from
.c_str(), to
.c_str());
269 /* This only handles file < 2GB. The chance that files in the distro
270 get bigger is rather small, though... */
272 io_stream_file::get_size ()
278 h
= CreateFileW (w_str (), GENERIC_READ
,
279 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
,
280 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_BACKUP_SEMANTICS
, 0);
281 if (h
!= INVALID_HANDLE_VALUE
)
283 ret
= GetFileSize (h
, NULL
);