reorganize file writing
fixes some unclosed file descriptors & files being made on an invalid argument
This commit is contained in:
parent
b6594008cd
commit
7ffd744375
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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" % (4‿2⥊"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 "." %% 0‿0‿0
|
||||
"testfile.bqn"‿"testfile2.bqn"‿"testfile3B.bqn"‿"badwrite" ∊ •file.List "." %% 0‿0‿0‿0
|
||||
|
||||
!"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 2‿2⥊0
|
||||
|
||||
|
||||
|
||||
# •ParseFloat & •Repr
|
||||
|
||||
Loading…
Reference in New Issue
Block a user