diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-01-31 23:46:11 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2007-01-31 23:46:11 -0800 |
commit | b77b67671c10d9b8990eb568cde43ad95ad5ba21 (patch) | |
tree | 5356709255777ea359a9abe6c280414cf5eee68a | |
parent | e28c72aaef6fc061e932ac1dd9be83fe62f1394d (diff) | |
parent | 1dbb3f4d9e4ca52f13ca4312a8c83245d8d986c9 (diff) | |
download | syslinux-b77b67671c10d9b8990eb568cde43ad95ad5ba21.tar.gz |
Merge with git+ssh://master.kernel.org/pub/scm/boot/syslinux/syslinux.git#syslinux-3.3x
-rw-r--r-- | unix/Makefile | 4 | ||||
-rw-r--r-- | unix/syslinux.c | 130 |
2 files changed, 63 insertions, 71 deletions
diff --git a/unix/Makefile b/unix/Makefile index 5dfc0513..021aa538 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -1,10 +1,10 @@ CC = gcc OPTFLAGS = -g -Os -INCLUDES = -I. -I.. -I../libfat +INCLUDES = -I. -I.. CFLAGS = -W -Wall -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES) LDFLAGS = -s -SRCS = syslinux.c ../syslxmod.c ../bootsect_bin.c ../ldlinux_bin.c $(wildcard ../libfat/*.c) +SRCS = syslinux.c ../syslxmod.c ../bootsect_bin.c ../ldlinux_bin.c OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS))) .SUFFIXES: .c .o .i .s .S diff --git a/unix/syslinux.c b/unix/syslinux.c index 36826a1b..308e52fd 100644 --- a/unix/syslinux.c +++ b/unix/syslinux.c @@ -13,7 +13,7 @@ /* * syslinux.c - Linux installer program for SYSLINUX * - * This program ought to be portable. I hope so, at least. + * This is Linux-specific by now. * * This is an alternate version of the installer which doesn't require * mtools, but requires root privilege. @@ -46,15 +46,14 @@ #include <sys/wait.h> #include <sys/mount.h> +#include <linux/fs.h> /* FIGETBSZ, FIBMAP */ +#include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES, SECTOR_* */ + #include "syslinux.h" -#include "libfat.h" #if DO_DIRECT_MOUNT - # include <linux/loop.h> - #else - # include <paths.h> # ifndef _PATH_MOUNT # define _PATH_MOUNT "/bin/mount" @@ -62,7 +61,6 @@ # ifndef _PATH_UMOUNT # define _PATH_UMOUNT "/bin/umount" # endif - #endif const char *program; /* Name of program */ @@ -156,17 +154,43 @@ ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset) } /* - * Version of the read function suitable for libfat + * Create a block map for ldlinux.sys */ -int libfat_xpread(intptr_t pp, void *buf, size_t secsize, libfat_sector_t sector) +int make_block_map(uint32_t *sectors, int len, int dev_fd, int fd) { - off_t offset = (off_t)sector * secsize + filesystem_offset; - return xpread(pp, buf, secsize, offset); + int nsectors = 0; + int blocksize, nblock, block; + int i; + + (void)dev_fd; + + if (ioctl(fd, FIGETBSZ, &blocksize) < 0) + die("ioctl FIGETBSZ failed"); + + blocksize >>= SECTOR_BITS; /* sectors/block */ + + nblock = 0; + while (len > 0) { + block = nblock++; + if (ioctl(fd, FIBMAP, &block) < 0) + die("ioctl FIBMAP failed"); + + for (i = 0; i < blocksize; i++) { + if (len <= 0) + break; + + *sectors++ = (block*blocksize)+i; + nsectors++; + len -= (1 << SECTOR_BITS); + } + } + + return nsectors; } int main(int argc, char *argv[]) { - static unsigned char sectbuf[512]; + static unsigned char sectbuf[SECTOR_SIZE]; unsigned char *dp; const unsigned char *cdp; int dev_fd, fd; @@ -179,10 +203,7 @@ int main(int argc, char *argv[]) char *ldlinux_name, **argp, *opt; int force = 0; /* -f (force) option */ const char *subdir = NULL; - struct libfat_filesystem *fs; - struct libfat_direntry dentry; - libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */ - int32_t ldlinux_cluster; + uint32_t sectors[65]; /* 65 is maximum possible */ int nsectors = 0; const char *errmsg; @@ -243,7 +264,7 @@ int main(int argc, char *argv[]) die("not a regular file and an offset specified (use -f to override)"); } - xpread(dev_fd, sectbuf, 512, filesystem_offset); + xpread(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset); fsync(dev_fd); /* @@ -370,13 +391,21 @@ int main(int argc, char *argv[]) #endif } - ldlinux_name = alloca(strlen(mntpath)+14); + ldlinux_name = alloca(strlen(mntpath)+14+ + (subdir ? strlen(subdir)+2 : 0)); if ( !ldlinux_name ) { perror(program); err = 1; goto umount; } - sprintf(ldlinux_name, "%s//ldlinux.sys", mntpath); + sprintf(ldlinux_name, "%s%s%s//ldlinux.sys", + subdir ? "//" : "", subdir ? subdir : "", mntpath); + + if ((fd = open(ldlinux_name, O_RDONLY)) >= 0) { + uint32_t zero_attr = 0; + ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &zero_attr); + close(fd); + } unlink(ldlinux_name); fd = open(ldlinux_name, O_WRONLY|O_CREAT|O_TRUNC, 0444); @@ -402,51 +431,22 @@ int main(int argc, char *argv[]) left -= nb; } + fsync(fd); /* - * I don't understand why I need this. Does the DOS filesystems - * not honour the mode passed to open()? + * Set the attributes */ - fchmod(fd, 0400); - - close(fd); - - sync(); + { + uint32_t attr = 0x07; /* Hidden+System+Readonly */ + ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr); + } /* - * Now, use libfat to create a block map. This probably - * should be changed to use ioctl(...,FIBMAP,...) since - * this is supposed to be a simple, privileged version - * of the installer. + * Create a block map. */ - fs = libfat_open(libfat_xpread, dev_fd); - ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", &dentry); - secp = sectors; - nsectors = 0; - s = libfat_clustertosector(fs, ldlinux_cluster); - while ( s && nsectors < 65 ) { - *secp++ = s; - nsectors++; - s = libfat_nextsector(fs, s); - } - libfat_close(fs); - - /* Move ldlinux.sys to the desired location */ - if (subdir) { - char *new_ldlinux_name = alloca(strlen(mntpath)+ - strlen(subdir)+15); - int mov_err = 1; - - if ( new_ldlinux_name ) { - sprintf(new_ldlinux_name, "%s//%s//ldlinux.sys", mntpath, subdir); - - if (!rename(ldlinux_name, new_ldlinux_name)) - mov_err = 0; - } + nsectors = make_block_map(sectors, syslinux_ldlinux_len, dev_fd, fd); - if (mov_err) - fprintf(stderr, "%s: warning: unable to move ldlinux.sys: %s\n", - device, strerror(errno)); - } + close(fd); + sync(); umount: #if DO_DIRECT_MOUNT @@ -491,29 +491,21 @@ umount: /* * Write the now-patched first sector of ldlinux.sys */ - xpwrite(dev_fd, syslinux_ldlinux, 512, filesystem_offset + ((off_t)sectors[0] << 9)); - - /* - * Patch the root directory to set attributes to - * HIDDEN|SYSTEM|READONLY - */ - { - const unsigned char attrib = 0x07; - xpwrite(dev_fd, &attrib, 1, ((off_t)dentry.sector << 9)+dentry.offset+11); - } + xpwrite(dev_fd, syslinux_ldlinux, SECTOR_SIZE, + filesystem_offset+((off_t)sectors[0] << SECTOR_BITS)); /* * To finish up, write the boot sector */ /* Read the superblock again since it might have changed while mounted */ - xpread(dev_fd, sectbuf, 512, filesystem_offset); + xpread(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset); /* Copy the syslinux code into the boot sector */ syslinux_make_bootsect(sectbuf); /* Write new boot sector */ - xpwrite(dev_fd, sectbuf, 512, filesystem_offset); + xpwrite(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset); close(dev_fd); sync(); |