static h_err* init_from_dir(h_section* section, char* path, char* spath, int depth) { section->posts = NULL; section->numposts = 0; section->drafts = NULL; section->numdrafts = 0; section->subs = NULL; section->numsubs = 0; struct dirent** namelist; int n; n = scandir(path, &namelist, 0, alphasort); if (n == -1) return h_err_from_errno(errno, path); //Loop through directory, adding posts and sub sections while (n--) { struct dirent* ent = namelist[n]; //Skip hidden entries, //or entries starting with _ if (ent->d_name[0] == '.') continue; if (ent->d_name[0] == '_') continue; //If entry is a file, add it to either posts or drafts if (ent->d_type == DT_REG) { h_post* post = malloc(sizeof(h_post)); if (post == NULL) return h_err_create(H_ERR_ALLOC, NULL); char* p = h_util_path_join(path, ent->d_name); if (p == NULL) return h_err_create(H_ERR_ALLOC, NULL); h_err* err = NULL; err = h_post_init_from_file(post, p, spath, depth + 1); if (err) return err; free(p); if (post->isdraft) err = h_section_add_draft(section, post); else err = h_section_add_post(section, post); if (err) return err; } //If it's a directory, it's a section and should be added to subs else if (ent->d_type == DT_DIR) { h_section* sub = malloc(sizeof(h_section)); if (sub == NULL) return h_err_create(H_ERR_ALLOC, NULL); char* p = h_util_path_join(path, ent->d_name); if (p == NULL) return h_err_create(H_ERR_ALLOC, NULL); char* sp = h_util_path_join(spath, ent->d_name + 6); if (sp == NULL) return h_err_create(H_ERR_ALLOC, NULL); if (sp[0] == '/') sp = sp + 1; h_err* err = NULL; err = init_from_dir(sub, p, sp, depth + 1); if (err) return err; err = h_section_add_sub(section, sub); free(p); if (err) return err; } free(namelist[n]); } //Both posts and subs are reversed now, as posts should be reversed; //we have to reverse the subs again though, as they shouldn't be reversed. reverse_subs(section); free(namelist); //Get a section's slug from the path int lastslash = 0; int length = strlen(path); int i; for (i = 0; i < length; ++i) { if (path[i] == '/') lastslash = i; } int chars = length - lastslash - 6; if (chars <= 0) { section->slug = NULL; section->title = NULL; return NULL; } section->path = spath; section->depth = depth; section->slug = malloc(chars * sizeof(char)); if (section->slug == NULL) return h_err_create(H_ERR_ALLOC, NULL); memcpy(section->slug, path + lastslash + 1 + 6, chars * sizeof(char)); section->slug[chars - 1] = '\0'; //Make a title from the slug length = chars; section->title = malloc(length * sizeof(char)); memcpy(section->title, section->slug, (length - 1) * sizeof(char)); for (i = 0; i < length - 1; ++i) { char c = section->title[i]; if (c == '-' || c == '_') section->title[i] = ' '; } section->title[length - 1] = '\0'; return NULL; }
void guid_init(void) { size_t bytes = 0; ENTER(""); /* Not needed; taken care of on first malloc. * guid_memchunk_init(); */ md5_init_ctx(&guid_context); /* entropy pool * FIXME /dev/urandom doesn't exist on Windows. We should * use the Windows native CryptGenRandom or RtlGenRandom * functions. See * http://en.wikipedia.org/wiki/CryptGenRandom */ bytes += init_from_file ("/dev/urandom", 512); /* files * FIXME none of these directories make sense on * Windows. We should figure out some proper * alternatives there. */ { const char * files[] = { "/etc/passwd", "/proc/loadavg", "/proc/meminfo", "/proc/net/dev", "/proc/rtc", "/proc/self/environ", "/proc/self/stat", "/proc/stat", "/proc/uptime", NULL }; int i; for (i = 0; files[i] != NULL; i++) bytes += init_from_file(files[i], BLOCKSIZE); } /* directories * Note: P_tmpdir is set to "\" by mingw (Windows) This seems to * trigger unwanted network access attempts (see bug #521817). * So on Windows we explicitly set the temporary directory. * FIXME other than "c:/temp" none of these directories make sense on * Windows. We should figure out some proper * alternatives there. */ { const char * dirname; const char * dirs[] = { "/proc", #ifndef G_OS_WIN32 P_tmpdir, #else "c:/temp", #endif "/var/lock", "/var/log", "/var/mail", "/var/spool/mail", "/var/run", NULL }; int i; for (i = 0; dirs[i] != NULL; i++) bytes += init_from_dir(dirs[i], 32); dirname = g_get_home_dir(); if (dirname != NULL) bytes += init_from_dir(dirname, 32); } /* process and parent ids */ { #ifdef HAVE_UNISTD_H pid_t pid; pid = getpid(); md5_process_bytes(&pid, sizeof(pid), &guid_context); bytes += sizeof(pid); #ifdef HAVE_GETPPID pid = getppid(); md5_process_bytes(&pid, sizeof(pid), &guid_context); bytes += sizeof(pid); #endif #endif } /* user info */ { #ifdef HAVE_GETUID uid_t uid; gid_t gid; char *s; s = getlogin(); if (s != NULL) { md5_process_bytes(s, strlen(s), &guid_context); bytes += strlen(s); } uid = getuid(); md5_process_bytes(&uid, sizeof(uid), &guid_context); bytes += sizeof(uid); gid = getgid(); md5_process_bytes(&gid, sizeof(gid), &guid_context); bytes += sizeof(gid); #endif } /* host info */ { #ifdef HAVE_GETHOSTNAME char string[1024]; memset(string, 0, sizeof(string)); gethostname(string, sizeof(string)); md5_process_bytes(string, sizeof(string), &guid_context); bytes += sizeof(string); #endif } /* plain old random */ { int n, i; srand((unsigned int) gnc_time (NULL)); for (i = 0; i < 32; i++) { n = rand(); md5_process_bytes(&n, sizeof(n), &guid_context); bytes += sizeof(n); } } /* time in secs and clock ticks */ bytes += init_from_time(); PINFO ("got %" G_GUINT64_FORMAT " bytes", (guint64) bytes); if (bytes < THRESHOLD) PWARN("only got %" G_GUINT64_FORMAT " bytes.\n" "The identifiers might not be very random.\n", (guint64)bytes); guid_initialized = TRUE; LEAVE(); }
h_err* h_section_init_from_dir(h_section* section, char* path) { return init_from_dir(section, path, "", 0); }