diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2009-07-01 20:56:58 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2009-07-02 10:11:55 +0100 |
commit | 5186251f8f681f2ebb028423bb49a748861fd11e (patch) | |
tree | b95ea92a8ed1b9443dc04aaf7cdacc8191291bc0 /ocaml | |
parent | f20854ec61eef1aea313920f0cf193a78c1a9219 (diff) | |
download | libguestfs-5186251f8f681f2ebb028423bb49a748861fd11e.tar.gz libguestfs-5186251f8f681f2ebb028423bb49a748861fd11e.tar.xz libguestfs-5186251f8f681f2ebb028423bb49a748861fd11e.zip |
Add 'readdir' call.
This adds a readdir call (mostly intended for programs). The
return value is a list of guestfs_dirent structures.
This adds the new types 'struct guestfs_dirent' and
'struct guestfs_dirent_list', along with all the code to
return these in the different language bindings.
Also includes additional tests for OCaml and Perl bindings
to test this.
Diffstat (limited to 'ocaml')
-rw-r--r-- | ocaml/Makefile.am | 9 | ||||
-rw-r--r-- | ocaml/guestfs.ml | 7 | ||||
-rw-r--r-- | ocaml/guestfs.mli | 9 | ||||
-rw-r--r-- | ocaml/guestfs_c_actions.c | 59 | ||||
-rw-r--r-- | ocaml/t/guestfs_060_readdir.ml | 54 |
5 files changed, 136 insertions, 2 deletions
diff --git a/ocaml/Makefile.am b/ocaml/Makefile.am index cb4ad347..bed1f929 100644 --- a/ocaml/Makefile.am +++ b/ocaml/Makefile.am @@ -50,9 +50,11 @@ TESTS_ENVIRONMENT = \ $(VG) TESTS = run-bindtests \ - t/guestfs_005_load t/guestfs_010_launch t/guestfs_050_lvcreate + t/guestfs_005_load t/guestfs_010_launch t/guestfs_050_lvcreate \ + t/guestfs_060_readdir noinst_DATA += bindtests \ - t/guestfs_005_load t/guestfs_010_launch t/guestfs_050_lvcreate + t/guestfs_005_load t/guestfs_010_launch t/guestfs_050_lvcreate \ + t/guestfs_060_readdir bindtests: bindtests.ml mlguestfs.cmxa $(OCAMLFIND) ocamlopt -cclib -L$(top_builddir)/src/.libs -I . unix.cmxa mlguestfs.cmxa $< -o $@ @@ -66,6 +68,9 @@ t/guestfs_010_launch: t/guestfs_010_launch.ml mlguestfs.cmxa t/guestfs_050_lvcreate: t/guestfs_050_lvcreate.ml mlguestfs.cmxa $(OCAMLFIND) ocamlopt -cclib -L$(top_builddir)/src/.libs -I . unix.cmxa mlguestfs.cmxa $< -o $@ +t/guestfs_060_readdir: t/guestfs_060_readdir.ml mlguestfs.cmxa + $(OCAMLFIND) ocamlopt -cclib -L$(top_builddir)/src/.libs -I . unix.cmxa mlguestfs.cmxa $< -o $@ + .mli.cmi: $(OCAMLFIND) ocamlc -c $< .ml.cmo: diff --git a/ocaml/guestfs.ml b/ocaml/guestfs.ml index 0bf458c4..0d3349f4 100644 --- a/ocaml/guestfs.ml +++ b/ocaml/guestfs.ml @@ -115,6 +115,12 @@ type statvfs = { namemax : int64; } +type dirent = { + ino : int64; + ftyp : char; + name : string; +} + external test0 : t -> string -> string option -> string array -> bool -> int -> string -> string -> unit = "ocaml_guestfs_test0_byte" "ocaml_guestfs_test0" external test0rint : t -> string -> int = "ocaml_guestfs_test0rint" external test0rinterr : t -> int = "ocaml_guestfs_test0rinterr" @@ -306,3 +312,4 @@ external mkfifo : t -> int -> string -> unit = "ocaml_guestfs_mkfifo" external mknod_b : t -> int -> int -> int -> string -> unit = "ocaml_guestfs_mknod_b" external mknod_c : t -> int -> int -> int -> string -> unit = "ocaml_guestfs_mknod_c" external umask : t -> int -> int = "ocaml_guestfs_umask" +external readdir : t -> string -> dirent array = "ocaml_guestfs_readdir" diff --git a/ocaml/guestfs.mli b/ocaml/guestfs.mli index 5cab5887..d15335e7 100644 --- a/ocaml/guestfs.mli +++ b/ocaml/guestfs.mli @@ -124,6 +124,12 @@ type statvfs = { namemax : int64; } +type dirent = { + ino : int64; + ftyp : char; + name : string; +} + val test0 : t -> string -> string option -> string array -> bool -> int -> string -> string -> unit (** internal test function - do not use *) @@ -697,3 +703,6 @@ val mknod_c : t -> int -> int -> int -> string -> unit val umask : t -> int -> int (** set file mode creation mask (umask) *) +val readdir : t -> string -> dirent array +(** read directories entries *) + diff --git a/ocaml/guestfs_c_actions.c b/ocaml/guestfs_c_actions.c index 6db72394..498b4b1e 100644 --- a/ocaml/guestfs_c_actions.c +++ b/ocaml/guestfs_c_actions.c @@ -328,6 +328,41 @@ copy_statvfs (const struct guestfs_statvfs *statvfs) CAMLreturn (rv); } +static CAMLprim value +copy_dirent (const struct guestfs_dirent *dirent) +{ + CAMLparam0 (); + CAMLlocal2 (rv, v); + + rv = caml_alloc (3, 0); + v = caml_copy_int64 (dirent->ino); + Store_field (rv, 0, v); + v = Val_int (dirent->ftyp); + Store_field (rv, 1, v); + v = caml_copy_string (dirent->name); + Store_field (rv, 2, v); + CAMLreturn (rv); +} + +static CAMLprim value +copy_dirent_list (const struct guestfs_dirent_list *dirents) +{ + CAMLparam0 (); + CAMLlocal2 (rv, v); + int i; + + if (dirents->len == 0) + CAMLreturn (Atom (0)); + else { + rv = caml_alloc (dirents->len, 0); + for (i = 0; i < dirents->len; ++i) { + v = copy_dirent (&dirents->val[i]); + caml_modify (&Field (rv, i), v); + } + CAMLreturn (rv); + } +} + CAMLprim value ocaml_guestfs_test0 (value gv, value strv, value optstrv, value strlistv, value bv, value integerv, value fileinv, value fileoutv) { @@ -4902,3 +4937,27 @@ ocaml_guestfs_umask (value gv, value maskv) CAMLreturn (rv); } +CAMLprim value +ocaml_guestfs_readdir (value gv, value dirv) +{ + CAMLparam2 (gv, dirv); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("readdir: used handle after closing it"); + + const char *dir = String_val (dirv); + struct guestfs_dirent_list *r; + + caml_enter_blocking_section (); + r = guestfs_readdir (g, dir); + caml_leave_blocking_section (); + if (r == NULL) + ocaml_guestfs_raise_error (g, "readdir"); + + rv = copy_dirent_list (r); + guestfs_free_dirent_list (r); + CAMLreturn (rv); +} + diff --git a/ocaml/t/guestfs_060_readdir.ml b/ocaml/t/guestfs_060_readdir.ml new file mode 100644 index 00000000..f333810e --- /dev/null +++ b/ocaml/t/guestfs_060_readdir.ml @@ -0,0 +1,54 @@ +(* libguestfs OCaml bindings + * Copyright (C) 2009 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., 675 Mass Ave, Cambridge, MA 02139, USA. + *) + +open Unix + +let () = + let g = Guestfs.create () in + + let fd = openfile "test.img" [O_WRONLY;O_CREAT;O_NOCTTY;O_TRUNC] 0o666 in + ftruncate fd (10 * 1024 * 1024); + close fd; + + Guestfs.add_drive g "test.img"; + Guestfs.launch g; + Guestfs.wait_ready g; + + Guestfs.sfdisk g "/dev/sda" 0 0 0 [|","|]; + Guestfs.mkfs g "ext2" "/dev/sda1"; + Guestfs.mount g "/dev/sda1" "/"; + Guestfs.mkdir g "/p"; + Guestfs.touch g "/q"; + + let dirs = Guestfs.readdir g "/" in + let dirs = Array.to_list dirs in + let cmp { Guestfs.name = n1 } { Guestfs.name = n2 } = compare n1 n2 in + let dirs = List.sort cmp dirs in + let dirs = List.map ( + fun { Guestfs.name = name; Guestfs.ftyp = ftyp } -> (name, ftyp) + ) dirs in + + if dirs <> [ ".", 'd'; + "..", 'd'; + "lost+found", 'd'; + "p", 'd'; + "q", 'r' ] then + failwith "Guestfs.readdir returned incorrect result"; + + Guestfs.close g; + unlink "test.img" |