// Recursively copies a directory. // // src - The path of the file or directory to copy. // dest - The path where the copy should be placed. // // Returns 0 if successful, otherwise returns -1. int sky_file_cp_r(bstring src, bstring dest) { int rc; bstring ent_src = NULL; bstring ent_dest = NULL; check(src != NULL, "Source path required"); check(dest != NULL, "Destination path required"); check(sky_file_exists(src), "Source file does not exist"); // If this is a directory then create a new dest directory and copy the // contents. if(sky_file_is_dir(src)) { // Create destination directory if it doesn't exist. if(!sky_file_exists(dest)) { struct stat st; rc = stat(bdatae(src, ""), &st); check(rc == 0, "Unable to stat source directory: %s", bdatae(src, "")); rc = mkdir(bdatae(dest, ""), st.st_mode); check(rc == 0, "Unable to create directory: %s", bdatae(dest, "")); } // Open directory. DIR *dir = opendir(bdatae(src, "")); check(dir != NULL, "Unable to open directory: %s", bdatae(src, "")); // Copy over contents of directory. struct dirent *ent; while((ent = readdir(dir))) { if(strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { ent_src = bformat("%s/%s", bdatae(src, ""), ent->d_name); check_mem(ent_src); ent_dest = bformat("%s/%s", bdatae(dest, ""), ent->d_name); check_mem(ent_dest); rc = sky_file_cp_r(ent_src, ent_dest); check(rc == 0, "Unable to copy: %s", bdatae(ent_src, "")); bdestroy(ent_src); bdestroy(ent_dest); } } // Close directory. closedir(dir); } // If this is a file then copy its contents. else { rc = sky_file_cp(src, dest); check(rc == 0, "Unable to copy file: %s", bdatae(src, "")); } return 0; error: bdestroy(ent_src); bdestroy(ent_dest); return -1; }
// Retrieves the size of a file, in bytes. // // path - The path of the file. // // Returns the size of the file at the given path in bytes. off_t sky_file_get_size(bstring path) { struct stat buffer; if(stat(bdatae(path, ""), &buffer) == 0) { return buffer.st_size; } else { return 0; } }
int Action_exec(Action *action, Profile *prof) { int rc = 0; char *procer_run_log = NULL; bstring pidfile_env = bformat("PROCER_PIDFILE=%s", bdata(prof->pid_file)); putenv(bdata(pidfile_env)); bstring action_env = bformat("PROCER_ACTION=%s", bdata(action->name)); putenv(bdata(action_env)); debug("ACTION: command=%s, pid_file=%s, restart=%d, depends=%s", bdata(prof->command), bdata(prof->pid_file), prof->restart, bdata(action->depends)); pid_t pid = fork(); check(pid >= 0, "Fork failed, WTF. How can fork fail?"); if(pid == 0) { rc = Unixy_drop_priv(action->profile_dir); if(rc != 0) { log_err("Not fatal, but we couldn't drop priv for %s", bdata(action->name)); } if( (procer_run_log = getenv("PROCER_RUN_LOG")) == NULL) procer_run_log = "run.log"; redirect_output(procer_run_log); rc = execle(bdatae(prof->command, ""), bdatae(prof->command, ""), NULL, environ); check(rc != -1, "Failed to exec command: %s", bdata(prof->command)); } else { int status = 0; debug("WAITING FOR CHILD."); pid = waitpid(pid, &status, 0); } debug("Command ran and exited successfully, now looking for the PID file."); return 0; error: return -1; }
// Checks if a file is a directory. // // path - The path of the file. // // Returns true if the file at the given path is a directory. Otherwise // returns false. bool sky_file_is_dir(bstring path) { struct stat buffer; int rc = stat(bdatae(path, ""), &buffer); if(rc == 0) { return S_ISDIR(buffer.st_mode); } else { return false; } }
void Action_task(void *v) { Action *action = (Action *)v; int rc = 0; pid_t child = 0; Profile *prof = Profile_load(action->profile_dir); taskname(bdata(action->name)); taskstate("depends"); rc = Rampart_wait(action->before); check(rc != -1, "A dependency failed to start, we can't start."); Rampart_running(&action->after); taskstate("ready"); debug("STARTED %s", bdata(action->name)); while(RUNNING) { taskstate("starting"); if(Unixy_still_running(prof->pid_file, &child)) { debug("Looks like %s is already running, we'll just leave it alone.", bdata(action->name)); } else { Unixy_remove_dead_pidfile(prof->pid_file); Action_exec(action, prof); } if(access(bdatae(prof->pid_file, ""), R_OK) != 0) { log_warn("%s didn't make pidfile %s. Waiting then trying again.", bdata(action->name), bdata(prof->pid_file)); Action_sleep(2); } taskstate("waiting"); while(Unixy_still_running(prof->pid_file, &child) && RUNNING) { Action_sleep(1); } if(!prof->restart) { break; } taskstate("restarting"); Action_sleep(1); } debug("ACTION %s exited.", bdata(action->name)); error: Rampart_failed(&action->after); return; }
// Copies a single file from the source path to the destination path. // // src - The path of the file to copy. // dest - The path where the copy should be placed. // // Returns 0 if successful, otherwise returns -1. int sky_file_cp(bstring src, bstring dest) { int rc; check(src != NULL, "Source path required"); check(dest != NULL, "Destination path required"); check(sky_file_exists(src), "Source file does not exist"); check(!sky_file_is_dir(src), "Source file cannot be a directory"); // Open source files. FILE *src_file = fopen(bdatae(src, ""), "r"); check(src_file != NULL, "Unable to open source file for reading"); // Open destination file. FILE *dest_file = fopen(bdatae(dest, ""), "w"); check(dest_file != NULL, "Unable to open destination file for writing"); // Read from source and write to destination until done. while(!feof(src_file)) { int buffer_size = 1024; char *buffer[buffer_size]; size_t sz = fread(buffer, sizeof(char), buffer_size, src_file); fwrite(buffer, sizeof(char), sz, dest_file); } // Close files. fclose(src_file); fclose(dest_file); // Copy permissions to destination file. struct stat st; stat(bdatae(src, ""), &st); rc = chmod(bdatae(dest, ""), st.st_mode); check(rc == 0, "Unable to copy permissions"); return 0; error: return -1; }
// Deletes a single file. // // path - The path of the file to delete. // // Returns 0 if successful, otherwise returns -1. int sky_file_rm(bstring path) { int rc; check(path != NULL, "Path required"); check(!sky_file_is_dir(path), "File cannot be a directory"); if(sky_file_exists(path)) { rc = remove(bdatae(path, "")); check(rc == 0, "Unable to delete file"); } return 0; error: return -1; }
// Writes the results to an output stream. // // worker - The worker. // output - The output stream. // // Returns 0 if successful, otherwise returns -1. int sky_lua_aggregate_message_worker_write(sky_worker *worker, FILE *output) { size_t sz; assert(worker != NULL); assert(output != NULL); // Ease-of-use references. sky_lua_aggregate_message *message = (sky_lua_aggregate_message*)worker->data; // Return. // {status:"ok", data:{<action_id>:{count:0}, ...}} check(minipack_fwrite_map(output, 2, &sz) == 0, "Unable to write root map"); check(sky_minipack_fwrite_bstring(output, &SKY_LUA_AGGREGATE_STATUS_STR) == 0, "Unable to write status key"); check(sky_minipack_fwrite_bstring(output, &SKY_LUA_AGGREGATE_OK_STR) == 0, "Unable to write status value"); check(sky_minipack_fwrite_bstring(output, &SKY_LUA_AGGREGATE_DATA_STR) == 0, "Unable to write data key"); check(fwrite(bdatae(message->results, ""), blength(message->results), 1, output) == 1, "Unable to write data value"); return 0; error: return -1; }
// Recursively deletes a file or directory. // // path - The path of the file or directory to delete. // // Returns 0 if successful, otherwise returns -1. int sky_file_rm_r(bstring path) { int rc; bstring ent_path = NULL; check(path != NULL, "Path required"); // If path doesn't exist then just ignore it. if(sky_file_exists(path)) { // If the file is a directory then delete its contents first and then // delete it. if(sky_file_is_dir(path)) { // Open directory. DIR *dir = opendir(bdatae(path, "")); check(dir != NULL, "Unable to open directory: %s", bdatae(path, "")); // Remove each file inside directory. struct dirent *ent; while((ent = readdir(dir))) { if(strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { ent_path = bformat("%s/%s", bdatae(path, ""), ent->d_name); check_mem(ent_path); rc = sky_file_rm_r(ent_path); check(rc == 0, "Unable to delete: %s", bdatae(ent_path, "")); bdestroy(ent_path); } } // Close directory. closedir(dir); // Remove directory. remove(bdatae(path, "")); } // If this is a file then delete it. else { rc = sky_file_rm(path); check(rc == 0, "Unable to delete file: %s", bdatae(path, "")); } } return 0; error: bdestroy(ent_path); return -1; }
// Creates the LLVM block for this AST but does not generate the statements. // // node - The node to generate an LLVM value for. // module - The compilation unit this node is a part of. // block - A pointer to where the LLVM basic block should be returned. // // Returns 0 if successful, otherwise returns -1. int qip_ast_block_codegen_block(qip_ast_node *node, qip_module *module, LLVMBasicBlockRef *block) { int rc; check(node != NULL, "Node required"); check(node->type == QIP_AST_TYPE_BLOCK, "Node type expected to be 'block'"); check(node->parent != NULL, "Node parent required"); check(module != NULL, "Module required"); // Retrieve current function scope. qip_scope *scope = NULL; rc = qip_module_get_current_function_scope(module, &scope); check(rc == 0 && scope != NULL, "Unable to retrieve current function scope"); // Create LLVM block. *block = LLVMAppendBasicBlock(scope->llvm_function, bdatae(node->block.name, "")); return 0; error: *block = NULL; return -1; }
// Append the contents of the AST node to the string. // // node - The node to dump. // ret - A pointer to the bstring to concatenate to. // // Return 0 if successful, otherwise returns -1.s int qip_ast_block_dump(qip_ast_node *node, bstring ret) { int rc; check(node != NULL, "Node required"); check(ret != NULL, "String required"); // Append dump. bstring str = bformat("<block name='%s'>\n", bdatae(node->block.name, "")); check_mem(str); check(bconcat(ret, str) == BSTR_OK, "Unable to append dump"); // Recursively dump children unsigned int i; for(i=0; i<node->block.expr_count; i++) { rc = qip_ast_node_dump(node->block.exprs[i], ret); check(rc == 0, "Unable to dump block expression"); } return 0; error: if(str != NULL) bdestroy(str); return -1; }
// Checks if a file exists. // // path - The path of the file. // // Returns true if the file at the given path exists. Otherwise returns false. bool sky_file_exists(bstring path) { struct stat buffer; int rc = stat(bdatae(path, ""), &buffer); return (rc == 0); }