Skip to content

Commit d7a9b69

Browse files
authored
Update stat from 3.13.5 (RustPython#5992)
* Update stat from 3.13.5 * Set correct value for S_IFWHT on macos
1 parent 4f9dd41 commit d7a9b69

3 files changed

Lines changed: 114 additions & 11 deletions

File tree

Lib/stat.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,22 +110,30 @@ def S_ISWHT(mode):
110110
S_IXOTH = 0o0001 # execute by others
111111

112112
# Names for file flags
113-
113+
UF_SETTABLE = 0x0000ffff # owner settable flags
114114
UF_NODUMP = 0x00000001 # do not dump file
115115
UF_IMMUTABLE = 0x00000002 # file may not be changed
116116
UF_APPEND = 0x00000004 # file may only be appended to
117117
UF_OPAQUE = 0x00000008 # directory is opaque when viewed through a union stack
118118
UF_NOUNLINK = 0x00000010 # file may not be renamed or deleted
119-
UF_COMPRESSED = 0x00000020 # OS X: file is hfs-compressed
120-
UF_HIDDEN = 0x00008000 # OS X: file should not be displayed
119+
UF_COMPRESSED = 0x00000020 # macOS: file is compressed
120+
UF_TRACKED = 0x00000040 # macOS: used for handling document IDs
121+
UF_DATAVAULT = 0x00000080 # macOS: entitlement needed for I/O
122+
UF_HIDDEN = 0x00008000 # macOS: file should not be displayed
123+
SF_SETTABLE = 0xffff0000 # superuser settable flags
121124
SF_ARCHIVED = 0x00010000 # file may be archived
122125
SF_IMMUTABLE = 0x00020000 # file may not be changed
123126
SF_APPEND = 0x00040000 # file may only be appended to
127+
SF_RESTRICTED = 0x00080000 # macOS: entitlement needed for writing
124128
SF_NOUNLINK = 0x00100000 # file may not be renamed or deleted
125129
SF_SNAPSHOT = 0x00200000 # file is a snapshot file
130+
SF_FIRMLINK = 0x00800000 # macOS: file is a firmlink
131+
SF_DATALESS = 0x40000000 # macOS: file is a dataless object
126132

127133

128134
_filemode_table = (
135+
# File type chars according to:
136+
# http://en.wikibooks.org/wiki/C_Programming/POSIX_Reference/sys/stat.h
129137
((S_IFLNK, "l"),
130138
(S_IFSOCK, "s"), # Must appear before IFREG and IFDIR as IFSOCK == IFREG | IFDIR
131139
(S_IFREG, "-"),
@@ -156,13 +164,17 @@ def S_ISWHT(mode):
156164
def filemode(mode):
157165
"""Convert a file's mode to a string of the form '-rwxrwxrwx'."""
158166
perm = []
159-
for table in _filemode_table:
167+
for index, table in enumerate(_filemode_table):
160168
for bit, char in table:
161169
if mode & bit == bit:
162170
perm.append(char)
163171
break
164172
else:
165-
perm.append("-")
173+
if index == 0:
174+
# Unknown filetype
175+
perm.append("?")
176+
else:
177+
perm.append("-")
166178
return "".join(perm)
167179

168180

Lib/test/test_stat.py

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
import os
33
import socket
44
import sys
5-
from test.support import os_helper
6-
from test.support import socket_helper
5+
from test.support import is_apple, os_helper, socket_helper
76
from test.support.import_helper import import_fresh_module
87
from test.support.os_helper import TESTFN
98

@@ -15,8 +14,10 @@ class TestFilemode:
1514
statmod = None
1615

1716
file_flags = {'SF_APPEND', 'SF_ARCHIVED', 'SF_IMMUTABLE', 'SF_NOUNLINK',
18-
'SF_SNAPSHOT', 'UF_APPEND', 'UF_COMPRESSED', 'UF_HIDDEN',
19-
'UF_IMMUTABLE', 'UF_NODUMP', 'UF_NOUNLINK', 'UF_OPAQUE'}
17+
'SF_SNAPSHOT', 'SF_SETTABLE', 'SF_RESTRICTED', 'SF_FIRMLINK',
18+
'SF_DATALESS', 'UF_APPEND', 'UF_COMPRESSED', 'UF_HIDDEN',
19+
'UF_IMMUTABLE', 'UF_NODUMP', 'UF_NOUNLINK', 'UF_OPAQUE',
20+
'UF_SETTABLE', 'UF_TRACKED', 'UF_DATAVAULT'}
2021

2122
formats = {'S_IFBLK', 'S_IFCHR', 'S_IFDIR', 'S_IFIFO', 'S_IFLNK',
2223
'S_IFREG', 'S_IFSOCK', 'S_IFDOOR', 'S_IFPORT', 'S_IFWHT'}
@@ -113,6 +114,7 @@ def assertS_IS(self, name, mode):
113114
else:
114115
self.assertFalse(func(mode))
115116

117+
@os_helper.skip_unless_working_chmod
116118
def test_mode(self):
117119
with open(TESTFN, 'w'):
118120
pass
@@ -121,8 +123,11 @@ def test_mode(self):
121123
st_mode, modestr = self.get_mode()
122124
self.assertEqual(modestr, '-rwx------')
123125
self.assertS_IS("REG", st_mode)
124-
self.assertEqual(self.statmod.S_IMODE(st_mode),
126+
imode = self.statmod.S_IMODE(st_mode)
127+
self.assertEqual(imode,
125128
self.statmod.S_IRWXU)
129+
self.assertEqual(self.statmod.filemode(imode),
130+
'?rwx------')
126131

127132
os.chmod(TESTFN, 0o070)
128133
st_mode, modestr = self.get_mode()
@@ -144,13 +149,21 @@ def test_mode(self):
144149
self.assertEqual(modestr, '-r--r--r--')
145150
self.assertEqual(self.statmod.S_IMODE(st_mode), 0o444)
146151
else:
152+
os.chmod(TESTFN, 0o500)
153+
st_mode, modestr = self.get_mode()
154+
self.assertEqual(modestr[:3], '-r-')
155+
self.assertS_IS("REG", st_mode)
156+
self.assertEqual(self.statmod.S_IMODE(st_mode), 0o444)
157+
147158
os.chmod(TESTFN, 0o700)
148159
st_mode, modestr = self.get_mode()
149160
self.assertEqual(modestr[:3], '-rw')
150161
self.assertS_IS("REG", st_mode)
151162
self.assertEqual(self.statmod.S_IFMT(st_mode),
152163
self.statmod.S_IFREG)
164+
self.assertEqual(self.statmod.S_IMODE(st_mode), 0o666)
153165

166+
@os_helper.skip_unless_working_chmod
154167
def test_directory(self):
155168
os.mkdir(TESTFN)
156169
os.chmod(TESTFN, 0o700)
@@ -161,7 +174,7 @@ def test_directory(self):
161174
else:
162175
self.assertEqual(modestr[0], 'd')
163176

164-
@unittest.skipUnless(hasattr(os, 'symlink'), 'os.symlink not available')
177+
@os_helper.skip_unless_symlink
165178
def test_link(self):
166179
try:
167180
os.symlink(os.getcwd(), TESTFN)
@@ -227,6 +240,18 @@ def test_module_attributes(self):
227240
self.assertTrue(callable(func))
228241
self.assertEqual(func(0), 0)
229242

243+
def test_flags_consistent(self):
244+
self.assertFalse(self.statmod.UF_SETTABLE & self.statmod.SF_SETTABLE)
245+
246+
for flag in self.file_flags:
247+
if flag.startswith("UF"):
248+
self.assertTrue(getattr(self.statmod, flag) & self.statmod.UF_SETTABLE, f"{flag} not in UF_SETTABLE")
249+
elif is_apple and self.statmod is c_stat and flag == 'SF_DATALESS':
250+
self.assertTrue(self.statmod.SF_DATALESS & self.statmod.SF_SYNTHETIC, "SF_DATALESS not in SF_SYNTHETIC")
251+
self.assertFalse(self.statmod.SF_DATALESS & self.statmod.SF_SETTABLE, "SF_DATALESS in SF_SETTABLE")
252+
else:
253+
self.assertTrue(getattr(self.statmod, flag) & self.statmod.SF_SETTABLE, f"{flag} notin SF_SETTABLE")
254+
230255
@unittest.skipUnless(sys.platform == "win32",
231256
"FILE_ATTRIBUTE_* constants are Win32 specific")
232257
def test_file_attribute_constants(self):
@@ -235,7 +260,68 @@ def test_file_attribute_constants(self):
235260
modvalue = getattr(self.statmod, key)
236261
self.assertEqual(value, modvalue, key)
237262

263+
@unittest.skipUnless(sys.platform == "darwin", "macOS system check")
264+
def test_macosx_attribute_values(self):
265+
self.assertEqual(self.statmod.UF_SETTABLE, 0x0000ffff)
266+
self.assertEqual(self.statmod.UF_NODUMP, 0x00000001)
267+
self.assertEqual(self.statmod.UF_IMMUTABLE, 0x00000002)
268+
self.assertEqual(self.statmod.UF_APPEND, 0x00000004)
269+
self.assertEqual(self.statmod.UF_OPAQUE, 0x00000008)
270+
self.assertEqual(self.statmod.UF_COMPRESSED, 0x00000020)
271+
self.assertEqual(self.statmod.UF_TRACKED, 0x00000040)
272+
self.assertEqual(self.statmod.UF_DATAVAULT, 0x00000080)
273+
self.assertEqual(self.statmod.UF_HIDDEN, 0x00008000)
274+
275+
if self.statmod is c_stat:
276+
self.assertEqual(self.statmod.SF_SUPPORTED, 0x009f0000)
277+
self.assertEqual(self.statmod.SF_SETTABLE, 0x3fff0000)
278+
self.assertEqual(self.statmod.SF_SYNTHETIC, 0xc0000000)
279+
else:
280+
self.assertEqual(self.statmod.SF_SETTABLE, 0xffff0000)
281+
self.assertEqual(self.statmod.SF_ARCHIVED, 0x00010000)
282+
self.assertEqual(self.statmod.SF_IMMUTABLE, 0x00020000)
283+
self.assertEqual(self.statmod.SF_APPEND, 0x00040000)
284+
self.assertEqual(self.statmod.SF_RESTRICTED, 0x00080000)
285+
self.assertEqual(self.statmod.SF_NOUNLINK, 0x00100000)
286+
self.assertEqual(self.statmod.SF_FIRMLINK, 0x00800000)
287+
self.assertEqual(self.statmod.SF_DATALESS, 0x40000000)
288+
289+
self.assertFalse(isinstance(self.statmod.S_IFMT, int))
290+
self.assertEqual(self.statmod.S_IFIFO, 0o010000)
291+
self.assertEqual(self.statmod.S_IFCHR, 0o020000)
292+
self.assertEqual(self.statmod.S_IFDIR, 0o040000)
293+
self.assertEqual(self.statmod.S_IFBLK, 0o060000)
294+
self.assertEqual(self.statmod.S_IFREG, 0o100000)
295+
self.assertEqual(self.statmod.S_IFLNK, 0o120000)
296+
self.assertEqual(self.statmod.S_IFSOCK, 0o140000)
297+
298+
if self.statmod is c_stat:
299+
self.assertEqual(self.statmod.S_IFWHT, 0o160000)
300+
301+
self.assertEqual(self.statmod.S_IRWXU, 0o000700)
302+
self.assertEqual(self.statmod.S_IRUSR, 0o000400)
303+
self.assertEqual(self.statmod.S_IWUSR, 0o000200)
304+
self.assertEqual(self.statmod.S_IXUSR, 0o000100)
305+
self.assertEqual(self.statmod.S_IRWXG, 0o000070)
306+
self.assertEqual(self.statmod.S_IRGRP, 0o000040)
307+
self.assertEqual(self.statmod.S_IWGRP, 0o000020)
308+
self.assertEqual(self.statmod.S_IXGRP, 0o000010)
309+
self.assertEqual(self.statmod.S_IRWXO, 0o000007)
310+
self.assertEqual(self.statmod.S_IROTH, 0o000004)
311+
self.assertEqual(self.statmod.S_IWOTH, 0o000002)
312+
self.assertEqual(self.statmod.S_IXOTH, 0o000001)
313+
self.assertEqual(self.statmod.S_ISUID, 0o004000)
314+
self.assertEqual(self.statmod.S_ISGID, 0o002000)
315+
self.assertEqual(self.statmod.S_ISVTX, 0o001000)
316+
317+
self.assertFalse(hasattr(self.statmod, "S_ISTXT"))
318+
self.assertEqual(self.statmod.S_IREAD, self.statmod.S_IRUSR)
319+
self.assertEqual(self.statmod.S_IWRITE, self.statmod.S_IWUSR)
320+
self.assertEqual(self.statmod.S_IEXEC, self.statmod.S_IXUSR)
321+
322+
238323

324+
@unittest.skipIf(c_stat is None, 'need _stat extension')
239325
class TestFilemodeCStat(TestFilemode, unittest.TestCase):
240326
statmod = c_stat
241327

vm/src/stdlib/stat.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ mod stat {
7272

7373
// TODO: RUSTPYTHON Support BSD
7474
// https://man.freebsd.org/cgi/man.cgi?stat(2)
75+
76+
#[cfg(target_os = "macos")]
77+
#[pyattr]
78+
pub const S_IFWHT: Mode = 0o160000;
79+
#[cfg(not(target_os = "macos"))]
7580
#[pyattr]
7681
pub const S_IFWHT: Mode = 0;
7782

0 commit comments

Comments
 (0)