int util_log_vasprintf(char **result, const char *fmt, va_list args) { int ret; struct timeval tv; struct timezone tz; struct tm tm_gmt; if( result ) *result = NULL; gettimeofday(&tv, &tz); time_t tt = tv.tv_sec; gmtime_r(&tt, &tm_gmt); char timestamp[ sizeof("YYYY-MM-DD HH:MM:SS") ]; strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &tm_gmt); char *msg = NULL; if( NULL != fmt ) util_vasprintf(&msg, fmt, args); #if 1 ret = util_asprintf(result, "%10llu.%06d %s %llu %s", (unsigned long long)tv.tv_sec, (int) tv.tv_usec, timestamp, (unsigned long long) getpid(), msg ? msg : ""); #else int minutes = tm_gmt.tm_hour * 60 + tm_gmt.tm_min - tz.tz_minuteswest; if( minutes < 0 ) minutes = 24 * 60 - ( -minutes % ( 24 * 60 ) ); if( minutes >= 24*60 ) minutes %= ( 24 * 60 ); ret = util_asprintf(result, "%s.%06dZ %02d:%02d %llu %s", timestamp, (int)tv.tv_usec, minutes / 60, minutes % 60, (unsigned long long) getpid(), msg ? msg : ""); #endif free(msg); return ret; }
/* * Extraction abilities. These work as you expect them to. */ static bool pak_extract_one(pak_file_t *pak, const char *file, const char *outdir) { pak_directory_t *dir = NULL; unsigned char *dat = NULL; char *local = NULL; FILE *out = NULL; if (!pak_exists(pak, file, &dir)) { return false; } if (!(dat = (unsigned char *)mem_a(dir->len))) goto err; /* * Generate the directory structure / tree that will be required * to store the extracted file. */ pak_tree_build(file); /* TODO portable path seperators */ util_asprintf(&local, "%s/%s", outdir, file); /* * Now create the file, if this operation fails. Then abort * It shouldn't fail though. */ if (!(out = fs_file_open(local, "wb"))) goto err; /* free memory for directory string */ mem_d(local); /* read */ if (fs_file_seek (pak->handle, dir->pos, SEEK_SET) != 0) goto err; fs_file_read (dat, 1, dir->len, pak->handle); fs_file_write(dat, 1, dir->len, out); fs_file_close(out); mem_d(dat); return true; err: if (dat) mem_d(dat); if (out) fs_file_close(out); return false; }
/* * Read a directory and searches for all template files in it * which is later used to run all tests. */ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { bool success = true; fs_dir_t *dir; fs_dirent_t *files; struct stat directory; char buffer[4096]; size_t found = 0; char **directories = NULL; char *claim = util_strdup(curdir); size_t i; vec_push(directories, claim); dir = fs_dir_open(claim); /* * Generate a list of subdirectories since we'll be checking them too * for tmpl files. */ while ((files = fs_dir_read(dir))) { util_asprintf(&claim, "%s/%s", curdir, files->d_name); if (stat(claim, &directory) == -1) { fs_dir_close(dir); mem_d(claim); return false; } if (S_ISDIR(directory.st_mode) && files->d_name[0] != '.') { vec_push(directories, claim); } else { mem_d(claim); claim = NULL; } } fs_dir_close(dir); /* * Now do all the work, by touching all the directories inside * test as well and compile the task templates into data we can * use to run the tests. */ for (i = 0; i < vec_size(directories); i++) { dir = fs_dir_open(directories[i]); while ((files = fs_dir_read(dir))) { util_snprintf(buffer, sizeof(buffer), "%s/%s", directories[i], files->d_name); if (stat(buffer, &directory) == -1) { con_err("internal error: stat failed, aborting\n"); abort(); } if (S_ISDIR(directory.st_mode)) continue; /* * We made it here, which concludes the file/directory is not * actually a directory, so it must be a file :) */ if (strcmp(files->d_name + strlen(files->d_name) - 5, ".tmpl") == 0) { task_template_t *tmpl = task_template_compile(files->d_name, directories[i], pad); char buf[4096]; /* one page should be enough */ const char *qcflags = NULL; task_t task; found ++; if (!tmpl) { con_err("error compiling task template: %s\n", files->d_name); success = false; continue; } /* * Generate a temportary file name for the output binary * so we don't trample over an existing one. */ tmpl->tempfilename = NULL; util_asprintf(&tmpl->tempfilename, "%s/TMPDAT.%s.dat", directories[i], files->d_name); /* * Additional QCFLAGS enviroment variable may be used * to test compile flags for all tests. This needs to be * BEFORE other flags (so that the .tmpl can override them) */ qcflags = platform_getenv("QCFLAGS"); /* * Generate the command required to open a pipe to a process * which will be refered to with a handle in the task for * reading the data from the pipe. */ if (strcmp(tmpl->proceduretype, "-pp")) { if (qcflags) { if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) { util_snprintf(buf, sizeof(buf), "%s %s/%s %s %s -o %s", task_bins[TASK_COMPILE], directories[i], tmpl->sourcefile, qcflags, tmpl->compileflags, tmpl->tempfilename ); } else { util_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s %s -o %s", task_bins[TASK_COMPILE], curdir, defs, directories[i], tmpl->sourcefile, qcflags, tmpl->compileflags, tmpl->tempfilename ); } } else { if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) { util_snprintf(buf, sizeof(buf), "%s %s/%s %s -o %s", task_bins[TASK_COMPILE], directories[i], tmpl->sourcefile, tmpl->compileflags, tmpl->tempfilename ); } else { util_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s -o %s", task_bins[TASK_COMPILE], curdir, defs, directories[i], tmpl->sourcefile, tmpl->compileflags, tmpl->tempfilename ); } } } else { /* Preprocessing (qcflags mean shit all here we don't allow them) */ if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) { util_snprintf(buf, sizeof(buf), "%s -E %s/%s -o %s", task_bins[TASK_COMPILE], directories[i], tmpl->sourcefile, tmpl->tempfilename ); } else { util_snprintf(buf, sizeof(buf), "%s -E %s/%s %s/%s -o %s", task_bins[TASK_COMPILE], curdir, defs, directories[i], tmpl->sourcefile, tmpl->tempfilename ); } } /* * The task template was compiled, now lets create a task from * the template data which has now been propagated. */ task.tmpl = tmpl; if (!(task.runhandles = task_popen(buf, "r"))) { con_err("error opening pipe to process for test: %s\n", tmpl->description); success = false; continue; } /* * Open up some file desciptors for logging the stdout/stderr * to our own. */ util_snprintf(buf, sizeof(buf), "%s.stdout", tmpl->tempfilename); task.stdoutlogfile = util_strdup(buf); if (!(task.stdoutlog = fs_file_open(buf, "w"))) { con_err("error opening %s for stdout\n", buf); continue; } util_snprintf(buf, sizeof(buf), "%s.stderr", tmpl->tempfilename); task.stderrlogfile = util_strdup(buf); if (!(task.stderrlog = fs_file_open(buf, "w"))) { con_err("error opening %s for stderr\n", buf); continue; } vec_push(task_tasks, task); } } fs_dir_close(dir); mem_d(directories[i]); /* free claimed memory */ } vec_free(directories); return success; }