void asset_reload_all() { debug("Reloading All Assets..."); list* asset_names = list_new(); for(int i = 0; i < asset_dict->size; i++) { struct bucket* b = asset_dict->buckets[i]; while(b != NULL) { char* new_name = malloc(strlen(b->key)+1); strcpy(new_name, b->key); list_push_back(asset_names, new_name); b = b->next; } } for(int i = 0; i < asset_names->num_items; i++) { file_unload(P(list_get(asset_names, i))); } for(int i = 0; i < asset_names->num_items; i++) { /* ** Assets can reload their child assets before we do ** So it is important we check before loading again */ if (!file_isloaded(P(list_get(asset_names, i)))) { file_load(P(list_get(asset_names, i))); } } list_delete_with(asset_names, free); asset_cache_flush(); }
void folder_unload(fpath folder) { folder = asset_map_filename(folder); debug("Unloading Folder: '%s'", folder.ptr); DIR* dir = opendir(folder.ptr); if (dir == NULL) { error("Could not open directory '%s' to unload.\n", folder.ptr); } struct dirent* ent; while ((ent = readdir(dir)) != NULL) { if ((strcmp(ent->d_name,".") != 0) && (strcmp(ent->d_name,"..") != 0)) { fpath filename = folder; strcat(filename.ptr, ent->d_name); if(dict_contains(asset_dict, filename.ptr) ) { file_unload(filename); } } } closedir(dir); }
void asset_reload_type_id(type_id type) { debug("Reloading Assets of type '%s'...", type_id_name(type)); fpath ext; /* Find the file extension for given type */ for(int i=0; i < num_asset_handlers; i++) { asset_handler handler = asset_handlers[i]; if (handler.type == type) { strcpy(ext.ptr, handler.extension); break; } } list* asset_names = list_new(); for(int i = 0; i < asset_dict->size; i++) { struct bucket* b = asset_dict->buckets[i]; while(b != NULL) { fpath bucket_ext; SDL_PathFileExtension(bucket_ext.ptr, b->key); if (strcmp(bucket_ext.ptr, ext.ptr) == 0) { char* new_name = malloc(strlen(b->key)+1); strcpy(new_name, b->key); list_push_back(asset_names, new_name); } b = b->next; } } for(int i = 0; i < asset_names->num_items; i++) { file_unload(P(list_get(asset_names, i))); } for(int i = 0; i < asset_names->num_items; i++) { /* ** Assets can reload their child assets before we do ** So it is important we check before loading again */ if (!file_isloaded(P(list_get(asset_names, i)))) { file_load(P(list_get(asset_names, i))); } } list_delete_with(asset_names, free); asset_cache_flush(); }
int kexecve(const char *filename, char *const argv[], char *const envp[]) { // If first line is #! exec interpreter and feed // it the command line options and the file. // Otherwise, load the entire file into RAM, // and call image_load. // On error, return -1 and set errno. // On success, no return (0). // The latter implies we have to setup the process context // and free prior RAM. char *image = NULL; unsigned int image_size = 0; unsigned int i = 0; unsigned int j = 0; unsigned int start = 0; unsigned int end = 0; unsigned int len = 0; int argc = 0; char interpreter[MAX_PATH] = {0}; char args[MAX_PATH] = {0}; char *arg = NULL; char **argv2 = NULL; static int nr_recursion = 0; int delete_argv2 = 0; start_t elf_entry = NULL; unsigned char *exec = NULL; unsigned int exec_size = 0; asm_disable_interrupt(); if(!file_load(filename, &image, &image_size)) { printk("execve:: error loading file\n"); asm_enable_interrupt(); return -1; } // TODO - We should store argv2 in the process and // and mark if it should be free'd on exit. // Handle interpreter invocation. if(image[0] == '#' && image[1] == '!') { #ifdef _TEST_EXEC printk("execve:: image = [%s]\n", image); #endif for(i = 2; i < image_size; ++i) { if(!isspace(image[i])) { start = i; break; } } for(i = start + 1; i < image_size; ++i) { if(isspace(image[i])) { end = i; break; } } for(i = start,j=0; i < end; ++i,++j) { if(j >= MAX_PATH) { printk("execve:: interpreter name too long\n"); asm_enable_interrupt(); return -1; } interpreter[j] = image[i]; } for(i = end,j=0; i < image_size; ++i,++j) { if(image[i]=='\n') { break; } args[j]=image[i]; } arg = strtok(args," \t"); i = 0; while(arg) { if(!argv2) { argv2 = (char **)malloc(sizeof(char *) * MAX_PATH + 1); } if(i >= MAX_PATH) { free((void *)argv2); printk("execve:: error processing interpreter args\n"); asm_enable_interrupt(); return -1; } len = strlen(arg); argv2[i] = (char *)malloc(len + 1); strcpy(argv2[i],arg); argv2[i][len]='\0'; ++i; arg = strtok(NULL," \t"); } /* Now get the rest of the args. */ j = 0; while(i < MAX_PATH && argv[j]) { len = strnlen(argv[j],1024); argv2[i] = (char *)malloc(len + 1); strncpy(argv2[i],argv[j],1024); argv2[i][len] = '\0'; ++i; ++j; } if(argv[j] != NULL) { free((void *)argv2); printk("execve:: error argv[j] != NULL\n"); asm_enable_interrupt(); return -1; } /* Now copy the script filename. */ if(i >= MAX_PATH) { free((void *)argv2); printk("execve:: error i >= MAX_PATH\n"); asm_enable_interrupt(); return -1; } #if 0 /* argv[0] should be the filename */ len = strlen(filename); argv2[i] = (char *)malloc(len + 1); strcpy(argv2[i],filename); argv2[i][len]='\0'; ++i; if(i >= MAX_PATH) { free((void *)argv2); printk("execve:: error i >= MAX_PATH[2]\n"); return -1; } #endif argv2[i]='\0'; // Free the original file loaded. if(!file_unload(&image)) { free((void *)argv2); printk("execve:: error unloading file [%s]\n",filename); asm_enable_interrupt(); return -1; } #ifdef _TEST_EXEC printk("interpreter [%s]\n",interpreter); for(i = 0; argv2[i]; ++i) { printk("argv2[%d]=[%s]\n",i,argv2[i]); } for(i = 0; envp[i]; ++i) { printk("envp[%d]=[%s]\n",i,envp[i]); } return 0; #else // Call ourselves with the proper paramters. if(nr_recursion > EXEC_MAX_RECURSION) { printk("execve:: error nr_recursion > EXEC_MAX_RECURSION\n"); asm_enable_interrupt(); return -1; } nr_recursion++; asm_enable_interrupt(); return kexecve(interpreter, argv2, envp); #endif } // If we are in a recursive call, then we // allocated argv2 and it must be free'd. if(nr_recursion) { delete_argv2 = 1; } else { delete_argv2 = 0; argv2 = (char **)argv; } for(i = 0; argv2[i]; ++i) { argc++; } nr_recursion--; // At this point, the ELF image is in RAM. // Parse it out and jump to it. LINE(); elf_entry = image_load(image, image_size, &exec, &exec_size); LINE(); // TODO - Do we put envp into the process struct // and make it accessible via getenv() ? #ifdef _TEST_EXEC printk("elf_entry=[%x]\n",elf_entry); LINE(); i = elf_entry(); printk("returns =[%d]\n",i); #endif LINE(); if(!file_unload(&image)) { if(nr_recursion) { for(i = 0; i < argc; ++i) { free((void *)argv2[i]); } free((void *)argv2); } #ifdef _TEST_EXEC munmap(elf_entry, image_size); #endif printk("execve:: error unloading file [%s]\n",filename); return -1; } #ifdef _TEST_EXEC munmap(exec,exec_size); #else // Kernel // // - Set up the entry point and args // into the process structure... // Mark flag for first time execution // as we need to call into the entry point // when we schedule the process. // - Free the old process image... // // We have:- // // exec - memory image to free // exec_size - size of image // elf_entry - pointer to the start method // argc - argument count // argv2 - arguments // envp - environment // delete_argv2 - flag to indicate if argv2 should be free'd // // Free up prior memory. // Should also happen in exit.c. if(current_process->p_exec) { mem_unset_read_only(current_process->p_exec, current_process->p_exec_size); free((void *)current_process->p_exec); } if(current_process->p_delete_argv) { for(i = 0; i < current_process->p_argc; ++i) { free((void *)current_process->p_argv[i]); } free((void *)current_process->p_argv); } // Close all open files. for(i = 0; i < MAX_FILES; ++i) { for(j = 0; j < MAX_FILES; ++j) { if(current_process->file_desc[i] == &(current_process->file_tab[j])) { kclose(i); } } } // Close all open directories. for(i = 0; i < MAX_DIR; ++i) { if(current_process->dir_tab[i].__allocation == DEV_BLOCK_SIZE) { kclosedir(&(current_process->dir_tab[i])); } } // Setup our new image. current_process->p_exec = exec; current_process->p_exec_size = exec_size; current_process->p_elf_entry = elf_entry; current_process->p_argc = argc; current_process->p_argv = argv2; current_process->p_envp = envp; current_process->p_delete_argv = delete_argv2; current_process->p_first_exec = 1; asm_enable_interrupt(); schedule(); #endif return 0; }/* kexecve */
void file_reload(fpath filename) { file_unload(filename); file_load(filename); asset_cache_flush(); }