components/cdrtools/patches/mkisofs.c.patch
author Phi Tran <Phi.Tran@Sun.COM>
Fri, 01 Jul 2011 11:11:11 -0700
changeset 356 cc77dce0ea27
permissions -rw-r--r--
PSARC/2011/154 mkisofs enhancements 7029174 mkisofs needs to support UEFI catalogue entry and setting modification time 7033042 migrate cdrtools to userland

--- cdrtools-3.00/mkisofs/mkisofs.c.orig	Tue Jun 28 15:31:06 2011
+++ cdrtools-3.00/mkisofs/mkisofs.c	Tue Jun 28 15:32:46 2011
@@ -66,7 +66,7 @@
 struct directory *root = NULL;
 int		path_ind;
 
-char	version_string[] = VERSION;
+char	version_string[] = VERSION "+eltorito-platform";
 
 char		*outfile;
 FILE		*discimage;
@@ -110,6 +110,8 @@
 int	osecsize = 0;	/* Output-sector size, 0 means default secsize 2048 */
 int	use_Joliet = 0;
 int	jlen = JMAX;	/* maximum Joliet file name length */
+
+int 	def_platid = EL_TORITO_ARCH_x86;
 /*
  *	Verbose levels currently used:
  *
@@ -182,6 +184,7 @@
 int	help;			/* CLI Parameter for -help option	    */
 int	joliet_long;		/* CLI Parameter for -joliet-long option    */
 char	*jcharset;		/* CLI Parameter for -jcharset option	    */
+char	*modification_date;	/* CLI Parameter for -modification-date	    */
 int	max_filenames;		/* CLI Parameter for -max-iso9660-filenames option */
 char	*log_file;		/* CLI Parameter for -log-file option	    */
 char	*dir_mode_str;		/* CLI Parameter for -new-dir-mode option   */
@@ -446,7 +449,374 @@
 	return (1);
 }
 
+#define	IS_SEPARATOR1(c)	(c == '/' || c == '-')
+
+LOCAL boolean_t
+isalldigits(char *p, int n)
+{
+	int i;
+	if (p == NULL)
+		return (B_FALSE);
+	for (i = 0; i < n;  i++) {
+		if (p[i] == 0)
+			return (B_FALSE);
+		if ((p[i] < '0') || (p[i] > '9'))
+			return (B_FALSE);
+	}
+	return (B_TRUE);
+}
+
+LOCAL char *
+findnextsep(char *p, char *matches)
+{
+	char *mp;
+	while (*p) {
+		if (matches == NULL) {
+			if ((*p < '0') || (*p > '9'))
+				return (p);
+		} else {
+			mp = matches;
+			while (*mp) {
+				if (*mp == *p)
+					return (p);
+				mp++;
+			}
+		}
+		p++;
+	}
+	if (*p == NULL)
+		return (NULL);
+	return (p);
+}
+
+LOCAL boolean_t
+check_n_get_val(char *s, int n, long *val, int checklower, long lower,
+int checkupper, long upper)
+{
+	char c;
+	long l;
+
+	if (isalldigits(s, n) != B_TRUE)
+		return (B_FALSE);
+
+	if (n > 20)
+		return (B_FALSE);
+
+	c = *(s+n);
+	*(s + n) = 0;
+
+	errno = 0;
+	l = strtol(s, NULL, 10);
+
+	*(s+n) = c;
+
+	if (errno)
+		return (B_FALSE);
+
+	if (val != NULL)
+		*val = l;
+
+	if (checklower)
+		if (l < lower)
+			return (B_FALSE);
+	if (checkupper)
+		if (l > upper)
+			return (B_FALSE);
+
+	return (B_TRUE);
+}
+
 LOCAL int
+get_gmt()
+{
+	time_t now;
+	struct tm gmt, *gmp, *localp, localt;
+	time_t		gmtoffsetsec = 0;
+
+	now = time(NULL);
+	if (now == -1)
+		comerrno(EX_BAD, "time failed internal error\n");
+
+	localp = localtime(&now);
+	if (localp == NULL)
+		comerrno(EX_BAD, "localtime failed internal error\n");
+
+	localt = *localp;
+
+	gmp = gmtime(&now);
+	if (gmp == NULL)
+		comerrno(EX_BAD, "gmtime failed internal error\n");
+
+	gmt = *gmp;
+
+	gmtoffsetsec = mktime(&localt) - mktime(&gmt);
+
+	return ((int)(gmtoffsetsec /(60 * 15)));
+}
+
+
+
+char modbuf[18];
+LOCAL int
+get_modification_date(opt_arg)
+	char	*opt_arg;
+{
+	int len;
+	char *optp = opt_arg;
+	char *dotp = NULL;
+	char *signp = NULL;
+	char *bufp = modbuf;
+	char *tmpp = NULL;
+	char *default_mod = "00010101000000000";
+	char tmpstr[5];
+	int gmtset = 0;
+
+	strncpy(modbuf, default_mod, 17);
+	modbuf[17] = 0;
+
+
+	len = strlen(opt_arg);
+
+	/* first find the gmt */
+	tmpp = strrchr(optp, '+');
+
+	if (tmpp != NULL || ((tmpp = strrchr(optp, '-')) != NULL)) {
+		/* it has to be the last 4 digits */
+		if ((tmpp - optp) != (len  - 5)) {
+			if (*tmpp == '+')
+				comerrno(EX_BAD, "Bad modification date\n");
+			/* if '-' take it as a separator */
+		} else {
+			long gh, gm, val;
+			if (check_n_get_val(tmpp + 1, 2, &gh, 0, 0, 0, 0)
+			    != B_TRUE)
+				comerrno(EX_BAD, "Bad modification date:gh\n");
+
+			if (check_n_get_val(tmpp + 3, 2, &gm, 0, 0, 0, 0)
+			    != B_TRUE)
+				comerrno(EX_BAD, "Bad modification date:gm\n");
+
+			val = (((gh * 60) + gm) / 15) *
+			    ((*tmpp == '-') ? -1 : 1);
+
+
+			if (val < -48 || val > 52)
+				comerrno(EX_BAD, "Bad modification date:"
+				    " gmt offset\n");
+			modbuf[16] = val;
+			gmtset = 1;
+
+			/* get rid of gmt in input str, we are done with it */
+			*tmpp = 0;
+		}
+	}
+	if (gmtset == 0) {
+		modbuf[16] = get_gmt();
+	}
+
+	len = strlen(optp);
+
+	if ((tmpp = strrchr(optp, '.')) != NULL) {
+
+		if ((tmpp - optp) != (len  - 3)) {
+			comerrno(EX_BAD, "Bad modification date:hundredth "
+			    "of sec\n");
+		}
+
+		if (check_n_get_val(tmpp + 1, 2, NULL, 0, 0, 0, 0) != B_TRUE)
+			comerrno(EX_BAD, "Bad modification date:hundredth of"
+			    " second length\n");
+
+		/* since all digits, can not be > 99 */
+		modbuf[14] = *(tmpp + 1);
+		modbuf[15] = *(tmpp + 2);
+
+		/* get rid of hh in input str, we are done with it */
+		*tmpp = 0;
+	}
+
+	tmpp = findnextsep(optp, "/-");
+
+	if (tmpp) {
+		if (tmpp - optp == 2) {
+			long year;
+			/* 2 digit year YY- */
+			if (check_n_get_val(optp, 2, &year, 0, 0, 0, 0)
+			    != B_TRUE)
+				comerrno(EX_BAD, "Bad modification date:year"
+				    "length \n");
+			/* 69-99 1969-1999, 00-68 2000 to 2068  */
+			if (year > 68)
+				strncpy(bufp, "19", 2);
+			else
+				strncpy(bufp, "20", 2);
+			bufp += 2;
+			strncpy(bufp, optp, 2);
+			bufp += 2;
+			optp = tmpp + 1;
+
+		} else if (tmpp - optp == 4) {
+			long year;
+
+			/* 4 digit year YYYY- */
+			if (check_n_get_val(optp, 4, &year, 1, 1, 0, 0)
+			    != B_TRUE)
+				comerrno(EX_BAD, "Bad modification date:"
+				    "year\n");
+			strncpy(bufp, optp, 4);
+			bufp += 4;
+			optp = tmpp + 1;
+
+		} else if (tmpp - optp == 6) {
+			/* YYYYMM- */
+			long year;
+			if (isalldigits(optp, 6) != B_TRUE)
+				comerrno(EX_BAD, "Bad modification date: "
+				    "year\n");
+
+			if (check_n_get_val(optp, 4, &year, 1, 1, 0, 0)
+			    != B_TRUE)
+				comerrno(EX_BAD, "Bad modification date: year "
+				    "length\n");
+
+			strncpy(bufp, optp, 4);
+			optp = optp + 4;
+			bufp += 4;
+		} else
+			comerrno(EX_BAD, "Bad modification date\n");
+
+	} else /* tmpp == NULL */ {
+		/* YYYY[MM[DD.... */
+		long year;
+
+		if (check_n_get_val(optp, 4, &year, 1, 1, 0, 0) != B_TRUE)
+			comerrno(EX_BAD, "Bad modification date year:length\n");
+
+		strncpy(bufp, optp, 4);
+		bufp += 4;
+		optp += 4;
+	}
+
+	if (*optp) {
+		long month;
+		/* optp should point to MM */
+		if (check_n_get_val(optp, 2, &month, 1, 1, 1, 12) != B_TRUE)
+			comerrno(EX_BAD, "Bad modification date:month\n");
+		strncpy(bufp, optp, 2);
+		bufp += 2;
+		optp += 2;
+	}
+	if ((*optp) && (IS_SEPARATOR1(*optp)))
+		optp++;
+
+	if (*optp) {
+		long day;
+
+		if (check_n_get_val(optp, 2, &day, 1, 1, 1, 31) != B_TRUE)
+			comerrno(EX_BAD, "Bad modification date: day\n");
+		/* DD */
+		strncpy(bufp, optp, 2);
+		bufp += 2;
+		optp += 2;
+	}
+
+	if (*optp == ' ')
+		optp++;
+
+	if (*optp) {
+		long hour;
+		if (check_n_get_val(optp, 2, &hour, 0, 0, 1, 23) != B_TRUE)
+			comerrno(EX_BAD, "Bad modification date: hour\n");
+
+		strncpy(bufp, optp, 2);
+		bufp += 2;
+		optp += 2;
+	}
+
+	if (*optp == ':')
+		optp++;
+
+	if (*optp) {
+		long min;
+		if (check_n_get_val(optp, 2, &min, 0, 0, 1, 59) != B_TRUE)
+			comerrno(EX_BAD, "Bad modification date: minute\n");
+		strncpy(bufp, optp, 2);
+		bufp += 2;
+		optp += 2;
+	}
+
+	if (*optp == ':')
+		optp++;
+
+	if (*optp) {
+		long sec;
+		if (check_n_get_val(optp, 2, &sec, 0, 0, 1, 59) != B_TRUE)
+			comerrno(EX_BAD, "Bad modification date: second\n");
+		strncpy(bufp, optp, 2);
+		bufp += 2;
+		optp += 2;
+	}
+
+	if (*optp == ' ')
+		/* optional space */
+		optp++;
+
+	if (*optp != 0) {
+		comerrno(EX_BAD, "Bad modification date: extra \n");
+	}
+
+	modification_date = modbuf;
+	return (1);
+
+}
+
+
+LOCAL int
+get_boot_platid(opt_arg)
+	char	*opt_arg;
+{
+	long	val;
+	char	*ptr;
+
+	use_eltorito++;
+
+	if (strcmp(opt_arg, "x86") == 0)
+		val = 0;
+	else if (strcmp(opt_arg, "PPC") == 0)
+		val = 1;
+	else if (strcmp(opt_arg, "Mac") == 0)
+		val = 2;
+	else if (strcmp(opt_arg, "efi") == 0)
+		val = 0xEF;
+	else {
+		val = strtol(opt_arg, &ptr, 0);
+		if (*ptr || val < 0 || val >= 0x100) {
+			comerrno(EX_BAD, "Bad boot system ID.\n");
+		}
+	}
+
+	if (boot_image == NULL) {
+		/* called before -eltorito-boot option */
+		def_platid = val;
+		return (1);
+
+	}
+
+	if (val != def_platid) {
+		new_boot_entry();
+		get_boot_entry();
+	}
+
+	if (current_boot_entry == NULL)
+		comerrno(EX_BAD, "No current boot entry.\n");
+
+	current_boot_entry->type = ELTORITO_SECTION_HEADER;
+	current_boot_entry->boot_platid = val;
+
+	return (1);
+}
+
+LOCAL int
 get_boot_size(opt_arg)
 	char	*opt_arg;
 {
@@ -840,7 +1210,8 @@
 	"Allow full 31 character filenames for ISO9660 names"},
 	{{"max-iso9660-filenames", &max_filenames },
 	"Allow 37 character filenames for ISO9660 names (violates ISO9660)"},
-
+	{{"modification-date&", NULL, (getpargfun)get_modification_date},
+	"\1[string]\1Set the modification date in the primary volume descriptor"},
 	{{"allow-leading-dots", &allow_leading_dots },
 	"Allow ISO9660 filenames to start with '.' (violates ISO9660)"},
 	{{"ldots", &allow_leading_dots },
@@ -968,6 +1339,8 @@
 	"Boot image is 'no emulation' image"},
 	{{"no-boot~", NULL, (getpargfun)get_no_boot },
 	"Boot image is not bootable"},
+	{{"eltorito-platform&", NULL, (getpargfun)get_boot_platid },
+	"\1#\1Set eltorito platform id"},
 	{{"boot-load-seg&", NULL, (getpargfun)get_boot_addr },
 	"\1#\1Set load segment for boot image"},
 	{{"boot-load-size&", NULL, (getpargfun)get_boot_size },