···2828 in
2929 loop [] json |> List.rev
30303131+module Flags = struct
3232+ type t = int
3333+3434+ include Config
3535+3636+ let mem (v : t) i = Int.equal (i land (v :> int)) (v :> int)
3737+end
3838+3139module Open_event = struct
3240 open Ctypes
3341···129137 in
130138 bpf_callback
131139132132-let all poll no_header =
140140+let filter_event_by_flag event flags =
141141+ flags = []
142142+ ||
143143+ let fs = Open_event.get_flags event in
144144+ List.for_all (fun flag -> Flags.mem flag fs) flags
145145+146146+let all poll no_header open_flags =
133147 if no_header then () else Format.printf "%s" Open_event.csv_header;
134148 let callback event =
135135- Format.printf "%s\n%!" (Open_event.to_csv_row event);
149149+ if filter_event_by_flag event open_flags then
150150+ Format.printf "%s\n%!" (Open_event.to_csv_row event);
136151 0
137152 in
138153 let bpf_callback = ringbuffer_polling_callback ~poll callback (fun _ -> ()) in
139154 run_ring_buffer bpf_callback
140155141141-let exec format output user poll (prog, args) =
156156+let exec format output user poll (prog, args) open_flags_filter =
142157 let output =
143158 match output with
144159 | Some file -> file
···190205 match Atomic.get pid with
191206 | None -> 0
192207 | Some pid ->
193193- (if Int.equal (Open_event.get_pid event) pid then
208208+ (if
209209+ Int.equal (Open_event.get_pid event) pid
210210+ && filter_event_by_flag event open_flags_filter
211211+ then
194212 match format with
195213 | Csv ->
196214 Out_channel.output_string oc (Open_event.to_csv_row event);
···228246 let doc = "Disable printing the CSV header" in
229247 Arg.(value & flag & info [ "no-header" ] ~doc)
230248249249+let flag_conv =
250250+ let of_string s =
251251+ try Ok (Flags.of_string s) with Invalid_argument m -> Error (`Msg m)
252252+ in
253253+ let pp ppf v = Format.pp_print_string ppf (Flags.to_string v) in
254254+ Arg.conv (of_string, pp)
255255+256256+let open_flags_filter =
257257+ let doc =
258258+ "Filter open events that include these flags (e.g. O_RDONLY, O_CREAT). \
259259+ Note the filter wants ALL of the flags to be present not just one of \
260260+ them."
261261+ in
262262+ Arg.(value & opt (list flag_conv) [] & info [ "flags" ] ~doc)
263263+231264let user =
232265 let doc = "Username or UID to execute program as" in
233266 Arg.(value & opt (some string) None & info [ "u"; "user" ] ~doc ~docv:"USER")
···250283let output =
251284 let doc =
252285 "Output file for trace. Defaults to trace.<csv|json> depending on the \
253253- $(format)."
286286+ format."
254287 in
255288 Arg.(
256289 value & opt (some string) None & info [ "o"; "output" ] ~docv:"OUTPUT" ~doc)
257290258291let all_cmd =
259259- let doc = "Trace all open system calls" in
292292+ let doc = "Trace all open system calls." in
260293 let man =
261294 [
262295 `P
···266299 in
267300 Cmd.v (Cmd.info ~doc ~man "all")
268301 @@
269269- let+ polling = polling and+ no_header = no_header in
270270- all polling no_header
302302+ let+ polling = polling
303303+ and+ no_header = no_header
304304+ and+ open_flags_filter = open_flags_filter in
305305+ all polling no_header open_flags_filter
271306272307let exec_cmd =
273273- let doc = "Execute a program and trace its open system calls" in
308308+ let doc = "Execute a program and trace its open system calls." in
274309 let man =
275310 [
276311 `P
···287322 and+ format = format
288323 and+ output = output
289324 and+ args = Arg.(value & pos_right 0 string [] & Arg.info [] ~docv:"ARGS")
325325+ and+ open_flags_filter = open_flags_filter
290326 and+ poll = polling in
291291- exec format output user poll (prog, args)
327327+ exec format output user poll (prog, args) open_flags_filter
292328293329let opentrace_cmd =
294330 let doc = "Trace all open system calls" in
295331 let man =
296332 [
297333 `S Manpage.s_description;
298298- `P "$(cmd) traces all open system calls";
334334+ `P "$(tool) traces all open system calls.";
299335 `P
300300- "$(cmd) can be used either to run an executable directly or to trace \
301301- all open calls";
336336+ "$(tool) can be used either to run an executable directly or to trace \
337337+ all open calls.";
302338 ]
303339 in
304340 let default = Term.(ret (const (`Help (`Auto, None)))) in