00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 module mango.io.FileProxy;
00044
00045 private import mango.sys.OS;
00046
00047 private import mango.io.FilePath,
00048 mango.io.Exception;
00049
00050 private import mango.convert.Unicode;
00051
00052 private import mango.io.model.IWriter;
00053
00054 version (Win32)
00055 {
00056 version (Win32SansUnicode)
00057 {
00058 private extern (C) int strlen (char *s);
00059 private alias WIN32_FIND_DATA FIND_DATA;
00060 }
00061 else
00062 {
00063 private extern (C) int wcslen (wchar *s);
00064 private alias WIN32_FIND_DATAW FIND_DATA;
00065 }
00066 }
00067
00068
00069 version (Posix)
00070 {
00071 private extern (C) int strlen (char *s);
00072
00073 private import std.c.stdio;
00074
00075 version (darwin)
00076 {
00077
00078
00079 alias long off_t;
00080
00081 extern (C)
00082 {
00083 struct dirent
00084 {
00085 int d_ino;
00086 off_t d_off;
00087 ushort d_reclen;
00088 ubyte d_type;
00089 char[256] d_name;
00090 }
00091
00092 struct DIR
00093 {
00094
00095 }
00096
00097 DIR* opendir(char* name);
00098 int closedir(DIR* dir);
00099 dirent* readdir(DIR* dir);
00100 void rewinddir(DIR* dir);
00101 off_t telldir(DIR* dir);
00102 void seekdir(DIR* dir, off_t offset);
00103 }
00104 }
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 class FileProxy : IWritable
00121 {
00122 private FilePath path;
00123
00124
00125
00126
00127
00128
00129
00130 this (FilePath path)
00131 {
00132 this.path = path;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141 this (char[] path)
00142 {
00143 this (new FilePath (path));
00144 }
00145
00146
00147
00148
00149
00150
00151
00152 FilePath getPath ()
00153 {
00154 return path;
00155 }
00156
00157
00158
00159
00160
00161
00162
00163 char[] toString ()
00164 {
00165 return path.toString();
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 bool isExisting ()
00175 {
00176 try {
00177 getSize();
00178 return true;
00179 } catch (IOException){}
00180 return false;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 FilePath[] toList ()
00197 {
00198
00199 return toList (delegate bool(FilePath fp) {return true;});
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209 void write (IWriter emit)
00210 {
00211 emit (path);
00212 }
00213
00214
00215
00216
00217
00218 version (Win32)
00219 {
00220
00221
00222
00223
00224
00225
00226 private void exception ()
00227 {
00228 throw new IOException (path.toString ~ ": " ~ OS.error);
00229 }
00230
00231
00232
00233
00234
00235
00236
00237 private uint getInfo (void delegate (FIND_DATA info) dg)
00238 {
00239 FIND_DATA info;
00240
00241 version (Win32SansUnicode)
00242 HANDLE h = FindFirstFileA (path.toUtf8, &info);
00243 else
00244 HANDLE h = FindFirstFileW (path.toUtf16, &info);
00245
00246 if (h == INVALID_HANDLE_VALUE)
00247 exception ();
00248
00249 if (dg)
00250 dg (info);
00251 FindClose (h);
00252
00253 return info.dwFileAttributes;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262 ulong getSize ()
00263 {
00264 ulong _size;
00265
00266 void size (FIND_DATA info)
00267 {
00268 _size = (cast(ulong) info.nFileSizeHigh << 32) +
00269 info.nFileSizeLow;
00270 }
00271
00272 getInfo (&size);
00273 return _size;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282 bool isWritable ()
00283 {
00284 return cast (bool) ((getInfo(null) & FILE_ATTRIBUTE_READONLY) == 0);
00285 }
00286
00287
00288
00289
00290
00291
00292
00293 bool isDirectory ()
00294 {
00295 return cast(bool) ((getInfo(null) & FILE_ATTRIBUTE_DIRECTORY) != 0);
00296 }
00297
00298
00299
00300
00301
00302
00303
00304 ulong getModifiedTime ()
00305 {
00306 ulong _time;
00307
00308 void time (FIND_DATA info)
00309 {
00310 _time = (cast(ulong) info.ftLastWriteTime.dwHighDateTime << 32) +
00311 info.ftLastWriteTime.dwLowDateTime;
00312 }
00313
00314 getInfo (&time);
00315 return _time;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324 void remove ()
00325 {
00326 if (isDirectory ())
00327 {
00328 version (Win32SansUnicode)
00329 {
00330 if (! RemoveDirectoryA (path.toUtf8))
00331 exception();
00332 }
00333 else
00334 {
00335 if (! RemoveDirectoryW (path.toUtf16))
00336 exception();
00337 }
00338 }
00339 else
00340 version (Win32SansUnicode)
00341 {
00342 if (! DeleteFileA (path.toUtf8))
00343 exception();
00344 }
00345 else
00346 {
00347 if (! DeleteFileW (path.toUtf16))
00348 exception();
00349 }
00350 }
00351
00352
00353
00354
00355
00356
00357
00358 FileProxy createFile ()
00359 {
00360 HANDLE h;
00361
00362 version (Win32SansUnicode)
00363 h = CreateFileA (path.toUtf8, GENERIC_WRITE,
00364 0, null, CREATE_ALWAYS,
00365 FILE_ATTRIBUTE_NORMAL, null);
00366 else
00367 h = CreateFileW (path.toUtf16, GENERIC_WRITE,
00368 0, null, CREATE_ALWAYS,
00369 FILE_ATTRIBUTE_NORMAL, null);
00370
00371 if (h == INVALID_HANDLE_VALUE)
00372 exception ();
00373
00374 if (! CloseHandle (h))
00375 exception ();
00376
00377 return this;
00378 }
00379
00380
00381
00382
00383
00384
00385
00386 FileProxy createDirectory ()
00387 {
00388 version (Win32SansUnicode)
00389 {
00390 if (! CreateDirectoryA (path.toUtf8, null))
00391 exception();
00392 }
00393 else
00394 {
00395 if (! CreateDirectoryW (path.toUtf16, null))
00396 exception();
00397 }
00398 return this;
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408 FilePath[] toList (bool delegate(FilePath fp) filter)
00409 {
00410 int i;
00411 wchar[] c;
00412 HANDLE h;
00413 FilePath fp;
00414 FilePath[] list;
00415 FIND_DATA fileinfo;
00416
00417 int next()
00418 {
00419 version (Win32SansUnicode)
00420 return FindNextFileA (h, &fileinfo);
00421 else
00422 return FindNextFileW (h, &fileinfo);
00423 }
00424
00425 list = new FilePath[50];
00426
00427 version (Win32SansUnicode)
00428 h = FindFirstFileA (path.toUtf8 ~ "\\*\0", &fileinfo);
00429 else
00430 h = FindFirstFileW (path.toUtf16 ~ cast(wchar[]) "\\*\0", &fileinfo);
00431
00432 if (h != INVALID_HANDLE_VALUE)
00433 try {
00434 do {
00435
00436 version (Win32SansUnicode)
00437 {
00438 int len = strlen (fileinfo.cFileName);
00439 fp = new FilePath (fileinfo.cFileName [0 .. len]);
00440 }
00441 else
00442 {
00443 int len = wcslen (fileinfo.cFileName);
00444 fp = new FilePath (Unicode.toUtf8(fileinfo.cFileName [0 .. len]));
00445 }
00446
00447 if (i >= list.length)
00448 list.length = list.length * 2;
00449
00450 if (filter (fp))
00451 {
00452 list[i] = fp;
00453 ++i;
00454 }
00455 } while (next);
00456 } finally {
00457 FindClose (h);
00458 }
00459 list.length = i;
00460 return list;
00461 }
00462 }
00463
00464
00465
00466
00467
00468 version (Posix)
00469 {
00470
00471
00472
00473
00474
00475
00476 private void exception ()
00477 {
00478 throw new IOException (path.toString ~ ": " ~ OS.error);
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 private uint getInfo (void delegate (struct_stat info) dg)
00488 {
00489 struct_stat stats;
00490
00491 if (posix.stat (path.toUtf8, &stats))
00492 exception();
00493
00494 if (dg)
00495 dg (stats);
00496
00497 return stats.st_mode;
00498 }
00499
00500
00501
00502
00503
00504
00505
00506 ulong getSize ()
00507 {
00508 ulong _size;
00509
00510 void size (struct_stat info)
00511 {
00512 _size = cast(ulong) info.st_size;
00513 }
00514
00515 getInfo (&size);
00516 return _size;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525 bool isWritable ()
00526 {
00527 return (getInfo(null) & O_RDONLY) == 0;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536 bool isDirectory ()
00537 {
00538 return (getInfo(null) & S_IFDIR) != 0;
00539 }
00540
00541
00542
00543
00544
00545
00546
00547 ulong getModifiedTime ()
00548 {
00549 ulong _time;
00550
00551 void time (struct_stat info)
00552 {
00553 _time = cast(ulong) info.st_mtime;
00554 }
00555
00556 getInfo (&time);
00557 return _time;
00558 }
00559
00560
00561
00562
00563
00564
00565
00566 void remove ()
00567 {
00568 if (isDirectory())
00569 {
00570 if (posix.rmdir (path.toUtf8))
00571 exception ();
00572 }
00573 else
00574 if (std.c.stdio.remove (path.toUtf8) == -1)
00575 exception ();
00576 }
00577
00578
00579
00580
00581
00582
00583
00584 FileProxy createFile ()
00585 {
00586 int fd;
00587
00588 fd = posix.open (path.toUtf8, O_CREAT | O_WRONLY | O_TRUNC, 0660);
00589 if (fd == -1)
00590 exception();
00591
00592 if (posix.close(fd) == -1)
00593 exception();
00594
00595 return this;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604 FileProxy createDirectory ()
00605 {
00606 if (posix.mkdir (path.toUtf8, 0777))
00607 exception();
00608
00609 return this;
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619 FilePath[] toList (bool delegate(FilePath fp) filter)
00620 {
00621 int i;
00622 DIR* dir;
00623 dirent* entry;
00624 FilePath[] list;
00625
00626 dir = opendir (path.toUtf8);
00627 if (! dir)
00628 exception();
00629
00630 list = new FilePath [50];
00631 while ((entry = readdir(dir)) != null)
00632 {
00633 int len = strlen (entry.d_name);
00634
00635
00636 FilePath fp = new FilePath (entry.d_name[0 ..len].dup);
00637
00638 if (i >= list.length)
00639 list.length = list.length * 2;
00640
00641 if (filter (fp))
00642 {
00643 list[i] = fp;
00644 ++i;
00645 }
00646 }
00647
00648 list.length = i;
00649 closedir (dir);
00650 return list;
00651 }
00652
00653 }
00654 }
00655