bool vogl_trace_file_reader::init_loose_file_blob_manager(const char *pTrace_filename, const char *pLoose_file_path) { VOGL_FUNC_TRACER dynamic_string loose_file_path("."); if ((pLoose_file_path) && vogl_strlen(pLoose_file_path)) loose_file_path = pLoose_file_path; else if ((pTrace_filename) && (vogl_strlen(pTrace_filename))) { dynamic_string fname; if (!file_utils::split_path(pTrace_filename, loose_file_path, fname)) { console::error("%s: Failed splitting trace filename \"%s\", assuming \".\" as the loose file path\n", VOGL_FUNCTION_INFO_CSTR, pTrace_filename); loose_file_path = "."; } } if (!m_loose_file_blob_manager.init(cBMFReadable, loose_file_path.get_ptr())) { close(); return false; } return true; }
uint32_t ktx_texture::add_key_value(const char *pKey, const void *pVal, uint32_t val_size) { const uint32_t idx = m_key_values.size(); m_key_values.resize(idx + 1); uint8_vec &v = m_key_values.back(); v.append(reinterpret_cast<const uint8_t *>(pKey), vogl_strlen(pKey) + 1); v.append(static_cast<const uint8_t *>(pVal), val_size); return idx; }
const uint8_vec *ktx_texture::find_key(const char *pKey) const { const uint32_t n = vogl_strlen(pKey) + 1; for (uint32_t i = 0; i < m_key_values.size(); i++) { const uint8_vec &v = m_key_values[i]; if ((v.size() >= n) && (!memcmp(&v[0], pKey, n))) return &v; } return NULL; }
bool ktx_texture::get_key_value_data(const char *pKey, uint8_vec &data) const { const uint8_vec *p = find_key(pKey); if (!p) { data.resize(0); return false; } const uint32_t ofs = vogl_strlen(pKey) + 1; const uint8_t *pValue = p->get_ptr() + ofs; const uint32_t n = p->size() - ofs; data.resize(n); if (n) memcpy(data.get_ptr(), pValue, n); return true; }
bool ktx_texture::get_key_value_as_string(const char *pKey, dynamic_string &str) const { const uint8_vec *p = find_key(pKey); if (!p) { str.clear(); return false; } const uint32_t ofs = vogl_strlen(pKey) + 1; const uint8_t *pValue = p->get_ptr() + ofs; const uint32_t n = p->size() - ofs; uint32_t i; for (i = 0; i < n; i++) if (!pValue[i]) break; str.set_from_buf(pValue, i); return true; }
bool data_stream::puts(const char *p) { uint len = vogl_strlen(p); return write(p, len * sizeof(char)) == len * sizeof(char); }
// init_uuid() is slow (~40ms, maybe slower), and forces a disk flush on a file, so don't call it more than once. // I'm a paranoid nut so this hashes a bunch of shit. It's probably completely overkill for my needs - I should stop reading RFC's. static md5_hash init_uuid() { static uint64_t s_counter; // Get as much entropy as we can here const uint N = 2; void *p[N]; memset(p, 0, sizeof(p)); md5_hash_gen gen; timer_ticks tick_hist[N]; for (uint i = 0; i < N; i++) { uint64_t start_rdtsc = utils::RDTSC(); gen.update(start_rdtsc); gen.update(s_counter); gen.update((uint64_t) & s_counter); s_counter++; // Hash stack address of gen_uuid gen.update((uint64_t) & gen_uuid); // Hash the initial timer ticks, and time(NULL) gen.update(timer::get_init_ticks()); gen.update((uint64_t)time(NULL)); // Hash user ID, name, shell, home dir uid_t uid = geteuid(); gen.update(uid); struct passwd *pw = getpwuid(uid); gen.update((uint64_t) & pw); if (pw) { gen.update(pw, sizeof(struct passwd)); if (pw->pw_name) gen.update(pw->pw_name, vogl_strlen(pw->pw_name)); if (pw->pw_passwd) gen.update(pw->pw_passwd, vogl_strlen(pw->pw_passwd)); if (pw->pw_shell) gen.update(pw->pw_shell, vogl_strlen(pw->pw_shell)); if (pw->pw_dir) gen.update(pw->pw_dir, vogl_strlen(pw->pw_dir)); if (pw->pw_gecos) gen.update(pw->pw_gecos, vogl_strlen(pw->pw_gecos)); } uint8_vec buf; timer_ticks ticks = timer::get_ticks(); gen.update(ticks); // This is obviously expensive (and questionable?), only do it once. But it helps us get some entropy from the disk subsystem. // This is also by far the slowest component of this function (~35ms out of ~40ms). if (!i) { uint64_t st = utils::RDTSC(); timer tm; tm.start(); const char *pFilename = "!_!_!_!_!_!_!_vogl_temp!_!_!_!_!_!_!_!_.txt"; FILE *pFile = vogl_fopen(pFilename, "wb"); gen.update_obj_bits(pFile); if (pFile) { fwrite("X", 1, 1, pFile); fflush(pFile); fsync(fileno(pFile)); vogl_fclose(pFile); remove(pFilename); } uint64_t t = utils::RDTSC() - st; gen.update(t); tm.stop(); gen.update(tm.get_elapsed_ticks()); } // Grab some bits from /dev/urandom (not /dev/random - it may block for a long time) { const uint N = 64; char buf[N]; FILE *fp = vogl_fopen("/dev/urandom", "rb"); gen.update_obj_bits(fp); if (fp) { size_t n = fread(buf, 1, N, fp); VOGL_NOTE_UNUSED(n); vogl_fclose(fp); gen.update(buf, sizeof(buf)); } } // It's fine if some/most/all of these files don't exist, the true/false results get fed into the hash too. // TODO: Double check that all the files we should be able to read are actually getting read and hashed here. #define HASH_FILE(filename) \ do \ { \ bool success = cfile_stream::read_file_into_array(filename, buf); \ gen.update_obj_bits(success); \ gen.update(buf); \ } while (0) HASH_FILE("/proc/sys/kernel/random/entropy_avail"); HASH_FILE("/proc/self/statm"); HASH_FILE("/proc/self/mounts"); HASH_FILE("/proc/self/io"); HASH_FILE("/proc/self/smaps"); HASH_FILE("/proc/self/stack"); HASH_FILE("/proc/self/status"); HASH_FILE("/proc/self/maps"); HASH_FILE("/proc/self/stat"); HASH_FILE("/proc/self/stat"); HASH_FILE("/proc/cpuinfo"); HASH_FILE("/proc/meminfo"); HASH_FILE("/proc/stat"); HASH_FILE("/proc/misc"); HASH_FILE("/proc/swaps"); HASH_FILE("/proc/version"); HASH_FILE("/proc/loadavg"); HASH_FILE("/proc/interrupts"); HASH_FILE("/proc/ioports"); HASH_FILE("/proc/partitions"); HASH_FILE("/proc/driver/rtc"); HASH_FILE("/proc/self/net/wireless"); HASH_FILE("/proc/self/net/netstat"); HASH_FILE("/proc/self/net/netlink"); HASH_FILE("/sys/class/net/eth0/address"); HASH_FILE("/sys/class/net/eth1/address"); HASH_FILE("/sys/class/net/wlan0/address"); #undef HASH_FILE gen.update(utils::RDTSC()); // Hash thread, process ID's, etc. pid_t tid = (pid_t)syscall(SYS_gettid); gen.update_obj_bits(tid); pid_t pid = getpid(); gen.update_obj_bits(pid); pid = getppid(); gen.update_obj_bits(pid); gen.update((uint64_t) & pid); ticks -= timer::get_ticks(); tick_hist[i] = ticks; gen.update(ticks); ticks = timer::get_ticks(); // Get some entropy from the stack. char purposely_uninitialized_buf[256]; gen.update(purposely_uninitialized_buf, sizeof(purposely_uninitialized_buf)); // Get some entropy from the heap. p[i] = vogl_malloc(65536 * (i + 1)); gen.update_obj_bits(p[i]); if (p[i]) { for (uint j = 0; j < 16; j++) gen.update_obj_bits(reinterpret_cast<const uint64_t *>(p)[j]); } struct timeval tv; gettimeofday(&tv, NULL); gen.update_obj_bits(tv); // Hash the current environment uint e = 0; while (environ[e]) { gen.update(environ[e], vogl_strlen(environ[e])); ++e; } uint64_t s = utils::RDTSC(); // Try to get some entropy from the scheduler. vogl_sleep(2); gen.update(utils::RDTSC() - s); ticks -= timer::get_ticks(); gen.update(ticks); gen.update(utils::RDTSC() - start_rdtsc); } for (uint i = 1; i < N; i++) { uint64_t t = tick_hist[i] - tick_hist[i - 1]; gen.update(t); } for (uint i = 0; i < N; i++) vogl_free(p[i]); return gen.finalize(); }