Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(3)

Side by Side Diff: Modules/posixmodule.c

Issue 10027: os.lstat/os.stat don't set st_nlink on Windows
Patch Set: Created 9 years, 5 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* POSIX module implementation */ 2 /* POSIX module implementation */
3 3
4 /* This file is also used for Windows NT/MS-Win and OS/2. In that case the 4 /* This file is also used for Windows NT/MS-Win and OS/2. In that case the
5 module actually calls itself 'nt' or 'os2', not 'posix', and a few 5 module actually calls itself 'nt' or 'os2', not 'posix', and a few
6 functions are either unimplemented or implemented differently. The source 6 functions are either unimplemented or implemented differently. The source
7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent 7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
8 of the compiler used. Different compilers define their own feature 8 of the compiler used. Different compilers define their own feature
9 test macro, e.g. '__BORLANDC__' or '_MSC_VER'. For OS/2, the compiler 9 test macro, e.g. '__BORLANDC__' or '_MSC_VER'. For OS/2, the compiler
10 independent macro PYOS_OS2 should be defined. On OS/2 the default 10 independent macro PYOS_OS2 should be defined. On OS/2 the default
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 structure for the target. In Windows, the equivalent GetFileAttributes by 989 structure for the target. In Windows, the equivalent GetFileAttributes by
990 default does not traverse symlinks and instead returns attributes for 990 default does not traverse symlinks and instead returns attributes for
991 the symlink. 991 the symlink.
992 992
993 Therefore, win32_lstat will get the attributes traditionally, and 993 Therefore, win32_lstat will get the attributes traditionally, and
994 win32_stat will first explicitly resolve the symlink target and then will 994 win32_stat will first explicitly resolve the symlink target and then will
995 call win32_lstat on that result. 995 call win32_lstat on that result.
996 996
997 The _w represent Unicode equivalents of the aformentioned ANSI functions. */ 997 The _w represent Unicode equivalents of the aformentioned ANSI functions. */
998 998
999 static int 999 static int
1000 win32_lstat(const char* path, struct win32_stat *result) 1000 win32_osfstat(HANDLE h, struct win32_stat *result)
1001 { 1001 {
1002 WIN32_FILE_ATTRIBUTE_DATA info; 1002 BY_HANDLE_FILE_INFORMATION info;
1003 int code; 1003 int type;
1004 char *dot; 1004
1005 WIN32_FIND_DATAA find_data; 1005 /* Protocol violation: we explicitly clear errno, instead of
1006 HANDLE find_data_handle; 1006 setting it to a POSIX error. Callers should use GetLastError. */
1007 if (!GetFileAttributesExA(path, GetFileExInfoStandard, &info)) { 1007 errno = 0;
1008 if (GetLastError() != ERROR_SHARING_VIOLATION) { 1008
1009 /* Protocol violation: we explicitly clear errno, instead of 1009 if (h == INVALID_HANDLE_VALUE) {
1010 setting it to a POSIX error. Callers should use GetLastError. */ 1010 /* This is really a C library error (invalid file handle).
1011 errno = 0; 1011 We set the Win32 error to the closes one matching. */
1012 return -1; 1012 SetLastError(ERROR_INVALID_HANDLE);
1013 } else { 1013 return -1;
1014 /* Could not get attributes on open file. Fall back to 1014 }
1015 reading the directory. */ 1015 memset(result, 0, sizeof(*result));
1016 if (!attributes_from_dir(path, &info)) { 1016
1017 /* Very strange. This should not fail now */ 1017 type = GetFileType(h);
1018 errno = 0; 1018 if (type == FILE_TYPE_UNKNOWN) {
1019 return -1; 1019 DWORD error = GetLastError();
1020 } 1020 if (error != 0) {
1021 return -1;
1021 } 1022 }
1023 /* else: valid but unknown file */
1022 } 1024 }
1023 1025
1024 code = attribute_data_to_stat(&info, result); 1026 if (type != FILE_TYPE_DISK) {
1025 if (code != 0) 1027 if (type == FILE_TYPE_CHAR)
1026 return code; 1028 result->st_mode = _S_IFCHR;
1027 1029 else if (type == FILE_TYPE_PIPE)
1028 /* Get WIN32_FIND_DATA structure for the path to determine if 1030 result->st_mode = _S_IFIFO;
1029 it is a symlink */ 1031 return 0;
1030 if(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1031 find_data_handle = FindFirstFileA(path, &find_data);
1032 if(find_data_handle != INVALID_HANDLE_VALUE) {
1033 if(find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
1034 /* first clear the S_IFMT bits */
1035 result->st_mode ^= (result->st_mode & 0170000);
1036 /* now set the bits that make this a symlink */
1037 result->st_mode |= 0120000;
1038 }
1039 FindClose(find_data_handle);
1040 }
1041 } 1032 }
1042 1033
1043 /* Set S_IFEXEC if it is an .exe, .bat, ... */ 1034 if (!GetFileInformationByHandle(h, &info)) {
1044 dot = strrchr(path, '.'); 1035 return -1;
1045 if (dot) {
1046 if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 ||
1047 stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0)
1048 result->st_mode |= 0111;
1049 } 1036 }
1050 return code; 1037
1038 /* similar to stat() */
1039 result->st_mode = attributes_to_mode(info.dwFileAttributes);
1040 result->st_size = (((__int64)info.nFileSizeHigh)<<32) + info.nFileSizeLow;
1041 FILE_TIME_to_time_t_nsec(&info.ftCreationTime, &result->st_ctime,
1042 &result->st_ctime_nsec);
1043 FILE_TIME_to_time_t_nsec(&info.ftLastWriteTime, &result->st_mtime,
1044 &result->st_mtime_nsec);
1045 FILE_TIME_to_time_t_nsec(&info.ftLastAccessTime, &result->st_atime,
1046 &result->st_atime_nsec);
1047 /* specific to fstat() */
1048 result->st_nlink = info.nNumberOfLinks;
1049 result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
1050 return 0;
1051 } 1051 }
1052 1052
1053 static int 1053 static int
1054 win32_lstat_w(const wchar_t* path, struct win32_stat *result) 1054 _win32_stat(const char* path, DWORD flag, struct win32_stat *result)
1055 {
1056 int code;
1057 const wchar_t *dot;
1058 WIN32_FILE_ATTRIBUTE_DATA info;
1059 WIN32_FIND_DATAW find_data;
1060 HANDLE find_data_handle;
1061 if (!GetFileAttributesExW(path, GetFileExInfoStandard, &info)) {
1062 if (GetLastError() != ERROR_SHARING_VIOLATION) {
1063 /* Protocol violation: we explicitly clear errno, instead of
1064 setting it to a POSIX error. Callers should use GetLastError. */
1065 errno = 0;
1066 return -1;
1067 } else {
1068 /* Could not get attributes on open file. Fall back to reading
1069 the directory. */
1070 if (!attributes_from_dir_w(path, &info)) {
1071 /* Very strange. This should not fail now */
1072 errno = 0;
1073 return -1;
1074 }
1075 }
1076 }
1077 code = attribute_data_to_stat(&info, result);
1078 if (code < 0)
1079 return code;
1080
1081 /* Get WIN32_FIND_DATA structure for the path to determine if
1082 it is a symlink */
1083 if(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1084 find_data_handle = FindFirstFileW(path, &find_data);
1085 if(find_data_handle != INVALID_HANDLE_VALUE) {
1086 if(find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
1087 /* first clear the S_IFMT bits */
1088 result->st_mode ^= (result->st_mode & 0170000);
1089 /* now set the bits that make this a symlink */
1090 result->st_mode |= 0120000;
1091 }
1092 FindClose(find_data_handle);
1093 }
1094 }
1095
1096 /* Set IFEXEC if it is an .exe, .bat, ... */
1097 dot = wcsrchr(path, '.');
1098 if (dot) {
1099 if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 ||
1100 _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0)
1101 result->st_mode |= 0111;
1102 }
1103 return code;
1104 }
1105
1106 /* Grab GetFinalPathNameByHandle dynamically from kernel32 */
1107 static int has_GetFinalPathNameByHandle = 0;
1108 static DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD,
1109 DWORD);
1110 static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD,
1111 DWORD);
1112 static int
1113 check_GetFinalPathNameByHandle()
1114 {
1115 HINSTANCE hKernel32;
1116 /* only recheck */
1117 if (!has_GetFinalPathNameByHandle)
1118 {
1119 hKernel32 = GetModuleHandle("KERNEL32");
1120 *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32,
1121 "GetFinalPathNameByHandleA");
1122 *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32,
1123 "GetFinalPathNameByHandleW");
1124 has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA &&
1125 Py_GetFinalPathNameByHandleW;
1126 }
1127 return has_GetFinalPathNameByHandle;
1128 }
1129
1130 static int
1131 win32_stat(const char* path, struct win32_stat *result)
1132 { 1055 {
1133 /* Traverse the symlink to the target using 1056 /* Traverse the symlink to the target using
1134 GetFinalPathNameByHandle() 1057 GetFinalPathNameByHandle()
1135 */ 1058 */
1136 int code; 1059 int code;
1137 HANDLE hFile; 1060 HANDLE hFile;
1138 int buf_size;
1139 char *target_path;
1140 int result_length;
1141 WIN32_FILE_ATTRIBUTE_DATA info; 1061 WIN32_FILE_ATTRIBUTE_DATA info;
1142
1143 if(!check_GetFinalPathNameByHandle()) {
1144 /* if the OS doesn't have GetFinalPathNameByHandle, it doesn't
1145 have symlinks, so just fall back to the traditional behavior
1146 found in lstat. */
1147 return win32_lstat(path, result);
1148 }
1149 1062
1150 hFile = CreateFileA( 1063 hFile = CreateFileA(
1151 path, 1064 path,
1152 0, /* desired access */ 1065 0, /* desired access */
1153 0, /* share mode */ 1066 0, /* share mode */
1154 NULL, /* security attributes */ 1067 NULL, /* security attributes */
1155 OPEN_EXISTING, 1068 OPEN_EXISTING,
1156 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ 1069 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1157 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, 1070 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|flag,
1158 NULL); 1071 NULL);
1159 1072
1160 if(hFile == INVALID_HANDLE_VALUE) { 1073 if(hFile == INVALID_HANDLE_VALUE) {
1161 /* Either the target doesn't exist, or we don't have access to 1074 /* Either the target doesn't exist, or we don't have access to
1162 get a handle to it. If the former, we need to return an error. 1075 get a handle to it. If the former, we need to return an error.
1163 If the latter, we can use attributes_from_dir. */ 1076 If the latter, we can use attributes_from_dir. */
1164 if (GetLastError() != ERROR_SHARING_VIOLATION) { 1077 if (GetLastError() != ERROR_SHARING_VIOLATION) {
1165 /* Protocol violation: we explicitly clear errno, instead of 1078 /* Protocol violation: we explicitly clear errno, instead of
1166 setting it to a POSIX error. Callers should use GetLastError. */ 1079 setting it to a POSIX error. Callers should use GetLastError. */
1167 errno = 0; 1080 errno = 0;
1168 return -1; 1081 return -1;
1169 } else { 1082 } else {
1170 /* Could not get attributes on open file. Fall back to 1083 /* Could not get attributes on open file. Fall back to
1171 reading the directory. */ 1084 reading the directory. */
1172 if (!attributes_from_dir(path, &info)) { 1085 if (!attributes_from_dir(path, &info)) {
1173 /* Very strange. This should not fail now */ 1086 /* Very strange. This should not fail now */
1174 errno = 0; 1087 errno = 0;
1175 return -1; 1088 return -1;
1176 } 1089 }
1177 } 1090 }
1178 code = attribute_data_to_stat(&info, result); 1091 code = attribute_data_to_stat(&info, result);
1179 } 1092 }
1180 else { 1093 else {
1181 /* We have a good handle to the target, use it to determine the target 1094 code = win32_osfstat(hFile, result);
1182 path name (then we'll call lstat on it). */ 1095 CloseHandle(hFile);
1183 buf_size = Py_GetFinalPathNameByHandleA(hFile, 0, 0, VOLUME_NAME_DOS);
1184 if(!buf_size) return -1;
1185 /* Due to a slight discrepancy between GetFinalPathNameByHandleA
1186 and GetFinalPathNameByHandleW, we must allocate one more byte
1187 than reported. */
1188 target_path = (char *)malloc((buf_size+2)*sizeof(char));
1189 result_length = Py_GetFinalPathNameByHandleA(hFile, target_path,
1190 buf_size+1, VOLUME_NAME_DOS );
1191
1192 if(!result_length) {
1193 free(target_path);
1194 return -1;
1195 }
1196
1197 if(!CloseHandle(hFile)) {
1198 free(target_path);
1199 return -1;
1200 }
1201
1202 target_path[result_length] = 0;
1203 code = win32_lstat(target_path, result);
1204 free(target_path);
1205 } 1096 }
1206 1097
1207 return code; 1098 return code;
1208 } 1099 }
1209 1100
1210 static int 1101 static int
1211 win32_stat_w(const wchar_t* path, struct win32_stat *result) 1102 _win32_stat_w(const wchar_t* path, DWORD flag, struct win32_stat *result)
1212 { 1103 {
1213 /* Traverse the symlink to the target using GetFinalPathNameByHandle() */ 1104 /* Traverse the symlink to the target using GetFinalPathNameByHandle() */
1214 int code; 1105 int code;
1215 HANDLE hFile; 1106 HANDLE hFile;
1216 int buf_size;
1217 wchar_t *target_path;
1218 int result_length;
1219 WIN32_FILE_ATTRIBUTE_DATA info; 1107 WIN32_FILE_ATTRIBUTE_DATA info;
1220
1221 if(!check_GetFinalPathNameByHandle()) {
1222 /* If the OS doesn't have GetFinalPathNameByHandle, it doesn't have
1223 symlinks, so just fall back to the traditional behavior found
1224 in lstat. */
1225 return win32_lstat_w(path, result);
1226 }
1227 1108
1228 hFile = CreateFileW( 1109 hFile = CreateFileW(
1229 path, 1110 path,
1230 0, /* desired access */ 1111 0, /* desired access */
1231 0, /* share mode */ 1112 0, /* share mode */
1232 NULL, /* security attributes */ 1113 NULL, /* security attributes */
1233 OPEN_EXISTING, 1114 OPEN_EXISTING,
1234 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ 1115 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1235 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, 1116 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|flag,
1236 NULL); 1117 NULL);
1237 1118
1238 if(hFile == INVALID_HANDLE_VALUE) { 1119 if(hFile == INVALID_HANDLE_VALUE) {
1239 /* Either the target doesn't exist, or we don't have access to 1120 /* Either the target doesn't exist, or we don't have access to
1240 get a handle to it. If the former, we need to return an error. 1121 get a handle to it. If the former, we need to return an error.
1241 If the latter, we can use attributes_from_dir. */ 1122 If the latter, we can use attributes_from_dir. */
1242 if (GetLastError() != ERROR_SHARING_VIOLATION) { 1123 if (GetLastError() != ERROR_SHARING_VIOLATION) {
1243 /* Protocol violation: we explicitly clear errno, instead of 1124 /* Protocol violation: we explicitly clear errno, instead of
1244 setting it to a POSIX error. Callers should use GetLastError. */ 1125 setting it to a POSIX error. Callers should use GetLastError. */
1245 errno = 0; 1126 errno = 0;
1246 return -1; 1127 return -1;
1247 } else { 1128 } else {
1248 /* Could not get attributes on open file. Fall back to 1129 /* Could not get attributes on open file. Fall back to
1249 reading the directory. */ 1130 reading the directory. */
1250 if (!attributes_from_dir_w(path, &info)) { 1131 if (!attributes_from_dir_w(path, &info)) {
1251 /* Very strange. This should not fail now */ 1132 /* Very strange. This should not fail now */
1252 errno = 0; 1133 errno = 0;
1253 return -1; 1134 return -1;
1254 } 1135 }
1255 } 1136 }
1256 code = attribute_data_to_stat(&info, result); 1137 code = attribute_data_to_stat(&info, result);
1257 } 1138 }
1258 else { 1139 else {
1259 /* We have a good handle to the target, use it to determine the target 1140 code = win32_osfstat(hFile, result);
1260 path name (then we'll call lstat on it). */ 1141 CloseHandle(hFile);
1261 buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_DOS);
1262 if(!buf_size)
1263 return -1;
1264
1265 target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
1266 result_length = Py_GetFinalPathNameByHandleW(hFile, target_path,
1267 buf_size, VOLUME_NAME_DOS);
1268
1269 if(!result_length) {
1270 free(target_path);
1271 return -1;
1272 }
1273
1274 if(!CloseHandle(hFile)) {
1275 free(target_path);
1276 return -1;
1277 }
1278
1279 target_path[result_length] = 0;
1280 code = win32_lstat_w(target_path, result);
1281 free(target_path);
1282 } 1142 }
1283 1143
1284 return code; 1144 return code;
1285 } 1145 }
1286 1146
1147 static int
1148 win32_lstat(const char* path, struct win32_stat *result)
1149 {
1150 return _win32_stat(path, FILE_FLAG_OPEN_REPARSE_POINT, result);
1151 }
1152
1153 static int
1154 win32_lstat_w(const wchar_t* path, struct win32_stat *result)
1155 {
1156 return _win32_stat_w(path, FILE_FLAG_OPEN_REPARSE_POINT, result);
1157 }
1158
1159 /* Grab GetFinalPathNameByHandle dynamically from kernel32 */
1160 static int has_GetFinalPathNameByHandle = 0;
1161 static DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD,
1162 DWORD);
1163 static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD,
1164 DWORD);
1165 static int
1166 check_GetFinalPathNameByHandle()
1167 {
1168 HINSTANCE hKernel32;
1169 /* only recheck */
1170 if (!has_GetFinalPathNameByHandle)
1171 {
1172 hKernel32 = GetModuleHandle("KERNEL32");
1173 *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32,
1174 "GetFinalPathNameByHandleA");
1175 *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32,
1176 "GetFinalPathNameByHandleW");
1177 has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA &&
1178 Py_GetFinalPathNameByHandleW;
1179 }
1180 return has_GetFinalPathNameByHandle;
1181 }
1182
1183 static int
1184 win32_stat(const char* path, struct win32_stat *result)
1185 {
1186 return _win32_stat(path, 0, result);
1187 }
1188
1189 static int
1190 win32_stat_w(const wchar_t* path, struct win32_stat *result)
1191 {
1192 return _win32_stat_w(path, 0, result);
1193 }
1194
1287 static int 1195 static int
1288 win32_fstat(int file_number, struct win32_stat *result) 1196 win32_fstat(int file_number, struct win32_stat *result)
1289 { 1197 {
1290 BY_HANDLE_FILE_INFORMATION info;
1291 HANDLE h; 1198 HANDLE h;
1292 int type;
1293 1199
1294 h = (HANDLE)_get_osfhandle(file_number); 1200 h = (HANDLE)_get_osfhandle(file_number);
1295 1201
1296 /* Protocol violation: we explicitly clear errno, instead of 1202 return win32_osfstat(h, result);
1297 setting it to a POSIX error. Callers should use GetLastError. */
1298 errno = 0;
1299
1300 if (h == INVALID_HANDLE_VALUE) {
1301 /* This is really a C library error (invalid file handle).
1302 We set the Win32 error to the closes one matching. */
1303 SetLastError(ERROR_INVALID_HANDLE);
1304 return -1;
1305 }
1306 memset(result, 0, sizeof(*result));
1307
1308 type = GetFileType(h);
1309 if (type == FILE_TYPE_UNKNOWN) {
1310 DWORD error = GetLastError();
1311 if (error != 0) {
1312 return -1;
1313 }
1314 /* else: valid but unknown file */
1315 }
1316
1317 if (type != FILE_TYPE_DISK) {
1318 if (type == FILE_TYPE_CHAR)
1319 result->st_mode = _S_IFCHR;
1320 else if (type == FILE_TYPE_PIPE)
1321 result->st_mode = _S_IFIFO;
1322 return 0;
1323 }
1324
1325 if (!GetFileInformationByHandle(h, &info)) {
1326 return -1;
1327 }
1328
1329 /* similar to stat() */
1330 result->st_mode = attributes_to_mode(info.dwFileAttributes);
1331 result->st_size = (((__int64)info.nFileSizeHigh)<<32) + info.nFileSizeLow;
1332 FILE_TIME_to_time_t_nsec(&info.ftCreationTime, &result->st_ctime,
1333 &result->st_ctime_nsec);
1334 FILE_TIME_to_time_t_nsec(&info.ftLastWriteTime, &result->st_mtime,
1335 &result->st_mtime_nsec);
1336 FILE_TIME_to_time_t_nsec(&info.ftLastAccessTime, &result->st_atime,
1337 &result->st_atime_nsec);
1338 /* specific to fstat() */
1339 result->st_nlink = info.nNumberOfLinks;
1340 result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
1341 return 0;
1342 } 1203 }
1343 1204
1344 #endif /* MS_WINDOWS */ 1205 #endif /* MS_WINDOWS */
1345 1206
1346 PyDoc_STRVAR(stat_result__doc__, 1207 PyDoc_STRVAR(stat_result__doc__,
1347 "stat_result: Result from stat or lstat.\n\n\ 1208 "stat_result: Result from stat or lstat.\n\n\
1348 This object may be accessed either as a tuple of\n\ 1209 This object may be accessed either as a tuple of\n\
1349 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ 1210 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1350 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ 1211 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1351 \n\ 1212 \n\
(...skipping 7032 matching lines...) Expand 10 before | Expand all | Expand 10 after
8384 8245
8385 8246
8386 #endif /* __APPLE__ */ 8247 #endif /* __APPLE__ */
8387 return m; 8248 return m;
8388 8249
8389 } 8250 }
8390 8251
8391 #ifdef __cplusplus 8252 #ifdef __cplusplus
8392 } 8253 }
8393 #endif 8254 #endif
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+