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

Changeset 3396

Show
Ignore:
Timestamp:
03/25/08 02:01:11 (8 months ago)
Author:
kris
Message:

split FilePath? in two, with discrete functions now residing in Path.d

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/tango/io/FilePath.d

    r3384 r3396  
    1414        author:         Kris 
    1515 
    16         There are two related parts to this module. The first is a Path 
    17         struct, which abstract away the differences between O/S and has 
    18         a char[] interface. The second is a FilePath class, combining a 
    19         means of efficiently editing and extracting path components, and 
    20         of accessing the underlying file systems too. 
    21  
    22         Use Path when you need pedestrian access to the file-system, and 
    23         are not manipulating the path components. Use FilePath for other 
    24         scenarios, since it will be notably more efficient in most cases. 
     16        FilePath combined a means of efficiently editing and extracting  
     17        path components and of accessing the underlying file system. 
     18 
     19        Use module Path.d instead when you need only pedestrian access to  
     20        the file-system, and are not manipulating the path components. Use  
     21        FilePath for other scenarios, since it will often be notably more  
     22        efficient 
    2523 
    2624*******************************************************************************/ 
     
    2826module tango.io.FilePath; 
    2927 
    30 private import  tango.time.Time; 
    31  
    32 private import  tango.sys.Common; 
     28private import  tango.io.Path; 
    3329 
    3430private import  tango.io.FileConst; 
    3531 
    36 private import  tango.core.Exception; 
    37  
    38 /******************************************************************************* 
    39  
    40 *******************************************************************************/ 
    41  
    42 version (Win32) 
    43         { 
    44         version (Win32SansUnicode) 
    45                 { 
    46                 alias char T; 
    47                 private extern (C) int strlen (char *s); 
    48                 private alias WIN32_FIND_DATA FIND_DATA; 
    49                 } 
    50              else 
    51                 { 
    52                 alias wchar T; 
    53                 private extern (C) int wcslen (wchar *s); 
    54                 private alias WIN32_FIND_DATAW FIND_DATA; 
    55                 } 
    56         } 
    57  
    58 version (Posix) 
    59         { 
    60         private import tango.stdc.stdio; 
    61         private import tango.stdc.string; 
    62         private import tango.stdc.posix.utime; 
    63         private import tango.stdc.posix.dirent; 
    64         } 
     32private import  tango.core.Exception : IllegalArgumentException; 
     33 
    6534 
    6635/******************************************************************************* 
     
    9665        version, use the native() method. To obtain a copy instead, use the  
    9766        path.dup.native sequence 
    98  
    99         Compile with -version=Win32SansUnicode to enable Win95 & Win32s file 
    100         support. 
    10167 
    10268*******************************************************************************/ 
     
    633599        static char[] join (char[][] paths...) 
    634600        { 
    635                 char[] result; 
    636  
    637                 foreach (path; paths) 
    638                          result ~= padded (path); 
    639  
    640                 return result.length ? result [0 .. $-1] : null; 
     601                return FS.join (paths); 
    641602        } 
    642603 
     
    650611        static char[] stripped (char[] path, char c = FileConst.PathSeparatorChar) 
    651612        { 
    652                 if (path.length && path[$-1] is c) 
    653                     path = path [0 .. $-1]; 
    654                 return path; 
     613                return FS.stripped (path, c); 
    655614        } 
    656615 
     
    664623        static char[] padded (char[] path, char c = FileConst.PathSeparatorChar) 
    665624        { 
    666                 if (path.length && path[$-1] != c) 
    667                     path = path ~ c; 
    668                 return path; 
     625                return FS.padded (path, c); 
    669626        } 
    670627 
     
    11021059} 
    11031060 
    1104  
    1105  
    1106 /******************************************************************************* 
    1107  
    1108         Wraps the O/S specific calls with a D API. Note that these accept 
    1109         null-terminated strings only, which is why it is a private struct 
    1110  
    1111 *******************************************************************************/ 
    1112  
    1113 private struct FS 
    1114 { 
    1115         /*********************************************************************** 
    1116  
    1117                 TimeStamp information. Accurate to whatever the OS supports 
    1118  
    1119         ***********************************************************************/ 
    1120  
    1121         struct Stamps 
    1122         { 
    1123                 Time    created,        /// time created 
    1124                         accessed,       /// last time accessed 
    1125                         modified;       /// last time modified 
    1126         } 
    1127  
    1128         /*********************************************************************** 
    1129  
    1130                 Passed around during file-scanning 
    1131  
    1132         ***********************************************************************/ 
    1133  
    1134         struct FileInfo 
    1135         { 
    1136                 char[]  path, 
    1137                         name; 
    1138                 ulong   bytes; 
    1139                 bool    folder; 
    1140         } 
    1141  
    1142         /*********************************************************************** 
    1143  
    1144                 Throw an exception using the last known error 
    1145  
    1146         ***********************************************************************/ 
    1147  
    1148         static void exception (char[] filename) 
    1149         { 
    1150                 throw new IOException (filename[0..$-1] ~ ": " ~ SysError.lastMsg); 
    1151         } 
    1152  
    1153         /*********************************************************************** 
    1154  
    1155                 Returns the time of the last modification. Accurate 
    1156                 to whatever the OS supports, and in a format dictated 
    1157                 by the file-system. For example NTFS keeps UTC time,  
    1158                 while FAT timestamps are based on the local time.  
    1159  
    1160         ***********************************************************************/ 
    1161  
    1162         static Time modified (char[] name) 
    1163         { 
    1164                 return timeStamps(name).modified; 
    1165         } 
    1166  
    1167         /*********************************************************************** 
    1168  
    1169                 Returns the time of the last access. Accurate to 
    1170                 whatever the OS supports, and in a format dictated 
    1171                 by the file-system. For example NTFS keeps UTC time,  
    1172                 while FAT timestamps are based on the local time. 
    1173  
    1174         ***********************************************************************/ 
    1175  
    1176         static Time accessed (char[] name) 
    1177         { 
    1178                 return timeStamps(name).accessed; 
    1179         } 
    1180  
    1181         /*********************************************************************** 
    1182  
    1183                 Returns the time of file creation. Accurate to 
    1184                 whatever the OS supports, and in a format dictated 
    1185                 by the file-system. For example NTFS keeps UTC time,   
    1186                 while FAT timestamps are based on the local time. 
    1187  
    1188         ***********************************************************************/ 
    1189  
    1190         static Time created (char[] name) 
    1191         { 
    1192                 return timeStamps(name).created; 
    1193         } 
    1194  
    1195         /*********************************************************************** 
    1196  
    1197                 Win32 API code 
    1198  
    1199         ***********************************************************************/ 
    1200  
    1201         version (Win32) 
    1202         { 
    1203                 /*************************************************************** 
    1204  
    1205                         return a wchar[] instance of the path 
    1206  
    1207                 ***************************************************************/ 
    1208  
    1209                 private static wchar[] toString16 (wchar[] tmp, char[] path) 
    1210                 { 
    1211                         auto i = MultiByteToWideChar (CP_UTF8, 0, 
    1212                                                       path.ptr, path.length, 
    1213                                                       tmp.ptr, tmp.length); 
    1214                         return tmp [0..i]; 
    1215                 } 
    1216  
    1217                 /*************************************************************** 
    1218  
    1219                         return a char[] instance of the path 
    1220  
    1221                 ***************************************************************/ 
    1222  
    1223                 private static char[] toString (char[] tmp, wchar[] path) 
    1224                 { 
    1225                         auto i = WideCharToMultiByte (CP_UTF8, 0, path.ptr, path.length, 
    1226                                                       tmp.ptr, tmp.length, null, null); 
    1227                         return tmp [0..i]; 
    1228                 } 
    1229  
    1230                 /*************************************************************** 
    1231  
    1232                         Get info about this path 
    1233  
    1234                 ***************************************************************/ 
    1235  
    1236                 private static bool fileInfo (char[] name, inout WIN32_FILE_ATTRIBUTE_DATA info) 
    1237                 { 
    1238                         version (Win32SansUnicode) 
    1239                                 { 
    1240                                 if (! GetFileAttributesExA (name.ptr, GetFileInfoLevelStandard, &info)) 
    1241                                       return false; 
    1242                                 } 
    1243                              else 
    1244                                 { 
    1245                                 wchar[MAX_PATH] tmp = void; 
    1246                                 if (! GetFileAttributesExW (toString16(tmp, name).ptr, GetFileInfoLevelStandard, &info)) 
    1247                                       return false; 
    1248                                 } 
    1249  
    1250                         return true; 
    1251                 } 
    1252  
    1253                 /*************************************************************** 
    1254  
    1255                         Get info about this path 
    1256  
    1257                 ***************************************************************/ 
    1258  
    1259                 private static DWORD getInfo (char[] name, inout WIN32_FILE_ATTRIBUTE_DATA info) 
    1260                 { 
    1261                         if (! fileInfo (name, info)) 
    1262                               exception (name); 
    1263                         return info.dwFileAttributes; 
    1264                 } 
    1265  
    1266                 /*************************************************************** 
    1267  
    1268                         Get flags for this path 
    1269  
    1270                 ***************************************************************/ 
    1271  
    1272                 private static DWORD getFlags (char[] name) 
    1273                 { 
    1274                         WIN32_FILE_ATTRIBUTE_DATA info = void; 
    1275  
    1276                         return getInfo (name, info); 
    1277                 } 
    1278  
    1279                 /*************************************************************** 
    1280  
    1281                         Return whether the file or path exists 
    1282  
    1283                 ***************************************************************/ 
    1284  
    1285                 static bool exists (char[] name) 
    1286                 { 
    1287                         WIN32_FILE_ATTRIBUTE_DATA info = void; 
    1288  
    1289                         return fileInfo (name, info); 
    1290                 } 
    1291  
    1292                 /*************************************************************** 
    1293  
    1294                         Return the file length (in bytes) 
    1295  
    1296                 ***************************************************************/ 
    1297  
    1298                 static ulong fileSize (char[] name) 
    1299                 { 
    1300                         WIN32_FILE_ATTRIBUTE_DATA info = void; 
    1301  
    1302                         getInfo (name, info); 
    1303                         return (cast(ulong) info.nFileSizeHigh << 32) + 
    1304                                             info.nFileSizeLow; 
    1305                 } 
    1306  
    1307                 /*************************************************************** 
    1308  
    1309                         Is this file writable? 
    1310  
    1311                 ***************************************************************/ 
    1312  
    1313                 static bool isWritable (char[] name) 
    1314                 { 
    1315                         return (getFlags(name) & FILE_ATTRIBUTE_READONLY) == 0; 
    1316                 } 
    1317  
    1318                 /*************************************************************** 
    1319  
    1320                         Is this file actually a folder/directory? 
    1321  
    1322                 ***************************************************************/ 
    1323  
    1324                 static bool isFolder (char[] name) 
    1325                 { 
    1326                         return (getFlags(name) & FILE_ATTRIBUTE_DIRECTORY) != 0; 
    1327                 } 
    1328  
    1329                 /*************************************************************** 
    1330  
    1331                         Return timestamp information 
    1332  
    1333                         Timstamps are returns in a format dictated by the  
    1334                         file-system. For example NTFS keeps UTC time,  
    1335                         while FAT timestamps are based on the local time 
    1336  
    1337                 ***************************************************************/ 
    1338  
    1339                 static Stamps timeStamps (char[] name) 
    1340                 { 
    1341                         static Time convert (FILETIME time) 
    1342                         { 
    1343                                 return Time (TimeSpan.Epoch1601 + *cast(long*) &time); 
    1344                         } 
    1345  
    1346                         WIN32_FILE_ATTRIBUTE_DATA info = void; 
    1347                         Stamps                    time = void; 
    1348  
    1349                         getInfo (name, info); 
    1350                         time.modified = convert (info.ftLastWriteTime); 
    1351                         time.accessed = convert (info.ftLastAccessTime); 
    1352                         time.created  = convert (info.ftCreationTime); 
    1353                         return time; 
    1354                 } 
    1355  
    1356                 /*************************************************************** 
    1357  
    1358                         Transfer the content of another file to this one.  
    1359                         Returns a reference to this class on success, or  
    1360                         throws an IOException upon failure. 
    1361  
    1362                 ***************************************************************/ 
    1363  
    1364                 static void copy (char[] src, char[] dst) 
    1365                 { 
    1366                         version (Win32SansUnicode) 
    1367                                 { 
    1368                                 if (! CopyFileA (src.ptr, dst.ptr, false)) 
    1369                                       exception (src); 
    1370                                 } 
    1371                              else 
    1372                                 { 
    1373                                 wchar[MAX_PATH+1] tmp1 = void; 
    1374                                 wchar[MAX_PATH+1] tmp2 = void; 
    1375  
    1376                                 if (! CopyFileW (toString16(tmp1, src).ptr, toString16(tmp2, dst).ptr, false)) 
    1377                                       exception (src); 
    1378                                 } 
    1379                 } 
    1380  
    1381                 /*************************************************************** 
    1382  
    1383                         Remove the file/directory from the file-system 
    1384  
    1385                 ***************************************************************/ 
    1386  
    1387                 static void remove (char[] name) 
    1388                 { 
    1389                         if (isFolder(name)) 
    1390                            { 
    1391                            version (Win32SansUnicode) 
    1392                                    { 
    1393                                    if (! RemoveDirectoryA (name.ptr)) 
    1394                                          exception (name); 
    1395                                    } 
    1396                                 else 
    1397                                    { 
    1398                                    wchar[MAX_PATH] tmp = void; 
    1399                                    if (! RemoveDirectoryW (toString16(tmp, name).ptr)) 
    1400                                          exception (name); 
    1401                                    } 
    1402                            } 
    1403                         else 
    1404                            version (Win32SansUnicode) 
    1405                                    { 
    1406                                    if (! DeleteFileA (name.ptr)) 
    1407                                          exception (name); 
    1408                                    } 
    1409                                 else 
    1410                                    { 
    1411                                    wchar[MAX_PATH] tmp = void; 
    1412                                    if (! DeleteFileW (toString16(tmp, name).ptr)) 
    1413                                          exception (name); 
    1414                                    } 
    1415                 } 
    1416  
    1417                 /*************************************************************** 
    1418  
    1419                        change the name or location of a file/directory, and 
    1420                        adopt the provided Path 
    1421  
    1422                 ***************************************************************/ 
    1423  
    1424                 static void rename (char[] src, char[] dst) 
    1425                 { 
    1426                         const int Typical = MOVEFILE_REPLACE_EXISTING + 
    1427                                             MOVEFILE_COPY_ALLOWED     + 
    1428                                             MOVEFILE_WRITE_THROUGH; 
    1429  
    1430                         int result; 
    1431                         version (Win32SansUnicode) 
    1432                                  result = MoveFileExA (src.ptr, dst.ptr, Typical); 
    1433                              else 
    1434                                 { 
    1435                                 wchar[MAX_PATH] tmp1 = void; 
    1436                                 wchar[MAX_PATH] tmp2 = void; 
    1437                                 result = MoveFileExW (toString16(tmp1, src).ptr, toString16(tmp2, dst).ptr, Typical); 
    1438                                 } 
    1439  
    1440                         if (! result) 
    1441                               exception (src); 
    1442                 } 
    1443  
    1444                 /*************************************************************** 
    1445  
    1446                         Create a new file 
    1447  
    1448                 ***************************************************************/ 
    1449  
    1450                 static void createFile (char[] name) 
    1451                 { 
    1452                         HANDLE h; 
    1453  
    1454                         version (Win32SansUnicode) 
    1455                                  h = CreateFileA (name.ptr, GENERIC_WRITE, 
    1456                                                   0, null, CREATE_ALWAYS, 
    1457                                                   FILE_ATTRIBUTE_NORMAL, cast(HANDLE) 0); 
    1458                              else 
    1459                                 { 
    1460                                 wchar[MAX_PATH] tmp = void; 
    1461                                 h = CreateFileW (toString16(tmp, name).ptr, GENERIC_WRITE, 
    1462                                                  0, null, CREATE_ALWAYS, 
    1463                                                  FILE_ATTRIBUTE_NORMAL, cast(HANDLE) 0); 
    1464                                 } 
    1465  
    1466                         if (h == INVALID_HANDLE_VALUE) 
    1467                             exception (name); 
    1468  
    1469                         if (! CloseHandle (h)) 
    1470                               exception (name); 
    1471                 } 
    1472  
    1473                 /*************************************************************** 
    1474  
    1475                         Create a new directory 
    1476  
    1477                 ***************************************************************/ 
    1478  
    1479                 static void createFolder (char[] name) 
    1480                 { 
    1481                         version (Win32SansUnicode) 
    1482                                 { 
    1483                                 if (! CreateDirectoryA (name.ptr, null)) 
    1484                                       exception (name); 
    1485                                 } 
    1486                              else 
    1487                                 { 
    1488                                 wchar[MAX_PATH] tmp = void; 
    1489                                 if (! CreateDirectoryW (toString16(tmp, name).ptr, null)) 
    1490                                       exception (name); 
    1491                                 } 
    1492                 } 
    1493  
    1494                 /*************************************************************** 
    1495  
    1496                         List the set of filenames within this folder. 
    1497  
    1498                         Each path and filename is passed to the provided 
    1499                         delegate, along with the path prefix and whether 
    1500                         the entry is a folder or not. 
    1501  
    1502                         Returns the number of files scanned. 
    1503  
    1504                 ***************************************************************/ 
    1505  
    1506                 static int list (char[] folder, int delegate(ref FileInfo) dg) 
    1507                 { 
    1508                         HANDLE                  h; 
    1509                         int                     ret; 
    1510                         char[]                  prefix; 
    1511                         char[MAX_PATH+1]        tmp = void; 
    1512                         FIND_DATA               fileinfo = void; 
    1513  
    1514                         int next() 
    1515                         { 
    1516                                 version (Win32SansUnicode) 
    1517                                          return FindNextFileA (h, &fileinfo); 
    1518                                    else 
    1519                                       return FindNextFileW (h, &fileinfo); 
    1520                         } 
    1521  
    1522                         static T[] padded (T[] s, T[] ext) 
    1523                         { 
    1524                                 if (s.length is 0 || s[$-1] != '\\') 
    1525                                     return s ~ "\\" ~ ext; 
    1526                                 return s ~ ext; 
    1527                         } 
    1528  
    1529                         version (Win32SansUnicode) 
    1530                                  h = FindFirstFileA (padded(folder[0..$-1], "*\0").ptr, &fileinfo); 
    1531                              else 
    1532                                 { 
    1533                                 wchar[MAX_PATH] host = void; 
    1534                                 h = FindFirstFileW (padded(toString16(host, folder[0..$-1]), "*\0").ptr, &fileinfo); 
    1535                                 } 
    1536  
    1537                         if (h is INVALID_HANDLE_VALUE) 
    1538                             exception (folder); 
    1539  
    1540                         scope (exit) 
    1541                                FindClose (h); 
    1542  
    1543                         prefix = FilePath.padded (folder[0..$-1]); 
    1544                         do { 
    1545                            version (Win32SansUnicode) 
    1546                                    { 
    1547                                    auto len = strlen (fileinfo.cFileName.ptr); 
    1548                                    auto str = fileinfo.cFileName.ptr [0 .. len]; 
    1549                                    } 
    1550                                 else 
    1551                                    { 
    1552                                    auto len = wcslen (fileinfo.cFileName.ptr); 
    1553                                    auto str = toString (tmp, fileinfo.cFileName [0 .. len]); 
    1554                                    } 
    1555  
    1556                            // skip hidden/system files 
    1557                            if ((fileinfo.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) is 0) 
    1558                               { 
    1559                               FileInfo info = void; 
    1560                               info.name   = str; 
    1561                               info.path   = prefix; 
    1562                               info.bytes  = (cast(ulong) fileinfo.nFileSizeHigh << 32) + fileinfo.nFileSizeLow; 
    1563                               info.folder = (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; 
    1564  
    1565                               // skip "..." names 
    1566                               if (str.length > 3 || str != "..."[0 .. str.length]) 
    1567                                   if ((ret = dg(info)) != 0) 
    1568                                        break; 
    1569                               } 
    1570                            } while (next); 
    1571  
    1572                         return ret; 
    1573                 } 
    1574         } 
    1575  
    1576         /*********************************************************************** 
    1577  
    1578                 Posix-specific code 
    1579  
    1580         ***********************************************************************/ 
    1581  
    1582         version (Posix) 
    1583         { 
    1584                 /*************************************************************** 
    1585  
    1586                         Get info about this path 
    1587  
    1588                 ***************************************************************/ 
    1589  
    1590                 private static uint getInfo (char[] name, inout stat_t stats) 
    1591                 { 
    1592                         if (posix.stat (name.ptr, &stats)) 
    1593                             exception (name); 
    1594  
    1595                         return stats.st_mode; 
    1596                 } 
    1597  
    1598                 /*************************************************************** 
    1599  
    1600                         Return whether the file or path exists 
    1601  
    1602                 ***************************************************************/ 
    1603  
    1604                 static bool exists (char[] name) 
    1605                 { 
    1606                         stat_t stats = void; 
    1607                         return posix.stat (name.ptr, &stats) is 0; 
    1608                 } 
    1609  
    1610                 /*************************************************************** 
    1611  
    1612                         Return the file length (in bytes) 
    1613  
    1614                 ***************************************************************/ 
    1615  
    1616                 static ulong fileSize (char[] name) 
    1617                 { 
    1618                         stat_t stats = void; 
    1619  
    1620                         getInfo (name, stats); 
    1621                         return cast(ulong) stats.st_size;    // 32 bits only 
    1622                 } 
    1623  
    1624                 /*************************************************************** 
    1625  
    1626                         Is this file writable? 
    1627  
    1628                 ***************************************************************/ 
    1629  
    1630                 static bool isWritable (char[] name) 
    1631                 { 
    1632                         stat_t stats = void; 
    1633  
    1634                         return (getInfo(name, stats) & O_RDONLY) == 0; 
    1635                 } 
    1636  
    1637                 /*************************************************************** 
    1638  
    1639                         Is this file actually a folder/directory? 
    1640  
    1641                 ***************************************************************/ 
    1642  
    1643                 static bool isFolder (char[] name) 
    1644                 { 
    1645                         stat_t stats = void; 
    1646  
    1647                         return (getInfo(name, stats) & S_IFDIR) != 0; 
    1648                 } 
    1649  
    1650                 /*************************************************************** 
    1651  
    1652                         Return timestamp information 
    1653  
    1654                         Timstamps are returns in a format dictated by the  
    1655                         file-system. For example NTFS keeps UTC time,  
    1656                         while FAT timestamps are based on the local time 
    1657  
    1658                 ***************************************************************/ 
    1659  
    1660                 static Stamps timeStamps (char[] name) 
    1661                 { 
    1662                         static Time convert (timeval* tv) 
    1663                         { 
    1664                                 return Time.epoch1970 + 
    1665                                        TimeSpan.seconds(tv.tv_sec) + 
    1666                                        TimeSpan.micros(tv.tv_usec); 
    1667                         } 
    1668  
    1669                         stat_t stats = void; 
    1670                         Stamps time  = void; 
    1671  
    1672                         getInfo (name, stats); 
    1673  
    1674                         time.modified = convert (cast(timeval*) &stats.st_mtime); 
    1675                         time.accessed = convert (cast(timeval*) &stats.st_atime); 
    1676                         time.created  = convert (cast(timeval*) &stats.st_ctime); 
    1677                         return time; 
    1678                 } 
    1679  
    1680                 /*********************************************************************** 
    1681  
    1682                         Transfer the content of another file to this one. Returns a 
    1683                         reference to this class on success, or throws an IOException 
    1684                         upon failure. 
    1685  
    1686                 ***********************************************************************/ 
    1687  
    1688                 static void copy (char[] source, char[] dest) 
    1689                 { 
    1690                         auto src = posix.open (source.ptr, O_RDONLY, 0640); 
    1691                         scope (exit) 
    1692                                if (src != -1) 
    1693                                    posix.close (src); 
    1694  
    1695                         auto dst = posix.open (dest.ptr, O_CREAT | O_RDWR, 0660); 
    1696                         scope (exit) 
    1697                                if (dst != -1) 
    1698                                    posix.close (dst); 
    1699  
    1700                         if (src is -1 || dst is -1) 
    1701                             exception (source); 
    1702  
    1703                         // copy content 
    1704                         ubyte[] buf = new ubyte [16 * 1024]; 
    1705                         int read = posix.read (src, buf.ptr, buf.length); 
    1706                         while (read > 0) 
    1707                               { 
    1708                               auto p = buf.ptr; 
    1709                               do { 
    1710                                  int written = posix.write (dst, p, read); 
    1711                                  p += written; 
    1712                                  read -= written; 
    1713                                  if (written is -1) 
    1714                                      exception (dest); 
    1715                                  } while (read > 0); 
    1716                               read = posix.read (src, buf.ptr, buf.length); 
    1717                               } 
    1718                         if (read is -1) 
    1719                             exception (source); 
    1720  
    1721                         // copy timestamps 
    1722                         stat_t stats; 
    1723                         if (posix.stat (source.ptr, &stats)) 
    1724                             exception (source); 
    1725  
    1726                         utimbuf utim; 
    1727                         utim.actime = stats.st_atime; 
    1728                         utim.modtime = stats.st_mtime; 
    1729                         if (utime (dest.ptr, &utim) is -1) 
    1730                             exception (dest); 
    1731                 } 
    1732  
    1733                 /*************************************************************** 
    1734  
    1735                         Remove the file/directory from the file-system 
    1736  
    1737                 ***************************************************************/ 
    1738  
    1739                 static void remove (char[] name) 
    1740                 { 
    1741                         if (isFolder (name)) 
    1742                            { 
    1743                            if (posix.rmdir (name.ptr)) 
    1744                                exception (name); 
    1745                            } 
    1746                         else 
    1747                            if (tango.stdc.stdio.remove (name.ptr) == -1) 
    1748                                exception (name); 
    1749                 } 
    1750  
    1751                 /*************************************************************** 
    1752  
    1753                        change the name or location of a file/directory, and 
    1754                        adopt the provided FilePath 
    1755  
    1756                 ***************************************************************/ 
    1757  
    1758                 static void rename (char[] src, char[] dst) 
    1759                 { 
    1760                         if (tango.stdc.stdio.rename (src.ptr, dst.ptr) == -1) 
    1761                             exception (src); 
    1762                 } 
    1763  
    1764                 /*************************************************************** 
    1765  
    1766                         Create a new file 
    1767  
    1768                 ***************************************************************/ 
    1769  
    1770                 static void createFile (char[] name) 
    1771                 { 
    1772                         int fd; 
    1773  
    1774                         fd = posix.open (name.ptr, O_CREAT | O_WRONLY | O_TRUNC, 0660); 
    1775                         if (fd == -1) 
    1776                             exception (name); 
    1777  
    1778                         if (posix.close(fd) == -1) 
    1779                             exception (name); 
    1780                 } 
    1781  
    1782                 /*************************************************************** 
    1783  
    1784                         Create a new directory 
    1785  
    1786                 ***************************************************************/ 
    1787  
    1788                 static void createFolder (char[] name) 
    1789                 { 
    1790                         if (posix.mkdir (name.ptr, 0777)) 
    1791                             exception (name); 
    1792                 } 
    1793                 /*************************************************************** 
    1794  
    1795                         List the set of filenames within this folder. 
    1796  
    1797                         Each path and filename is passed to the provided 
    1798                         delegate, along with the path prefix and whether 
    1799                         the entry is a folder or not. 
    1800  
    1801                         Returns the number of files scanned. 
    1802  
    1803                 ***************************************************************/ 
    1804  
    1805                 static int list (char[] folder, int delegate(ref FileInfo) dg)