From fdeae8fbfeb3b25f7b1015162c3285fcb32cf02e Mon Sep 17 00:00:00 2001 From: "Paul A. Patience" Date: Tue, 10 May 2022 21:41:03 -0400 Subject: [PATCH] =?UTF-8?q?Add=20=E2=80=A2file.Rename?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/sysfn.c | 14 ++++++++++++-- src/utils/file.c | 12 ++++++++++++ src/utils/file.h | 1 + 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 90450a12..7cbdb7da 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -676,6 +676,8 @@ static NFnDesc* fExistsDesc; static NFnDesc* fListDesc; static NFnDesc* fMapBytesDesc; static NFnDesc* createdirDesc; +static NFnDesc* renameDesc; + B list_c1(B d, B x) { return path_list(path_rel(nfn_objU(d), x)); } @@ -685,6 +687,13 @@ B createdir_c1(B d, B x) { thrM("(file).CreateDir: Failed to create directory"); } +B rename_c2(B d, B w, B x) { + d = nfn_objU(d); + B p = path_rel(d, w); + if (path_rename(path_rel(d, x), p)) return p; + thrM("(file).Rename: Failed to rename file"); +} + B ftype_c1(B d, B x) { char ty = path_type(path_rel(nfn_objU(d), x)); if (ty==0) thrM("•file.Type: Error while accessing file"); @@ -1101,7 +1110,7 @@ B sys_c1(B t, B x) { if(!fileNS.u) { REQ_PATH; #define F(X) m_nfn(X##Desc, inc(path)) - fileNS = m_nns(file_nsGen, q_N(path)? m_c32(0) : inc(path), F(fileAt), F(fList), F(fBytes), F(fChars), F(fLines), F(fType), F(fExists), inc(bi_fName), F(fMapBytes), F(createdir)); + fileNS = m_nns(file_nsGen, q_N(path)? m_c32(0) : inc(path), F(fileAt), F(fList), F(fBytes), F(fChars), F(fLines), F(fType), F(fExists), inc(bi_fName), F(fMapBytes), F(createdir), F(rename)); #undef F } cr = inc(fileNS); @@ -1170,12 +1179,13 @@ void sysfn_init() { fListDesc = registerNFn(m_str8l("(file).List"), list_c1, c2_bad); fTypeDesc = registerNFn(m_str8l("(file).Type"), ftype_c1, c2_bad); createdirDesc = registerNFn(m_str8l("(file).CreateDir"), createdir_c1, c2_bad); + renameDesc = registerNFn(m_str8l("(file).Rename"), c1_bad, rename_c2); fMapBytesDesc = registerNFn(m_str8l("(file).MapBytes"), mapBytes_c1, c2_bad); fExistsDesc = registerNFn(m_str8l("(file).Exists"), fexists_c1, c2_bad); importDesc = registerNFn(m_str32(U"•Import"), import_c1, import_c2); reBQNDesc = registerNFn(m_str8l("(REPL)"), repl_c1, repl_c2); } void sysfnPost_init() { - file_nsGen = m_nnsDesc("path","at","list","bytes","chars","lines","type","exists","name","mapbytes","createdir"); + file_nsGen = m_nnsDesc("path","at","list","bytes","chars","lines","type","exists","name","mapbytes","createdir","rename"); c(BMd1,bi_bitcast)->im = bitcast_im; } diff --git a/src/utils/file.c b/src/utils/file.c index 952649b3..72150801 100644 --- a/src/utils/file.c +++ b/src/utils/file.c @@ -1,4 +1,5 @@ #include +#include #include "../core.h" #include "file.h" #include "mut.h" @@ -312,6 +313,17 @@ bool dir_create(B path) { return r; } +bool path_rename(B old_path, B new_path) { + char* old = toCStr(old_path); + char* new = toCStr(new_path); + // TODO Fix race condition, e.g., with renameat2 on Linux, etc. + bool ok = access(new, F_OK) != 0 && rename(old, new) == 0; + freeCStr(new); + freeCStr(old); + dec(old_path); + return ok; +} + char path_type(B path) { char* p = toCStr(path); struct stat path_stat; diff --git a/src/utils/file.h b/src/utils/file.h index 27036c7c..3a6e69bc 100644 --- a/src/utils/file.h +++ b/src/utils/file.h @@ -15,6 +15,7 @@ I8Arr* stream_bytes(FILE* f); B mmap_file(B path); // consumes bool dir_create(B path); // doesn't consume +bool path_rename(B old_path, B new_path); // consumes only old_path void path_wChars(B path, B x); // consumes path void path_wBytes(B path, B x); // consumes path