added /RAD_WRITE_TEMP_FILES

When enabled linker writes image and debug info to temporary files
and renames them after all writes are done.
This commit is contained in:
Nikita Smith
2025-02-25 14:41:34 -08:00
parent 8a8a8bcc8d
commit bbce89eada
10 changed files with 148 additions and 47 deletions
+16 -11
View File
@@ -358,7 +358,7 @@ lnk_manifest_from_inputs(Arena *arena,
// write linker manifest to temp file // write linker manifest to temp file
String8 linker_manifest_path = push_str8f(scratch.arena, "%S.manifest.temp", manifest_name); String8 linker_manifest_path = push_str8f(scratch.arena, "%S.manifest.temp", manifest_name);
lnk_write_data_to_file_path(linker_manifest_path, linker_manifest); lnk_write_data_to_file_path(linker_manifest_path, str8_zero(), linker_manifest);
// push linker manifest // push linker manifest
str8_list_push(scratch.arena, &input_manifest_path_list, linker_manifest_path); str8_list_push(scratch.arena, &input_manifest_path_list, linker_manifest_path);
@@ -3079,7 +3079,7 @@ lnk_write_thread(void *raw_ctx)
{ {
ProfBeginFunction(); ProfBeginFunction();
LNK_WriteThreadContext *ctx = raw_ctx; LNK_WriteThreadContext *ctx = raw_ctx;
lnk_write_data_to_file_path(ctx->path, ctx->data); lnk_write_data_to_file_path(ctx->path, ctx->temp_path, ctx->data);
ProfEnd(); ProfEnd();
} }
@@ -3254,7 +3254,7 @@ lnk_run(int argc, char **argv)
LNK_ObjList obj_list = {0}; LNK_ObjList obj_list = {0};
LNK_LibList lib_index[LNK_InputSource_Count] = {0}; LNK_LibList lib_index[LNK_InputSource_Count] = {0};
String8 image_data = str8_zero(); String8 image_data = str8_zero();
OS_Handle image_write_thread = {0}; OS_Handle image_write_thread = {0};
// init state machine // init state machine
struct StateList state_list = {0}; struct StateList state_list = {0};
@@ -3763,7 +3763,7 @@ lnk_run(int argc, char **argv)
ProfBeginDynamic("Write Manifest To: %.*s", str8_varg(config->manifest_name)); ProfBeginDynamic("Write Manifest To: %.*s", str8_varg(config->manifest_name));
Temp temp = temp_begin(scratch.arena); Temp temp = temp_begin(scratch.arena);
String8 manifest_data = lnk_manifest_from_inputs(temp.arena, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list); String8 manifest_data = lnk_manifest_from_inputs(temp.arena, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list);
lnk_write_data_to_file_path(config->manifest_name, manifest_data); lnk_write_data_to_file_path(config->manifest_name, str8_zero(), manifest_data);
temp_end(temp); temp_end(temp);
ProfEnd(); ProfEnd();
} break; } break;
@@ -4080,10 +4080,14 @@ lnk_run(int argc, char **argv)
} }
} }
LNK_WriteThreadContext *ctx = push_array(scratch.arena, LNK_WriteThreadContext, 1); // write image file in background
ctx->path = config->image_name; {
ctx->data = image_data; LNK_WriteThreadContext *ctx = push_array(scratch.arena, LNK_WriteThreadContext, 1);
image_write_thread = os_thread_launch(lnk_write_thread, ctx, 0); ctx->path = config->image_name;
ctx->temp_path = config->temp_image_name;
ctx->data = image_data;
image_write_thread = os_thread_launch(lnk_write_thread, ctx, 0);
}
if (lnk_get_log_status(LNK_Log_InputObj)) { if (lnk_get_log_status(LNK_Log_InputObj)) {
U64 total_input_size = 0; U64 total_input_size = 0;
@@ -4110,7 +4114,7 @@ lnk_run(int argc, char **argv)
ProfBegin("Build Imp Lib"); ProfBegin("Build Imp Lib");
lnk_timer_begin(LNK_Timer_Lib); lnk_timer_begin(LNK_Timer_Lib);
String8List lib_list = lnk_build_import_lib(tp, tp_arena, config->machine, config->time_stamp, config->imp_lib_name, config->image_name, exptab); String8List lib_list = lnk_build_import_lib(tp, tp_arena, config->machine, config->time_stamp, config->imp_lib_name, config->image_name, exptab);
lnk_write_data_list_to_file_path(config->imp_lib_name, lib_list); lnk_write_data_list_to_file_path(config->imp_lib_name, str8_zero(), lib_list);
lnk_timer_end(LNK_Timer_Lib); lnk_timer_end(LNK_Timer_Lib);
ProfEnd(); ProfEnd();
} break; } break;
@@ -4143,7 +4147,8 @@ lnk_run(int argc, char **argv)
input.parsed_symbols, input.parsed_symbols,
types); types);
lnk_write_data_list_to_file_path(config->rad_debug_name, rdi_data); lnk_write_data_list_to_file_path(config->rad_debug_name, config->temp_rad_debug_name, rdi_data);
lnk_timer_end(LNK_Timer_Rdi); lnk_timer_end(LNK_Timer_Rdi);
} }
@@ -4177,7 +4182,7 @@ lnk_run(int argc, char **argv)
input.parsed_symbols, input.parsed_symbols,
types); types);
lnk_write_data_list_to_file_path(config->pdb_name, pdb_data); lnk_write_data_list_to_file_path(config->pdb_name, config->temp_pdb_name, pdb_data);
lnk_timer_end(LNK_Timer_Pdb); lnk_timer_end(LNK_Timer_Pdb);
} }
+1
View File
@@ -224,6 +224,7 @@ typedef struct
typedef struct typedef struct
{ {
String8 path; String8 path;
String8 temp_path;
String8 data; String8 data;
} LNK_WriteThreadContext; } LNK_WriteThreadContext;
+13 -2
View File
@@ -152,17 +152,17 @@ global read_only struct
{ LNK_CmdSwitch_Rad_PdbHashTypeNames, "RAD_PDB_HASH_TYPE_NAMES", ":{NONE|LENIENT|FULL}", "Replace type names in LF_STRUCTURE and LF_CLASS with hashes." }, { LNK_CmdSwitch_Rad_PdbHashTypeNames, "RAD_PDB_HASH_TYPE_NAMES", ":{NONE|LENIENT|FULL}", "Replace type names in LF_STRUCTURE and LF_CLASS with hashes." },
{ LNK_CmdSwitch_Rad_SectVirtOff, "RAD_SECT_VIRT_OFF", ":#", "Set RVA where section data is placed in memory. For internal use only." }, { LNK_CmdSwitch_Rad_SectVirtOff, "RAD_SECT_VIRT_OFF", ":#", "Set RVA where section data is placed in memory. For internal use only." },
{ LNK_CmdSwitch_Rad_SharedThreadPool, "RAD_SHARED_THREAD_POOL", "[:STRING]", "Default value \"" LNK_DEFAULT_THREAD_POOL_NAME "\"" }, { LNK_CmdSwitch_Rad_SharedThreadPool, "RAD_SHARED_THREAD_POOL", "[:STRING]", "Default value \"" LNK_DEFAULT_THREAD_POOL_NAME "\"" },
{ LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers, "RAD_SHARED_THREAD_POOL_MAX_WORKERS", ":#", "Sets maximum number of workers in a thread pool." }, { LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers, "RAD_SHARED_THREAD_POOL_MAX_WORKERS", ":#", "Sets maximum number of workers in a thread pool." },
{ LNK_CmdSwitch_Rad_SuppressError, "RAD_SUPPRESS_ERROR", ":#", "" }, { LNK_CmdSwitch_Rad_SuppressError, "RAD_SUPPRESS_ERROR", ":#", "" },
{ LNK_CmdSwitch_Rad_SymbolTableCapDefined, "RAD_SYMBOL_TABLE_CAP_DEFINED", ":#", "Number of buckets allocated in the symbol table for defined symbols." }, { LNK_CmdSwitch_Rad_SymbolTableCapDefined, "RAD_SYMBOL_TABLE_CAP_DEFINED", ":#", "Number of buckets allocated in the symbol table for defined symbols." },
{ LNK_CmdSwitch_Rad_SymbolTableCapInternal, "RAD_SYMBOL_TABLE_CAP_INTERNAL", ":#", "Number of buckets allocated in the symbol table for internal symbols." }, { LNK_CmdSwitch_Rad_SymbolTableCapInternal, "RAD_SYMBOL_TABLE_CAP_INTERNAL", ":#", "Number of buckets allocated in the symbol table for internal symbols." },
{ LNK_CmdSwitch_Rad_SymbolTableCapLib, "RAD_SYMBOL_TABLE_CAP_LIB", ":#", "Number of buckets allocated in the symbol table for library symbols." }, { LNK_CmdSwitch_Rad_SymbolTableCapLib, "RAD_SYMBOL_TABLE_CAP_LIB", ":#", "Number of buckets allocated in the symbol table for library symbols." },
{ LNK_CmdSwitch_Rad_SymbolTableCapWeak, "RAD_SYMBOL_TABLE_CAP_WEAK", ":#", "Number of buckets allocated in the symbol table for weak symbols." }, { LNK_CmdSwitch_Rad_SymbolTableCapWeak, "RAD_SYMBOL_TABLE_CAP_WEAK", ":#", "Number of buckets allocated in the symbol table for weak symbols." },
{ LNK_CmdSwitch_Rad_TargetOs, "RAD_TARGET_OS", ":{WINDOWS,LINUX,MAC}" }, { LNK_CmdSwitch_Rad_TargetOs, "RAD_TARGET_OS", ":{WINDOWS,LINUX,MAC}" },
{ LNK_CmdSwitch_Rad_WriteTempFiles, "RAD_WRITE_TEMP_FILES", "[:NO]", "When speicifed linker writes image and debug info to temporary files and renames after link is done." },
{ LNK_CmdSwitch_Rad_TimeStamp, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." }, { LNK_CmdSwitch_Rad_TimeStamp, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." },
{ LNK_CmdSwitch_Rad_Version, "RAD_VERSION", "", "Print version and exit." }, { LNK_CmdSwitch_Rad_Version, "RAD_VERSION", "", "Print version and exit." },
{ LNK_CmdSwitch_Rad_Workers, "RAD_WORKERS", ":#", "Sets number of workers created in the pool. Number is capped at 1024. When /RAD_SHARED_THREAD_POOL is specified this number cant exceed /RAD_SHARED_THREAD_POOL_MAX_WORKERS." }, { LNK_CmdSwitch_Rad_Workers, "RAD_WORKERS", ":#", "Sets number of workers created in the pool. Number is capped at 1024. When /RAD_SHARED_THREAD_POOL is specified this number cant exceed /RAD_SHARED_THREAD_POOL_MAX_WORKERS." },
{ LNK_CmdSwitch_Help, "HELP", "", "" }, { LNK_CmdSwitch_Help, "HELP", "", "" },
{ LNK_CmdSwitch_Help, "?", "", "" }, { LNK_CmdSwitch_Help, "?", "", "" },
}; };
@@ -1754,6 +1754,10 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
} }
} break; } break;
case LNK_CmdSwitch_Rad_WriteTempFiles: {
lnk_cmd_switch_parse_flag(obj_path, lib_path, cmd_switch, value_strings, &config->write_temp_files);
} break;
case LNK_CmdSwitch_Rad_TimeStamp: { case LNK_CmdSwitch_Rad_TimeStamp: {
lnk_cmd_switch_parse_u32(obj_path, lib_path, cmd_switch, value_strings, &config->time_stamp, 0); lnk_cmd_switch_parse_u32(obj_path, lib_path, cmd_switch, value_strings, &config->time_stamp, 0);
} break; } break;
@@ -2054,6 +2058,13 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
// :Rad_DebugAltPath // :Rad_DebugAltPath
config->rad_debug_alt_path = lnk_expand_env_vars_windows(arena, env_vars, config->rad_debug_alt_path); config->rad_debug_alt_path = lnk_expand_env_vars_windows(arena, env_vars, config->rad_debug_alt_path);
// create temporary files names
if (config->write_temp_files == LNK_SwitchState_Yes) {
config->temp_image_name = push_str8f(arena, "%S.tmp%x", config->image_name, config->time_stamp);
config->temp_pdb_name = push_str8f(arena, "%S.tmp%x", config->pdb_name, config->time_stamp);
config->temp_rad_debug_name = push_str8f(arena, "%S.tmp%x", config->rad_debug_name, config->time_stamp);
}
if (lnk_get_log_status(LNK_Log_Debug)) { if (lnk_get_log_status(LNK_Log_Debug)) {
String8 full_cmd_line = str8_list_join(scratch.arena, &raw_cmd_line, &(StringJoin){ .sep = str8_lit_comp(" ") }); String8 full_cmd_line = str8_list_join(scratch.arena, &raw_cmd_line, &(StringJoin){ .sep = str8_lit_comp(" ") });
fprintf(stderr, "--------------------------------------------------------------------------------\n"); fprintf(stderr, "--------------------------------------------------------------------------------\n");
+5
View File
@@ -155,6 +155,7 @@ typedef enum
LNK_CmdSwitch_Rad_SymbolTableCapInternal, LNK_CmdSwitch_Rad_SymbolTableCapInternal,
LNK_CmdSwitch_Rad_SymbolTableCapWeak, LNK_CmdSwitch_Rad_SymbolTableCapWeak,
LNK_CmdSwitch_Rad_SymbolTableCapLib, LNK_CmdSwitch_Rad_SymbolTableCapLib,
LNK_CmdSwitch_Rad_WriteTempFiles,
LNK_CmdSwitch_Rad_TargetOs, LNK_CmdSwitch_Rad_TargetOs,
LNK_CmdSwitch_Rad_TimeStamp, LNK_CmdSwitch_Rad_TimeStamp,
LNK_CmdSwitch_Rad_Version, LNK_CmdSwitch_Rad_Version,
@@ -364,6 +365,10 @@ typedef struct LNK_Config
U64 symbol_table_cap_lib; U64 symbol_table_cap_lib;
B32 build_imp_lib; B32 build_imp_lib;
B32 build_exp; B32 build_exp;
LNK_SwitchState write_temp_files;
String8 temp_image_name;
String8 temp_pdb_name;
String8 temp_rad_debug_name;
} LNK_Config; } LNK_Config;
typedef enum typedef enum
+1 -1
View File
@@ -2676,7 +2676,7 @@ lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, CV_DebugT de
if (task.make_map) { if (task.make_map) {
String8List map = {0}; String8List map = {0};
str8_list_concat_in_place_array(&map, task.maps, tp->worker_count); str8_list_concat_in_place_array(&map, task.maps, tp->worker_count);
lnk_write_data_list_to_file_path(map_name, map); lnk_write_data_list_to_file_path(map_name, str8_zero(), map);
tp_arena_release(&task.map_arena); tp_arena_release(&task.map_arena);
} }
+56 -17
View File
@@ -10,6 +10,15 @@ lnk_open_file_read(char *path, uint64_t path_size, void *handle_buffer, uint64_t
return !os_handle_match(handle, os_handle_zero()); return !os_handle_match(handle, os_handle_zero());
} }
shared_function int
lnk_open_file_write_rename(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max)
{
OS_Handle handle = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_ShareDelete, str8((U8*)path, path_size));
Assert(sizeof(handle) <= handle_buffer_max);
MemoryCopy(handle_buffer, &handle, sizeof(handle));
return !os_handle_match(handle, os_handle_zero());
}
shared_function int shared_function int
lnk_open_file_write(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max) lnk_open_file_write(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max)
{ {
@@ -26,6 +35,14 @@ lnk_close_file(void *raw_handle)
os_file_close(handle); os_file_close(handle);
} }
shared_function int
lnk_rename_file(void *raw_handle, char *new_file_path, uint64_t new_file_path_size)
{
OS_Handle handle = *(OS_Handle *)raw_handle;
B32 is_renamed = os_rename_file_by_handle(handle, str8((U8*)new_file_path, new_file_path_size));
return (int)is_renamed;
}
shared_function uint64_t shared_function uint64_t
lnk_size_from_file(void *raw_handle) lnk_size_from_file(void *raw_handle)
{ {
@@ -163,34 +180,56 @@ lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, String8Array
} }
internal void internal void
lnk_write_data_list_to_file_path(String8 path, String8List data) lnk_write_data_list_to_file_path(String8 path, String8 temp_path, String8List data)
{ {
ProfBeginV("Write %M to %S", data.total_size, path); ProfBeginV("Write %M to %S", data.total_size, path);
B32 is_written = 0; U64 bytes_written = 0;
OS_Handle handle; B32 open_with_rename = (temp_path.size > 0);
if (lnk_open_file_write((char*)path.str, path.size, &handle, sizeof(handle))) { OS_Handle file_handle = {0};
U64 offset = 0; if (open_with_rename) {
for (String8Node *data_n = data.first; data_n != 0; data_n = data_n->next) { lnk_open_file_write_rename((char*)temp_path.str, temp_path.size, &file_handle, sizeof(file_handle));
U64 write_size = lnk_write_file(&handle, offset, data_n->string.str, data_n->string.size); } else {
if (write_size != data_n->string.size) { lnk_open_file_write((char*)path.str, path.size, &file_handle, sizeof(file_handle));
break; }
if (!os_handle_match(file_handle, os_handle_zero())) {
// write data nodes
{
for (String8Node *data_n = data.first; data_n != 0; data_n = data_n->next) {
U64 write_size = lnk_write_file(&file_handle, bytes_written, data_n->string.str, data_n->string.size);
if (write_size != data_n->string.size) {
break;
}
bytes_written += data_n->string.size;
} }
offset += data_n->string.size;
} }
lnk_close_file(&handle); B32 is_write_complete = (bytes_written == data.total_size);
is_written = (offset == data.total_size); if (is_write_complete) {
if (is_written) { // rename file to original name
if (open_with_rename) {
if (lnk_rename_file(&file_handle, (char*)path.str, path.size)) {
lnk_log(LNK_Log_IO_Write, "Renamed %S -> %S", temp_path, path);
} else {
lnk_error(LNK_Error_IO, "failed to rename %S -> %S", temp_path, path);
}
}
}
// log write
if (is_write_complete) {
if (lnk_get_log_status(LNK_Log_IO_Write)) { if (lnk_get_log_status(LNK_Log_IO_Write)) {
lnk_log(LNK_Log_IO_Write, "File \"%S\" %M written", path, data.total_size); lnk_log(LNK_Log_IO_Write, "File \"%S\" %M written", path, data.total_size);
} }
} else { } else {
lnk_error(LNK_Error_IO, "incomplete write occurred, %M written, expected %M, file %S", lnk_error(LNK_Error_IO, "incomplete write, %M written, expected %M, file %S", bytes_written, data.total_size, path);
offset, data.total_size, path);
} }
// clean up handle
lnk_close_file(&file_handle);
} else { } else {
lnk_error(LNK_Error_NoAccess, "don't have access to write to %S", path); lnk_error(LNK_Error_NoAccess, "don't have access to write to %S", path);
} }
@@ -199,12 +238,12 @@ lnk_write_data_list_to_file_path(String8 path, String8List data)
} }
internal void internal void
lnk_write_data_to_file_path(String8 path, String8 data) lnk_write_data_to_file_path(String8 path, String8 temp_path, String8 data)
{ {
Temp scratch = scratch_begin(0,0); Temp scratch = scratch_begin(0,0);
String8List data_list = {0}; String8List data_list = {0};
str8_list_push(scratch.arena, &data_list, data); str8_list_push(scratch.arena, &data_list, data);
lnk_write_data_list_to_file_path(path, data_list); lnk_write_data_list_to_file_path(path, temp_path, data_list);
scratch_end(scratch); scratch_end(scratch);
} }
+4 -2
View File
@@ -17,7 +17,9 @@ typedef struct
shared_function int lnk_open_file_read(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max); shared_function int lnk_open_file_read(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max);
shared_function int lnk_open_file_write(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max); shared_function int lnk_open_file_write(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max);
shared_function int lnk_open_file_write_rename(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max);
shared_function void lnk_close_file(void *raw_handle); shared_function void lnk_close_file(void *raw_handle);
shared_function int lnk_rename_file(void *raw_handle, char *new_file_path, uint64_t new_file_path_size);
shared_function uint64_t lnk_size_from_file(void *raw_handle); shared_function uint64_t lnk_size_from_file(void *raw_handle);
shared_function uint64_t lnk_read_file(void *raw_handle, void *buffer, uint64_t buffer_max); shared_function uint64_t lnk_read_file(void *raw_handle, void *buffer, uint64_t buffer_max);
shared_function uint64_t lnk_write_file(void *raw_handle, uint64_t offset, void *buffer, uint64_t buffer_size); shared_function uint64_t lnk_write_file(void *raw_handle, uint64_t offset, void *buffer, uint64_t buffer_size);
@@ -27,8 +29,8 @@ shared_function uint64_t lnk_write_file(void *raw_handle, uint64_t offset, void
internal String8 lnk_read_data_from_file_path(Arena *arena, String8 path); internal String8 lnk_read_data_from_file_path(Arena *arena, String8 path);
internal String8Array lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, String8Array path_arr); internal String8Array lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, String8Array path_arr);
internal void lnk_write_data_list_to_file_path(String8 path, String8List list); internal void lnk_write_data_list_to_file_path(String8 path, String8 temp_path, String8List list);
internal void lnk_write_data_to_file_path(String8 path, String8 data); internal void lnk_write_data_to_file_path(String8 path, String8 temp_path, String8 data);
internal String8List lnk_file_search(Arena *arena, String8List dir_list, String8 file_path); internal String8List lnk_file_search(Arena *arena, String8List dir_list, String8 file_path);
+10
View File
@@ -151,6 +151,16 @@ os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range)
return result; return result;
} }
internal B32
os_rename_file(String8 orig_name, String8 new_name)
{
Temp scratch = scratch_begin(0,0);
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareWrite|OS_AccessFlag_ShareDelete, orig_name);
B32 is_renamed = os_rename_file_by_handle(file, new_name);
os_file_close(file);
return is_renamed;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Process Launcher Helpers //~ rjf: Process Launcher Helpers
+10 -7
View File
@@ -38,13 +38,14 @@ struct OS_ProcessInfo
typedef U32 OS_AccessFlags; typedef U32 OS_AccessFlags;
enum enum
{ {
OS_AccessFlag_Read = (1<<0), OS_AccessFlag_Read = (1<<0),
OS_AccessFlag_Write = (1<<1), OS_AccessFlag_Write = (1<<1),
OS_AccessFlag_Execute = (1<<2), OS_AccessFlag_Execute = (1<<2),
OS_AccessFlag_Append = (1<<3), OS_AccessFlag_Append = (1<<3),
OS_AccessFlag_ShareRead = (1<<4), OS_AccessFlag_ShareRead = (1<<4),
OS_AccessFlag_ShareWrite = (1<<5), OS_AccessFlag_ShareWrite = (1<<5),
OS_AccessFlag_Inherited = (1<<6), OS_AccessFlag_ShareDelete = (1<<6),
OS_AccessFlag_Inherited = (1<<7),
}; };
//////////////////////////////// ////////////////////////////////
@@ -206,6 +207,8 @@ internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data);
internal B32 os_file_set_times(OS_Handle file, DateTime time); internal B32 os_file_set_times(OS_Handle file, DateTime time);
internal FileProperties os_properties_from_file(OS_Handle file); internal FileProperties os_properties_from_file(OS_Handle file);
internal OS_FileID os_id_from_file(OS_Handle file); internal OS_FileID os_id_from_file(OS_Handle file);
internal B32 os_rename_file_by_handle(OS_Handle file, String8 new_name);
internal B32 os_rename_file(String8 orig_name, String8 new_name);
internal B32 os_delete_file_at_path(String8 path); internal B32 os_delete_file_at_path(String8 path);
internal B32 os_copy_file_path(String8 dst, String8 src); internal B32 os_copy_file_path(String8 dst, String8 src);
internal String8 os_full_path_from_path(Arena *arena, String8 path); internal String8 os_full_path_from_path(Arena *arena, String8 path);
+32 -7
View File
@@ -321,13 +321,14 @@ os_file_open(OS_AccessFlags flags, String8 path)
DWORD share_mode = 0; DWORD share_mode = 0;
DWORD creation_disposition = OPEN_EXISTING; DWORD creation_disposition = OPEN_EXISTING;
SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), 0, 0}; SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), 0, 0};
if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;} if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;}
if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;} if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;}
if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;} if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;}
if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;} if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;}
if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;} if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;}
if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;} if(flags & OS_AccessFlag_ShareDelete) {share_mode |= FILE_SHARE_DELETE; access_flags |= DELETE;}
if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS; access_flags |= FILE_APPEND_DATA; } if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;}
if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS; access_flags |= FILE_APPEND_DATA; }
if(flags & OS_AccessFlag_Inherited) if(flags & OS_AccessFlag_Inherited)
{ {
security_attributes.bInheritHandle = 1; security_attributes.bInheritHandle = 1;
@@ -469,6 +470,30 @@ os_id_from_file(OS_Handle file)
return result; return result;
} }
internal B32
os_rename_file_by_handle(OS_Handle file, String8 new_name)
{
Temp scratch = scratch_begin(0,0);
HANDLE handle = (HANDLE)file.u64[0];
String16 new_name16 = str16_from_8(scratch.arena, new_name);
U64 file_rename_info_size = sizeof(FILE_RENAME_INFO);
U64 buffer_size = file_rename_info_size + sizeof(WCHAR)*new_name16.size;
U8 *buffer = push_array(scratch.arena, U8, buffer_size);
FILE_RENAME_INFO *rename_info = (FILE_RENAME_INFO *)buffer;
rename_info->ReplaceIfExists = 1;
rename_info->FileNameLength = new_name16.size * sizeof(new_name16.str[0]);
MemoryCopy(rename_info->FileName, new_name16.str, new_name16.size * sizeof(new_name16.str[0]));
BOOL is_renamed = SetFileInformationByHandle(handle, FileRenameInfo, buffer, buffer_size);
scratch_end(scratch);
return is_renamed;
}
internal B32 internal B32
os_delete_file_at_path(String8 path) os_delete_file_at_path(String8 path)
{ {