this repo has no description
1
fork

Configure Feed

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

Half-complete libproc API, some procedure moves in kernel-mach

+508 -45
+1
src/libSystem/CMakeLists.txt
··· 92 92 kernel-bsd/sockets.cpp 93 93 kernel-bsd/fs.cpp 94 94 kernel-bsd/fcntl.cpp 95 + kernel-bsd/proc.cpp 95 96 ) 96 97 97 98 set(machkern_SRCS
+392
src/libSystem/kernel-bsd/proc.cpp
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2013 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include "proc.h" 21 + #include <fstream> 22 + #include <sstream> 23 + #include <string> 24 + #include <errno.h> 25 + #include <unistd.h> 26 + #include <cstring> 27 + #include <dirent.h> 28 + #include <sys/stat.h> 29 + #include <sys/types.h> 30 + #include <sys/syscall.h> 31 + #include <ctype.h> 32 + #include <string> 33 + #include <memory> 34 + #include "../libc/darwin_errno_codes.h" 35 + #include "../libc/errno.h" 36 + 37 + static std::string getProcStatElement(const char* pid, int elem); 38 + static int sys_syslog(int type, char *bufp, int len); /* No wrapper provided in glibc */ 39 + 40 + int proc_name(int pid, void * buffer, uint32_t buffersize) 41 + { 42 + std::stringstream path; 43 + std::ifstream procf; 44 + char procname[1024]; 45 + size_t read; 46 + 47 + path << "/proc/" << pid << "/cmdline"; 48 + procf.open(path.str().c_str()); 49 + 50 + if (!procf.is_open()) 51 + { 52 + errno = DARWIN_ENOENT; 53 + return 0; 54 + } 55 + 56 + procf.read(procname, sizeof procname); 57 + read = procf.gcount(); 58 + 59 + for (size_t i = 0; i < read-1; i++) 60 + { 61 + if (!procname[i]) 62 + procname[i] = ' '; 63 + } 64 + 65 + if (buffer) 66 + { 67 + if (buffersize >= read) 68 + { 69 + memcpy(buffer, procname, read); 70 + return read; 71 + } 72 + else 73 + { 74 + *((char*) buffer) = 0; 75 + return 0; 76 + } 77 + } 78 + 79 + return 0; 80 + } 81 + 82 + int proc_pidpath(int pid, void * buffer, uint32_t buffersize) 83 + { 84 + std::stringstream path; 85 + char exe[1024]; 86 + ssize_t len; 87 + 88 + path << "/proc/" << pid << "/exe"; 89 + 90 + if (access(path.str().c_str(), F_OK) != 0) 91 + { 92 + errno = DARWIN_ENOENT; 93 + return 0; 94 + } 95 + 96 + len = readlink(path.str().c_str(), exe, sizeof(exe)-1); 97 + if (len < 0) 98 + { 99 + errnoOut(); 100 + return 0; 101 + } 102 + exe[len] = 0; 103 + 104 + if (buffer && buffersize >= len+1) 105 + { 106 + memcpy(buffer, exe, len+1); 107 + return len+1; 108 + } 109 + 110 + return 0; 111 + } 112 + 113 + int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) 114 + { 115 + // TODO 116 + return 0; 117 + } 118 + 119 + int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) 120 + { 121 + // buffer is an array of pid_t 122 + pid_t* pidOut = static_cast<pid_t*>(buffer); 123 + DIR* dirProc = opendir("/proc"); 124 + const uid_t uid = getuid(); 125 + int count = 0; 126 + 127 + if (!dirProc) 128 + return 0; 129 + 130 + while (struct dirent* ent = readdir(dirProc)) 131 + { 132 + if (!isdigit(ent->d_name[0])) 133 + continue; 134 + 135 + bool pass; 136 + 137 + if (type == PROC_ALL_PIDS) 138 + pass = true; 139 + else if (type == PROC_UID_ONLY || type == PROC_RUID_ONLY) // not sure what to do with PROC_RUID_ONLY 140 + { 141 + char path[100]; 142 + struct stat st; 143 + 144 + strcpy(path, "/proc/"); 145 + strcat(path, ent->d_name); 146 + strcat(path, "/cmdline"); 147 + 148 + if (stat(path, &st) == -1) 149 + continue; 150 + 151 + pass = st.st_uid == uid; 152 + } 153 + else if (type == PROC_PGRP_ONLY) 154 + { 155 + std::string grp = getProcStatElement(ent->d_name, 4); 156 + if (atoi(grp.c_str()) == typeinfo) 157 + pass = true; 158 + } 159 + else if (type == PROC_TTY_ONLY) 160 + { 161 + std::string grp = getProcStatElement(ent->d_name, 6); 162 + if (atoi(grp.c_str()) == typeinfo) 163 + pass = true; 164 + } 165 + else 166 + return 0; 167 + 168 + if (pidOut && count < buffersize / sizeof(pid_t)) 169 + pidOut[count++] = atoi(ent->d_name); 170 + } 171 + 172 + closedir(dirProc); 173 + 174 + return count*sizeof(pid_t); 175 + } 176 + 177 + int proc_pidfdinfo(int pid, int fd, int flavor, void* buffer, int buffersize) 178 + { 179 + // TODO 180 + return 0; 181 + } 182 + 183 + int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) 184 + { 185 + std::ifstream file; 186 + std::string line; 187 + std::stringstream fname; 188 + 189 + fname << "/proc/" << pid << "/maps"; 190 + file.open(fname.str().c_str()); 191 + 192 + if (!file.is_open()) 193 + return 0; 194 + 195 + while (std::getline(file, line)) 196 + { 197 + if (line.empty()) continue; 198 + 199 + const char* s = line.c_str(); 200 + uint64_t start, end; 201 + 202 + start = strtoll(s, (char**) &s, 16); 203 + s++; 204 + end = strtoll(s, (char**) &s, 16); 205 + 206 + if (address >= start && address < end) 207 + { 208 + if (line.size() > 74) 209 + { 210 + const char* file = line.c_str()+73; 211 + 212 + strncpy((char*) buffer, file, buffersize-1); 213 + *((char*) buffer + buffersize) = 0; 214 + 215 + return strlen((char*) buffer) + 1; 216 + } 217 + else 218 + { 219 + *((char*) buffer) = 0; 220 + return 1; 221 + } 222 + } 223 + 224 + } 225 + return 0; 226 + } 227 + 228 + int proc_kmsgbuf(void* buffer, uint32_t buffersize) 229 + { 230 + if (buffer) 231 + { 232 + int rv = sys_syslog(/*SYSLOG_ACTION_READ_ALL*/ 3, static_cast<char*>(buffer), buffersize); 233 + if (rv == -1) 234 + { 235 + errnoOut(); 236 + return 0; 237 + } 238 + else 239 + return rv; 240 + } 241 + 242 + return 0; 243 + } 244 + 245 + int proc_libversion(int *major, int * minor) 246 + { 247 + if (major) 248 + *major = 1; 249 + if (minor) 250 + *minor = 1; 251 + return 0; 252 + } 253 + 254 + int proc_setpcontrol(const int control) 255 + { 256 + // TODO: specify options how to react on resource starvation 257 + // Doable on Linux? 258 + return 0; 259 + } 260 + 261 + int proc_listpidspath(uint32_t type, uint32_t typeInfo, const char* path, uint32_t pathFlags, void* buffer, int buffersize) 262 + { 263 + // fuser-like functionality 264 + std::unique_ptr<pid_t[]> pids(new pid_t[4096]); 265 + int count = 0; 266 + int npids; 267 + dev_t devid; 268 + 269 + auto AddElem = [&](pid_t pid) -> void 270 + { 271 + if (buffer) 272 + { 273 + pid_t* p = static_cast<pid_t*>(buffer); 274 + if (buffersize/sizeof(pid_t) >= (count+1)) 275 + p[count++] = pid; 276 + } 277 + }; 278 + 279 + if (pathFlags & PROC_LISTPIDSPATH_PATH_IS_VOLUME) 280 + { 281 + struct stat st; 282 + if (stat(path, &st) == -1) 283 + return 0; 284 + devid = st.st_dev; 285 + } 286 + 287 + npids = proc_listpids(type, typeInfo, pids.get(), 4096*sizeof(pid_t)); 288 + 289 + for (int i = 0; i < npids/sizeof(pid_t); i++) 290 + { 291 + char dpath[100]; 292 + DIR* dir; 293 + struct dirent* ent; 294 + int orig; 295 + 296 + sprintf(dpath, "/proc/%d/fd/", pids[i]); 297 + orig = strlen(dpath); 298 + dir = opendir(dpath); 299 + 300 + if (!dir) 301 + continue; 302 + 303 + while ((ent = readdir(dir))) 304 + { 305 + if (ent->d_name[0] == '.') 306 + continue; 307 + 308 + strcat(dpath, ent->d_name); 309 + 310 + if (pathFlags & PROC_LISTPIDSPATH_PATH_IS_VOLUME) // like `fuser -m` 311 + { 312 + struct stat st; 313 + int rv; 314 + 315 + rv = stat(dpath, &st); 316 + dpath[orig] = 0; 317 + 318 + if (rv == -1) 319 + continue; 320 + 321 + if (st.st_dev == devid) 322 + AddElem(pids[i]); 323 + } 324 + else // like `fuser` 325 + { 326 + char lpath[PATH_MAX]; 327 + ssize_t bytes; 328 + 329 + bytes = readlink(dpath, lpath, sizeof(lpath)); 330 + dpath[orig] = 0; 331 + 332 + if (bytes < 0) 333 + continue; 334 + 335 + lpath[bytes] = 0; 336 + 337 + if (strcmp(lpath, path) == 0) 338 + AddElem(pids[i]); 339 + } 340 + } 341 + 342 + closedir(dir); 343 + } 344 + 345 + return count*sizeof(pid_t); 346 + } 347 + 348 + std::string getProcStatElement(const char* pid, int elem) 349 + { 350 + char path[100] = "/proc/"; 351 + std::ifstream file; 352 + std::string result; 353 + 354 + strcat(path, pid); 355 + strcat(path, "/stat"); 356 + 357 + file.open(path); 358 + 359 + if (!file.is_open()) 360 + return std::string(); 361 + 362 + for (int p = 0; p <= elem; p++) 363 + { 364 + int par = 0; 365 + while (true) 366 + { 367 + int c = file.get(); 368 + if (!par && c == ' ') 369 + break; 370 + if (par == 2 && c == ')') 371 + { 372 + file.get(); 373 + break; 374 + } 375 + if (!par && c == '(') 376 + par = 2; 377 + else 378 + { 379 + par = 1; 380 + result += char(c); 381 + } 382 + } 383 + } 384 + 385 + return result; 386 + } 387 + 388 + int sys_syslog(int type, char *bufp, int len) 389 + { 390 + return syscall(SYS_syslog, type, bufp, len); 391 + } 392 +
+98
src/libSystem/kernel-bsd/proc.h
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2013 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef MACH_PROC_H 21 + #define MACH_PROC_H 22 + #include <stdint.h> 23 + 24 + extern "C" 25 + { 26 + 27 + // For proc_listpidspath 28 + #define PROC_LISTPIDSPATH_PATH_IS_VOLUME 1 29 + #define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY 2 // exclude O_EVTONLY fds, not doable on Linux (no O_EVTONLY on Linux) 30 + 31 + // For proc_listpids 32 + #define PROC_ALL_PIDS 1 33 + #define PROC_PGRP_ONLY 2 34 + #define PROC_TTY_ONLY 3 35 + #define PROC_UID_ONLY 4 36 + #define PROC_RUID_ONLY 5 37 + 38 + int proc_name(int pid, void* buffer, uint32_t buffersize); 39 + int proc_pidpath(int pid, void* buffer, uint32_t buffersize); 40 + int proc_pidinfo(int pid, int flavor, uint64_t arg, void* buffer, int buffersize); 41 + int proc_listpids(uint32_t type, uint32_t typeinfo, void* buffer, int buffersize); 42 + int proc_pidfdinfo(int pid, int fd, int flavor, void* buffer, int buffersize); 43 + int proc_regionfilename(int pid, uint64_t address, void* buffer, uint32_t buffersize); 44 + int proc_kmsgbuf(void* buffer, uint32_t buffersize); 45 + int proc_libversion(int* major, int* minor); 46 + int proc_setpcontrol(const int control); 47 + int proc_listpidspath(uint32_t type, uint32_t typeInfo, const char* path, uint32_t pathFlags, void* buffer, int buffersize); 48 + 49 + struct proc_taskinfo 50 + { 51 + uint64_t pti_virtual_size, 52 + pti_resident_size, 53 + pti_total_user, 54 + pti_total_system, 55 + pti_threads_user, 56 + pti_threads_system; 57 + int32_t pti_policy, 58 + pti_faults, 59 + pti_pageins, 60 + pti_cow_faults, 61 + pti_messages_sent, 62 + pti_messages_received, 63 + pti_syscalls_mach, 64 + pti_syscalls_unix, 65 + pti_csw, 66 + pti_threadnum, 67 + pti_numrunning, 68 + pti_priority; 69 + }; 70 + 71 + struct proc_regioninfo 72 + { 73 + uint32_t pri_protection, 74 + pri_max_protection, 75 + pri_inheritance, 76 + pri_flags; 77 + uint64_t pri_offset; 78 + uint32_t pri_behavior, 79 + pri_user_wired_count, 80 + pri_user_tag, 81 + pri_pages_resident, 82 + pri_pages_shared_now_private, 83 + pri_pages_swapped_out, 84 + pri_pages_dirtied, 85 + pri_ref_count, 86 + pri_shadow_depth, 87 + pri_share_mode, 88 + pri_private_pages_resident, 89 + pri_shared_pages_resident, 90 + pri_obj_id, 91 + pri_depth; 92 + uint64_t pri_address, 93 + pri_size; 94 + }; 95 + } 96 + 97 + #endif 98 +
+8 -40
src/libSystem/kernel-mach/task.cpp
··· 5 5 #include <cstdlib> 6 6 #include <iostream> 7 7 #include <execinfo.h> 8 + #include <fstream> 9 + #include <sstream> 8 10 9 11 darwin_task_t mach_task_self_ = new darwin_task(::getpid()); 10 12 ··· 84 86 task_dyld_info_t dyld_info = (task_dyld_info_t)task_info_out; 85 87 dyld_info->all_image_info_addr = (mach_vm_address_t)&dyld_all_image_infos; 86 88 dyld_info->all_image_info_size = sizeof(dyld_all_image_infos); 87 - #ifdef __x86_64__ 88 - dyld_info->all_image_info_format = TASK_DYLD_ALL_IMAGE_INFO_64; 89 - #else 90 - dyld_info->all_image_info_format = TASK_DYLD_ALL_IMAGE_INFO_32; 91 - #endif 89 + 90 + if (sizeof(void*) == 8) 91 + dyld_info->all_image_info_format = TASK_DYLD_ALL_IMAGE_INFO_64; 92 + else 93 + dyld_info->all_image_info_format = TASK_DYLD_ALL_IMAGE_INFO_32; 94 + 92 95 break; 93 96 } 94 97 default: ··· 103 106 return KERN_SUCCESS; 104 107 } 105 108 106 - kern_return_t mach_vm_region_recurse(vm_map_t target_task, mach_vm_address_t *address, mach_vm_size_t *size, natural_t *nesting_depth, vm_region_recurse_info_t info, mach_msg_type_number_t *infoCnt) 107 - { 108 - // TODO 109 - *infoCnt = 0; 110 - return KERN_SUCCESS; 111 - } 112 109 113 - int proc_name(int pid, void * buffer, uint32_t buffersize) 114 - { 115 - // TODO: get process name 116 - if (buffer) 117 - { 118 - *(char*)buffer = 0; 119 - } 120 - return 0; 121 - } 122 - 123 - int proc_pidpath(int pid, void * buffer, uint32_t buffersize) 124 - { 125 - // TODO: get process path 126 - if (buffer) 127 - { 128 - *(char*)buffer = 0; 129 - } 130 - return 0; 131 - } 132 - 133 - int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) 134 - { 135 - // TODO: get other pid info? 136 - if (buffer) 137 - { 138 - *(char*)buffer = 0; 139 - } 140 - return 0; 141 - }
-5
src/libSystem/kernel-mach/task.h
··· 40 40 kern_return_t task_info(task_name_t target_task, task_flavor_t flavor, task_info_t task_info_out, mach_msg_type_number_t *task_info_outCnt); 41 41 42 42 // mach_vm.h 43 - kern_return_t mach_vm_region_recurse(vm_map_t target_task, mach_vm_address_t *address, mach_vm_size_t *size, natural_t *nesting_depth, vm_region_recurse_info_t info, mach_msg_type_number_t *infoCnt); 44 43 45 - // libproc.h 46 - int proc_name(int pid, void * buffer, uint32_t buffersize); 47 - int proc_pidpath(int pid, void * buffer, uint32_t buffersize); 48 - int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize); 49 44 #ifdef __cplusplus 50 45 } 51 46 #endif
+8
src/libSystem/kernel-mach/vm.cpp
··· 222 222 CHECK_TASK_SELF(target_task); 223 223 MACH_STUB(); 224 224 } 225 + 226 + kern_return_t mach_vm_region_recurse(vm_task_t target_task, void *address, vm_size_t *size, natural_t *nesting_depth, void* info, mach_msg_type_number_t *infoCnt) 227 + { 228 + // TODO: browse /proc/$pid/maps 229 + *infoCnt = 0; 230 + return KERN_SUCCESS; 231 + } 232 +
+1
src/libSystem/kernel-mach/vm.h
··· 43 43 vm_prot_t cur_protection, vm_prot_t max_protection, vm_inherit_t inheritance); 44 44 45 45 kern_return_t vm_wire(host_priv_t host, vm_task_t target_task, void* address, vm_size_t size, vm_prot_t wired_access); 46 + kern_return_t mach_vm_region_recurse(vm_task_t target_task, void *address, vm_size_t *size, natural_t *nesting_depth, void* info, mach_msg_type_number_t *infoCnt); 46 47 47 48 #ifdef __cplusplus 48 49 } // extern "C"