Skip to content

Commit 1d7a956

Browse files
author
Arvid Jakobsson
committed
[Files.save_as]: just write directly to special files
Also, if [name] is a symbolic link, resolve it first.
1 parent f1b26ec commit 1d7a956

2 files changed

Lines changed: 15 additions & 2 deletions

File tree

files.ml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ let mkdir_p ?(perm=0o755) path =
6767
in
6868
aux path
6969

70-
let save_as name ?(mode=0o644) f =
70+
let save_as_regular name ?(mode=0o644) f =
7171
(* not using make_temp_file cause same dir is needed for atomic rename *)
7272
let temp = Printf.sprintf "%s.save.%d.tmp" name (U.gettid ()) in
7373
bracket (Unix.openfile temp [Unix.O_WRONLY;Unix.O_CREAT] mode) Unix.close begin fun fd ->
@@ -81,3 +81,13 @@ let save_as name ?(mode=0o644) f =
8181
with
8282
exn -> Exn.suppress Unix.unlink temp; raise exn
8383
end
84+
85+
let save_as name ?mode f =
86+
let name =
87+
match (Unix.lstat name).st_kind with
88+
| Unix.S_LNK -> Unix.realpath name
89+
| (exception Unix.Unix_error (Unix.ENOENT, _, _)) | _ -> name
90+
in
91+
match (Unix.stat name).st_kind with
92+
| Unix.S_REG | (exception Unix.Unix_error (Unix.ENOENT, _, _)) -> save_as_regular name ?mode f
93+
| _ -> Out_channel.with_open_gen [ Open_wronly ] 0 name f

files.mli

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ val open_out_append_text : string -> out_channel
2222
val mkdir_p : ?perm:Unix.file_perm -> string -> unit
2323

2424
(** [save_as filename ?mode f] is similar to
25-
[Control.with_open_file_bin] except that writing is done to a
25+
[Control.with_open_file_bin] for regular files, except that writing is done to a
2626
temporary file that will be renamed to [filename] after [f] has
2727
succesfully terminated. Therefore this guarantee that either
2828
[filename] will not be modified or will contain whatever [f] was
2929
writing to it as a side-effect.
3030
31+
There is no such special treatment for special files, instead they
32+
are written to directly.
33+
3134
FIXME windows *)
3235
val save_as : string -> ?mode:Unix.file_perm -> (out_channel -> unit) -> unit

0 commit comments

Comments
 (0)