X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fgenerator.ml;h=71aeeed84f7c8fb4e29b4a8412e5ce08dd4f00ef;hp=18504d5520afd4d7c26d7b5b96a60889e80e9a11;hb=f04ee08806ec7bd313e9d54f48f2eb911fcb3067;hpb=53ce488f380e3dd94c26bf507c5639975125a1ee diff --git a/src/generator.ml b/src/generator.ml index 18504d5..71aeeed 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -178,13 +178,13 @@ type flags = * * Note that the test environment has 3 block devices, of size 500MB, * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and - * a fourth squashfs block device with some known files on it (/dev/sdd). + * a fourth ISO block device with some known files on it (/dev/sdd). * * Note for partitioning purposes, the 500MB device has 1015 cylinders. * Number of cylinders was 63 for IDE emulated disks with precisely * the same size. How exactly this is calculated is a mystery. * - * The squashfs block device (/dev/sdd) comes from images/test.sqsh. + * The ISO block device (/dev/sdd) comes from images/test.iso. * * To be able to run the tests in a reasonable amount of time, * the virtual machine and block devices are reused between tests. @@ -326,10 +326,10 @@ and test_init = *) | InitBasicFSonLVM - (* /dev/sdd (the squashfs, see images/ directory in source) + (* /dev/sdd (the ISO, see images/ directory in source) * is mounted on / *) - | InitSquashFS + | InitISOFS (* Sequence of commands for testing. *) and seq = cmd list @@ -805,6 +805,32 @@ is passed to the appliance at boot time. See C. For more information on the architecture of libguestfs, see L."); + ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"], + [InitNone, Always, TestOutputTrue ( + [["set_trace"; "true"]; + ["get_trace"]])], + "enable or disable command traces", + "\ +If the command trace flag is set to 1, then commands are +printed on stdout before they are executed in a format +which is very similar to the one used by guestfish. In +other words, you can run a program with this enabled, and +you will get out a script which you can feed to guestfish +to perform the same set of actions. + +If you want to trace C API calls into libguestfs (and +other libraries) then possibly a better way is to use +the external ltrace(1) command. + +Command traces are disabled unless the environment variable +C is defined and set to C<1>."); + + ("get_trace", (RBool "trace", []), -1, [], + [], + "get command trace enabled flag", + "\ +Return the command trace flag."); + ] (* daemon_functions are any functions which cause some action @@ -859,7 +885,7 @@ update the timestamps on a file, or, if the file does not exist, to create a new zero-length file."); ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutput ( + [InitISOFS, Always, TestOutput ( [["cat"; "/known-2"]], "abcdef\n")], "list the contents of a file", "\ @@ -1007,9 +1033,9 @@ List all the logical volumes detected. This is the equivalent of the L command. The \"full\" version includes all fields."); ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]); - InitSquashFS, Always, TestOutputList ( + InitISOFS, Always, TestOutputList ( [["read_lines"; "/empty"]], [])], "read file as lines", "\ @@ -1271,9 +1297,9 @@ names, you will need to locate and parse the password file yourself (Augeas support makes this relatively easy)."); ("exists", (RBool "existsflag", [Pathname "path"]), 36, [], - [InitSquashFS, Always, TestOutputTrue ( + [InitISOFS, Always, TestOutputTrue ( [["exists"; "/empty"]]); - InitSquashFS, Always, TestOutputTrue ( + InitISOFS, Always, TestOutputTrue ( [["exists"; "/directory"]])], "test if file or directory exists", "\ @@ -1283,9 +1309,9 @@ This returns C if and only if there is a file, directory See also C, C, C."); ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [], - [InitSquashFS, Always, TestOutputTrue ( + [InitISOFS, Always, TestOutputTrue ( [["is_file"; "/known-1"]]); - InitSquashFS, Always, TestOutputFalse ( + InitISOFS, Always, TestOutputFalse ( [["is_file"; "/directory"]])], "test if file exists", "\ @@ -1296,9 +1322,9 @@ other objects like directories. See also C."); ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [], - [InitSquashFS, Always, TestOutputFalse ( + [InitISOFS, Always, TestOutputFalse ( [["is_dir"; "/known-3"]]); - InitSquashFS, Always, TestOutputTrue ( + InitISOFS, Always, TestOutputTrue ( [["is_dir"; "/directory"]])], "test if file exists", "\ @@ -1493,11 +1519,11 @@ This command removes all LVM logical volumes, volume groups and physical volumes."); ("file", (RString "description", [Dev_or_Path "path"]), 49, [], - [InitSquashFS, Always, TestOutput ( + [InitISOFS, Always, TestOutput ( [["file"; "/empty"]], "empty"); - InitSquashFS, Always, TestOutput ( + InitISOFS, Always, TestOutput ( [["file"; "/known-1"]], "ASCII text"); - InitSquashFS, Always, TestLastFail ( + InitISOFS, Always, TestLastFail ( [["file"; "/notexists"]])], "determine file type", "\ @@ -1646,7 +1672,7 @@ result into a list of lines. See also: C"); ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [], - [InitSquashFS, Always, TestOutputStruct ( + [InitISOFS, Always, TestOutputStruct ( [["stat"; "/empty"]], [CompareWithInt ("size", 0)])], "get file information", "\ @@ -1655,7 +1681,7 @@ Returns file information for the given C. This is the same as the C system call."); ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [], - [InitSquashFS, Always, TestOutputStruct ( + [InitISOFS, Always, TestOutputStruct ( [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])], "get file information for a symbolic link", "\ @@ -1668,8 +1694,8 @@ refers to. This is the same as the C system call."); ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [], - [InitSquashFS, Always, TestOutputStruct ( - [["statvfs"; "/"]], [CompareWithInt ("namemax", 256)])], + [InitISOFS, Always, TestOutputStruct ( + [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])], "get file system statistics", "\ Returns file system statistics for any mounted file system. @@ -1834,21 +1860,21 @@ C can also be a named pipe. See also C, C."); ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [], - [InitSquashFS, Always, TestOutput ( + [InitISOFS, Always, TestOutput ( [["checksum"; "crc"; "/known-3"]], "2891671662"); - InitSquashFS, Always, TestLastFail ( + InitISOFS, Always, TestLastFail ( [["checksum"; "crc"; "/notexists"]]); - InitSquashFS, Always, TestOutput ( + InitISOFS, Always, TestOutput ( [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c"); - InitSquashFS, Always, TestOutput ( + InitISOFS, Always, TestOutput ( [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15"); - InitSquashFS, Always, TestOutput ( + InitISOFS, Always, TestOutput ( [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741"); - InitSquashFS, Always, TestOutput ( + InitISOFS, Always, TestOutput ( [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30"); - InitSquashFS, Always, TestOutput ( + InitISOFS, Always, TestOutput ( [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640"); - InitSquashFS, Always, TestOutput ( + InitISOFS, Always, TestOutput ( [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")], "compute MD5, SHAx or CRC checksum of file", "\ @@ -2288,9 +2314,9 @@ true if their content is exactly equal, or false otherwise. The external L program is used for the comparison."); ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]); - InitSquashFS, Always, TestOutputList ( + InitISOFS, Always, TestOutputList ( [["strings"; "/empty"]], [])], "print the printable strings in a file", "\ @@ -2298,7 +2324,7 @@ This runs the L command on a file and returns the list of printable strings found."); ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["strings_e"; "b"; "/known-5"]], []); InitBasicFS, Disabled, TestOutputList ( [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"]; @@ -2316,12 +2342,12 @@ show strings inside Windows/x86 files. The returned strings are transcoded to UTF-8."); ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutput ( + [InitISOFS, Always, TestOutput ( [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n"); (* Test for RHBZ#501888c2 regression which caused large hexdump * commands to segfault. *) - InitSquashFS, Always, TestRun ( + InitISOFS, Always, TestRun ( [["hexdump"; "/100krandom"]])], "dump a file in hexadecimal", "\ @@ -2663,7 +2689,7 @@ directory and its contents after use. See also: L"); ("wc_l", (RInt "lines", [Pathname "path"]), 118, [], - [InitSquashFS, Always, TestOutputInt ( + [InitISOFS, Always, TestOutputInt ( [["wc_l"; "/10klines"]], 10000)], "count lines in a file", "\ @@ -2671,7 +2697,7 @@ This command counts the lines in a file, using the C external command."); ("wc_w", (RInt "words", [Pathname "path"]), 119, [], - [InitSquashFS, Always, TestOutputInt ( + [InitISOFS, Always, TestOutputInt ( [["wc_w"; "/10klines"]], 10000)], "count words in a file", "\ @@ -2679,7 +2705,7 @@ This command counts the words in a file, using the C external command."); ("wc_c", (RInt "chars", [Pathname "path"]), 120, [], - [InitSquashFS, Always, TestOutputInt ( + [InitISOFS, Always, TestOutputInt ( [["wc_c"; "/100kallspaces"]], 102400)], "count characters in a file", "\ @@ -2687,7 +2713,7 @@ This command counts the characters in a file, using the C external command."); ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])], "return first 10 lines of a file", "\ @@ -2695,11 +2721,11 @@ This command returns up to the first 10 lines of a file as a list of strings."); ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]); - InitSquashFS, Always, TestOutputList ( + InitISOFS, Always, TestOutputList ( [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]); - InitSquashFS, Always, TestOutputList ( + InitISOFS, Always, TestOutputList ( [["head_n"; "0"; "/10klines"]], [])], "return first N lines of a file", "\ @@ -2712,7 +2738,7 @@ from the file C, excluding the last C lines. If the parameter C is zero, this returns an empty list."); ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])], "return last 10 lines of a file", "\ @@ -2720,11 +2746,11 @@ This command returns up to the last 10 lines of a file as a list of strings."); ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]); - InitSquashFS, Always, TestOutputList ( + InitISOFS, Always, TestOutputList ( [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]); - InitSquashFS, Always, TestOutputList ( + InitISOFS, Always, TestOutputList ( [["tail_n"; "0"; "/10klines"]], [])], "return last N lines of a file", "\ @@ -2762,8 +2788,8 @@ is I intended that you try to parse the output string. Use C from programs."); ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [], - [InitSquashFS, Always, TestOutputInt ( - [["du"; "/directory"]], 0 (* squashfs doesn't have blocks *))], + [InitISOFS, Always, TestOutputInt ( + [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))], "estimate file space usage", "\ This command runs the C command to estimate file space @@ -2777,7 +2803,7 @@ The result is the estimated size in I (ie. units of 1024 bytes)."); ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])], "list files in an initrd", "\ @@ -2968,7 +2994,7 @@ were rarely if ever used anyway. See also C and the L manpage."); - ("zfile", (RString "description", [String "method"; Pathname "path"]), 140, [DeprecatedBy "file"], + ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"], [], "determine file type inside a compressed file", "\ @@ -3089,7 +3115,7 @@ with C. See C for full details."); ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputBuffer ( + [InitISOFS, Always, TestOutputBuffer ( [["read_file"; "/known-4"]], "abc\ndef\nghi")], "read a file", "\ @@ -3102,9 +3128,9 @@ However unlike C, this function is limited in the total size of file that can be handled."); ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]); - InitSquashFS, Always, TestOutputList ( + InitISOFS, Always, TestOutputList ( [["grep"; "nomatch"; "/test-grep.txt"]], [])], "return lines matching a pattern", "\ @@ -3112,7 +3138,7 @@ This calls the external C program and returns the matching lines."); ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])], "return lines matching a pattern", "\ @@ -3120,7 +3146,7 @@ This calls the external C program and returns the matching lines."); ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])], "return lines matching a pattern", "\ @@ -3128,7 +3154,7 @@ This calls the external C program and returns the matching lines."); ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])], "return lines matching a pattern", "\ @@ -3136,7 +3162,7 @@ This calls the external C program and returns the matching lines."); ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])], "return lines matching a pattern", "\ @@ -3144,7 +3170,7 @@ This calls the external C program and returns the matching lines."); ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])], "return lines matching a pattern", "\ @@ -3152,7 +3178,7 @@ This calls the external C program and returns the matching lines."); ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])], "return lines matching a pattern", "\ @@ -3160,7 +3186,7 @@ This calls the external C program and returns the matching lines."); ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])], "return lines matching a pattern", "\ @@ -3168,7 +3194,7 @@ This calls the external C program and returns the matching lines."); ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])], "return lines matching a pattern", "\ @@ -3176,7 +3202,7 @@ This calls the external C program and returns the matching lines."); ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])], "return lines matching a pattern", "\ @@ -3184,7 +3210,7 @@ This calls the external C program and returns the matching lines."); ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])], "return lines matching a pattern", "\ @@ -3192,7 +3218,7 @@ This calls the external C program and returns the matching lines."); ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning], - [InitSquashFS, Always, TestOutputList ( + [InitISOFS, Always, TestOutputList ( [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])], "return lines matching a pattern", "\ @@ -3200,7 +3226,7 @@ This calls the external C program and returns the matching lines."); ("realpath", (RString "rpath", [Pathname "path"]), 163, [], - [InitSquashFS, Always, TestOutput ( + [InitISOFS, Always, TestOutput ( [["realpath"; "/../directory"]], "/directory")], "canonicalized absolute pathname", "\ @@ -3361,7 +3387,7 @@ This command just writes a swap file signature to an existing file. To create the file itself, use something like C."); ("inotify_init", (RErr, [Int "maxevents"]), 179, [], - [InitSquashFS, Always, TestRun ( + [InitISOFS, Always, TestRun ( [["inotify_init"; "0"]])], "create an inotify handle", "\ @@ -3560,8 +3586,8 @@ an external journal on the journal with UUID C. See also C."); - ("modprobe", (RErr, [String "module"]), 194, [], - [InitNone, Always, TestRun [["modprobe"; "ext2"]]], + ("modprobe", (RErr, [String "modulename"]), 194, [], + [InitNone, Always, TestRun [["modprobe"; "fat"]]], "load a kernel module", "\ This loads a kernel module in the appliance. @@ -3569,6 +3595,19 @@ This loads a kernel module in the appliance. The kernel module must have been whitelisted when libguestfs was built (see C in the source)."); + ("echo_daemon", (RString "output", [StringList "words"]), 195, [], + [InitNone, Always, TestOutput ( + [["echo_daemon"; "This is a test"]], "This is a test" + )], + "echo arguments back to the client", + "\ +This command concatenate the list of C passed with single spaces between +them and returns the resulting string. + +You can use this command to test the connection through to the daemon. + +See also C."); + ] let all_functions = non_daemon_functions @ daemon_functions @@ -4050,7 +4089,36 @@ let check_functions () = if n = "i" || n = "n" then failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name; if n = "argv" || n = "args" then - failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name + failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name; + + (* List Haskell, OCaml and C keywords here. + * http://www.haskell.org/haskellwiki/Keywords + * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char + * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords + * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \ + * |perl -pe 's/(.+)/"$1";/'|fmt -70 + * Omitting _-containing words, since they're handled above. + * Omitting the OCaml reserved word, "val", is ok, + * and saves us from renaming several parameters. + *) + let reserved = [ + "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case"; + "char"; "class"; "const"; "constraint"; "continue"; "data"; + "default"; "deriving"; "do"; "done"; "double"; "downto"; "else"; + "end"; "enum"; "exception"; "extern"; "external"; "false"; "float"; + "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto"; + "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl"; + "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int"; + "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor"; + "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new"; + "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified"; + "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed"; + "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try"; + "type"; "typedef"; "union"; "unsigned"; "virtual"; "void"; + "volatile"; "when"; "where"; "while"; + ] in + if List.mem n reserved then + failwithf "%s has param/ret using reserved word %s" name n; in (match fst style with @@ -4519,6 +4587,16 @@ and generate_actions_h () = name style ) all_functions +(* Generate the guestfs-internal-actions.h file. *) +and generate_internal_actions_h () = + generate_header CStyle LGPLv2; + List.iter ( + fun (shortname, style, _, _, _, _, _) -> + let name = "guestfs__" ^ shortname in + generate_prototype ~single_line:true ~newline:true ~handle:"handle" + name style + ) non_daemon_functions + (* Generate the client-side dispatch stubs. *) and generate_client_actions () = generate_header CStyle LGPLv2; @@ -4528,20 +4606,21 @@ and generate_client_actions () = #include #include \"guestfs.h\" +#include \"guestfs-internal-actions.h\" #include \"guestfs_protocol.h\" #define error guestfs_error -#define perrorf guestfs_perrorf -#define safe_malloc guestfs_safe_malloc +//#define perrorf guestfs_perrorf +//#define safe_malloc guestfs_safe_malloc #define safe_realloc guestfs_safe_realloc -#define safe_strdup guestfs_safe_strdup +//#define safe_strdup guestfs_safe_strdup #define safe_memdup guestfs_safe_memdup /* Check the return message from a call for validity. */ static int check_reply_header (guestfs_h *g, const struct guestfs_message_header *hdr, - int proc_nr, int serial) + unsigned int proc_nr, unsigned int serial) { if (hdr->prog != GUESTFS_PROGRAM) { error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM); @@ -4590,6 +4669,68 @@ check_state (guestfs_h *g, const char *caller) "; + (* Generate code to generate guestfish call traces. *) + let trace_call shortname style = + pr " if (guestfs__get_trace (g)) {\n"; + + let needs_i = + List.exists (function + | StringList _ | DeviceList _ -> true + | _ -> false) (snd style) in + if needs_i then ( + pr " int i;\n"; + pr "\n" + ); + + pr " printf (\"%s\");\n" shortname; + List.iter ( + function + | String n (* strings *) + | Device n + | Pathname n + | Dev_or_Path n + | FileIn n + | FileOut n -> + (* guestfish doesn't support string escaping, so neither do we *) + pr " printf (\" \\\"%%s\\\"\", %s);\n" n + | OptString n -> (* string option *) + pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n; + pr " else printf (\" null\");\n" + | StringList n + | DeviceList n -> (* string list *) + pr " putchar (' ');\n"; + pr " putchar ('\"');\n"; + pr " for (i = 0; %s[i]; ++i) {\n" n; + pr " if (i > 0) putchar (' ');\n"; + pr " fputs (%s[i], stdout);\n" n; + pr " }\n"; + pr " putchar ('\"');\n"; + | Bool n -> (* boolean *) + pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n + | Int n -> (* int *) + pr " printf (\" %%d\", %s);\n" n + ) (snd style); + pr " putchar ('\\n');\n"; + pr " }\n"; + pr "\n"; + in + + (* For non-daemon functions, generate a wrapper around each function. *) + List.iter ( + fun (shortname, style, _, _, _, _, _) -> + let name = "guestfs_" ^ shortname in + + generate_prototype ~extern:false ~semicolon:false ~newline:true + ~handle:"g" name style; + pr "{\n"; + trace_call shortname style; + pr " return guestfs__%s " shortname; + generate_c_call_args ~handle:"g" style; + pr ";\n"; + pr "}\n"; + pr "\n" + ) non_daemon_functions; + (* Client-side stubs for each function. *) List.iter ( fun (shortname, style, _, _, _, _, _) -> @@ -4690,6 +4831,7 @@ check_state (guestfs_h *g, const char *caller) pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n"; pr " int serial;\n"; pr "\n"; + trace_call shortname style; pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code; pr " guestfs_set_busy (g);\n"; pr "\n"; @@ -5350,7 +5492,7 @@ static void print_table (char const *const *argv) int main (int argc, char *argv[]) { char c = 0; - int failed = 0; + unsigned long int n_failed = 0; const char *filename; int fd; int nr_tests, test_num = 0; @@ -5453,8 +5595,8 @@ int main (int argc, char *argv[]) exit (1); } - if (guestfs_add_drive_ro (g, \"../images/test.sqsh\") == -1) { - printf (\"guestfs_add_drive_ro ../images/test.sqsh FAILED\\n\"); + if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) { + printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\"); exit (1); } @@ -5484,7 +5626,7 @@ int main (int argc, char *argv[]) pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name; pr " if (%s () == -1) {\n" test_name; pr " printf (\"%s FAILED\\n\");\n" test_name; - pr " failed++;\n"; + pr " n_failed++;\n"; pr " }\n"; ) test_names; pr "\n"; @@ -5495,8 +5637,8 @@ int main (int argc, char *argv[]) pr " unlink (\"test3.img\");\n"; pr "\n"; - pr " if (failed > 0) {\n"; - pr " printf (\"***** %%d / %%d tests FAILED *****\\n\", failed, nr_tests);\n"; + pr " if (n_failed > 0) {\n"; + pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n"; pr " exit (1);\n"; pr " }\n"; pr "\n"; @@ -5612,13 +5754,13 @@ and generate_one_test_body name i test_name init test = ["lvcreate"; "LV"; "VG"; "8"]; ["mkfs"; "ext2"; "/dev/VG/LV"]; ["mount"; "/dev/VG/LV"; "/"]] - | InitSquashFS -> - pr " /* InitSquashFS for %s */\n" test_name; + | InitISOFS -> + pr " /* InitISOFS for %s */\n" test_name; List.iter (generate_test_command_call test_name) [["blockdev_setrw"; "/dev/sda"]; ["umount_all"]; ["lvm_remove_all"]; - ["mount_vfs"; "ro"; "squashfs"; "/dev/sdd"; "/"]] + ["mount_ro"; "/dev/sdd"; "/"]] ); let get_seq_last = function @@ -6080,7 +6222,7 @@ and generate_fish_cmds () = pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ; pr "{\n"; - pr " int i;\n"; + pr " unsigned int i;\n"; pr "\n"; pr " for (i = 0; i < %ss->len; ++i) {\n" typ; pr " printf (\"[%%d] = {\\n\", i);\n"; @@ -6100,7 +6242,7 @@ and generate_fish_cmds () = pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ; pr "{\n"; if needs_i then ( - pr " int i;\n"; + pr " unsigned int i;\n"; pr "\n" ); List.iter ( @@ -6192,7 +6334,7 @@ and generate_fish_cmds () = | OptString n | FileIn n | FileOut n -> pr " const char *%s;\n" n - | StringList n | DeviceList n -> pr " char *const *%s;\n" n + | StringList n | DeviceList n -> pr " char **%s;\n" n | Bool n -> pr " int %s;\n" n | Int n -> pr " int %s;\n" n ) (snd style); @@ -6235,6 +6377,15 @@ and generate_fish_cmds () = generate_c_call_args ~handle:"g" style; pr ";\n"; + List.iter ( + function + | Pathname name | Device name | Dev_or_Path name | String name + | OptString name | FileIn name | FileOut name | Bool name + | Int name -> () + | StringList name | DeviceList name -> + pr " free_strings (%s);\n" name + ) (snd style); + (* Check return value for errors and display command results. *) (match fst style with | RErr -> pr " return r;\n" @@ -6663,6 +6814,29 @@ copy_table (char * const * argv) "; (* Struct copy functions. *) + + let emit_ocaml_copy_list_function typ = + pr "static CAMLprim value\n"; + pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ; + pr "{\n"; + pr " CAMLparam0 ();\n"; + pr " CAMLlocal2 (rv, v);\n"; + pr " unsigned int i;\n"; + pr "\n"; + pr " if (%ss->len == 0)\n" typ; + pr " CAMLreturn (Atom (0));\n"; + pr " else {\n"; + pr " rv = caml_alloc (%ss->len, 0);\n" typ; + pr " for (i = 0; i < %ss->len; ++i) {\n" typ; + pr " v = copy_%s (&%ss->val[i]);\n" typ typ; + pr " caml_modify (&Field (rv, i), v);\n"; + pr " }\n"; + pr " CAMLreturn (rv);\n"; + pr " }\n"; + pr "}\n"; + pr "\n"; + in + List.iter ( fun (typ, cols) -> let has_optpercent_col = @@ -6709,29 +6883,17 @@ copy_table (char * const * argv) pr " CAMLreturn (rv);\n"; pr "}\n"; pr "\n"; - - pr "static CAMLprim value\n"; - pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" - typ typ typ; - pr "{\n"; - pr " CAMLparam0 ();\n"; - pr " CAMLlocal2 (rv, v);\n"; - pr " int i;\n"; - pr "\n"; - pr " if (%ss->len == 0)\n" typ; - pr " CAMLreturn (Atom (0));\n"; - pr " else {\n"; - pr " rv = caml_alloc (%ss->len, 0);\n" typ; - pr " for (i = 0; i < %ss->len; ++i) {\n" typ; - pr " v = copy_%s (&%ss->val[i]);\n" typ typ; - pr " caml_modify (&Field (rv, i), v);\n"; - pr " }\n"; - pr " CAMLreturn (rv);\n"; - pr " }\n"; - pr "}\n"; - pr "\n"; ) structs; + (* Emit a copy_TYPE_list function definition only if that function is used. *) + List.iter ( + function + | typ, (RStructListOnly | RStructAndList) -> + (* generate the function for typ *) + emit_ocaml_copy_list_function typ + | typ, _ -> () (* empty *) + ) rstructs_used; + (* The wrappers. *) List.iter ( fun (name, style, _, _, _, _, _) -> @@ -6741,6 +6903,10 @@ copy_table (char * const * argv) let needs_extra_vs = match fst style with RConstOptString _ -> true | _ -> false in + pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n"; + pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params); + List.iter (pr ", value %s") (List.tl params); pr ");\n"; + pr "CAMLprim value\n"; pr "ocaml_guestfs_%s (value %s" name (List.hd params); List.iter (pr ", value %s") (List.tl params); @@ -6874,6 +7040,9 @@ copy_table (char * const * argv) pr "\n"; if List.length params > 5 then ( + pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n"; + pr "CAMLprim value "; + pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name; pr "CAMLprim value\n"; pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name; pr "{\n"; @@ -9042,6 +9211,7 @@ and generate_bindtests () = #include #include \"guestfs.h\" +#include \"guestfs-internal-actions.h\" #include \"guestfs_protocol.h\" #define error guestfs_error @@ -9072,7 +9242,7 @@ print_strings (char *const *argv) let () = let (name, style, _, _, _, _, _) = test0 in generate_prototype ~extern:false ~semicolon:false ~newline:true - ~handle:"g" ~prefix:"guestfs_" name style; + ~handle:"g" ~prefix:"guestfs__" name style; pr "{\n"; List.iter ( function @@ -9097,7 +9267,7 @@ print_strings (char *const *argv) if String.sub name (String.length name - 3) 3 <> "err" then ( pr "/* Test normal return. */\n"; generate_prototype ~extern:false ~semicolon:false ~newline:true - ~handle:"g" ~prefix:"guestfs_" name style; + ~handle:"g" ~prefix:"guestfs__" name style; pr "{\n"; (match fst style with | RErr -> @@ -9163,7 +9333,7 @@ print_strings (char *const *argv) ) else ( pr "/* Test error return. */\n"; generate_prototype ~extern:false ~semicolon:false ~newline:true - ~handle:"g" ~prefix:"guestfs_" name style; + ~handle:"g" ~prefix:"guestfs__" name style; pr "{\n"; pr " error (g, \"error\");\n"; (match fst style with @@ -9486,6 +9656,10 @@ Run it from the top source directory using the command generate_actions_h (); close (); + let close = output_to "src/guestfs-internal-actions.h" in + generate_internal_actions_h (); + close (); + let close = output_to "src/guestfs-actions.c" in generate_client_actions (); close ();