summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-01-31 23:46:11 -0800
committerH. Peter Anvin <hpa@zytor.com>2007-01-31 23:46:11 -0800
commitb77b67671c10d9b8990eb568cde43ad95ad5ba21 (patch)
tree5356709255777ea359a9abe6c280414cf5eee68a
parente28c72aaef6fc061e932ac1dd9be83fe62f1394d (diff)
parent1dbb3f4d9e4ca52f13ca4312a8c83245d8d986c9 (diff)
downloadsyslinux-b77b67671c10d9b8990eb568cde43ad95ad5ba21.tar.gz
Merge with git+ssh://master.kernel.org/pub/scm/boot/syslinux/syslinux.git#syslinux-3.3x
-rw-r--r--unix/Makefile4
-rw-r--r--unix/syslinux.c130
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();