diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2010-06-22 16:52:32 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2010-06-22 16:52:32 -0700 |
commit | a73b14259504d25e782df6cef4331fbd8710f575 (patch) | |
tree | 8bb189a08cf9b705af566d0f1f7e9f21fbba0ece | |
parent | ad0d53c9ed34da93d7b9ce96ffaf5570c7c2a95b (diff) | |
download | syslinux-a73b14259504d25e782df6cef4331fbd8710f575.tar.gz |
win32: vacuous ADV support
Install an empty ADV in the Windows installer to keep it from being
broken. In order to do that, separate the Unix-specific ADV I/O
functions from the generic data structure manipulation.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r-- | extlinux/Makefile | 1 | ||||
-rw-r--r-- | libinstaller/advio.c | 159 | ||||
-rw-r--r-- | libinstaller/setadv.c | 130 | ||||
-rw-r--r-- | linux/Makefile | 1 | ||||
-rw-r--r-- | linux/syslinux.c | 6 | ||||
-rw-r--r-- | win32/Makefile | 1 | ||||
-rw-r--r-- | win32/syslinux.c | 20 |
7 files changed, 176 insertions, 142 deletions
diff --git a/extlinux/Makefile b/extlinux/Makefile index 2501a454..83cf1a54 100644 --- a/extlinux/Makefile +++ b/extlinux/Makefile @@ -28,6 +28,7 @@ SRCS = main.c \ ../libinstaller/syslxopt.c \ ../libinstaller/syslxcom.c \ ../libinstaller/setadv.c \ + ../libinstaller/advio.c \ ../libinstaller/bootsect_bin.c \ ../libinstaller/ldlinux_bin.c OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS))) diff --git a/libinstaller/advio.c b/libinstaller/advio.c new file mode 100644 index 00000000..3112fa42 --- /dev/null +++ b/libinstaller/advio.c @@ -0,0 +1,159 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * advio.c + * + * Linux ADV I/O + * + * Return 0 on success, -1 on error, and set errno. + * + */ +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include "syslxint.h" +#include "syslxcom.h" + +/* + * Read the ADV from an existing instance, or initialize if invalid. + * Returns -1 on fatal errors, 0 if ADV is okay, and 1 if no valid + * ADV was found. + */ +int read_adv(const char *path, const char *cfg) +{ + char *file; + int fd = -1; + struct stat st; + int err = 0; + + asprintf(&file, "%s%s%s", + path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg); + + if (!file) { + perror(program); + return -1; + } + + fd = open(file, O_RDONLY); + if (fd < 0) { + if (errno != ENOENT) { + err = -1; + } else { + syslinux_reset_adv(syslinux_adv); + } + } else if (fstat(fd, &st)) { + err = -1; + } else if (st.st_size < 2 * ADV_SIZE) { + /* Too small to be useful */ + syslinux_reset_adv(syslinux_adv); + err = 0; /* Nothing to read... */ + } else if (xpread(fd, syslinux_adv, 2 * ADV_SIZE, + st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) { + err = -1; + } else { + /* We got it... maybe? */ + err = syslinux_validate_adv(syslinux_adv) ? 1 : 0; + } + + if (err < 0) + perror(file); + + if (fd >= 0) + close(fd); + + free(file); + + return err; +} + +/* + * Update the ADV in an existing installation. + */ +int write_adv(const char *path, const char *cfg) +{ + unsigned char advtmp[2 * ADV_SIZE]; + char *file; + int fd = -1; + struct stat st, xst; + int err = 0; + + err = asprintf(&file, "%s%s%s", + path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg); + + if (!file) { + perror(program); + return -1; + } + + fd = open(file, O_RDONLY); + if (fd < 0) { + err = -1; + } else if (fstat(fd, &st)) { + err = -1; + } else if (st.st_size < 2 * ADV_SIZE) { + /* Too small to be useful */ + err = -2; + } else if (xpread(fd, advtmp, 2 * ADV_SIZE, + st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) { + err = -1; + } else { + /* We got it... maybe? */ + err = syslinux_validate_adv(advtmp) ? -2 : 0; + if (!err) { + /* Got a good one, write our own ADV here */ + clear_attributes(fd); + + /* Need to re-open read-write */ + close(fd); + fd = open(file, O_RDWR | O_SYNC); + if (fd < 0) { + err = -1; + } else if (fstat(fd, &xst) || xst.st_ino != st.st_ino || + xst.st_dev != st.st_dev || xst.st_size != st.st_size) { + fprintf(stderr, "%s: race condition on write\n", file); + err = -2; + } + /* Write our own version ... */ + if (xpwrite(fd, syslinux_adv, 2 * ADV_SIZE, + st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) { + err = -1; + } + + sync(); + set_attributes(fd); + } + } + + if (err == -2) + fprintf(stderr, "%s: cannot write auxilliary data (need --update)?\n", + file); + else if (err == -1) + perror(file); + + if (fd >= 0) + close(fd); + if (file) + free(file); + + return err; +} diff --git a/libinstaller/setadv.c b/libinstaller/setadv.c index c891b87f..61f1f345 100644 --- a/libinstaller/setadv.c +++ b/libinstaller/setadv.c @@ -1,6 +1,7 @@ /* ----------------------------------------------------------------------- * * * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2010 Intel Corporation; author: H. Peter Anvin * * 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 @@ -26,12 +27,7 @@ #include <stddef.h> #include <stdint.h> #include <string.h> -#include <getopt.h> -#include <unistd.h> #include <errno.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <sys/stat.h> #include <sys/types.h> #include "syslxint.h" #include "syslxcom.h" @@ -170,127 +166,3 @@ int syslinux_validate_adv(unsigned char *advbuf) return -1; } } - -/* - * Read the ADV from an existing instance, or initialize if invalid. - * Returns -1 on fatal errors, 0 if ADV is okay, and 1 if no valid - * ADV was found. - */ -int read_adv(const char *path, const char *cfg) -{ - char *file; - int fd = -1; - struct stat st; - int err = 0; - - asprintf(&file, "%s%s%s", - path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg); - - if (!file) { - perror(program); - return -1; - } - - fd = open(file, O_RDONLY); - if (fd < 0) { - if (errno != ENOENT) { - err = -1; - } else { - syslinux_reset_adv(syslinux_adv); - } - } else if (fstat(fd, &st)) { - err = -1; - } else if (st.st_size < 2 * ADV_SIZE) { - /* Too small to be useful */ - syslinux_reset_adv(syslinux_adv); - err = 0; /* Nothing to read... */ - } else if (xpread(fd, syslinux_adv, 2 * ADV_SIZE, - st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) { - err = -1; - } else { - /* We got it... maybe? */ - err = syslinux_validate_adv(syslinux_adv) ? 1 : 0; - } - - if (err < 0) - perror(file); - - if (fd >= 0) - close(fd); - - free(file); - - return err; -} - -/* - * Update the ADV in an existing installation. - */ -int write_adv(const char *path, const char *cfg) -{ - unsigned char advtmp[2 * ADV_SIZE]; - char *file; - int fd = -1; - struct stat st, xst; - int err = 0; - - err = asprintf(&file, "%s%s%s", - path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg); - - if (!file) { - perror(program); - return -1; - } - - fd = open(file, O_RDONLY); - if (fd < 0) { - err = -1; - } else if (fstat(fd, &st)) { - err = -1; - } else if (st.st_size < 2 * ADV_SIZE) { - /* Too small to be useful */ - err = -2; - } else if (xpread(fd, advtmp, 2 * ADV_SIZE, - st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) { - err = -1; - } else { - /* We got it... maybe? */ - err = syslinux_validate_adv(advtmp) ? -2 : 0; - if (!err) { - /* Got a good one, write our own ADV here */ - clear_attributes(fd); - - /* Need to re-open read-write */ - close(fd); - fd = open(file, O_RDWR | O_SYNC); - if (fd < 0) { - err = -1; - } else if (fstat(fd, &xst) || xst.st_ino != st.st_ino || - xst.st_dev != st.st_dev || xst.st_size != st.st_size) { - fprintf(stderr, "%s: race condition on write\n", file); - err = -2; - } - /* Write our own version ... */ - if (xpwrite(fd, syslinux_adv, 2 * ADV_SIZE, - st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) { - err = -1; - } - - sync(); - set_attributes(fd); - } - } - - if (err == -2) - fprintf(stderr, "%s: cannot write auxilliary data (need --update)?\n", - file); - else if (err == -1) - perror(file); - - if (fd >= 0) - close(fd); - if (file) - free(file); - - return err; -} diff --git a/linux/Makefile b/linux/Makefile index c3877f23..ffe22728 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -26,6 +26,7 @@ SRCS = syslinux.c \ ../libinstaller/syslxopt.c \ ../libinstaller/syslxcom.c \ ../libinstaller/setadv.c \ + ../libinstaller/advio.c \ ../libinstaller/fat.c \ ../libinstaller/syslxmod.c \ ../libinstaller/bootsect_bin.c \ diff --git a/linux/syslinux.c b/linux/syslinux.c index fa500cf7..ed65619f 100644 --- a/linux/syslinux.c +++ b/linux/syslinux.c @@ -77,12 +77,6 @@ extern const char *program; /* Name of program */ pid_t mypid; char *mntpath = NULL; /* Path on which to mount */ -/* - * Image file - */ -#define boot_image syslinux_ldlinux -#define boot_image_len syslinux_ldlinux_len - #if DO_DIRECT_MOUNT int loop_fd = -1; /* Loop device */ #endif diff --git a/win32/Makefile b/win32/Makefile index 9009ccd0..a077b30c 100644 --- a/win32/Makefile +++ b/win32/Makefile @@ -49,6 +49,7 @@ SRCS = syslinux.c OBJS = $(patsubst %.c,%.obj,$(notdir $(SRCS))) LIBSRC = ../libinstaller/fat.c \ ../libinstaller/syslxmod.c \ + ../libinstaller/setadv.c \ ../libinstaller/bootsect_bin.c \ ../libinstaller/ldlinux_bin.c \ ../libinstaller/mbr_bin.c \ diff --git a/win32/syslinux.c b/win32/syslinux.c index 297b97b5..ca98d78b 100644 --- a/win32/syslinux.c +++ b/win32/syslinux.c @@ -23,6 +23,7 @@ #include "syslinux.h" #include "libfat.h" +#include "setadv.h" #ifdef __GNUC__ # define noreturn void __attribute__((noreturn)) @@ -384,6 +385,9 @@ int main(int argc, char *argv[]) /* Just ignore error if the file do not exists */ DeleteFile(ldlinux_name); + /* Initialize the ADV -- this should be smarter */ + syslinux_reset_adv(syslinux_adv); + /* Create ldlinux.sys file */ f_handle = CreateFile(ldlinux_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -397,15 +401,16 @@ int main(int argc, char *argv[]) } /* Write ldlinux.sys file */ - if (!WriteFile - (f_handle, syslinux_ldlinux, syslinux_ldlinux_len, &bytes_written, - NULL)) { + if (!WriteFile(f_handle, syslinux_ldlinux, syslinux_ldlinux_len, + &bytes_written, NULL) || + bytes_written != syslinux_ldlinux_len) { error("Could not write ldlinux.sys"); exit(1); } - - if (bytes_written != syslinux_ldlinux_len) { - fprintf(stderr, "Could not write whole ldlinux.sys\n"); + if (!WriteFile(f_handle, syslinux_adv, 2 * ADV_SIZE, + &bytes_written, NULL) || + bytes_written != 2 * ADV_SIZE) { + error("Could not write ADV to ldlinux.sys"); exit(1); } @@ -416,7 +421,8 @@ int main(int argc, char *argv[]) } /* Map the file (is there a better way to do this?) */ - ldlinux_sectors = (syslinux_ldlinux_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT; + ldlinux_sectors = (syslinux_ldlinux_len + 2 * ADV_SIZE + SECTOR_SIZE - 1) + >> SECTOR_SHIFT; sectors = calloc(ldlinux_sectors, sizeof *sectors); fs = libfat_open(libfat_readfile, (intptr_t) d_handle); ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL); |