aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile19
-rw-r--r--README6
-rw-r--r--bin2c.pl4
-rw-r--r--ldlinux.asm3
-rw-r--r--now.pl2
-rw-r--r--syslinux.c194
6 files changed, 208 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index a8aecaa2..a441779b 100644
--- a/Makefile
+++ b/Makefile
@@ -30,8 +30,15 @@ TARGETS=bootsect.bin ldlinux.sys syslinux.com syslinux
all: $(TARGETS)
ls -l $(TARGETS)
+# The DATE is set on the make command line when building binaries for
+# official release. Otherwise, substitute a hex string that is pretty much
+# guaranteed to be unique to be unique from build to build.
+ifndef DATE
+DATE = $(shell perl now.pl)
+endif
+
ldlinux.bin: ldlinux.asm
- $(NASM) -f bin -dHEX_TIME="`perl now.pl`" -l ldlinux.lst -o ldlinux.bin ldlinux.asm
+ $(NASM) -f bin -dDATE_STR="'$(DATE)'" -l ldlinux.lst -o ldlinux.bin ldlinux.asm
bootsect.bin: ldlinux.bin
dd if=ldlinux.bin of=bootsect.bin bs=512 count=1
@@ -62,3 +69,13 @@ clean: tidy
dist: tidy
rm -f *~ \#*
+
+#
+# This should only be used by the maintainer to generate official binaries
+# for release. Please do not "make official" and distribute the binaries,
+# please.
+#
+official:
+ $(MAKE) clean
+ $(MAKE) all DATE=`date +'%Y-%m-%d'`
+ $(MAKE) dist
diff --git a/README b/README
new file mode 100644
index 00000000..80901a66
--- /dev/null
+++ b/README
@@ -0,0 +1,6 @@
+Please read the file syslinux.doc for information on how to use
+SYSLINUX.
+
+SYSLINUX now builds in a Linux environment, using nasm. You need nasm
+version 0.97 or later to build SYSLINUX from source. See
+http://www.cryogen.com/Nasm for information about nasm.
diff --git a/bin2c.pl b/bin2c.pl
index 2a9c0f8b..9dc8f9f8 100644
--- a/bin2c.pl
+++ b/bin2c.pl
@@ -22,7 +22,7 @@ if ( $#ARGV != 0 ) {
($table_name) = @ARGV;
-printf "const unsigned char %s[] = {\n", $table_name;
+printf "unsigned char %s[] = {\n", $table_name;
$pos = 0;
$linelen = 8;
@@ -46,5 +46,5 @@ while ( ($n = read(STDIN, $data, 4096)) > 0 ) {
}
}
-printf "\n};\n\nconst unsigned int %s_len = %u;\n", $table_name, $total_len;
+printf "\n};\n\nunsigned int %s_len = %u;\n", $table_name, $total_len;
diff --git a/ldlinux.asm b/ldlinux.asm
index 8cfbb841..ab448221 100644
--- a/ldlinux.asm
+++ b/ldlinux.asm
@@ -36,8 +36,7 @@ retry_count equ 6 ; How patient are we with the disk?
; Should be updated with every release to avoid bootsector/SYS file mismatch
;
%define version_str '1.31' ; Must be 4 characters long!
-;%define date '1998-01-31' ; Must be 10 characters long!
-%define date HEX_TIME ; Used while developing
+%define date DATE_STR ; Defined from the Makefile
%define year '1998'
;
; Debgging stuff
diff --git a/now.pl b/now.pl
index 3f63cc73..824dcc8f 100644
--- a/now.pl
+++ b/now.pl
@@ -4,4 +4,4 @@
# Print the time as a hexadecimal integer
#
-printf "\'0x%08x\'\n", time;
+printf "0x%08x\n", time;
diff --git a/syslinux.c b/syslinux.c
index 7088fc08..016d39a1 100644
--- a/syslinux.c
+++ b/syslinux.c
@@ -32,19 +32,25 @@
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/wait.h>
#ifndef _PATH_MOUNT
#define _PATH_MOUNT "/bin/mount"
#endif
-extern const unsigned char bootsect[];
-extern const unsigned int bootsect_len;
+#ifndef _PATH_UMOUNT
+#define _PATH_UMOUNT "/bin/umount"
+#endif
+
+extern unsigned char bootsect[];
+extern unsigned int bootsect_len;
-extern const unsigned char ldlinux[];
-extern const unsigned int ldlinux_len;
+extern unsigned char ldlinux[];
+extern unsigned int ldlinux_len;
char *program; /* Name of program */
char *device; /* Device to install to */
+uid_t euid; /* Our current euid */
enum bs_offsets {
bsJump = 0x00,
@@ -90,15 +96,22 @@ static u_int32_t get_32(unsigned char *p)
int main(int argc, char *argv[])
{
- static unsigned char sectbuf[512], *dp;
- int dev_fd;
+ static unsigned char sectbuf[512];
+ unsigned char *dp;
+ const unsigned char *cdp;
+ int dev_fd, fd;
struct stat st;
int nb, left, veryold;
unsigned int sectors, clusters;
+ int err = 0;
+ pid_t f, w;
+ int status;
+ char *mntpath = NULL, mntname[64];
+ int my_umask;
program = argv[0];
- if ( argc != 2 ) {
+ if ( argc != 2 || argv[1][0] == '-' ) {
fprintf(stderr, "Usage: %s device\n", program);
exit(1);
}
@@ -115,7 +128,7 @@ int main(int argc, char *argv[])
exit(1);
}
- if ( !S_ISBLK(st.st_mode) || !S_ISREG(st.st_mode) ) {
+ if ( !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode) ) {
fprintf(stderr, "%s: not a block device or regular file\n", device);
exit(1);
}
@@ -193,9 +206,10 @@ int main(int argc, char *argv[])
/*
* Now mount the device. If we are non-root we need to find an fstab
- * entry for this device which has the user flag set.
+ * entry for this device which has the user flag and the appropriate
+ * options set.
*/
- if ( geteuid() ) {
+ if ( (euid = geteuid()) ) {
FILE *fstab;
struct mntent *mnt;
@@ -204,16 +218,168 @@ int main(int argc, char *argv[])
}
while ( (mnt = getmntent(fstab)) ) {
- if ( !strcmp(device, mnt->mnt_fsname) ) {
- if ( !strcmp(mnt->mnt_type, "msdos") ||
+ if ( !strcmp(device, mnt->mnt_fsname) &&
+ ( !strcmp(mnt->mnt_type, "msdos") ||
!strcmp(mnt->mnt_type, "umsdos") ||
!strcmp(mnt->mnt_type, "vfat") ||
!strcmp(mnt->mnt_type, "uvfat") ||
- !strcmp(mnt->mnt_type, "auto") ) {
- }
+ !strcmp(mnt->mnt_type, "auto") ) &&
+ hasmntopt(mnt, "user") &&
+ !hasmntopt(mnt, "ro") &&
+ !!hasmntopt(mnt, "loop") == !!S_ISREG(st.st_mode)) {
+ /* Okay, this is an fstab entry we should be able to live with. */
+
+ mntpath = mnt->mnt_dir;
+ break;
}
}
+ endmntent(fstab);
+
+ if ( !mntpath ) {
+ fprintf(stderr, "%s: not root and no appropriate entry for %s in "
+ MNTTAB "\n", program, device);
+ exit(1);
+ }
+
+ f = fork();
+ if ( f < 0 ) {
+ perror(program);
+ exit(1);
+ } else if ( f == 0 ) {
+ execl(_PATH_MOUNT, _PATH_MOUNT, mntpath, NULL);
+ _exit(255); /* If execl failed, trouble... */
+ }
+ } else {
+ int i = 0;
+
+ /* We're root. Make a temp dir and pass all the gunky options to mount. */
+
+ do {
+ sprintf(mntname, "/tmp/syslinux.mnt.%lu.%d", (unsigned long)getpid(), i++);
+ } while ( (errno = 0, mkdir(mntname, 0700) == -1) &&
+ (errno == EEXIST || errno == EINTR) );
+ if ( errno ) {
+ perror(program);
+ exit(1);
+ }
+
+ mntpath = mntname;
+
+ f = fork();
+ if ( f < 0 ) {
+ perror(program);
+ rmdir(mntpath);
+ exit(1);
+ } else if ( f == 0 ) {
+ if ( S_ISREG(st.st_mode) )
+ execl(_PATH_MOUNT, _PATH_MOUNT, "-t", "msdos", "-o", "loop", "-w",
+ device, mntpath);
+ else
+ execl(_PATH_MOUNT, _PATH_MOUNT, "-t", "msdos", "-w", device, mntpath);
+ _exit(255); /* execl failed */
+ }
+ }
+
+ w = waitpid(f, &status, 0);
+ if ( w != f || status ) {
+ if ( !euid )
+ rmdir(mntpath);
+ exit(1); /* Mount failed */
+ }
+
+ if ( chdir(mntpath) ) {
+ perror("chdir");
+ if ( !euid )
+ rmdir(mntpath);
+ exit(1);
+ }
+
+ unlink("ldlinux.sys");
+ fd = open("ldlinux.sys", O_WRONLY|O_CREAT|O_TRUNC, 0444);
+ if ( fd < 0 ) {
+ perror(device);
+ err = 1;
+ goto umount;
+ }
+
+ cdp = ldlinux;
+ left = ldlinux_len;
+ while ( left ) {
+ nb = write(fd, cdp, left);
+ if ( nb == -1 && errno == EINTR )
+ continue;
+ else if ( nb <= 0 ) {
+ perror(device);
+ err = 1;
+ goto umount;
+ }
+
+ dp += nb;
+ left -= nb;
}
+ /*
+ * 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);
+
+ close(fd);
+
+umount:
+ chdir("/");
+
+ f = fork();
+ if ( f < 0 ) {
+ perror("fork");
+ exit(1);
+ } else if ( f == 0 ) {
+ execl(_PATH_UMOUNT, _PATH_UMOUNT, mntpath, NULL);
+ }
+
+ w = waitpid(f, &status, 0);
+ if ( w != f || status ) {
+ exit(1);
+ }
+
+ if ( !euid )
+ rmdir(mntpath);
+
+ if ( err )
+ exit(err);
+
+ /*
+ * To finish up, write the boot sector
+ */
+
+ dev_fd = open(device, O_RDWR);
+ if ( dev_fd < 0 ) {
+ perror(device);
+ exit(1);
+ }
+
+ /* Copy the old superblock into the new boot sector */
+ memcpy(bootsect+bsCopyStart, sectbuf+bsCopyStart, bsCopyLen);
+
+ dp = bootsect;
+ left = bootsect_len;
+ while ( left ) {
+ nb = write(dev_fd, dp, left);
+ if ( nb == -1 && errno == EINTR )
+ continue;
+ else if ( nb <= 0 ) {
+ perror(device);
+ exit(1);
+ }
+
+ dp += nb;
+ left -= nb;
+ }
+ close(dev_fd);
+
+ /* Done! */
+
return 0;
}