]> cygwin.com Git - cygwin-apps/setup.git/blame - io_stream_cygfile.cc
2002-04-27 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / io_stream_cygfile.cc
CommitLineData
b24c88b3
RC
1/*
2 * Copyright (c) 2001, Robert Collins.
3 *
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.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Robert Collins <rbtcollins@hotmail.com>
13 *
14 */
15
16#if 0
17static const char *cvsid =
18 "\n%%% $Id$\n";
19#endif
20
21
22#include "win32.h"
23#include <stdio.h>
24#include <stdlib.h>
ca9506cc 25#include <errno.h>
b24c88b3
RC
26#include "log.h"
27#include "port.h"
28#include "mount.h"
29#include "mkdir.h"
30#include "mklink2.h"
31#include <unistd.h>
341988b9 32#include "filemanip.h"
b24c88b3
RC
33
34#include "io_stream.h"
35#include "io_stream_cygfile.h"
36
37/* For set mtime */
38#define FACTOR (0x19db1ded53ea710LL)
39#define NSPERSEC 10000000LL
40
f2e49cf8
RC
41String io_stream_cygfile::cwd("/");
42
43// Normalise a unix style path relative to
44// cwd.
45String
46io_stream_cygfile::normalise (String const &unixpath)
47{
48 char *path,*tempout;
49
50 if (unixpath.cstr_oneuse()[0]=='/')
51 {
52 // rooted path
53 path = unixpath.cstr();
54 tempout = unixpath.cstr(); // paths only shrink.
55 }
56 else
57 {
58 path = (cwd + unixpath).cstr();
59 tempout = (cwd + unixpath).cstr(); //paths only shrink.
60 }
61
62 // FIXME: handle .. depth tests to prevent / + ../foo/ stepping out
63 // of the cygwin tree
64 // FIXME: handle /./ sequences
65 bool sawslash = false;
66 char *outptr = tempout;
67 for (char *ptr=path; *ptr; ++ptr)
68 {
69 if (*ptr == '/' && sawslash)
70 --outptr;
71 else if (*ptr == '/')
72 sawslash=true;
73 else
74 sawslash=false;
75 *outptr++ = *ptr;
76 }
77 String rv = tempout;
78 delete[] path;
79 delete[] tempout;
80 return rv;
81}
82
b24c88b3
RC
83static void
84get_root_dir_now ()
85{
3c054baf 86 if (get_root_dir ().size())
b24c88b3
RC
87 return;
88 read_mounts ();
89}
90
3c054baf 91io_stream_cygfile::io_stream_cygfile (String const &name, String const &mode) : fp(), fname()
b24c88b3 92{
b24c88b3 93 errno = 0;
3c054baf 94 if (!name.size() || !mode.size())
b24c88b3
RC
95 return;
96
97 /* do this every time because the mount points may change due to fwd/back button use...
98 * TODO: make this less...manual
99 */
100 get_root_dir_now ();
3c054baf 101 if (!get_root_dir ().size())
b24c88b3
RC
102 /* TODO: assign a errno for "no mount table :} " */
103 return;
104
f2e49cf8 105 fname = cygpath (normalise(name));
3c054baf
RC
106 lmode = mode;
107 fp = fopen (fname.cstr_oneuse(), mode.cstr_oneuse());
b24c88b3
RC
108 if (!fp)
109 lasterr = errno;
110}
111
112io_stream_cygfile::~io_stream_cygfile ()
113{
b24c88b3
RC
114 if (fp)
115 fclose (fp);
e9440f0f 116 destroyed = 1;
b24c88b3
RC
117}
118
119/* Static members */
120int
3c054baf 121io_stream_cygfile::exists (String const &path)
b24c88b3
RC
122{
123 get_root_dir_now ();
f2e49cf8 124 if (get_root_dir ().size() && _access (cygpath (normalise(path)).cstr_oneuse(), 0) == 0)
b24c88b3
RC
125 return 1;
126 return 0;
127}
128
129int
3c054baf 130io_stream_cygfile::remove (String const &path)
b24c88b3 131{
3c054baf 132 if (!path.size())
b24c88b3
RC
133 return 1;
134 get_root_dir_now ();
3c054baf 135 if (!get_root_dir ().size())
b24c88b3
RC
136 /* TODO: assign a errno for "no mount table :} " */
137 return 1;
138
f2e49cf8 139 unsigned long w = GetFileAttributes (cygpath (normalise(path)).cstr_oneuse());
b24c88b3
RC
140 if (w != 0xffffffff && w & FILE_ATTRIBUTE_DIRECTORY)
141 {
f2e49cf8 142 char tmp[cygpath (normalise(path)).size() + 10];
b24c88b3
RC
143 int i = 0;
144 do
145 {
3c054baf 146 ++i;
f2e49cf8 147 sprintf (tmp, "%s.old-%d", cygpath (normalise(path)).cstr_oneuse(), i);
b24c88b3
RC
148 }
149 while (GetFileAttributes (tmp) != 0xffffffff);
150 fprintf (stderr, "warning: moving directory \"%s\" out of the way.\n",
f2e49cf8
RC
151 normalise(path).cstr_oneuse());
152 MoveFile (cygpath (normalise(path)).cstr_oneuse(), tmp);
b24c88b3 153 }
f2e49cf8 154 return !DeleteFileA (cygpath (normalise(path)).cstr_oneuse());
b24c88b3
RC
155}
156
157int
f2e49cf8 158io_stream_cygfile::mklink (String const &_from, String const &_to,
b24c88b3
RC
159 io_stream_link_t linktype)
160{
f2e49cf8 161 if (!_from.size() || !_to.size())
b24c88b3 162 return 1;
f2e49cf8
RC
163 String from(normalise(_from));
164 String to (normalise(_to));
b24c88b3
RC
165 switch (linktype)
166 {
167 case IO_STREAM_SYMLINK:
f2e49cf8
RC
168 // symlinks are arbitrary targets, can be anything, and are
169 // not subject to translation
170 return mkcygsymlink (cygpath (from).cstr_oneuse(), _to.cstr_oneuse());
b24c88b3
RC
171 case IO_STREAM_HARDLINK:
172 {
173 /* For now, just copy */
174 /* textmode alert: should we translate when linking from an binmode to a
175 text mode mount and vice verca?
176 */
2fa7c5a4 177 io_stream *in = io_stream::open (String ("cygfile://") + to, "rb");
b24c88b3
RC
178 if (!in)
179 {
3c054baf 180 log (LOG_TIMESTAMP, String("could not open ") + to +" for reading in mklink");
b24c88b3
RC
181 return 1;
182 }
2fa7c5a4 183 io_stream *out = io_stream::open (String ("cygfile://") + from, "wb");
b24c88b3
RC
184 if (!out)
185 {
2fa7c5a4 186 log (LOG_TIMESTAMP, String("could not open ") + from + " for writing in mklink");
b24c88b3
RC
187 delete in;
188 return 1;
189 }
190
3c054baf 191 if (io_stream::copy (in, out))
b24c88b3 192 {
3c054baf
RC
193 log (LOG_TIMESTAMP, String ("Failed to hardlink ")+ from + "->" +to +
194 " during file copy.");
195 delete in;
196 delete out;
197 return 1;
b24c88b3
RC
198 }
199 delete in;
200 delete out;
3c054baf 201 return 0;
b24c88b3
RC
202 }
203 }
204 return 1;
205}
206
207
208/* virtuals */
209
7c7034e8
RC
210ssize_t
211io_stream_cygfile::read (void *buffer, size_t len)
b24c88b3
RC
212{
213 if (fp)
214 return fread (buffer, 1, len, fp);
215 return 0;
216}
217
7c7034e8
RC
218ssize_t
219io_stream_cygfile::write (const void *buffer, size_t len)
b24c88b3
RC
220{
221 if (fp)
222 return fwrite (buffer, 1, len, fp);
223 return 0;
224}
225
7c7034e8
RC
226ssize_t
227io_stream_cygfile::peek (void *buffer, size_t len)
b24c88b3 228{
b24c88b3
RC
229 if (fp)
230 {
7c7034e8
RC
231 int pos = ftell (fp);
232 ssize_t rv = fread (buffer, 1, len, fp);
b24c88b3
RC
233 fseek (fp, pos, SEEK_SET);
234 return rv;
235 }
236 return 0;
237}
238
239long
240io_stream_cygfile::tell ()
241{
242 if (fp)
243 {
244 return ftell (fp);
245 }
246 return 0;
247}
248
ca9506cc
RC
249int
250io_stream_cygfile::seek (long where, io_stream_seek_t whence)
251{
252 if (fp)
7c7034e8
RC
253 {
254 return fseek (fp, where, (int) whence);
255 }
ca9506cc
RC
256 lasterr = EBADF;
257 return -1;
258}
259
b24c88b3
RC
260int
261io_stream_cygfile::error ()
262{
263 if (fp)
264 return ferror (fp);
265 return lasterr;
266}
267
268int
f2e49cf8 269cygmkdir_p (enum path_type_t isadir, String const &_name)
b24c88b3 270{
f2e49cf8 271 if (!_name.size())
b24c88b3 272 return 1;
f2e49cf8 273 String name(io_stream_cygfile::normalise(_name));
b24c88b3 274 get_root_dir_now ();
3c054baf 275 if (!get_root_dir ().size())
b24c88b3
RC
276 /* TODO: assign a errno for "no mount table :} " */
277 return 1;
1ac649ed 278 return mkdir_p (isadir == PATH_TO_DIR ? 1 : 0, cygpath (name).cstr_oneuse());
b24c88b3
RC
279}
280
b24c88b3
RC
281int
282io_stream_cygfile::set_mtime (int mtime)
283{
3c054baf 284 if (!fname.size())
b24c88b3
RC
285 return 1;
286 if (fp)
287 fclose (fp);
288 long long ftimev = mtime * NSPERSEC + FACTOR;
289 FILETIME ftime;
290 ftime.dwHighDateTime = ftimev >> 32;
291 ftime.dwLowDateTime = ftimev;
292 HANDLE h =
3c054baf 293 CreateFileA (fname.cstr_oneuse(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
b24c88b3
RC
294 0, OPEN_EXISTING,
295 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
296 if (h)
297 {
298 SetFileTime (h, 0, 0, &ftime);
299 CloseHandle (h);
bb849dbd 300#if 0
b24c88b3
RC
301 fp = fopen (fname, lmode);
302 if (!fp)
303 lasterr = errno;
bb849dbd 304#endif
b24c88b3
RC
305 return 0;
306 }
bb849dbd
RC
307#if 0
308// this results in truncated files.
309// also, semantically, it's nonsense, you cannot write to a file after setting the
310// mtime without changing the mtime
b24c88b3
RC
311 fp = fopen (fname, lmode);
312 if (!fp)
313 lasterr = errno;
bb849dbd 314#endif
b24c88b3
RC
315 return 1;
316}
7c7034e8
RC
317
318int
f2e49cf8 319io_stream_cygfile::move (String const &_from, String const &_to)
7c7034e8 320{
f2e49cf8 321 if (!_from.size() || !_to.size())
7c7034e8 322 return 1;
f2e49cf8
RC
323 String from (normalise(_from));
324 String to(normalise(_to));
7c7034e8 325 get_root_dir_now ();
3c054baf 326 if (!get_root_dir ().size())
7c7034e8
RC
327 /* TODO: assign a errno for "no mount table :} " */
328 return 1;
1ac649ed 329 return rename (cygpath (from).cstr_oneuse(), cygpath (to).cstr_oneuse());
7c7034e8 330}
341988b9
RC
331
332size_t
333io_stream_cygfile::get_size ()
334{
3c054baf 335 if (!fname.size() )
341988b9
RC
336 return 0;
337 return get_file_size (fname);
338}
This page took 0.062541 seconds and 5 git commands to generate.