reorganize file writing

fixes some unclosed file descriptors & files being made on an invalid argument
This commit is contained in:
dzaima 2023-10-28 19:26:01 +03:00
parent b6594008cd
commit 7ffd744375
4 changed files with 39 additions and 25 deletions

View File

@ -1204,12 +1204,12 @@ B tFlush_c1(B t, B x) {
}
B tOutRaw_c1(B t, B x) {
if (isAtm(x) || RNK(x)!=1) thrM("•term.OutRaw: 𝕩 must be a list");
file_wBytes(stdout, bi_N, x);
file_wBytes(stdout, "stdout", x);
return x;
}
B tErrRaw_c1(B t, B x) {
if (isAtm(x) || RNK(x)!=1) thrM("•term.ErrRaw: 𝕩 must be a list");
file_wBytes(stderr, bi_N, x);
file_wBytes(stderr, "stderr", x);
return x;
}

View File

@ -217,37 +217,44 @@ void free_chars(CharBuf b) {
if (b.alloc) TFREE(b.data);
}
void path_wChars(B path, B x) { // consumes path
static u64 file_openWriteClose(B path, char* data, u64 len) {
FILE* f = file_open(path, "write to", "wb");
u64 written = fwrite(data, 1, len, f);
fclose(f);
return written;
}
static void file_checkWritten(B path, u64 written, u64 len) {
if (written != len) thrF("Error writing to file \"%R\"", path);
}
void path_wChars(B path, B x) { // consumes path
u64 len = utf8lenB(x);
TALLOC(char, val, len);
toUTF8(x, val);
if (fwrite(val, 1, len, f) != len) { fclose(f); thrF("Error writing to file \"%R\"", path); }
u64 written = file_openWriteClose(path, val, len);
TFREE(val);
file_checkWritten(path, written, len);
dec(path);
fclose(f);
}
void file_wBytes(FILE* f, B name, B x) {
u64 len = IA(x);
CharBuf buf = get_chars(x);
if (fwrite(buf.data, 1, len, f) != len) {
if (q_N(name)) thrM("Error writing to file");
else thrF("Error writing to file \"%R\"", name);
}
free_chars(buf);
}
void path_wBytes(B path, B x) { // consumes path
FILE* f = file_open(path, "write to", "wb");
file_wBytes(f, path, x);
fclose(f);
u64 len = IA(x);
CharBuf buf = get_chars(x);
u64 written = file_openWriteClose(path, buf.data, len);
free_chars(buf);
file_checkWritten(path, written, len);
dec(path);
}
void file_wBytes(FILE* f, char* name, B x) {
u64 len = IA(x);
CharBuf buf = get_chars(x);
if (fwrite(buf.data, 1, len, f) != len) thrF("Error writing data to %S", name);
free_chars(buf);
}
B path_list(B path) {
DIR* d = dir_open(path);
struct dirent *c;

View File

@ -24,7 +24,7 @@ bool path_remove(B path); // consumes
void path_wChars(B path, B x); // consumes path
void path_wBytes(B path, B x); // consumes path
void file_wBytes(FILE* file, B name, B x); // doesn't consume
void file_wBytes(FILE* file, char* name, B x); // doesn't consume
B path_list(B path); // consumes
char path_type(B path); // consumes; errors only if path isn't a string

View File

@ -1,4 +1,4 @@
# not tested here: •Out •Show •Exit •term •GetLine •Cmp •CurrentError •FFI •internal.HeapDump •file.MapBytes
# not tested here: •Out •Show •Exit •GetLine •Cmp •CurrentError •FFI •internal.HeapDump •file.MapBytes
%DEF var V•internal.Variation LV•internal.ListVariations CLR•internal.ClearRefs
%DEF tvar %USE var _tvar {F _𝕣 x: (CLR@) {F 𝕩 V x}¨ LV 𝕩; w F _𝕣 x: (CLR@) (LV 𝕨) {(𝕨 V w) F 𝕩 V x} LV 𝕩}
@ -62,7 +62,7 @@ f ← •ReBQN{repl⇐"none"} ⋄ !6≡•Type F "⇐"
# files; tests are ordered!
{•file.Exists 𝕩? •SH"rmdir", •file.At 𝕩; 0} "testdirNested" %% 0
•file.Remove•file.Exists¨ "testfile.bqn""testfile2.bqn""testfile3B.bqn" 1 %% 1
•file.Remove•file.Exists¨ "testfile.bqn""testfile2.bqn""testfile3B.bqn""badwrite" 1 %% 1
•file.At "/a/b" %% "/a/b"
! (•file.At "a/b") •file.path •file.At "a/b"
"a/b" •file.At "c/d" %% "a/b/c/d"
@ -85,6 +85,9 @@ f ← •ReBQN{repl⇐"none"} ⋄ !6≡•Type F "⇐"
!"•file.Bytes: 𝕩 must be a list" % "testfile.bqn" •file.Bytes <'a'
!"Path wasn't a list of characters" % 'a' •FChars "hi"
!"Path wasn't a list of characters" % (42"testfile.bqn") •file.Chars "hi"
!"Expected character" % "badwrite"•FChars """"
!"Expected character" % "badwrite"•FLines "foo"
!"•file.Chars: 𝕩 must be a list of characters" % "badwrite"•FChars @
! {𝕩•file.Name 𝕩 •FChars "abc"(@+10)"def𝕩"}"testfile.bqn"
! {𝕩•file.Name 𝕩 •FBytes •ToUTF8 "abc"(@+10)"def𝕩"}"testfile2.bqn"
@ -111,11 +114,15 @@ f ← •ReBQN{repl⇐"none"} ⋄ !6≡•Type F "⇐"
•file.Remove "testfile.bqn" %% 1
•file.Remove "testfile2.bqn" %% 1
•file.Remove "testfile3B.bqn" %% 1
"testfile.bqn""testfile2.bqn""testfile3B.bqn" •file.List "." %% 000
"testfile.bqn""testfile2.bqn""testfile3B.bqn""badwrite" •file.List "." %% 0000
!"Failed to resolve ""/dev/file that doesn't exist"": No such file or directory" % •file.RealPath "/dev/file that doesn't exist"
!"Failed to resolve ""/dev/file that doesn't exist"": No such file or directory" % •Import "/dev/file that doesn't exist"
# some of •term
!"Expected character" % •term.OutRaw 2{}
!"•term.ErrRaw: 𝕩 must be a list" % •term.ErrRaw 220
# •ParseFloat & •Repr