|
Packit |
9ff65e |
(******************************************************************************)
|
|
Packit |
9ff65e |
(* ocaml-fileutils: files and filenames common operations *)
|
|
Packit |
9ff65e |
(* *)
|
|
Packit |
9ff65e |
(* Copyright (C) 2003-2014, Sylvain Le Gall *)
|
|
Packit |
9ff65e |
(* *)
|
|
Packit |
9ff65e |
(* This library is free software; you can redistribute it and/or modify it *)
|
|
Packit |
9ff65e |
(* under the terms of the GNU Lesser General Public License as published by *)
|
|
Packit |
9ff65e |
(* the Free Software Foundation; either version 2.1 of the License, or (at *)
|
|
Packit |
9ff65e |
(* your option) any later version, with the OCaml static compilation *)
|
|
Packit |
9ff65e |
(* exception. *)
|
|
Packit |
9ff65e |
(* *)
|
|
Packit |
9ff65e |
(* This library is distributed in the hope that it will be useful, but *)
|
|
Packit |
9ff65e |
(* WITHOUT ANY WARRANTY; without even the implied warranty of *)
|
|
Packit |
9ff65e |
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file *)
|
|
Packit |
9ff65e |
(* COPYING for more details. *)
|
|
Packit |
9ff65e |
(* *)
|
|
Packit |
9ff65e |
(* You should have received a copy of the GNU Lesser General Public License *)
|
|
Packit |
9ff65e |
(* along with this library; if not, write to the Free Software Foundation, *)
|
|
Packit |
9ff65e |
(* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *)
|
|
Packit |
9ff65e |
(******************************************************************************)
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
type who = [`User | `Group | `Other | `All]
|
|
Packit |
9ff65e |
type wholist = [ who | `List of who list ]
|
|
Packit |
9ff65e |
type permcopy = [`User | `Group | `Other]
|
|
Packit |
9ff65e |
type perm = [ `Read | `Write | `Exec | `ExecX | `Sticky | `StickyO ]
|
|
Packit |
9ff65e |
type permlist = [ perm | `List of perm list ]
|
|
Packit |
9ff65e |
type actionarg = [ permlist | permcopy ]
|
|
Packit |
9ff65e |
type action = [ `Set of actionarg | `Add of actionarg | `Remove of actionarg]
|
|
Packit |
9ff65e |
type actionlist = [ action | `List of action list ]
|
|
Packit |
9ff65e |
type clause = [ `User of actionlist | `Group of actionlist
|
|
Packit |
9ff65e |
| `Other of actionlist | `All of actionlist
|
|
Packit |
9ff65e |
| `None of actionlist ]
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
type t = clause list
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
let all_masks =
|
|
Packit |
9ff65e |
[
|
|
Packit |
9ff65e |
`User, `Sticky, 0o4000;
|
|
Packit |
9ff65e |
`User, `Exec, 0o0100;
|
|
Packit |
9ff65e |
`User, `Write, 0o0200;
|
|
Packit |
9ff65e |
`User, `Read, 0o0400;
|
|
Packit |
9ff65e |
`Group, `Sticky, 0o2000;
|
|
Packit |
9ff65e |
`Group, `Exec, 0o0010;
|
|
Packit |
9ff65e |
`Group, `Write, 0o0020;
|
|
Packit |
9ff65e |
`Group, `Read, 0o0040;
|
|
Packit |
9ff65e |
`Other, `StickyO, 0o1000;
|
|
Packit |
9ff65e |
`Other, `Exec, 0o0001;
|
|
Packit |
9ff65e |
`Other, `Write, 0o0002;
|
|
Packit |
9ff65e |
`Other, `Read, 0o0004;
|
|
Packit |
9ff65e |
]
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
let mask =
|
|
Packit |
9ff65e |
let module M =
|
|
Packit |
9ff65e |
Map.Make
|
|
Packit |
9ff65e |
(struct
|
|
Packit |
9ff65e |
type t = who * perm
|
|
Packit |
9ff65e |
let compare = Pervasives.compare
|
|
Packit |
9ff65e |
end)
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let m =
|
|
Packit |
9ff65e |
List.fold_left
|
|
Packit |
9ff65e |
(fun m (who, prm, msk) -> M.add (who, prm) msk m)
|
|
Packit |
9ff65e |
M.empty all_masks
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
fun who prm ->
|
|
Packit |
9ff65e |
try
|
|
Packit |
9ff65e |
M.find (who, prm) m
|
|
Packit |
9ff65e |
with Not_found ->
|
|
Packit |
9ff65e |
0
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
let of_int i =
|
|
Packit |
9ff65e |
let user, group, other =
|
|
Packit |
9ff65e |
List.fold_left
|
|
Packit |
9ff65e |
(fun (user, group, other) (who, perm, mask) ->
|
|
Packit |
9ff65e |
if (i land mask) <> 0 then begin
|
|
Packit |
9ff65e |
match who with
|
|
Packit |
9ff65e |
| `User -> perm :: user, group, other
|
|
Packit |
9ff65e |
| `Group -> user, perm :: group, other
|
|
Packit |
9ff65e |
| `Other -> user, group, perm :: other
|
|
Packit |
9ff65e |
end else begin
|
|
Packit |
9ff65e |
(user, group, other)
|
|
Packit |
9ff65e |
end)
|
|
Packit |
9ff65e |
([], [], [])
|
|
Packit |
9ff65e |
all_masks
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
[`User (`Set (`List user));
|
|
Packit |
9ff65e |
`Group (`Set (`List group));
|
|
Packit |
9ff65e |
`Other (`Set (`List other))]
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
let to_string =
|
|
Packit |
9ff65e |
let perm =
|
|
Packit |
9ff65e |
function
|
|
Packit |
9ff65e |
| `Read -> "r"
|
|
Packit |
9ff65e |
| `Write -> "w"
|
|
Packit |
9ff65e |
| `Exec -> "x"
|
|
Packit |
9ff65e |
| `Sticky -> "s"
|
|
Packit |
9ff65e |
| `ExecX -> "X"
|
|
Packit |
9ff65e |
| `StickyO -> "t"
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let permlist =
|
|
Packit |
9ff65e |
function
|
|
Packit |
9ff65e |
| `List lst -> String.concat "" (List.map perm lst)
|
|
Packit |
9ff65e |
| #perm as prm -> perm prm
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let permcopy =
|
|
Packit |
9ff65e |
function
|
|
Packit |
9ff65e |
| `User -> "u"
|
|
Packit |
9ff65e |
| `Group -> "g"
|
|
Packit |
9ff65e |
| `Other -> "o"
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let action act =
|
|
Packit |
9ff65e |
let sact, arg =
|
|
Packit |
9ff65e |
match act with
|
|
Packit |
9ff65e |
| `Set arg -> "=", arg
|
|
Packit |
9ff65e |
| `Add arg -> "+", arg
|
|
Packit |
9ff65e |
| `Remove arg -> "-", arg
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let sarg =
|
|
Packit |
9ff65e |
match arg with
|
|
Packit |
9ff65e |
| #permlist as lst -> permlist lst
|
|
Packit |
9ff65e |
| #permcopy as prm -> permcopy prm
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
sact^sarg
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let actionlist =
|
|
Packit |
9ff65e |
function
|
|
Packit |
9ff65e |
| `List lst -> String.concat "" (List.map action lst)
|
|
Packit |
9ff65e |
| #action as act -> action act
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let clause cls =
|
|
Packit |
9ff65e |
let swho, lst =
|
|
Packit |
9ff65e |
match cls with
|
|
Packit |
9ff65e |
| `User lst -> "u", lst
|
|
Packit |
9ff65e |
| `Group lst -> "g", lst
|
|
Packit |
9ff65e |
| `Other lst -> "o", lst
|
|
Packit |
9ff65e |
| `All lst -> "a", lst
|
|
Packit |
9ff65e |
| `None lst -> "", lst
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
swho^(actionlist lst)
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
fun t -> String.concat "," (List.map clause t)
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
let apply ~is_dir ~umask i (t: t) =
|
|
Packit |
9ff65e |
let set who prm b i =
|
|
Packit |
9ff65e |
let m = mask who prm in
|
|
Packit |
9ff65e |
if b then i lor m else i land (lnot m)
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let get who prm i =
|
|
Packit |
9ff65e |
let m = mask who prm in
|
|
Packit |
9ff65e |
(i land m) <> 0
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let permlist _who i lst =
|
|
Packit |
9ff65e |
List.fold_left
|
|
Packit |
9ff65e |
(fun acc ->
|
|
Packit |
9ff65e |
function
|
|
Packit |
9ff65e |
| `Exec | `Read | `Write | `Sticky | `StickyO as a -> a :: acc
|
|
Packit |
9ff65e |
| `ExecX ->
|
|
Packit |
9ff65e |
if is_dir ||
|
|
Packit |
9ff65e |
List.exists (fun who -> get who `Exec i)
|
|
Packit |
9ff65e |
[`User; `Group; `Other] then
|
|
Packit |
9ff65e |
`Exec :: acc
|
|
Packit |
9ff65e |
else
|
|
Packit |
9ff65e |
acc)
|
|
Packit |
9ff65e |
[]
|
|
Packit |
9ff65e |
(match lst with
|
|
Packit |
9ff65e |
| `List lst -> lst
|
|
Packit |
9ff65e |
| #perm as prm -> [prm])
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let permcopy _who i =
|
|
Packit |
9ff65e |
List.fold_left
|
|
Packit |
9ff65e |
(fun acc (who, prm, _) ->
|
|
Packit |
9ff65e |
if get who prm i then
|
|
Packit |
9ff65e |
prm :: acc
|
|
Packit |
9ff65e |
else
|
|
Packit |
9ff65e |
acc)
|
|
Packit |
9ff65e |
[] all_masks
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let args who i =
|
|
Packit |
9ff65e |
function
|
|
Packit |
9ff65e |
| #permlist as lst -> permlist who i lst
|
|
Packit |
9ff65e |
| #permcopy as who -> permcopy who i
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let rec action who i act =
|
|
Packit |
9ff65e |
match act with
|
|
Packit |
9ff65e |
| `Set arg ->
|
|
Packit |
9ff65e |
action who
|
|
Packit |
9ff65e |
(action who i (`Remove (`List (permcopy who i))))
|
|
Packit |
9ff65e |
(`Add arg)
|
|
Packit |
9ff65e |
| `Add arg ->
|
|
Packit |
9ff65e |
List.fold_left (fun i prm -> set who prm true i) i (args who i arg)
|
|
Packit |
9ff65e |
| `Remove arg ->
|
|
Packit |
9ff65e |
List.fold_left (fun i prm -> set who prm false i) i (args who i arg)
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let actionlist who i lst =
|
|
Packit |
9ff65e |
match lst with
|
|
Packit |
9ff65e |
| `List lst -> List.fold_left (action who) i lst
|
|
Packit |
9ff65e |
| #action as act -> action who i act
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
let actionlist_none i lst =
|
|
Packit |
9ff65e |
let numask = lnot umask in
|
|
Packit |
9ff65e |
let arg_set_if_mask who i arg b =
|
|
Packit |
9ff65e |
List.fold_left
|
|
Packit |
9ff65e |
(fun i prm ->
|
|
Packit |
9ff65e |
if get who prm numask then
|
|
Packit |
9ff65e |
set who prm b i
|
|
Packit |
9ff65e |
else
|
|
Packit |
9ff65e |
i)
|
|
Packit |
9ff65e |
i (args who i arg)
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
List.fold_left
|
|
Packit |
9ff65e |
(fun i who ->
|
|
Packit |
9ff65e |
List.fold_left
|
|
Packit |
9ff65e |
(fun i ->
|
|
Packit |
9ff65e |
function
|
|
Packit |
9ff65e |
| `Set _ -> i
|
|
Packit |
9ff65e |
| `Add arg -> arg_set_if_mask who i arg true
|
|
Packit |
9ff65e |
| `Remove arg -> arg_set_if_mask who i arg false)
|
|
Packit |
9ff65e |
i
|
|
Packit |
9ff65e |
(match lst with
|
|
Packit |
9ff65e |
| `List lst -> lst
|
|
Packit |
9ff65e |
| #action as act -> [act]))
|
|
Packit |
9ff65e |
i [`User; `Group; `Other]
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
|
|
Packit |
9ff65e |
let rec clause i cls =
|
|
Packit |
9ff65e |
match cls with
|
|
Packit |
9ff65e |
| `User lst -> actionlist `User i lst
|
|
Packit |
9ff65e |
| `Group lst -> actionlist `Group i lst
|
|
Packit |
9ff65e |
| `Other lst -> actionlist `Other i lst
|
|
Packit |
9ff65e |
| `All lst ->
|
|
Packit |
9ff65e |
List.fold_left clause i [`User lst; `Group lst; `Other lst]
|
|
Packit |
9ff65e |
| `None lst -> actionlist_none i lst
|
|
Packit |
9ff65e |
in
|
|
Packit |
9ff65e |
List.fold_left clause i t
|