Changeset 683
- Timestamp:
- 05/02/08 15:08:11 (4 years ago)
- Files:
-
- trunk/phobos/std/file.d (modified) (43 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/phobos/std/file.d
r589 r683 46 46 private import std.c.string; 47 47 private import std.traits; 48 import std.conv; 49 private import std.stdio; // for testing only 48 private import std.conv; 49 private import std.contracts; 50 private import std.utf; 51 version (unittest) { 52 private import std.stdio; // for testing only 53 } 50 54 51 55 /* =========================== Win32 ======================= */ … … 60 64 private import std.date; 61 65 62 int useWfuncs = 1;66 enum useWfuncs = true; 63 67 64 68 static this() … … 74 78 class FileException : Exception 75 79 { 76 77 80 uint errno; // operating system error code 78 81 … … 99 102 100 103 /******************************************** 101 * Read file name[], return array of bytes read.102 * Throws:103 * FileExceptionon error.104 * Read file $(D name), return array of bytes read. 105 * 106 * Throws: $(D FileException) on error. 104 107 */ 105 108 … … 154 157 /********************************************* 155 158 * Write buffer[] to file name[]. 156 * Throws: FileExceptionon error.159 * Throws: $(D FileException) on error. 157 160 */ 158 161 … … 196 199 /********************************************* 197 200 * Append buffer[] to file name[]. 198 * Throws: FileExceptionon error.201 * Throws: $(D FileException) on error. 199 202 */ 200 203 … … 240 243 /*************************************************** 241 244 * Rename file from[] to to[]. 242 * Throws: FileExceptionon error.245 * Throws: $(D FileException) on error. 243 246 */ 244 247 245 248 void rename(in string from, in string to) 246 249 { 247 BOOL result ;250 BOOL result = void; 248 251 249 252 if (useWfuncs) … … 258 261 /*************************************************** 259 262 * Delete file name[]. 260 * Throws: FileExceptionon error.263 * Throws: $(D FileException) on error. 261 264 */ 262 265 263 266 void remove(in string name) 264 267 { 265 BOOL result ;268 BOOL result = void; 266 269 267 270 if (useWfuncs) … … 276 279 /*************************************************** 277 280 * Get size of file name[]. 278 * Throws: FileExceptionon error.281 * Throws: $(D FileException) on error. 279 282 */ 280 283 … … 311 314 312 315 /************************* 313 * Get creation/access/modified times of file name[].314 * Throws: FileExceptionon error.316 * Get creation/access/modified times of file $(D name). 317 * Throws: $(D FileException) on error. 315 318 */ 316 319 … … 351 354 */ 352 355 353 int exists(string name)356 bool exists(in string name) 354 357 { 355 358 uint result; … … 361 364 result = GetFileAttributesA(toMBSz(name)); 362 365 363 return (result == 0xFFFFFFFF) ? 0 : 1;366 return result == 0xFFFFFFFF; 364 367 } 365 368 366 369 /*************************************************** 367 370 * Get file name[] attributes. 368 * Throws: FileExceptionon error.371 * Throws: $(D FileException) on error. 369 372 */ 370 373 … … 386 389 /**************************************************** 387 390 * Is name[] a file? 388 * Throws: FileExceptionif name[] doesn't exist.389 */ 390 391 intisfile(in string name)391 * Throws: $(D FileException) if name[] doesn't exist. 392 */ 393 394 bool isfile(in string name) 392 395 { 393 396 return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0; … … 396 399 /**************************************************** 397 400 * Is name[] a directory? 398 * Throws: FileExceptionif name[] doesn't exist.399 */ 400 401 intisdir(in string name)401 * Throws: $(D FileException) if name[] doesn't exist. 402 */ 403 404 bool isdir(in string name) 402 405 { 403 406 return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0; … … 406 409 /**************************************************** 407 410 * Change directory to pathname[]. 408 * Throws: FileExceptionon error.411 * Throws: $(D FileException) on error. 409 412 */ 410 413 … … 425 428 /**************************************************** 426 429 * Make directory pathname[]. 427 * Throws: FileExceptionon error.430 * Throws: $(D FileException) on error. 428 431 */ 429 432 430 433 void mkdir(in string pathname) 431 { BOOL result ;434 { BOOL result = void; 432 435 433 436 if (useWfuncs) … … 444 447 /**************************************************** 445 448 * Remove directory pathname[]. 446 * Throws: FileExceptionon error.449 * Throws: $(D FileException) on error. 447 450 */ 448 451 449 452 void rmdir(in string pathname) 450 { BOOL result ;453 { BOOL result = void; 451 454 452 455 if (useWfuncs) … … 463 466 /**************************************************** 464 467 * Get current directory. 465 * Throws: FileExceptionon error.468 * Throws: $(D FileException) on error. 466 469 */ 467 470 … … 569 572 * Return contents of directory pathname[]. 570 573 * The names in the contents do not include the pathname. 571 * Throws: FileExceptionon error574 * Throws: $(D FileException) on error 572 575 * Example: 573 576 * This program lists all the files and subdirectories in its … … 850 853 void copy(in string from, in string to) 851 854 { 852 BOOL result; 853 854 if (useWfuncs) 855 result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false); 856 else 857 result = CopyFileA(toMBSz(from), toMBSz(to), false); 855 invariant result = useWfuncs 856 ? CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false) 857 : CopyFileA(toMBSz(from), toMBSz(to), false); 858 858 if (!result) 859 throw new FileException(to, GetLastError ());859 throw new FileException(to, GetLastError); 860 860 } 861 861 … … 876 876 class FileException : Exception 877 877 { 878 879 878 uint errno; // operating system error code 880 879 … … 890 889 891 890 this(string name, uint errno) 892 { char[80] buf = void; 891 { 892 char[1024] buf = void; 893 893 auto s = strerror_r(errno, buf.ptr, buf.length); 894 this(name, std.string.toString(s) .idup);894 this(name, std.string.toString(s)); 895 895 this.errno = errno; 896 896 } 897 897 } 898 899 private T cenforce(T)(T condition, lazy string name) 900 { 901 if (!condition) throw new FileException(name, getErrno); 902 return condition; 903 } 904 898 905 899 906 /******************************************** … … 903 910 */ 904 911 905 void[] read(in string name) 906 { 907 uint numread; 908 struct_stat statbuf; 909 910 auto namez = toStringz(name); 911 //printf("file.read('%s')\n",namez); 912 auto fd = std.c.linux.linux.open(namez, O_RDONLY); 913 if (fd == -1) 914 { 915 //printf("\topen error, errno = %d\n",getErrno()); 916 goto err1; 917 } 918 919 //printf("\tfile opened\n"); 920 if (std.c.linux.linux.fstat(fd, &statbuf)) 921 { 922 //printf("\tfstat error, errno = %d\n",getErrno()); 923 goto err2; 924 } 925 auto size = statbuf.st_size; 912 void[] read(string name) 913 { 914 invariant fd = std.c.linux.linux.open(toStringz(name), O_RDONLY); 915 cenforce(fd != -1, name); 916 scope(exit) std.c.linux.linux.close(fd); 917 918 struct_stat statbuf = void; 919 cenforce(std.c.linux.linux.fstat(fd, &statbuf) == 0, name); 920 invariant size = statbuf.st_size; 921 if (!size) return null; 926 922 auto buf = std.gc.malloc(size); 927 if (buf.ptr) 928 std.gc.hasNoPointers(buf.ptr); 929 930 numread = std.c.linux.linux.read(fd, buf.ptr, size); 931 if (numread != size) 932 { 933 //printf("\tread error, errno = %d\n",getErrno()); 934 goto err2; 935 } 936 937 if (std.c.linux.linux.close(fd) == -1) 938 { 939 //printf("\tclose error, errno = %d\n",getErrno()); 940 goto err; 941 } 923 enforce(buf, "Out of memory"); 924 scope(failure) delete buf; 925 std.gc.hasNoPointers(buf.ptr); 926 927 cenforce(std.c.linux.linux.read(fd, buf.ptr, size) == size, name); 942 928 943 929 return buf[0 .. size]; 944 945 err2: 946 std.c.linux.linux.close(fd); 947 err: 948 delete buf; 949 950 err1: 951 throw new FileException(name.idup, getErrno()); 952 } 930 } 931 932 /******************************************** 933 * Read and validates (using $(XREF utf, validate)) a text file. $(D 934 * S) can be a type of array of characters of any width and constancy. 935 * 936 * Returns: array of characters read 937 * 938 * Throws: $(D FileException) on file error, $(D UtfException) on UTF 939 * decoding error. 940 * 941 */ 942 943 S readText(S)(in string name) 944 { 945 auto result = cast(S) read(name); 946 std.utf.validate(result); 947 return result; 948 } 949 950 // Implementation helper for write and append 951 952 private void writeImpl(in string name, in void[] buffer, in uint mode) 953 { 954 invariant fd = std.c.linux.linux.open(toStringz(name), 955 mode, 0660); 956 cenforce(fd != -1, name); 957 { 958 scope(failure) std.c.linux.linux.close(fd); 959 invariant size = buffer.length; 960 cenforce(std.c.linux.linux.write(fd, buffer.ptr, size) == size, name); 961 } 962 cenforce(std.c.linux.linux.close(fd) == 0, name); 963 } 964 953 965 954 966 /********************************************* 955 967 * Write a file. 956 * Returns:957 * 0 success958 968 */ 959 969 960 970 void write(in string name, in void[] buffer) 961 971 { 962 int fd; 963 int numwritten; 964 965 auto namez = toStringz(name); 966 fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC, 0660); 967 if (fd == -1) 968 goto err; 969 970 numwritten = std.c.linux.linux.write(fd, buffer.ptr, buffer.length); 971 if (buffer.length != numwritten) 972 goto err2; 973 974 if (std.c.linux.linux.close(fd) == -1) 975 goto err; 976 977 return; 978 979 err2: 980 std.c.linux.linux.close(fd); 981 err: 982 throw new FileException(name.idup, getErrno()); 983 } 984 972 return writeImpl(name, buffer, O_CREAT | O_WRONLY | O_TRUNC); 973 } 985 974 986 975 /********************************************* … … 990 979 void append(in string name, in void[] buffer) 991 980 { 992 int fd; 993 int numwritten; 994 char *namez; 995 996 namez = toStringz(name); 997 fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT, 0660); 998 if (fd == -1) 999 goto err; 1000 1001 numwritten = std.c.linux.linux.write(fd, buffer.ptr, buffer.length); 1002 if (buffer.length != numwritten) 1003 goto err2; 1004 1005 if (std.c.linux.linux.close(fd) == -1) 1006 goto err; 1007 1008 return; 1009 1010 err2: 1011 std.c.linux.linux.close(fd); 1012 err: 1013 throw new FileException(name.idup, getErrno()); 1014 } 1015 981 return writeImpl(name, buffer, O_APPEND | O_WRONLY | O_CREAT); 982 } 1016 983 1017 984 /*************************************************** … … 1021 988 void rename(in string from, in string to) 1022 989 { 1023 char *fromz = toStringz(from); 1024 char *toz = toStringz(to); 1025 1026 if (std.c.stdio.rename(fromz, toz) == -1) 1027 throw new FileException(to.idup, getErrno()); 1028 } 1029 990 cenforce(std.c.stdio.rename(toStringz(from), toStringz(to)) == -1, to); 991 } 1030 992 1031 993 /*************************************************** … … 1035 997 void remove(in string name) 1036 998 { 1037 if (std.c.stdio.remove(toStringz(name)) == -1) 1038 throw new FileException(name.idup, getErrno()); 999 cenforce(std.c.stdio.remove(toStringz(name)) != -1, name); 1039 1000 } 1040 1001 … … 1046 1007 ulong getSize(in string name) 1047 1008 { 1048 struct_stat statbuf; 1049 if (std.c.linux.linux.stat(toStringz(name), &statbuf)) 1050 { 1051 throw new FileException(name, getErrno()); 1052 } 1009 struct_stat statbuf = void; 1010 cenforce(std.c.linux.linux.stat(toStringz(name), &statbuf) == 0, name); 1053 1011 return statbuf.st_size; 1054 1012 } … … 1071 1029 uint getAttributes(in string name) 1072 1030 { 1073 struct_stat statbuf; 1074 1075 auto namez = toStringz(name); 1076 if (std.c.linux.linux.stat(namez, &statbuf)) 1077 { 1078 throw new FileException(name.idup, getErrno()); 1079 } 1080 1031 struct_stat statbuf = void; 1032 cenforce(std.c.linux.linux.stat(toStringz(name), &statbuf) == 0, name); 1081 1033 return statbuf.st_mode; 1082 1034 } 1083 1035 1084 1036 /************************* 1085 * Get creation/access/modified times of file name[].1086 * Throws: FileExceptionon error.1037 * Get creation/access/modified times of file $(D name). 1038 * Throws: $(D FileException) on error. 1087 1039 */ 1088 1040 1089 1041 void getTimes(in string name, out d_time ftc, out d_time fta, out d_time ftm) 1090 1042 { 1091 struct_stat statbuf; 1092 char *namez; 1093 1094 namez = toStringz(name); 1095 if (std.c.linux.linux.stat(namez, &statbuf)) 1096 { 1097 throw new FileException(name.idup, getErrno()); 1098 } 1099 1100 ftc = cast(d_time)statbuf.st_ctime * std.date.TicksPerSecond; 1101 fta = cast(d_time)statbuf.st_atime * std.date.TicksPerSecond; 1102 ftm = cast(d_time)statbuf.st_mtime * std.date.TicksPerSecond; 1103 } 1104 1043 struct_stat statbuf = void; 1044 cenforce(std.c.linux.linux.stat(toStringz(name), &statbuf) == 0, name); 1045 ftc = cast(d_time) statbuf.st_ctime * std.date.TicksPerSecond; 1046 fta = cast(d_time) statbuf.st_atime * std.date.TicksPerSecond; 1047 ftm = cast(d_time) statbuf.st_mtime * std.date.TicksPerSecond; 1048 } 1049 1050 /************************* 1051 * Set access/modified times of file $(D name). 1052 * Throws: $(D FileException) on error. 1053 */ 1054 1055 void setTimes(in string name, d_time fta, d_time ftm) 1056 { 1057 version (linux) 1058 { 1059 // utimbuf times = { 1060 // cast(__time_t) (fta / std.date.TicksPerSecond), 1061 // cast(__time_t) (ftm / std.date.TicksPerSecond) }; 1062 // enforce(utime(toStringz(name), ×) == 0); 1063 timeval[2] t = void; 1064 t[0].tv_sec = fta / std.date.TicksPerSecond; 1065 t[0].tv_usec = cast(long) ((cast(double) fta / std.date.TicksPerSecond) 1066 * 1_000_000) % 1_000_000; 1067 t[1].tv_sec = ftm / std.date.TicksPerSecond; 1068 t[1].tv_usec = cast(long) ((cast(double) ftm / std.date.TicksPerSecond) 1069 * 1_000_000) % 1_000_000; 1070 enforce(utimes(toStringz(name), t.ptr) == 0); 1071 } 1072 else 1073 { 1074 if (true) enforce(false, "Not implemented"); 1075 } 1076 } 1077 1078 unittest 1079 { 1080 system("touch deleteme") == 0 || assert(false); 1081 scope(exit) remove("deleteme"); 1082 d_time ftc1, fta1, ftm1; 1083 getTimes("deleteme", ftc1, fta1, ftm1); 1084 setTimes("deleteme", fta1 + 1000, ftm1 + 1000); 1085 d_time ftc2, fta2, ftm2; 1086 getTimes("deleteme", ftc2, fta2, ftm2); 1087 assert(fta1 + 1000 == fta2); 1088 assert(ftm1 + 1000 == ftm2); 1089 } 1090 1091 /** 1092 Returns the time of the last modification of file $(D name). If the 1093 file does not exist, throws a $(D FileException). 1094 */ 1095 1096 d_time lastModified(in string name) 1097 { 1098 struct_stat statbuf = void; 1099 cenforce(std.c.linux.linux.stat(toStringz(name), &statbuf) == 0, name); 1100 return cast(d_time) statbuf.st_mtime * std.date.TicksPerSecond; 1101 } 1102 1103 /** 1104 Returns the time of the last modification of file $(D name). If the 1105 file does not exist, returns $(D returnIfMissing). 1106 1107 A frequent usage pattern occurs in build automation tools such as 1108 $(WEB www.gnu.org/software/make, make) or $(WEB 1109 en.wikipedia.org/wiki/Apache_Ant, ant). To check whether file $(D 1110 target) must be rebuilt from file $(D source) (i.e., $(D target) is 1111 older than $(D source) or does not exist), use the comparison below. 1112 1113 ---------------------------- 1114 if (lastModified(source) >= lastModified(target, d_time.min)) 1115 { 1116 ... must (re)build ... 1117 } 1118 else 1119 { 1120 ... target's up-to-date ... 1121 } 1122 ---------------------------- 1123 1124 The code above throws a $(D FileException) if $(D source) does not 1125 exist (as it should). On the other hand, the $(D d_time.min) default 1126 makes a non-existing $(D target) seem infinitely old so the test 1127 correctly prompts building it. 1128 1129 */ 1130 1131 d_time lastModified(string name, d_time returnIfMissing) 1132 { 1133 struct_stat statbuf = void; 1134 return std.c.linux.linux.stat(toStringz(name), &statbuf) != 0 1135 ? returnIfMissing 1136 : cast(d_time) statbuf.st_mtime * std.date.TicksPerSecond; 1137 } 1138 1139 unittest 1140 { 1141 system("touch deleteme") == 0 || assert(false); 1142 scope(exit) remove("deleteme"); 1143 assert(lastModified("deleteme") > 1144 lastModified("this file does not exist", d_time.min)); 1145 assert(lastModified("deleteme") > lastModified(__FILE__)); 1146 } 1105 1147 1106 1148 /**************************************************** … … 1108 1150 */ 1109 1151 1110 int exists(in string name) 1111 { 1112 return access(toStringz(name),0) == 0; 1113 1114 /+ 1115 struct_stat statbuf; 1116 char *namez; 1117 1118 namez = toStringz(name); 1119 if (std.c.linux.linux.stat(namez, &statbuf)) 1120 { 1121 return 0; 1122 } 1123 return 1; 1124 +/ 1152 bool exists(in string name) 1153 { 1154 return access(toStringz(name), 0) == 0; 1125 1155 } 1126 1156 … … 1128 1158 { 1129 1159 assert(exists(".")); 1160 assert(!exists("this file does not exist")); 1161 system("touch deleteme") == 0 || assert(false); 1162 scope(exit) remove("deleteme"); 1163 assert(exists("deleteme")); 1130 1164 } 1131 1165 … … 1134 1168 */ 1135 1169 1136 intisfile(in string name)1170 bool isfile(in string name) 1137 1171 { 1138 1172 return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file … … 1143 1177 */ 1144 1178 1145 int isdir(string name)1179 bool isdir(in string name) 1146 1180 { 1147 1181 return (getAttributes(name) & S_IFMT) == S_IFDIR; … … 1154 1188 void chdir(string pathname) 1155 1189 { 1156 if (std.c.linux.linux.chdir(toStringz(pathname))) 1157 { 1158 throw new FileException(pathname, getErrno()); 1159 } 1190 cenforce(std.c.linux.linux.chdir(toStringz(pathname)) == 0, pathname); 1160 1191 } 1161 1192 … … 1166 1197 void mkdir(string pathname) 1167 1198 { 1168 if (std.c.linux.linux.mkdir(toStringz(pathname), 0777)) 1169 { 1170 throw new FileException(pathname, getErrno()); 1171 } 1199 cenforce(std.c.linux.linux.mkdir(toStringz(pathname), 0777) == 0, pathname); 1172 1200 } 1173 1201 … … 1178 1206 void rmdir(string pathname) 1179 1207 { 1180 if (std.c.linux.linux.rmdir(toStringz(pathname))) 1181 { 1182 throw new FileException(pathname, getErrno()); 1183 } 1208 cenforce(std.c.linux.linux.rmdir(toStringz(pathname)) == 0, pathname); 1184 1209 } 1185 1210 … … 1190 1215 string getcwd() 1191 1216 { 1192 auto p = std.c.linux.linux.getcwd(null, 0); 1193 if (!p) 1194 { 1195 throw new FileException("cannot get cwd", getErrno()); 1196 } 1217 auto p = cenforce(std.c.linux.linux.getcwd(null, 0), 1218 "cannot get cwd"); 1197 1219 scope(exit) std.c.stdlib.free(p); 1198 auto len = std.string.strlen(p); 1199 return p[0 .. len].idup; 1220 return p[0 .. std.string.strlen(p)].idup; 1200 1221 } 1201 1222 … … 1212 1233 d_time _lastWriteTime = d_time_nan; // time file was last written to 1213 1234 ubyte d_type; 1214 ubyte didstat; // done lazy evaluation of stat() 1235 struct_stat statbuf; 1236 bool didstat; // done lazy evaluation of stat() 1215 1237 1216 1238 void init(string path, dirent *fd) 1217 { size_t len = std.string.strlen(fd.d_name.ptr); 1239 { 1240 invariant len = std.string.strlen(fd.d_name.ptr); 1218 1241 name = std.path.join(path, fd.d_name[0 .. len].idup); 1219 1242 d_type = fd.d_type; 1220 didstat = 0;1221 } 1222 1223 intisdir()1224 { 1225 return d_type & DT_DIR;1226 } 1227 1228 intisfile()1229 { 1230 return d_type & DT_REG;1243 didstat = false; 1244 } 1245 1246 bool isdir() 1247 { 1248 return (d_type & DT_DIR) != 0; 1249 } 1250 1251 bool isfile() 1252 { 1253 return (d_type & DT_REG) != 0; 1231 1254 } 1232 1255 1233 1256 ulong size() 1234 1257 { 1235 if (!didstat) 1236 doStat(); 1258 ensureStatDone; 1237 1259 return _size; 1238 1260 } … … 1240 1262 d_time creationTime() 1241 1263 { 1242 if (!didstat) 1243 doStat(); 1264 ensureStatDone; 1244 1265 return _creationTime; 1245 1266 } … … 1247 1268 d_time lastAccessTime() 1248 1269 { 1249 if (!didstat) 1250 doStat(); 1270 ensureStatDone; 1251 1271 return _lastAccessTime; 1252 1272 } … … 1254 1274 d_time lastWriteTime() 1255 1275 { 1256 if (!didstat) 1257 doStat(); 1276 ensureStatDone; 1258 1277 return _lastWriteTime; 1259 1278 } … … 1263 1282 */ 1264 1283 1265 void doStat() 1266 { 1267 int fd; 1268 struct_stat statbuf; 1269 1270 auto namez = toStringz(name); 1271 if (std.c.linux.linux.stat(namez, &statbuf)) 1272 { 1273 //printf("\tstat error, errno = %d\n",getErrno()); 1274 return; 1275 } 1284 void ensureStatDone() 1285 { 1286 if (didstat) return; 1287 enforce(std.c.linux.linux.stat(toStringz(name), &statbuf) == 0, 1288 "Failed to stat file `"~name~"'"); 1276 1289 _size = statbuf.st_size; 1277 1290 _creationTime = cast(d_time)statbuf.st_ctime * std.date.TicksPerSecond; 1278 1291 _lastAccessTime = cast(d_time)statbuf.st_atime * std.date.TicksPerSecond; 1279 1292 _lastWriteTime = cast(d_time)statbuf.st_mtime * std.date.TicksPerSecond; 1280 1281 didstat = 1; 1293 didstat = true; 1282 1294 } 1283 1295 } … … 1350 1362 void listdir(string pathname, bool delegate(DirEntry* de) callback) 1351 1363 { 1352 DIR* h;1353 dirent* fdata;1364 auto h = cenforce(opendir(toStringz(pathname)), pathname); 1365 scope(exit) closedir(h); 1354 1366 DirEntry de; 1355 1356 h = opendir(toStringz(pathname)); 1357 if (h) 1358 { 1359 try 1360 { 1361 while((fdata = readdir(h)) != null) 1362 { 1363 // Skip "." and ".." 1364 if (!std.string.strcmp(fdata.d_name.ptr, ".") || 1365 !std.string.strcmp(fdata.d_name.ptr, "..")) 1366 continue; 1367 1368 de.init(pathname, fdata); 1369 if (!callback(&de)) 1370 break; 1371 } 1372 } 1373 finally 1374 { 1375 closedir(h); 1376 } 1377 } 1378 else 1379 { 1380 throw new FileException(pathname, getErrno()); 1381 } 1382 } 1383 1367 for (dirent* fdata; (fdata = readdir(h)) != null; ) 1368 { 1369 // Skip "." and ".." 1370 if (!std.string.strcmp(fdata.d_name.ptr, ".") || 1371 !std.string.strcmp(fdata.d_name.ptr, "..")) 1372 continue; 1373 de.init(pathname, fdata); 1374 if (!callback(&de)) 1375 break; 1376 } 1377 } 1384 1378 1385 1379 /*************************************************** … … 1389 1383 void copy(in string from, in string to) 1390 1384 { 1391 version (all) 1392 { 1393 struct_stat statbuf; 1394 1395 char* fromz = toStringz(from); 1396 char* toz = toStringz(to); 1397 //printf("file.copy(from='%s', to='%s')\n", fromz, toz); 1398 1399 int fd = std.c.linux.linux.open(fromz, O_RDONLY); 1400 if (fd == -1) 1401 { 1402 //printf("\topen error, errno = %d\n",getErrno()); 1403 goto err1; 1404 } 1405 1406 //printf("\tfile opened\n"); 1407 if (std.c.linux.linux.fstat(fd, &statbuf)) 1408 { 1409 //printf("\tfstat error, errno = %d\n",getErrno()); 1410 goto err2; 1411 } 1412 1413 int fdw = std.c.linux.linux.open(toz, O_CREAT | O_WRONLY | O_TRUNC, 0660); 1414 if (fdw == -1) 1415 { 1416 //printf("\topen error, errno = %d\n",getErrno()); 1417 goto err2; 1418 } 1419 1420 size_t BUFSIZ = 4096 * 16; 1421 void* buf = std.c.stdlib.malloc(BUFSIZ); 1422 if (!buf) 1423 { BUFSIZ = 4096; 1424 buf = std.c.stdlib.malloc(BUFSIZ); 1425 } 1426 if (!buf) 1427 { 1428 //printf("\topen error, errno = %d\n",getErrno()); 1429 goto err4; 1430 } 1431 1432 for (size_t size = statbuf.st_size; size; ) 1433 { size_t toread = (size > BUFSIZ) ? BUFSIZ : size; 1434 1435 auto n = std.c.linux.linux.read(fd, buf, toread); 1436 if (n != toread) 1437 { 1438 //printf("\tread error, errno = %d\n",getErrno()); 1439 goto err5; 1440 } 1441 n = std.c.linux.linux.write(fdw, buf, toread); 1442 if (n != toread) 1443 { 1444 //printf("\twrite error, errno = %d\n",getErrno()); 1445 goto err5; 1446 } 1447 size -= toread; 1448 } 1449 1450 std.c.stdlib.free(buf); 1451 1452 if (std.c.linux.linux.close(fdw) == -1) 1453 { 1454 //printf("\tclose error, errno = %d\n",getErrno()); 1455 goto err2; 1456 } 1457 1458 utimbuf utim; 1459 utim.actime = cast(__time_t)statbuf.st_atime; 1460 utim.modtime = cast(__time_t)statbuf.st_mtime; 1461 if (utime(toz, &utim) == -1) 1462 { 1463 //printf("\tutime error, errno = %d\n",getErrno()); 1464 goto err3; 1465 } 1466 1467 if (std.c.linux.linux.close(fd) == -1) 1468 { 1469 //printf("\tclose error, errno = %d\n",getErrno()); 1470 goto err1; 1471 } 1472 1473 return; 1474 1475 err5: 1476 std.c.stdlib.free(buf); 1477 err4: 1478 std.c.linux.linux.close(fdw); 1479 err3: 1480 std.c.stdio.remove(toz); 1481 err2: 1482 std.c.linux.linux.close(fd); 1483 err1: 1484 throw new FileException(from.idup, getErrno()); 1485 } 1486 else 1487 { 1488 void[] buffer; 1489 1490 buffer = read(from); 1491 write(to, buffer); 1492 delete buffer; 1493 } 1385 version (all) 1386 { 1387 invariant fd = std.c.linux.linux.open(toStringz(from), O_RDONLY); 1388 cenforce(fd != -1, from); 1389 scope(exit) std.c.linux.linux.close(fd); 1390 1391 struct_stat statbuf = void; 1392 cenforce(std.c.linux.linux.fstat(fd, &statbuf) == 0, from); 1393 1394 auto toz = toStringz(to); 1395 invariant fdw = std.c.linux.linux.open(toz, 1396 O_CREAT | O_WRONLY | O_TRUNC, 0660); 1397 cenforce(fdw != -1, from); 1398 scope(failure) std.c.stdio.remove(toz); 1399 { 1400 scope(failure) std.c.linux.linux.close(fdw); 1401 auto BUFSIZ = 4096u * 16; 1402 auto buf = std.c.stdlib.malloc(BUFSIZ); 1403 if (!buf) 1404 { 1405 BUFSIZ = 4096; 1406 buf = enforce(std.c.stdlib.malloc(BUFSIZ), "Out of memory"); 1407 } 1408 scope(exit) std.c.stdlib.free(buf); 1409 1410 for (size_t size = statbuf.st_size; size; ) 1411 { 1412 invariant toxfer = (size > BUFSIZ) ? BUFSIZ : size; 1413 cenforce(std.c.linux.linux.read(fd, buf, toxfer) == toxfer 1414 && std.c.linux.linux.write(fdw, buf, toxfer) == toxfer, 1415 from); 1416 assert(size >= toxfer); 1417 size -= toxfer; 1418 } 1419 } 1420 1421 cenforce(std.c.linux.linux.close(fdw) != -1, from); 1422 1423 utimbuf utim = void; 1424 utim.actime = cast(__time_t) statbuf.st_atime; 1425 utim.modtime = cast(__time_t) statbuf.st_mtime; 1426 cenforce(utime(toz, &utim) != -1, from); 1427 } 1428 else 1429 { 1430 void[] buffer; 1431 1432 buffer = read(from); 1433 write(to, buffer); 1434 delete buffer; 1435 } 1494 1436 } 1495 1437
