24 |
22 |
25 listdir_batch_size = 4096 |
23 listdir_batch_size = 4096 |
26 # tweakable number, only affects performance, which chunks |
24 # tweakable number, only affects performance, which chunks |
27 # of bytes do we get back from getattrlistbulk |
25 # of bytes do we get back from getattrlistbulk |
28 |
26 |
29 attrkinds = [None] * 20 # we need the max no for enum VXXX, 20 is plenty |
27 attrkinds = [None] * 20 # we need the max no for enum VXXX, 20 is plenty |
30 |
28 |
31 attrkinds[lib.VREG] = statmod.S_IFREG |
29 attrkinds[lib.VREG] = statmod.S_IFREG |
32 attrkinds[lib.VDIR] = statmod.S_IFDIR |
30 attrkinds[lib.VDIR] = statmod.S_IFDIR |
33 attrkinds[lib.VLNK] = statmod.S_IFLNK |
31 attrkinds[lib.VLNK] = statmod.S_IFLNK |
34 attrkinds[lib.VBLK] = statmod.S_IFBLK |
32 attrkinds[lib.VBLK] = statmod.S_IFBLK |
58 lgt = cur.length |
56 lgt = cur.length |
59 assert lgt == ffi.cast('uint32_t*', cur)[0] |
57 assert lgt == ffi.cast('uint32_t*', cur)[0] |
60 ofs = cur.name_info.attr_dataoffset |
58 ofs = cur.name_info.attr_dataoffset |
61 str_lgt = cur.name_info.attr_length |
59 str_lgt = cur.name_info.attr_length |
62 base_ofs = ffi.offsetof('val_attrs_t', 'name_info') |
60 base_ofs = ffi.offsetof('val_attrs_t', 'name_info') |
63 name = str(ffi.buffer(ffi.cast("char*", cur) + base_ofs + ofs, |
61 name = str( |
64 str_lgt - 1)) |
62 ffi.buffer( |
|
63 ffi.cast("char*", cur) + base_ofs + ofs, str_lgt - 1 |
|
64 ) |
|
65 ) |
65 tp = attrkinds[cur.obj_type] |
66 tp = attrkinds[cur.obj_type] |
66 if name == "." or name == "..": |
67 if name == "." or name == "..": |
67 continue |
68 continue |
68 if skip == name and tp == statmod.S_ISDIR: |
69 if skip == name and tp == statmod.S_ISDIR: |
69 return [] |
70 return [] |
70 if stat: |
71 if stat: |
71 mtime = cur.mtime.tv_sec |
72 mtime = cur.mtime.tv_sec |
72 mode = (cur.accessmask & ~lib.S_IFMT)| tp |
73 mode = (cur.accessmask & ~lib.S_IFMT) | tp |
73 ret.append((name, tp, stat_res(st_mode=mode, st_mtime=mtime, |
74 ret.append( |
74 st_size=cur.datalength))) |
75 ( |
|
76 name, |
|
77 tp, |
|
78 stat_res( |
|
79 st_mode=mode, |
|
80 st_mtime=mtime, |
|
81 st_size=cur.datalength, |
|
82 ), |
|
83 ) |
|
84 ) |
75 else: |
85 else: |
76 ret.append((name, tp)) |
86 ret.append((name, tp)) |
77 cur = ffi.cast("val_attrs_t*", int(ffi.cast("intptr_t", cur)) |
87 cur = ffi.cast( |
78 + lgt) |
88 "val_attrs_t*", int(ffi.cast("intptr_t", cur)) + lgt |
|
89 ) |
79 return ret |
90 return ret |
80 |
91 |
81 def listdir(path, stat=False, skip=None): |
92 def listdir(path, stat=False, skip=None): |
82 req = ffi.new("struct attrlist*") |
93 req = ffi.new("struct attrlist*") |
83 req.bitmapcount = lib.ATTR_BIT_MAP_COUNT |
94 req.bitmapcount = lib.ATTR_BIT_MAP_COUNT |
84 req.commonattr = (lib.ATTR_CMN_RETURNED_ATTRS | |
95 req.commonattr = ( |
85 lib.ATTR_CMN_NAME | |
96 lib.ATTR_CMN_RETURNED_ATTRS |
86 lib.ATTR_CMN_OBJTYPE | |
97 | lib.ATTR_CMN_NAME |
87 lib.ATTR_CMN_ACCESSMASK | |
98 | lib.ATTR_CMN_OBJTYPE |
88 lib.ATTR_CMN_MODTIME) |
99 | lib.ATTR_CMN_ACCESSMASK |
|
100 | lib.ATTR_CMN_MODTIME |
|
101 ) |
89 req.fileattr = lib.ATTR_FILE_DATALENGTH |
102 req.fileattr = lib.ATTR_FILE_DATALENGTH |
90 dfd = lib.open(path, lib.O_RDONLY, 0) |
103 dfd = lib.open(path, lib.O_RDONLY, 0) |
91 if dfd == -1: |
104 if dfd == -1: |
92 raise OSError(ffi.errno, os.strerror(ffi.errno)) |
105 raise OSError(ffi.errno, os.strerror(ffi.errno)) |
93 |
106 |