diff options
author | H. Peter Anvin <hpa@zytor.com> | 2010-08-12 20:48:33 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-08-12 20:52:53 -0700 |
commit | a104d9a4fd0762b4167668bb43eaeef10469ee9c (patch) | |
tree | 397f11badacb1c864e689a0aaaba17e051cff171 /libinstaller | |
parent | 0fb20934d2145e43f08650dbbf6613f24f2df8c6 (diff) | |
parent | f3ab4925bd8c5c42cf17a34377f82b53b48b132e (diff) | |
download | syslinux-a104d9a4fd0762b4167668bb43eaeef10469ee9c.tar.gz |
Merge branch 'master' into elflink-merge
Resolved Conflicts:
core/diskfs.inc
core/mem/free.c
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'libinstaller')
-rw-r--r-- | libinstaller/getopt/getopt.h | 25 | ||||
-rw-r--r-- | libinstaller/getopt/getopt_long.c | 152 | ||||
-rw-r--r-- | libinstaller/syslxint.h | 6 | ||||
-rw-r--r-- | libinstaller/syslxopt.c | 58 | ||||
-rw-r--r-- | libinstaller/syslxopt.h | 5 |
5 files changed, 229 insertions, 17 deletions
diff --git a/libinstaller/getopt/getopt.h b/libinstaller/getopt/getopt.h new file mode 100644 index 00000000..a1b74b10 --- /dev/null +++ b/libinstaller/getopt/getopt.h @@ -0,0 +1,25 @@ +#ifndef _GETOPT_H +#define _GETOPT_H + +/* (Very slightly) adapted from klibc */ + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +enum { + no_argument = 0, + required_argument = 1, + optional_argument = 2, +}; + +extern char *optarg; +extern int optind, opterr, optopt; + +extern int getopt_long(int, char *const *, const char *, + const struct option *, int *); + +#endif /* _GETOPT_H */ diff --git a/libinstaller/getopt/getopt_long.c b/libinstaller/getopt/getopt_long.c new file mode 100644 index 00000000..cd7fef5a --- /dev/null +++ b/libinstaller/getopt/getopt_long.c @@ -0,0 +1,152 @@ +/* + * getopt.c + * + * getopt_long(), or at least a common subset thereof: + * + * - Option reordering is not supported + * - -W foo is not supported + * - First optstring character "-" not supported. + */ + +#include <stdint.h> +#include <string.h> +#include <stddef.h> +#include <getopt.h> + +char *optarg; +int optind, opterr, optopt; +static struct getopt_private_state { + const char *optptr; + const char *last_optstring; + char *const *last_argv; +} pvt; + +static inline const char *option_matches(const char *arg_str, + const char *opt_name) +{ + while (*arg_str != '\0' && *arg_str != '=') { + if (*arg_str++ != *opt_name++) + return NULL; + } + + if (*opt_name) + return NULL; + + return arg_str; +} + +int getopt_long(int argc, char *const *argv, const char *optstring, + const struct option *longopts, int *longindex) +{ + const char *carg; + const char *osptr; + int opt; + + /* getopt() relies on a number of different global state + variables, which can make this really confusing if there is + more than one use of getopt() in the same program. This + attempts to detect that situation by detecting if the + "optstring" or "argv" argument have changed since last time + we were called; if so, reinitialize the query state. */ + + if (optstring != pvt.last_optstring || argv != pvt.last_argv || + optind < 1 || optind > argc) { + /* optind doesn't match the current query */ + pvt.last_optstring = optstring; + pvt.last_argv = argv; + optind = 1; + pvt.optptr = NULL; + } + + carg = argv[optind]; + + /* First, eliminate all non-option cases */ + + if (!carg || carg[0] != '-' || !carg[1]) + return -1; + + if (carg[1] == '-') { + const struct option *lo; + const char *opt_end = NULL; + + optind++; + + /* Either it's a long option, or it's -- */ + if (!carg[2]) { + /* It's -- */ + return -1; + } + + for (lo = longopts; lo->name; lo++) { + if ((opt_end = option_matches(carg+2, lo->name))) + break; + } + if (!opt_end) + return '?'; + + if (longindex) + *longindex = lo-longopts; + + if (*opt_end == '=') { + if (lo->has_arg) + optarg = (char *)opt_end+1; + else + return '?'; + } else if (lo->has_arg == 1) { + if (!(optarg = argv[optind])) + return '?'; + optind++; + } + + if (lo->flag) { + *lo->flag = lo->val; + return 0; + } else { + return lo->val; + } + } + + if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) { + /* Someone frobbed optind, change to new opt. */ + pvt.optptr = carg + 1; + } + + opt = *pvt.optptr++; + + if (opt != ':' && (osptr = strchr(optstring, opt))) { + if (osptr[1] == ':') { + if (*pvt.optptr) { + /* Argument-taking option with attached + argument */ + optarg = (char *)pvt.optptr; + optind++; + } else { + /* Argument-taking option with non-attached + argument */ + if (argv[optind + 1]) { + optarg = (char *)argv[optind+1]; + optind += 2; + } else { + /* Missing argument */ + optind++; + return (optstring[0] == ':') + ? ':' : '?'; + } + } + return opt; + } else { + /* Non-argument-taking option */ + /* pvt.optptr will remember the exact position to + resume at */ + if (!*pvt.optptr) + optind++; + return opt; + } + } else { + /* Unknown option */ + optopt = opt; + if (!*pvt.optptr) + optind++; + return '?'; + } +} diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h index f16c2e5c..14a7fc2b 100644 --- a/libinstaller/syslxint.h +++ b/libinstaller/syslxint.h @@ -111,8 +111,6 @@ static inline void set_64(uint64_t *p, uint64_t v) */ #ifdef __MSDOS__ -extern uint16_t ldlinux_seg; /* Defined in dos/syslinux.c */ - static inline __attribute__ ((const)) uint16_t ds(void) { @@ -125,7 +123,7 @@ static inline void *set_fs(const void *p) { uint16_t seg; - seg = ldlinux_seg + ((size_t) p >> 4); + seg = ds() + ((size_t) p >> 4); asm volatile ("movw %0,%%fs"::"rm" (seg)); return (void *)((size_t) p & 0xf); } @@ -139,6 +137,7 @@ void set_16_sl(uint16_t * p, uint16_t v); void set_32_sl(uint32_t * p, uint32_t v); void set_64_sl(uint64_t * p, uint64_t v); void memcpy_to_sl(void *dst, const void *src, size_t len); +void memcpy_from_sl(void *dst, const void *src, size_t len); #else @@ -152,6 +151,7 @@ void memcpy_to_sl(void *dst, const void *src, size_t len); #define set_32_sl(x,y) set_32(x,y) #define set_64_sl(x,y) set_64(x,y) #define memcpy_to_sl(d,s,l) memcpy(d,s,l) +#define memcpy_from_sl(d,s,l) memcpy(d,s,l) #endif diff --git a/libinstaller/syslxopt.c b/libinstaller/syslxopt.c index 0ff2efbb..9b42c66f 100644 --- a/libinstaller/syslxopt.c +++ b/libinstaller/syslxopt.c @@ -40,10 +40,14 @@ struct sys_options opt = { .device = NULL, .offset = 0, .menu_save = NULL, + .install_mbr = 0, + .activate_partition = 0, + .force = 0, + .bootsecfile = NULL, }; const struct option long_options[] = { - {"force", 0, NULL, 'f'}, /* dummy option for compatibility */ + {"force", 0, NULL, 'f'}, /* DOS/Win32/mtools only */ {"install", 0, NULL, 'i'}, {"directory", 1, NULL, 'd'}, {"offset", 1, NULL, 't'}, @@ -59,10 +63,12 @@ const struct option long_options[] = { {"clear-once", 0, NULL, 'O'}, {"reset-adv", 0, NULL, OPT_RESET_ADV}, {"menu-save", 1, NULL, 'M'}, + {"mbr", 0, NULL, 'm'}, /* DOS/Win32 only */ + {"active", 0, NULL, 'a'}, /* DOS/Win32 only */ {0, 0, 0, 0} }; -const char short_options[] = "t:fid:UuzS:H:rvho:OM:"; +const char short_options[] = "t:fid:UuzS:H:rvho:OM:ma"; void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode) { @@ -83,11 +89,19 @@ void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode) "Usage: %s [options] directory\n", program); break; + + case MODE_SYSLINUX_DOSWIN: + /* For fs installation under Windows (syslinux.exe) */ + fprintf(stderr, + "Usage: %s [options] <drive>: [bootsecfile]\n" + " --directory -d Directory for installation target\n", + program); + break; } fprintf(stderr, " --install -i Install over the current bootsector\n" - " --update -U Update a previous EXTLINUX installation\n" + " --update -U Update a previous installation\n" " --zip -z Force zipdrive geometry (-H 64 -S 32)\n" " --sectors=# -S Force the number of sectors per track\n" " --heads=# -H Force number of heads\n" @@ -95,17 +109,22 @@ void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode) " --raid -r Fall back to the next device on boot failure\n" " --once=... %s Execute a command once upon boot\n" " --clear-once -O Clear the boot-once command\n" - " --reset-adv Reset auxilliary data\n" - " --menu-save= -M Set the label to select as default on the next boot\n" - "\n" - " Note: geometry is determined at boot time for devices which\n" - " are considered hard disks by the BIOS. Unfortunately, this is\n" - " not possible for devices which are considered floppy disks,\n" - " which includes zipdisks and LS-120 superfloppies.\n" - "\n" - " The -z option is useful for USB devices which are considered\n" - " hard disks by some BIOSes and zipdrives by other BIOSes.\n", - mode == MODE_SYSLINUX ? " " : "-o"); + " --reset-adv Reset auxilliary data\n", + mode == MODE_SYSLINUX ? " " : "-o"); + /* + * Have to chop this roughly in half for the DOS installer due + * to limited output buffer size + */ + fprintf(stderr, + " --menu-save= -M Set the label to select as default on the next boot\n"); + if (mode == MODE_SYSLINUX_DOSWIN) + fprintf(stderr, + " --mbr -m Install an MBR\n" + " --active -a Mark partition as active\n"); + + if (mode == MODE_SYSLINUX_DOSWIN || mode == MODE_SYSLINUX) + fprintf(stderr, + " --force -f Ignore precautions\n"); exit(rv); } @@ -119,6 +138,7 @@ void parse_options(int argc, char *argv[], enum syslinux_mode mode) long_options, NULL)) != EOF) { switch (o) { case 'f': + opt.force = 1; break; case 'z': opt.heads = 64; @@ -183,6 +203,12 @@ void parse_options(int argc, char *argv[], enum syslinux_mode mode) case 'M': opt.menu_save = optarg; break; + case 'm': + opt.install_mbr = 1; + break; + case 'a': + opt.activate_partition = 1; + break; case 'v': fprintf(stderr, "%s " VERSION_STR " Copyright 1994-" YEAR_STR @@ -196,6 +222,7 @@ void parse_options(int argc, char *argv[], enum syslinux_mode mode) switch (mode) { case MODE_SYSLINUX: + case MODE_SYSLINUX_DOSWIN: opt.device = argv[optind++]; break; case MODE_EXTLINUX: @@ -204,6 +231,9 @@ void parse_options(int argc, char *argv[], enum syslinux_mode mode) break; } + if (argv[optind] && (mode == MODE_SYSLINUX_DOSWIN)) + /* Allow for the boot-sector argument */ + opt.bootsecfile = argv[optind++]; if (argv[optind]) usage(EX_USAGE, mode); /* Excess arguments */ } diff --git a/libinstaller/syslxopt.h b/libinstaller/syslxopt.h index 446ab9af..bcbe0352 100644 --- a/libinstaller/syslxopt.h +++ b/libinstaller/syslxopt.h @@ -14,6 +14,10 @@ struct sys_options { const char *device; unsigned int offset; const char *menu_save; + int force; + int install_mbr; + int activate_partition; + const char *bootsecfile; }; enum long_only_opt { @@ -25,6 +29,7 @@ enum long_only_opt { enum syslinux_mode { MODE_SYSLINUX, /* Unmounted filesystem */ MODE_EXTLINUX, + MODE_SYSLINUX_DOSWIN, }; void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode); |