From fdc68217604abef76159a23f50acb5aa6dac211d Mon Sep 17 00:00:00 2001 From: hpa Date: Sun, 13 Jun 2004 06:05:02 +0000 Subject: [PATCH] Add support for building under klibc. --- NEWS | 2 + syslinux-nomtools.c | 162 ++++++++++++++++++++++++++++++++++++++-------------- syslinux.h | 2 +- syslxmod.c | 2 +- 4 files changed, 123 insertions(+), 45 deletions(-) diff --git a/NEWS b/NEWS index 279c54e..50bc957 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,8 @@ Changes in 2.10: 100-109 and 200-209. * ALL: New option "allowoptions" (defaults to 1), which controls if options are allowed on the command line or not. + * SYSLINUX: Support building under klibc (see the klibc + distribution for details.) Changes in 2.09: * SYSLINUX: Remove residual setuid crap from diff --git a/syslinux-nomtools.c b/syslinux-nomtools.c index f438343..25538d6 100644 --- a/syslinux-nomtools.c +++ b/syslinux-nomtools.c @@ -20,12 +20,17 @@ * mtools, but requires root privilege. */ +#ifdef __KLIBC__ +# define DO_DIRECT_MOUNT 1 /* Call mount(2) directly */ +#else +# define DO_DIRECT_MOUNT 0 /* Call /bin/mount instead */ +#endif + #define _XOPEN_SOURCE 500 /* For pread() pwrite() */ #define _LARGEFILE64_SOURCE /* For O_LARGEFILE */ #include #include #include -#include #include #include #include @@ -34,27 +39,58 @@ #include #include #include +#include #include "syslinux.h" -#ifndef _PATH_MOUNT -#define _PATH_MOUNT "/bin/mount" -#endif +#if DO_DIRECT_MOUNT + +# include + +#else + +# include +# ifndef _PATH_MOUNT +# define _PATH_MOUNT "/bin/mount" +# endif +# ifndef _PATH_UMOUNT +# define _PATH_UMOUNT "/bin/umount" +# endif -#ifndef _PATH_UMOUNT -#define _PATH_UMOUNT "/bin/umount" #endif -char *program; /* Name of program */ -char *device; /* Device to install to */ +const char *program; /* Name of program */ +const char *device; /* Device to install to */ pid_t mypid; +char *mntpath = NULL; /* Path on which to mount */ +#if DO_DIRECT_MOUNT +int loop_fd = -1; /* Loop device */ +#endif -void usage(void) +void __attribute__((noreturn)) usage(void) { fprintf(stderr, "Usage: %s [-sf] [-o offset] device\n", program); exit(1); } +void __attribute__((noreturn)) die(const char *msg) +{ + fprintf(stderr, "%s: %s\n", program, msg); + +#if DO_DIRECT_MOUNT + if ( loop_fd != -1 ) { + ioctl(loop_fd, LOOP_CLR_FD, 0); /* Free loop device */ + close(loop_fd); + loop_fd = -1; + } +#endif + + if ( mntpath ) + unlink(mntpath); + + exit(1); +} + /* * read/write wrapper functions */ @@ -66,8 +102,7 @@ ssize_t xpread(int fd, void *buf, size_t count, off_t offset) while ( count ) { rv = pread(fd, buf, count, offset); if ( rv == 0 ) { - fprintf(stderr, "%s: short read\n", program); - exit(1); + die("short read"); } else if ( rv == -1 ) { if ( errno == EINTR ) { continue; @@ -93,8 +128,7 @@ ssize_t xpwrite(int fd, void *buf, size_t count, off_t offset) while ( count ) { rv = pwrite(fd, buf, count, offset); if ( rv == 0 ) { - fprintf(stderr, "%s: short write\n", program); - exit(1); + die("short write"); } else if ( rv == -1 ) { if ( errno == EINTR ) { continue; @@ -123,17 +157,19 @@ int main(int argc, char *argv[]) int err = 0; pid_t f, w; int status; - char *mntpath = NULL, mntname[64], devfdname[64]; + char mntname[64], devfdname[64]; char *ldlinux_name, **argp, *opt; int my_umask; int force = 0; /* -f (force) option */ - off_t offset = 0; /* -o (offset) option */ + int offset = 0; /* -o (offset) option */ program = argv[0]; mypid = getpid(); device = NULL; + umask(077); + for ( argp = argv+1 ; *argp ; argp++ ) { if ( **argp == '-' ) { opt = *argp + 1; @@ -173,20 +209,11 @@ int main(int argc, char *argv[]) } if ( !force && !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode) ) { - fprintf(stderr, "%s: not a block device or regular file (use -f to override)\n", device); - exit(1); + die("not a block device or regular file (use -f to override)"); } if ( !force && offset != 0 && !S_ISREG(st.st_mode) ) { - fprintf(stderr, "%s: not a regular file and an offset specified (use -f to override)\n", device); - exit(1); - } - - if ( lseek(dev_fd, offset, SEEK_SET) != offset ) { - if ( !(force && errno == EBADF) ) { - fprintf(stderr, "%s: seek error", device); - exit(1); - } + die("not a regular file and an offset specified (use -f to override)"); } xpread(dev_fd, sectbuf, 512, offset); @@ -203,8 +230,7 @@ int main(int argc, char *argv[]) * Now mount the device. */ if ( geteuid() ) { - fprintf(stderr, "%s: This program needs root privilege\n", program); - exit(1); + die("This program needs root privilege"); } else { int i = 0; struct stat dst; @@ -222,8 +248,7 @@ int main(int argc, char *argv[]) if ( stat(".", &dst) || !S_ISDIR(dst.st_mode) || (dst.st_mode & TMP_MODE) != TMP_MODE ) { - fprintf(stderr, "%s: possibly unsafe /tmp permissions\n", program); - exit(1); + die("possibly unsafe /tmp permissions"); } for ( i = 0 ; ; i++ ) { @@ -244,14 +269,49 @@ int main(int argc, char *argv[]) if ( lstat(mntname, &dst) || dst.st_mode != (S_IFDIR|0000) || dst.st_uid != 0 ) { - fprintf(stderr, "%s: someone is trying to symlink race us!\n", program); - exit(1); + die("someone is trying to symlink race us!"); } break; /* OK, got something... */ } mntpath = mntname; +#if DO_DIRECT_MOUNT + if ( S_ISREG(st.st_mode) ) { + /* It's file, need to mount it loopback */ + unsigned int n = 0; + struct loop_info64 loopinfo; + + for ( n = 0 ; loop_fd < 0 ; n++ ) { + snprintf(devfdname, sizeof devfdname, "/dev/loop%u", n); + loop_fd = open(devfdname, O_RDWR); + if ( loop_fd < 0 && errno == ENOENT ) { + die("no available loopback device!"); + } + if ( ioctl(loop_fd, LOOP_SET_FD, (void *)dev_fd) ) { + close(loop_fd); loop_fd = -1; + if ( errno != EBUSY ) + die("cannot set up loopback device"); + else + continue; + } + + if ( ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo) || + (loopinfo.lo_offset = offset, + ioctl(loop_fd, LOOP_SET_STATUS64, &loopinfo)) ) + die("cannot set up loopback device"); + } + } else { + snprintf(devfdname, sizeof devfdname, "/proc/%lu/fd/%d", + (unsigned long)mypid, dev_fd); + } + + if ( mount(devfdname, mntpath, "msdos", + MS_NOEXEC|MS_NOSUID, "umask=077,quiet") ) + die("could not mount filesystem"); + +#else + snprintf(devfdname, sizeof devfdname, "/proc/%lu/fd/%d", (unsigned long)mypid, dev_fd); @@ -263,23 +323,25 @@ int main(int argc, char *argv[]) } else if ( f == 0 ) { char mnt_opts[128]; if ( S_ISREG(st.st_mode) ) { - snprintf(mnt_opts, sizeof mnt_opts, "rw,nodev,noexec,loop,offset=%llu,umask=077", + snprintf(mnt_opts, sizeof mnt_opts, "rw,nodev,noexec,loop,offset=%llu,umask=077,quiet", (unsigned long long)offset); } else { - snprintf(mnt_opts, sizeof mnt_opts, "rw,nodev,noexec,umask=077"); + snprintf(mnt_opts, sizeof mnt_opts, "rw,nodev,noexec,umask=077,quiet"); } execl(_PATH_MOUNT, _PATH_MOUNT, "-t", "msdos", "-o", mnt_opts,\ devfdname, mntpath, NULL); _exit(255); /* execl failed */ } - } - w = waitpid(f, &status, 0); - if ( w != f || status ) { - rmdir(mntpath); - exit(1); /* Mount failed */ + w = waitpid(f, &status, 0); + if ( w != f || status ) { + rmdir(mntpath); + exit(1); /* Mount failed */ + } + +#endif } - + ldlinux_name = alloca(strlen(mntpath)+13); if ( !ldlinux_name ) { perror(program); @@ -316,13 +378,24 @@ int main(int argc, char *argv[]) * I don't understand why I need this. Does the DOS filesystems * not honour the mode passed to open()? */ - my_umask = umask(0777); - umask(my_umask); - fchmod(fd, 0444 & ~my_umask); + fchmod(fd, 0400); close(fd); umount: +#if DO_DIRECT_MOUNT + + if ( umount2(mntpath, 0) ) + die("could not umount path"); + + if ( loop_fd != -1 ) { + ioctl(loop_fd, LOOP_CLR_FD, 0); /* Free loop device */ + close(loop_fd); + loop_fd = -1; + } + +#else + f = fork(); if ( f < 0 ) { perror("fork"); @@ -336,6 +409,8 @@ umount: exit(1); } +#endif + sync(); rmdir(mntpath); @@ -362,3 +437,4 @@ umount: return 0; } + diff --git a/syslinux.h b/syslinux.h index c40926a..d022647 100644 --- a/syslinux.h +++ b/syslinux.h @@ -30,6 +30,6 @@ void syslinux_make_stupid(void); void syslinux_make_bootsect(void *); /* Check to see that what we got was indeed an MS-DOS boot sector/superblock */ -int syslinux_check_bootsect(void *bs, char* device); +int syslinux_check_bootsect(const void *bs, const char *device); #endif diff --git a/syslxmod.c b/syslxmod.c index 8225d06..a5d9e79 100644 --- a/syslxmod.c +++ b/syslxmod.c @@ -100,7 +100,7 @@ void syslinux_make_bootsect(void *bs) /* * Check to see that what we got was indeed an MS-DOS boot sector/superblock */ -int syslinux_check_bootsect(void *bs, char* device) +int syslinux_check_bootsect(const void *bs, const char *device) { int veryold; unsigned int sectors, clusters; -- 2.7.4