Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

root/trunk/tango/io/FileSystem.d

Revision 3856, 13.2 kB (checked in by kris, 4 months ago)

moved Conduit and friends into tango.io.device in an effort to bring further clarity into tango.io -- this requires adjusting imports such that, for example, tango.io.FileConduit? becomes tango.io.device.FileConduit?

  • Property svn:mime-type set to text/x-dsrc
  • Property svn:eol-style set to native
Line 
1 /*******************************************************************************
2
3         copyright:      Copyright (c) 2004 Kris Bell. All rights reserved
4
5         license:        BSD style: $(LICENSE)
6
7         version:        Mar 2004: Initial release
8         version:        Feb 2007: Now using mutating paths
9
10         author:         Kris, Chris Sauls (Win95 file support)
11
12 *******************************************************************************/
13
14 module tango.io.FileSystem;
15
16 private import  tango.sys.Common;
17
18 private import  tango.io.Path;
19
20 private import  tango.io.FilePath;
21
22 private import  tango.core.Exception;
23
24 version (Win32)
25         {
26         private import Text = tango.text.Util;
27         private extern (Windows) DWORD GetLogicalDriveStringsA (DWORD, LPSTR);
28         }
29
30 version (Posix)
31         {
32         private import tango.stdc.string;
33         private import tango.stdc.posix.unistd;
34
35         private import tango.io.device.FileConduit;
36         private import Integer = tango.text.convert.Integer;
37         }
38
39 /*******************************************************************************
40
41         Models an OS-specific file-system. Included here are methods to
42         manipulate the current working directory, and to convert a path
43         to its absolute form.
44
45 *******************************************************************************/
46
47 struct FileSystem
48 {
49         /***********************************************************************
50
51                 Convert the provided path to an absolute path, using the
52                 current working directory where prefix is not provided.
53                 If the given path is already an absolute path, return it
54                 intact.
55
56                 Returns the provided path, adjusted as necessary
57
58         ***********************************************************************/
59
60         static FilePath toAbsolute (FilePath target, char[] prefix=null)
61         {
62                 if (! target.isAbsolute)
63                    {
64                    if (prefix is null)
65                        prefix = getDirectory;
66
67                    target.prepend (target.padded(prefix));
68                    }
69                 return target;
70         }
71
72         /***********************************************************************
73
74                 Convert the provided path to an absolute path, using the
75                 current working directory where prefix is not provided.
76                 If the given path is already an absolute path, return it
77                 intact.
78
79                 Returns the provided path, adjusted as necessary
80
81         ***********************************************************************/
82
83         static char[] toAbsolute (char[] path, char[] prefix=null)
84         {
85                 scope target = new FilePath (path);
86                 return toAbsolute (target, prefix).toString;
87         }
88
89         /***********************************************************************
90
91                 Compare to paths for absolute equality. The given prefix
92                 is prepended to the paths where they are not already in
93                 absolute format (start with a '/'). Where prefix is not
94                 provided, the current working directory will be used
95
96                 Returns true if the paths are equivalent, false otherwise
97
98         ***********************************************************************/
99
100         static bool equals (char[] path1, char[] path2, char[] prefix=null)
101         {
102                 scope p1 = new FilePath (path1);
103                 scope p2 = new FilePath (path2);
104                 return (toAbsolute(p1, prefix) == toAbsolute(p2, prefix)) is 0;
105         }
106
107         /***********************************************************************
108
109         ***********************************************************************/
110
111         private static void exception (char[] msg)
112         {
113                 throw new IOException (msg);
114         }
115
116         /***********************************************************************
117
118         ***********************************************************************/
119
120         version (Win32)
121         {
122                 /***************************************************************
123
124                         Set the current working directory
125
126                 ***************************************************************/
127
128                 static void setDirectory (char[] path)
129                 {
130                         version (Win32SansUnicode)
131                                 {
132                                 char[MAX_PATH+1] tmp = void;
133                                 tmp[0..path.length] = path;
134                                 tmp[path.length] = 0;
135
136                                 if (! SetCurrentDirectoryA (tmp.ptr))
137                                       exception ("Failed to set current directory");
138                                 }
139                              else
140                                 {
141                                 // convert into output buffer
142                                 wchar[MAX_PATH+1] tmp = void;
143                                 assert (path.length < tmp.length);
144                                 auto i = MultiByteToWideChar (CP_UTF8, 0,
145                                                               cast(PCHAR)path.ptr, path.length,
146                                                               tmp.ptr, tmp.length);
147                                 tmp[i] = 0;
148
149                                 if (! SetCurrentDirectoryW (tmp.ptr))
150                                       exception ("Failed to set current directory");
151                                 }
152                 }
153
154                 /***************************************************************
155
156                         Return the current working directory
157
158                 ***************************************************************/
159
160                 static char[] getDirectory ()
161                 {
162                         char[] path;
163
164                         version (Win32SansUnicode)
165                                 {
166                                 int len = GetCurrentDirectoryA (0, null);
167                                 auto dir = new char [len];
168                                 GetCurrentDirectoryA (len, dir.ptr);
169                                 if (len)
170                                    {
171                                    dir[len-1] = '/';                                   
172                                    path = standard (dir);
173                                    }
174                                 else
175                                    exception ("Failed to get current directory");
176                                 }
177                              else
178                                 {
179                                 wchar[MAX_PATH+2] tmp = void;
180
181                                 auto len = GetCurrentDirectoryW (0, null);
182                                 assert (len < tmp.length);
183                                 auto dir = new char [len * 3];
184                                 GetCurrentDirectoryW (len, tmp.ptr);
185                                 auto i = WideCharToMultiByte (CP_UTF8, 0, tmp.ptr, len,
186                                                               cast(PCHAR)dir.ptr, dir.length, null, null);
187                                 if (len && i)
188                                    {
189                                    path = standard (dir[0..i]);
190                                    path[$-1] = '/';
191                                    }
192                                 else
193                                    exception ("Failed to get current directory");
194                                 }
195
196                         return path;
197                 }
198
199                 /***************************************************************
200                         
201                         List the set of root devices (C:, D: etc)
202
203                 ***************************************************************/
204
205                 static char[][] roots ()
206                 {
207                         int             len;
208                         char[]          str;
209                         char[][]        roots;
210
211                         // acquire drive strings
212                         len = GetLogicalDriveStringsA (0, null);
213                         if (len)
214                            {
215                            str = new char [len];
216                            GetLogicalDriveStringsA (len, cast(PCHAR)str.ptr);
217
218                            // split roots into seperate strings
219                            roots = Text.delimit (str [0 .. $-1], "\0");
220                            }
221                         return roots;
222                 }
223         }
224
225         /***********************************************************************
226
227         ***********************************************************************/
228
229         version (Posix)
230         {
231                 /***************************************************************
232
233                         Set the current working directory
234
235                 ***************************************************************/
236
237                 static void setDirectory (char[] path)
238                 {
239                         char[512] tmp = void;
240                         tmp [path.length] = 0;
241                         tmp[0..path.length] = path;
242
243                         if (tango.stdc.posix.unistd.chdir (tmp.ptr))
244                             exception ("Failed to set current directory");
245                 }
246
247                 /***************************************************************
248
249                         Return the current working directory
250
251                 ***************************************************************/
252
253                 static char[] getDirectory ()
254                 {
255                         char[512] tmp = void;
256
257                         char *s = tango.stdc.posix.unistd.getcwd (tmp.ptr, tmp.length);
258                         if (s is null)
259                             exception ("Failed to get current directory");
260
261                         auto path = s[0 .. strlen(s)+1].dup;
262                         path[$-1] = '/';
263                         return path;
264                 }
265
266                 /***************************************************************
267
268                         List the set of root devices.
269
270                  ***************************************************************/
271
272                 static char[][] roots ()
273                 {
274                         version(darwin)
275                         {
276                             assert(0);
277                         }
278                         else
279                         {
280                             char[] path = "";
281                             char[][] list;
282                             int spaces;
283
284                             auto fc = new FileConduit("/etc/mtab");
285                             scope (exit)
286                                    fc.close;
287                            
288                             auto content = new char[cast(int) fc.length];
289                             fc.input.read (content);
290                            
291                             for(int i = 0; i < content.length; i++)
292                             {
293                                 if(content[i] == ' ') spaces++;
294                                 else if(content[i] == '\n')
295                                 {
296                                     spaces = 0;
297                                     list ~= path;
298                                     path = "";
299                                 }
300                                 else if(spaces == 1)
301                                 {
302                                     if(content[i] == '\\')
303                                     {
304                                         path ~= Integer.parse(content[++i..i+3], 8u);
305                                         i += 2;
306                                     }
307                                     else path ~= content[i];
308                                 }
309                             }
310                            
311                             return list;
312                         }
313                 }
314         }
315 }
316
317
318 /******************************************************************************
319
320 ******************************************************************************/
321
322 debug (FileSystem)
323 {
324         import tango.io.Stdout;
325
326         static void foo (FilePath path)
327         {
328         Stdout("all: ") (path).newline;
329         Stdout("path: ") (path.path).newline;
330         Stdout("file: ") (path.file).newline;
331         Stdout("folder: ") (path.folder).newline;
332         Stdout("name: ") (path.name).newline;
333         Stdout("ext: ") (path.ext).newline;
334         Stdout("suffix: ") (path.suffix).newline.newline;
335         }
336
337         void main()
338         {
339         Stdout.formatln ("dir: {}", FileSystem.getDirectory);
340
341         auto path = new FilePath (".");
342         foo (path);
343
344         path.set ("..");
345         foo (path);
346
347         path.set ("...");
348         foo (path);
349
350         path.set (r"/x/y/.file");
351         foo (path);
352
353         path.suffix = ".foo";
354         foo (path);
355
356         path.set ("file.bar");
357         FileSystem.toAbsolute(path);
358         foo(path);
359
360         path.set (r"arf/test");
361         foo(path);
362         FileSystem.toAbsolute(path);
363         foo(path);
364
365         path.name = "foo";
366         foo(path);
367
368         path.suffix = ".d";
369         path.name = path.suffix;
370         foo(path);
371
372         }
373 }
Note: See TracBrowser for help on using the browser.