this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Implement ATTR_CMN_OBJTAG and ATTR_DIR_ENTRYCOUNT for getattrlist

+61 -2
+61 -2
src/kernel/emulation/linux/xattr/getattrlist_generic.c
··· 3 3 #include <sys/errno.h> 4 4 #include "../common_at.h" 5 5 #include "../vchroot_expand.h" 6 + #include "../dirent/getdirentries.h" 7 + #include "../unistd/dup.h" 8 + #include "../fcntl/open.h" 6 9 #include <lkm/api.h> 7 10 #include <linux-syscalls/linux.h> 8 11 #include <stddef.h> 9 12 10 13 #define ATTR_BIT_MAP_COUNT 5 11 14 12 - #define COMMON_SUPPORTED (ATTR_CMN_FNDRINFO) 15 + #define COMMON_SUPPORTED (ATTR_CMN_FNDRINFO | ATTR_CMN_OBJTAG) 13 16 #define VOLUME_SUPPORTED 0 14 - #define DIR_SUPPORTED 0 17 + #define DIR_SUPPORTED (ATTR_DIR_ENTRYCOUNT) 15 18 #define FILE_SUPPORTED (ATTR_FILE_RSRCLENGTH) 16 19 #define FORK_SUPPORTED 0 17 20 18 21 #define ATTR_CMN_FNDRINFO 0x4000 19 22 #define ATTR_FILE_RSRCLENGTH 0x1000 23 + #define ATTR_CMN_OBJTAG 0x00000010 24 + #define ATTR_DIR_ENTRYCOUNT 0x00000002 20 25 21 26 #define XATTR_FINDER_INFO "com.apple.FinderInfo" 22 27 #define XATTR_RESOURCE_FORK "com.apple.ResourceFork" 23 28 24 29 #define FSOPT_NOFOLLOW 1 25 30 #define FSOPT_REPORT_FULLSIZE 4 31 + 32 + #define VT_HFS 16 26 33 27 34 #define min(a,b) (((a) < (b)) ? (a) : (b)) 28 35 ··· 79 86 spaceNeeded += 32; 80 87 if (alist->fileattr & ATTR_FILE_RSRCLENGTH) 81 88 spaceNeeded += 8; // off_t 89 + if (alist->commonattr & ATTR_CMN_OBJTAG) 90 + spaceNeeded += sizeof(uint32_t); // fsobj_tag_t 91 + if (alist->dirattr & ATTR_DIR_ENTRYCOUNT) 92 + spaceNeeded += sizeof(uint32_t); 82 93 83 94 ourBuffer = (char*) __builtin_alloca(spaceNeeded); 84 95 next = ourBuffer + 4; ··· 105 116 *((uint32_t*) next) = 0; 106 117 else 107 118 *((uint32_t*) next) = rv; 119 + next += 4; 120 + } 121 + 122 + if (alist->commonattr & ATTR_CMN_OBJTAG) { 123 + // pretend we're always on HFS 124 + *((uint32_t*)next) = VT_HFS; 125 + next += 4; 126 + } 127 + 128 + if (alist->dirattr & ATTR_DIR_ENTRYCOUNT) { 129 + char buf[1024]; // maybe this should be smaller? 130 + int tmp_fd; 131 + 132 + *((uint32_t*)next) = 0; 133 + 134 + #if HAS_PATH 135 + tmp_fd = LINUX_SYSCALL(__NR_openat, vc.dfd, vc.path, LINUX_O_RDONLY | LINUX_O_DIRECTORY, 0); 136 + if (tmp_fd < 0) { 137 + rv = -EIO; // translate all errors into EIO (to avoid confusing our caller) 138 + goto attr_dir_entrycount_out_no_fd; 139 + } 140 + #else 141 + // dupe it to avoid advancing the internal `getdents` position if our caller is using that 142 + tmp_fd = sys_dup(fd); 143 + if (tmp_fd < 0) { 144 + rv = -EIO; // see above 145 + goto attr_dir_entrycount_out_no_fd; 146 + } 147 + #endif 148 + 149 + while (1) { 150 + // there's basically no other way to do this (at least none that either i or the internet know of) 151 + rv = LINUX_SYSCALL(__NR_getdents64, tmp_fd, buf, sizeof(buf)); 152 + if (rv < 0) { 153 + rv = -EIO; // same as before: avoid confusing our caller with unexepected errnos 154 + goto attr_dir_entrycount_out; 155 + } else if (rv == 0) { 156 + break; 157 + } 158 + 159 + for (char* iter = buf; iter < buf + rv; iter += ((struct linux_dirent64*)iter)->d_reclen) { 160 + ++(*((uint32_t*)next)); 161 + } 162 + } 163 + 164 + attr_dir_entrycount_out: 165 + close_internal(tmp_fd); 166 + attr_dir_entrycount_out_no_fd: 108 167 next += 4; 109 168 } 110 169