File: append_line.ml

package info (click to toggle)
libguestfs 1%3A1.44.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 118,932 kB
  • sloc: ansic: 458,017; ml: 51,424; sh: 13,191; java: 9,578; makefile: 7,931; cs: 6,328; haskell: 5,674; python: 3,871; perl: 3,528; erlang: 2,446; xml: 1,347; ruby: 350; pascal: 257; javascript: 157; lex: 135; yacc: 128; cpp: 10
file content (72 lines) | stat: -rw-r--r-- 2,397 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
(* virt-customize
 * Copyright (C) 2016 Red Hat Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *)

open Std_utils
open Tools_utils
open Common_gettext.Gettext

module G = Guestfs

let append_line (g : G.guestfs) root path line =
  (* The default line ending for this guest type.  This is only
   * used when we don't know anything more about the file.
   *)
  let default_newline () =
    match g#inspect_get_type root with
    | "windows" -> "\r\n"
    | _ -> "\n"
  in

  if not (g#exists path) then (
    g#write path (line ^ default_newline ())
  )
  else (
    (* Stat the file.  We want to know it's a regular file, and
     * also its size.
     *)
    let { G.st_mode; st_size = size } = g#statns path in
    if Int64.logand st_mode 0o170000_L <> 0o100000_L then
      error (f_"append_line: %s is not a file") path;

    (* Guess the line ending from the first part of the file, else
     * use the default for this guest type.
     *)
    let newline =
      let content = g#pread path 8192 0L in
      if String.find content "\r\n" >= 0 then "\r\n"
      else if String.find content "\n" >= 0 then "\n"
      else if String.find content "\r" >= 0 then "\r"
      else default_newline () in

    let line = line ^ newline in

    (* Do we need to append a newline to the existing file? *)
    let last_chars =
      let len = String.length newline in
      if size <= 0L then newline (* empty file ends in virtual newline *)
      else if size >= Int64.of_int len then
        g#pread path len (size -^ Int64.of_int len)
      else
        g#pread path len 0L in
    let line =
      if last_chars = newline then line
      else newline ^ line in

    (* Finally, append. *)
    g#write_append path line
  )