From 4ddb4999e2ec2de02a40085ad75f43c92a220f21 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 25 Dec 2013 08:49:39 +0800 Subject: [PATCH] Tools/DiskTool - Added script file support --- Tools/DiskTool/main.c | 263 +++++++++++++++++++++++++++++++----------- 1 file changed, 198 insertions(+), 65 deletions(-) diff --git a/Tools/DiskTool/main.c b/Tools/DiskTool/main.c index f8781a49..3dd2aa09 100644 --- a/Tools/DiskTool/main.c +++ b/Tools/DiskTool/main.c @@ -5,9 +5,77 @@ #include #include #include +#include +#include #include +#define ACESS_VERSION "0.15-pr" +#define VERSION_STR "Acess2 DiskTool v"ACESS_VERSION + + int main(int argc, const char *argv[]); +void PrintUsage(void); + int RunCommand(int argc, const char *argv[]); +void RunScript(const char *Filename); + // === CODE === +int main(int argc, const char *argv[]) +{ + // Parse arguments + for( int i = 1; i < argc; i ++ ) + { + const char *arg = argv[i]; + if( arg[0] != '-' ) + { + int rv = RunCommand(argc-i, argv+i); + if( rv == 0 ) { + PrintUsage(); + return 1; + } + else if( rv < 0 ) { + return 0; + } + else { + } + i += rv; + } + else if( arg[1] != '-' ) + { + switch( *++arg ) + { + case 's': + if( i+1 >= argc ) { + fprintf(stderr, "Option '-s' requires an argument\n"); + return 1; + } + RunScript( argv[++i] ); + break; + default: + fprintf(stderr, "Unkown option '-%c', try --help\n", *arg); + return 1; + } + } + else + { + if( strcmp(arg, "--help") == 0 ) { + PrintUsage(); + return 0; + } + else if( strcmp(arg, "--version") == 0 ) { + fprintf(stderr, VERSION_STR); + return 0; + } + else { + fprintf(stderr, "Unknown option '%s', try --help\n", arg); + return 1; + } + } + } + + DiskTool_Cleanup(); + + return 0; +} + void PrintUsage(void) { fprintf(stderr, @@ -33,92 +101,157 @@ void PrintUsage(void) ); } -int main(int argc, char *argv[]) +int RunCommand(int argc, const char *argv[]) { - // Parse arguments - for( int i = 1; i < argc; i ++ ) + if( argc < 1 ) return 0; + + const char *name = argv[0]; + if( strcmp("mount", name) == 0 ) { - if( strcmp("mount", argv[i]) == 0 || strcmp("-i", argv[i]) == 0 ) { - // Mount an image - if( argc - i < 3 ) { - fprintf(stderr, "mount takes 2 arguments (image and mountpoint)\n"); - PrintUsage(); - exit(-1); - } + // Mount an image + if( argc < 3 ) { + fprintf(stderr, "mount takes 2 arguments (image and mountpoint)\n"); + return 0; + } - if( DiskTool_MountImage(argv[i+2], argv[i+1]) ) { - fprintf(stderr, "Unable to mount '%s' as '%s'\n", argv[i+1], argv[i+2]); - break; - } + if( DiskTool_MountImage(argv[2], argv[1]) ) { + fprintf(stderr, "Unable to mount '%s' as '%s'\n", argv[1], argv[2]); + return -1; + } - i += 2; - continue ; + return 2; + } + else if( strcmp("lvm", name) == 0 ) + { + // Bind a "file" to LVM + if( argc < 3 ) { + fprintf(stderr, "lvm takes 2 arguments (iamge and ident)\n"); + return 0; } - - if( strcmp("mountlvm", argv[i]) == 0 || strcmp("lvm", argv[i]) == 0 ) { - - if( argc - i < 3 ) { - fprintf(stderr, "lvm takes 2 arguments (iamge and ident)\n"); - PrintUsage(); - exit(-1); - } - if( DiskTool_RegisterLVM(argv[i+2], argv[i+1]) ) { - fprintf(stderr, "Unable to register '%s' as LVM '%s'\n", argv[i+1], argv[i+2]); - break; - } - - i += 2; - continue ; + if( DiskTool_RegisterLVM(argv[2], argv[1]) ) { + fprintf(stderr, "Unable to register '%s' as LVM '%s'\n", argv[1], argv[2]); + return -1; } - if( strcmp("ls", argv[i]) == 0 ) { - if( argc - i < 2 ) { - fprintf(stderr, "ls takes 1 argument (path)\n"); - PrintUsage(); - break; - } - - DiskTool_ListDirectory(argv[i+1]); - i += 1; - continue ; + return 2; + } + else if( strcmp("ls", name) == 0 ) + { + if( argc < 2 ) { + fprintf(stderr, "ls takes 1 argument (path)\n"); + return 0; } + + DiskTool_ListDirectory(argv[1]); + return 1; + } + else if( strcmp("cp", name) == 0 ) + { - if( strcmp("cp", argv[i]) == 0 ) { - - if( argc - i < 3 ) { - fprintf(stderr, "cp takes 2 arguments (source and destination)\n"); - PrintUsage(); - break; - } + if( argc < 3 ) { + fprintf(stderr, "cp takes 2 arguments (source and destination)\n"); + return 0; + } + + DiskTool_Copy(argv[1], argv[2]); - DiskTool_Copy(argv[i+1], argv[i+2]); + return 2; + } + else if( strcmp("cat", name) == 0 ) { - i += 2; - continue ; + if( argc < 2 ) { + fprintf(stderr, "cat takes 1 argument (path)\n"); + return 0; } - if( strcmp("cat", argv[i]) == 0 ) { + DiskTool_Cat(argv[1]); - if( argc - 1 < 2 ) { - fprintf(stderr, "cat takes 1 argument (path)\n"); - PrintUsage(); - break; + return 1; + } + else { + fprintf(stderr, "Unknown command '%s'\n", name); + return 0; + } +} + +int tokenise(const char **ptrs, int max_ptrs, char *buffer) +{ + int idx = 0; + while( *buffer ) + { + // Eat leading whitespace + while( *buffer && isspace(*buffer) ) + buffer ++; + if( *buffer == '"' ) { + // Double-quoted string + buffer ++; + ptrs[idx++] = buffer; + while( *buffer && *buffer != '"' ) + { + if( *buffer == '\\' && buffer[1] == '"' ) { + char *tmp = buffer; + while( tmp[1] ) { + tmp[0] = tmp[1]; + tmp ++; + } + } + buffer ++; } + if( *buffer ) + *buffer++ = '\0'; + } + else { + // whitespace delimited string + ptrs[idx++] = buffer; + while( *buffer && !isspace(*buffer) ) + buffer ++; + if( *buffer ) + *buffer++ = '\0'; + } + } + return idx; +} - DiskTool_Cat(argv[i+1]); +void RunScript(const char *Filename) +{ + FILE *fp = fopen(Filename, "r"); + if( !fp ) { + fprintf(stderr, "Unable to open script '%s': %s\n", Filename, strerror(errno)); + exit(1); + } - i += 1; - continue; + int line = 0; + char buf[128]; + while( NULL != fgets(buf, sizeof(buf), fp) ) + { + line ++; + const int max_tokens = 4; + const char *tokens[max_tokens]; + int ntok = tokenise(tokens, max_tokens, buf); + + if( ntok > max_tokens ) { + // ... + break ; + } + + int rv = RunCommand(ntok, tokens); + assert(rv + 1 <= ntok); + if( rv == 0 ) { + // Oops, bad command + break; + } + else if( rv == -1 ) { + // Internal error + break; + } + else if( rv + 1 != ntok ) { + // Too many arguments + break; } - - fprintf(stderr, "Unknown command '%s'\n", argv[i]); - PrintUsage(); } - DiskTool_Cleanup(); - - return 0; + fclose(fp); } // NOTE: This is in a native compiled file because it needs access to the real errno macro -- 2.20.1