#! /bin/sh -e
## 99_archimedes.dpatch by Darren Salt <linux@youmustbejoking.demon.co.uk>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Create dir entries with the ARCHIMEDES extension block (as needed).
## DP: The original patch was downloaded from:
## DP: http://ftp.scarlet.be/pub/netbsd/bjh21/cdrtools-1.11a27-archimedes.patch

if [ $# -lt 1 ]; then
    echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
    exit 1
fi

[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
patch_opts="${patch_opts:--f --no-backup-if-mismatch} ${2:+-d $2}"

case "$1" in
    -patch) patch -p1 ${patch_opts} < $0;;
    -unpatch) patch -R -p1 ${patch_opts} < $0;;
    *)
        echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
        exit 1;;
esac

exit 0

@DPATCH@
diff -urNad /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/Makefile cdrtools-2.0+a30.pre1/mkisofs/Makefile
--- /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/Makefile	2004-06-04 22:17:30.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs/Makefile	2004-06-04 22:17:31.000000000 +0100
@@ -43,6 +43,7 @@
 		scsi.c \
 		scsi_cdr.c cd_misc.c \
 		modes.c \
+		archimedes.c \
 		apple.c volume.c desktop.c mac_label.c stream.c \
 		ifo_read.c dvd_file.c dvd_reader.c \
 		defaults.c getnum.c
diff -urNad /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/archimedes.c cdrtools-2.0+a30.pre1/mkisofs/archimedes.c
--- /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/archimedes.c	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs/archimedes.c	2004-06-04 22:17:46.000000000 +0100
@@ -0,0 +1,173 @@
+/*
+ * File archimedes.c - generate ARCHIMEDES records for iso9660 filesystems.
+
+   Ben Harris, 2002.
+   Darren Salt, 2004.
+   Loosely based on rock.c, which was written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   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; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <mconfig.h>
+#include "mkisofs.h"
+#include <device.h>
+#include <schily.h>
+
+/*
+ * I've never seen any real documentation of the ARCHIMEDES extension, but
+ * Stephen Borrill has provided the following:
+ *
+ * Directory record has 32 byte system use area
+ *
+ *   0-9 "ARCHIMEDES"
+ *                          13121110
+ * 10-13 Load address      &FFFtttdd
+ *                          17161514
+ * 14-17 Execution address &dddddddd
+ *                          21201918
+ * 18-21 Attributes        &ffffffaa
+ * 22-31 Reserved          0
+ *
+ * ttt = filetype
+ * dd  = date stamp (ignored - use directory record date)
+ * ffffff = filesystem specific attributes (bit 0 of offset 19 is
+ *          set if initial underscore should be replaced by !)
+ * aa  = RISCOS access permissions (ignore - read access is forced)
+ */
+
+/*
+ * Buffer to build ARCHIMEDES attributes
+ */
+static int      currlen = 0;
+
+static void
+archimedes_date(result, crtime)
+	long	*result;
+	time_t	crtime;
+{
+	unsigned long baselow, basehigh, low, high, offlow, offhigh;
+
+	/*
+	 * RISC OS date stamps are five-byte integers counting
+	 * centi-seconds since 1900-01-01 00:00:00Z.  We only
+	 * bother with the whole seconds, since there's no portable
+	 * way to get sub-second resolution from stat() and it's not
+	 * worth the hassle.  To avoid using 64-bit integers, we build
+	 * the result in two parts.
+	 */
+
+	/* RISC OS representation of the Unix epoch (1970-01-01 00:00:00Z) */
+	baselow = 0x6e996a00;
+	basehigh = 0x33;
+	
+	/* Short multiplication, using 16-bit digits */
+	offlow = (((unsigned long)crtime & 0xffff) * 100);
+	offhigh = (((unsigned long)crtime >> 16) * 100) + (offlow >> 16);
+	offlow = (offlow & 0xffff) + ((offhigh & 0xffff) << 16);
+	offhigh >>= 16;
+
+	low = baselow + offlow;
+	high = basehigh + offhigh + (low < baselow);
+	result[0] = low;
+	result[1] = high;
+}
+
+int
+generate_archimedes_attributes(whole_name, name,
+	                s_entry,
+	                statbuf,
+	                lstatbuf,
+	                deep_opt)
+	char           *whole_name;
+	char           *name;
+	struct directory_entry *s_entry;
+	struct stat    *statbuf,
+	               *lstatbuf;
+	int             deep_opt;
+
+{
+	unsigned char *p;
+	int typed = 0;
+
+	/* no need to fill in the ARCHIMEDES stuff if we won't see the file */
+	if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
+		return 0;
+
+	/* Decide if this file needs the extension */
+	p = strrchr(name, ',');
+	if (p)
+	{
+		if (isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3])
+		    && p[4] == 0)
+			typed = 1;
+		else if (!strcmp (p, ",lxa"))
+			typed = 2;
+	}
+	if (typed || name[0] == '!')
+	{
+		unsigned char arcext[32];
+		unsigned long loadaddr = 0xffffff49;
+		unsigned long execaddr = 0x8a2169c1;
+		unsigned long attribs  = 0x11; /* read-only */
+
+		if (name[0] == '!')
+			attribs |= 0x100;
+
+		if (typed != 2)
+		{
+			unsigned long arcdate[2];
+			archimedes_date(arcdate, lstatbuf->st_mtime);
+			/* type is either 0xFFD ("Data") or in the ,XXX */
+			loadaddr = p ? strtoul (p + 1, NULL, 16) : 0xFFD;
+			loadaddr = 0xFFF00000 | loadaddr << 8 | arcdate[1];
+			execaddr = arcdate[0];
+		}
+		else
+		{
+			/* need to read the load & exec from the file */
+			char buf[8];
+			FILE *fd = fopen (whole_name, "rb");
+			if (fd && !fseek (fd, -8, SEEK_END)
+			       && fread (buf, 1, 8, fd) == 8)
+			{
+				loadaddr = get_731 (buf);
+				execaddr = get_731 (buf + 4);
+				/* don't put these bytes in the copy of the
+				 * file in the CD/DVD image */
+				s_entry->size -= 8;
+				set_733((char *) s_entry->isorec.size,
+				  get_733 ((char *) s_entry->isorec.size) - 8);
+				lstatbuf->st_size -= 8;
+			}				
+			if (fd)
+				fclose (fd);
+		}
+
+		memset(arcext, 0, 32);
+		memcpy(arcext, "ARCHIMEDES", 10);
+
+		set_731(arcext + 10, loadaddr);
+		set_731(arcext + 14, execaddr);
+		set_731(arcext + 18, attribs);
+		
+		s_entry->archimedes_attributes =
+		    (unsigned char *) e_malloc(32);
+		memcpy(s_entry->archimedes_attributes, arcext, 32);
+		return 32;
+	}
+		
+	return 0;
+}
diff -urNad /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/mkisofs.8 cdrtools-2.0+a30.pre1/mkisofs/mkisofs.8
--- /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/mkisofs.8	2004-06-04 22:17:29.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs/mkisofs.8	2004-06-04 22:17:31.000000000 +0100
@@ -44,6 +44,11 @@
 as longer filenames, uid/gid, posix permissions, symbolic links,
 block and character devices.
 .PP
+.B mkisofs
+is also capable of generating the
+.B ARCHIMEDES
+extension, used by RISC OS systems to store file type information.
+.PP
 If Joliet or HFS hybrid command line options are specified, 
 .B mkisofs
 will create additional filesystem meta data for Joliet or HFS.
@@ -202,6 +207,16 @@
 This violates the ISO9660 standard, but it happens to work on many systems.
 Use with caution.
 .TP
+.B \-archimedes
+Generate ARCHIMEDES records for files and directories whose names
+begin with an exclamation mark or end with a comma and three
+hexadecimal digits.  In the latter case, the hex digits will be used
+to form the RISC OS type of the file.  Note that the same file cannot
+have both ARCHIMEDES and Rock Ridge records, and
+.B mkisofs
+will generate ARCHIMEDES records in preference.  Also note that a CD
+with both kinds of record violates the Rock Ridge specification.
+.TP
 .BI \-biblio " FILE
 Specifies the bibliographic file name.
 This parameter can also be set in the file
diff -urNad /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/mkisofs.c cdrtools-2.0+a30.pre1/mkisofs/mkisofs.c
--- /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/mkisofs.c	2004-06-04 22:17:31.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs/mkisofs.c	2004-06-04 22:17:31.000000000 +0100
@@ -103,6 +103,7 @@
 int	use_sparcboot = 0;
 int	use_sunx86boot = 0;
 int	use_genboot = 0;
+int	use_ARCHIMEDES = 0;
 int	use_RockRidge = 0;
 int	use_XA = 0;
 int	osecsize = 0;	/* Output-sector size, 0 means default secsize 2048 */
@@ -373,6 +374,8 @@
 #define	OPTION_SUNX86BOOT		1068
 #define	OPTION_SUNX86LABEL		1069
 
+#define OPTION_USE_ARCHIMEDES		1499
+
 #ifdef UDF
 #define	OPTION_UDF			1500
 #endif
@@ -448,6 +451,8 @@
 	'\0', "FILE", "Set Abstract filename", ONE_DASH},
 	{{"appid", required_argument, NULL, 'A'},
 	'A', "ID", "Set Application ID", ONE_DASH},
+	{{"archimedes", no_argument, NULL, OPTION_USE_ARCHIMEDES},
+	'\0', NULL, "Generate ARCHIMEDES records", ONE_DASH},
 	{{"biblio", required_argument, NULL, OPTION_BIBLIO},
 	'\0', "FILE", "Set Bibliographic filename", ONE_DASH},
 	{{"cache-inodes", no_argument, NULL, OPTION_CACHE_INODES},
@@ -2021,6 +2026,9 @@
 			get_boot_entry();
 			current_boot_entry->boot_info_table = 1;
 			break;
+		case OPTION_USE_ARCHIMEDES:
+			use_ARCHIMEDES++;
+			break;
 #ifdef APPLE_HYB
 		case OPTION_HFS_TYPE:
 			deftype = optarg;
diff -urNad /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/mkisofs.h cdrtools-2.0+a30.pre1/mkisofs/mkisofs.h
--- /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/mkisofs.h	2004-06-04 22:17:31.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs/mkisofs.h	2004-06-04 22:17:31.000000000 +0100
@@ -108,6 +108,7 @@
 	unsigned int	rr_attr_size;
 	unsigned int	total_rr_attr_size;
 	unsigned int	got_rr_name;
+	unsigned char	*archimedes_attributes;
 #ifdef APPLE_HYB
 	struct directory_entry *assoc;	/* entry has a resource fork */
 	hfsdirent	*hfs_ent;	/* HFS parameters */
@@ -314,6 +315,7 @@
 extern int	load_addr;
 extern int	load_size;
 extern int	boot_info_table;
+extern int	use_ARCHIMEDES;
 extern int	use_RockRidge;
 extern int	osecsize;
 extern int	use_XA;
@@ -549,6 +551,11 @@
 				char *descriptor,
 				char *source, int *size));
 
+extern int	generate_archimedes_attributes __PR((char *, char *,
+				struct directory_entry *,
+				struct stat *, struct stat *,
+				int deep_flag));
+
 extern int	check_prev_session __PR((struct directory_entry **, int len,
 				struct directory_entry *,
 				struct stat *,
diff -urNad /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/name.c cdrtools-2.0+a30.pre1/mkisofs/name.c
--- /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/name.c	2004-06-04 22:17:29.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs/name.c	2004-06-04 22:17:31.000000000 +0100
@@ -117,6 +117,7 @@
 	int		extra = 0;
 	int		ignore = 0;
 	char		*last_dot;
+	char		*archimedes_comma;
 	const char	*pnt;
 	int		priority = 32767;
 	char		*result;
@@ -154,6 +155,22 @@
 	 */
 	pnt = name;
 
+	archimedes_comma = NULL;
+	if (use_ARCHIMEDES) {
+		/*
+		 * If the filename ends in comma followed by three hex
+		 * digits, those specify the RISC OS file type.
+		 * If the filename ends in ",lxa", the file is untyped.
+		 * Either way, trim the comma extension off, since we don't
+		 * want to see it in RISC OS.
+		 */
+		char *p = strrchr(pnt, ',');
+		if (p && ((isxdigit (p[1]) && isxdigit (p[2]) &&
+			   isxdigit (p[3]) && p[4] == 0)
+			  || !strcmp (p, ",lxa")))
+			archimedes_comma = p;
+	}
+
 	/*
 	 * Find the '.' that we intend to use for the extension.
 	 * Usually this is the last dot, but if we have . followed by nothing
@@ -295,6 +312,12 @@
 			continue;
 		}
 
+		if (pnt == archimedes_comma) {
+			/* Skip the file type */
+			ignore++;
+			continue;
+		}
+
 		if (*pnt == '.') {
 			if (!allow_multidot) {
 				if (strcmp(pnt, ".tar.gz") == 0)
diff -urNad /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/rock.c cdrtools-2.0+a30.pre1/mkisofs/rock.c
--- /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/rock.c	2004-06-04 22:17:29.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs/rock.c	2004-06-04 22:17:31.000000000 +0100
@@ -257,6 +257,13 @@
 		return (0);
 
 	/*
+	 * Rock Ridge and ARCHIMEDES attributes can't
+	 * co-exist on a file.
+	 */
+	if (s_entry->archimedes_attributes != NULL)
+		return 0;
+
+	/*
 	 * Obtain the amount of space that is currently used for the directory
 	 * record.  We may safely use the current name length; because if name
 	 * confilcts force us to change the ISO-9660 name later, the name will
diff -urNad /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/tree.c cdrtools-2.0+a30.pre1/mkisofs/tree.c
--- /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/tree.c	2004-06-04 22:17:29.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs/tree.c	2004-06-04 22:17:50.000000000 +0100
@@ -446,6 +446,11 @@
 					new_reclen++; /* Pad to an even byte */
 				new_reclen += s_entry->rr_attr_size;
 			}
+			if (s_entry->archimedes_attributes != NULL) {
+				if (new_reclen & 1)
+					new_reclen++; /* Pad to an even byte */
+				new_reclen += 32;
+			}
 			if (new_reclen & 1)
 				new_reclen++;	/* Pad to an even byte */
 			s_entry->isorec.length[0] = new_reclen;
@@ -484,6 +489,11 @@
 					new_reclen++; /* Pad to an even byte */
 				new_reclen += s_entry1->rr_attr_size;
 			}
+			if (s_entry1->archimedes_attributes != NULL) {
+				if (new_reclen & 1)
+					new_reclen++; /* Pad to an even byte */
+				new_reclen += 32;
+			}
 			if (new_reclen & 1)
 				new_reclen++;	/* Pad to an even byte */
 			s_entry1->isorec.length[0] = new_reclen;
@@ -620,6 +630,11 @@
 
 		new_reclen += s_entry->rr_attr_size;
 
+		if (s_entry->archimedes_attributes != NULL) {
+			if (new_reclen & 1)
+				new_reclen++; /* Pad to an even byte */
+			new_reclen += 32;
+		}
 		if (new_reclen & 1)
 			new_reclen++;
 
@@ -2133,6 +2148,11 @@
 	}
 	/* Now figure out how much room this file will take in the directory */
 
+	if (use_ARCHIMEDES) {
+		generate_archimedes_attributes(whole_path,
+			short_name, s_entry,
+			&statbuf, &lstatbuf, deep_flag);
+	}
 #ifdef APPLE_HYB
 	/* if the file is HFS excluded, then we don't have an hfs_ent */
 	if (apple_both && !have_rsrc && s_entry->hfs_ent) {
diff -urNad /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/write.c cdrtools-2.0+a30.pre1/mkisofs/write.c
--- /home/ds/src/mkisofs/cdrtools-2.0+a30.pre1/mkisofs/write.c	2004-06-04 22:17:30.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs/write.c	2004-06-04 22:17:31.000000000 +0100
@@ -1478,6 +1478,13 @@
 				s_entry->rr_attributes,
 				s_entry->rr_attr_size);
 			dir_index += s_entry->rr_attr_size;
+		} else if (s_entry->archimedes_attributes != NULL) {
+			if (dir_index & 1) {
+				directory_buffer[dir_index++] = 0;
+			}
+			memcpy(directory_buffer + dir_index,
+				s_entry->archimedes_attributes, 32);
+			dir_index += 32;
 		}
 		if (dir_index & 1) {
 			directory_buffer[dir_index++] = 0;
@@ -1493,6 +1500,10 @@
 			free(s_entry_d->rr_attributes);
 			s_entry_d->rr_attributes = NULL;
 		}
+		if (s_entry_d->archimedes_attributes) {
+			free(s_entry_d->archimedes_attributes);
+			s_entry_d->archimedes_attributes = NULL;
+		}
 	}
 
 	if (dpnt->size != dir_index) {
