Translated using Weblate (Chinese (Simplified))
[cygwin-setup.git] / io_stream_file.cc
blob053229c66fe4fd92360d8c97121bea2bca17db77
1 /*
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
10 * http://www.gnu.org/
12 * Written by Robert Collins <rbtcollins@hotmail.com>
16 #include "win32.h"
17 #include "mklink2.h"
18 #include "filemanip.h"
19 #include "mkdir.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <unistd.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
33 public:
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);}
42 ~FileProvider (){}
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);
49 protected:
50 FileProvider() // no creating this
52 io_stream::registerProvider (theInstance, "file://");
54 FileProvider(FileProvider const &); // no copying
55 FileProvider &operator=(FileProvider const &); // no assignment
56 private:
57 static FileProvider theInstance;
59 FileProvider FileProvider::theInstance = FileProvider();
61 wchar_t *
62 io_stream_file::w_str ()
64 if (!wname)
66 wname = new wchar_t [fname.size () + 7];
67 if (wname)
68 mklongpath (wname, fname.c_str (), fname.size () + 7);
70 return wname;
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)
75 errno = 0;
76 if (!name.size())
77 return;
78 if (mode.size ())
80 fp = nt_wfopen (w_str (), mode.c_str (), perms);
81 if (!fp)
82 lasterr = errno;
86 io_stream_file::~io_stream_file ()
88 if (fp)
89 fclose (fp);
90 if (wname)
91 delete [] wname;
94 int
95 io_stream_file::exists (const std::string& path)
97 DWORD attr;
98 size_t len = 2 * path.size () + 7;
99 WCHAR wname[len];
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)
109 if (!path.size())
110 return 1;
111 size_t len = path.size () + 7;
112 WCHAR wpath[len];
113 mklongpath (wpath, path.c_str (), len);
115 unsigned long w = GetFileAttributesW (wpath);
116 if (w == INVALID_FILE_ATTRIBUTES)
117 return 0;
118 if (w & FILE_ATTRIBUTE_DIRECTORY)
120 len = wcslen (wpath);
121 WCHAR tmp[len + 10];
122 wcscpy (tmp, wpath);
123 int i = 0;
126 i++;
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())
143 return 1;
144 switch (linktype)
146 case IO_STREAM_SYMLINK:
147 return mkcygsymlink (from.c_str(), to.c_str());
148 case IO_STREAM_HARDLINK:
149 return 1;
151 return 1;
154 /* virtuals */
157 ssize_t
158 io_stream_file::read (void *buffer, size_t len)
160 ssize_t ret = 0;
162 if (len && fp && !feof (fp))
164 clearerr (fp);
165 size_t fret = fread (buffer, 1, len, fp);
166 if (fret < len && ferror (fp))
168 lasterr = errno;
169 ret = -1;
171 else
172 ret = (ssize_t) fret;
174 return ret;
177 ssize_t
178 io_stream_file::write (const void *buffer, size_t len)
180 ssize_t ret = 0;
182 if (len && fp)
184 clearerr (fp);
185 size_t fret = fwrite (buffer, 1, len, fp);
186 if (fret < len && ferror (fp))
188 lasterr = errno;
189 ret = -1;
191 else
192 ret = (ssize_t) fret;
194 return ret;
197 ssize_t
198 io_stream_file::peek (void *buffer, size_t len)
200 if (fp)
202 off_t pos = ftello (fp);
203 ssize_t rv = read (buffer, len);
204 fseeko (fp, pos, SEEK_SET);
205 return rv;
207 return 0;
210 off_t
211 io_stream_file::tell ()
213 if (fp)
214 return ftello (fp);
216 return 0;
219 off_t
220 io_stream_file::seek (off_t where, io_stream_seek_t whence)
222 if (fp)
223 return fseeko (fp, where, (int) whence);
225 lasterr = EBADF;
226 return -1;
230 io_stream_file::error ()
232 if (fp)
233 return ferror (fp);
234 return lasterr;
238 io_stream_file::set_mtime (time_t mtime)
240 if (!fname.size())
241 return 1;
242 if (fp)
243 fclose (fp);
244 long long ftimev = mtime * NSPERSEC + FACTOR;
245 FILETIME ftime;
246 ftime.dwHighDateTime = ftimev >> 32;
247 ftime.dwLowDateTime = ftimev;
248 HANDLE h;
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);
255 CloseHandle (h);
256 return 0;
258 return 1;
262 io_stream_file::move (const std::string& from, const std::string& to)
264 if (!from.size()|| !to.size())
265 return 1;
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... */
271 size_t
272 io_stream_file::get_size ()
274 if (!fname.size())
275 return 0;
276 HANDLE h;
277 DWORD ret = 0;
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);
284 CloseHandle (h);
286 return ret;