Hello community,

here is the log from the commit of package mksusecd for openSUSE:Factory 
checked in at 2017-04-07 13:55:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/mksusecd (Old)
 and      /work/SRC/openSUSE:Factory/.mksusecd.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "mksusecd"

Fri Apr  7 13:55:52 2017 rev:34 rq:485854 version:1.49

Changes:
--------
--- /work/SRC/openSUSE:Factory/mksusecd/mksusecd.changes        2017-03-21 
22:51:13.656545141 +0100
+++ /work/SRC/openSUSE:Factory/.mksusecd.new/mksusecd.changes   2017-04-07 
13:55:58.484865701 +0200
@@ -1,0 +2,25 @@
+Wed Apr  5 15:00:18 UTC 2017 - snw...@suse.com
+
+- add support for disk images with FAT file system
+- 1.49
+
+-------------------------------------------------------------------
+Mon Apr  3 15:30:15 UTC 2017 - snw...@suse.com
+
+- undo accidental mksusecd patch
+- 1.48
+
+-------------------------------------------------------------------
+Mon Apr  3 15:20:13 UTC 2017 - snw...@suse.com
+
+- some small doc fixes
+- add dvd/disk image layout description
+- 1.47
+
+-------------------------------------------------------------------
+Mon Apr  3 10:15:13 UTC 2017 - snw...@suse.com
+
+- isohybrid: add --size option to specify image size
+- 1.46
+
+-------------------------------------------------------------------

Old:
----
  mksusecd-1.45.tar.xz

New:
----
  mksusecd-1.49.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ mksusecd.spec ++++++
--- /var/tmp/diff_new_pack.SQL81q/_old  2017-04-07 13:56:00.764543677 +0200
+++ /var/tmp/diff_new_pack.SQL81q/_new  2017-04-07 13:56:00.764543677 +0200
@@ -18,7 +18,7 @@
 
 
 Name:           mksusecd
-Version:        1.45
+Version:        1.49
 Release:        0
 Summary:        Create SUSE Linux installation ISOs
 License:        GPL-3.0+

++++++ mksusecd-1.45.tar.xz -> mksusecd-1.49.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mksusecd-1.45/VERSION new/mksusecd-1.49/VERSION
--- old/mksusecd-1.45/VERSION   2017-03-20 17:19:36.000000000 +0100
+++ new/mksusecd-1.49/VERSION   2017-04-05 16:57:14.000000000 +0200
@@ -1 +1 @@
-1.45
+1.49
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mksusecd-1.45/changelog new/mksusecd-1.49/changelog
--- old/mksusecd-1.45/changelog 2017-03-20 17:19:36.000000000 +0100
+++ new/mksusecd-1.49/changelog 2017-04-05 16:57:14.000000000 +0200
@@ -1,3 +1,16 @@
+2017-04-05:    1.49
+       - add support for disk images with FAT file system
+
+2017-04-03:    1.48
+       - undo accidental mksusecd patch
+
+2017-04-03:    1.47
+       - some small doc fixes
+       - add dvd/disk image layout description
+
+2017-03-31:    1.46
+       - isohybrid: add --size option to specify image size
+
 2017-03-17:    1.45
        - fix typo
        - add --rebuild-initrd option for smaller initrds
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mksusecd-1.45/isohybrid.c 
new/mksusecd-1.49/isohybrid.c
--- old/mksusecd-1.45/isohybrid.c       2017-03-20 17:19:36.000000000 +0100
+++ new/mksusecd-1.49/isohybrid.c       2017-04-05 16:57:14.000000000 +0200
@@ -76,6 +76,7 @@
   unsigned no_mbr:1;           /* gpt: don't write protective mbr */
   unsigned no_code:1;          /* no mbr boot code */
   unsigned no_chs:1;           /* fill in 0xffffff instead of real chs values 
*/
+  off_t size;                  /* total size MBR partition table should cover 
*/
 } opt;
 
 
@@ -252,6 +253,7 @@
     printf(FMT, "   --no-mbr", "Don't write protective MBR for GPT");
     printf(FMT, "   --no-code", "Don't include MBR boot code");
     printf(FMT, "   --no-chs", "Don't fill in CHS values, use 0xffffff 
instead");
+    printf(FMT, "   --size", "Specify disk size to assume when writing MBR (in 
512 byte units)");
 
     printf("\n");
     printf(FMT, "   --forcehd0", "Assume we are loaded as disk ID 0");
@@ -279,6 +281,7 @@
     {
         { "entry", required_argument, NULL, 'e' },
         { "offset", required_argument, NULL, 'o' },
+        { "size", required_argument, NULL, 1006 },
         { "type", required_argument, NULL, 't' },
         { "id", required_argument, NULL, 'i' },
         { "gpt", no_argument, NULL, 1001 },
@@ -385,6 +388,12 @@
             opt.no_chs = 1;
             break;
 
+        case 1006:
+            opt.size = strtoul(optarg, &err, 0);
+            if (*err)
+                errx(1, "invalid size: `%s'", optarg);
+            break;
+
         case 'V':
             printf("%s version %s\n", prog, VERSION);
             exit(0);
@@ -615,7 +624,11 @@
   s = (ofs % sector) + 1;
   h = (ofs / sector) % head;
   c = ofs / (sector * head);
-  if(c > 1023) c = 1023;
+  if(c > 1023) {
+    c = 1023;
+    s = sector;
+    h = head - 1;
+  }
 
   return ((c & 0xff) << 24) + ((s + ((c >> 8) << 6)) << 16) + (h << 8);
 }
@@ -689,7 +702,7 @@
             mbr[1] = chs >> 8;
             mbr[2] = chs >> 16;
             mbr[3] = chs >> 24;
-            chs = ofs2chs(c * head * sector - 1);
+            chs = ofs2chs((opt.size ?: c * head * sector) - 1);
             mbr[4] = type;
             mbr[5] = chs >> 8;
             mbr[6] = chs >> 16;
@@ -698,7 +711,7 @@
             tmp = lendian_int(offset);
             memcpy(&mbr[8], &tmp, sizeof(tmp));
 
-            tmp = lendian_int(c * head * sector - offset);
+            tmp = lendian_int((opt.size ?: c * head * sector) - offset);
             memcpy(&mbr[12], &tmp, sizeof(tmp));
         }
 
@@ -1219,7 +1232,7 @@
        fwrite(buf, sizeof(char), apm_size, fp);
     }
 
-    if (padding)
+    if (padding && !opt.size)
     {
         if (fsync(fileno(fp)))
             err(1, "%s: could not synchronise", argv[0]);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mksusecd-1.45/layout.md new/mksusecd-1.49/layout.md
--- old/mksusecd-1.45/layout.md 1970-01-01 01:00:00.000000000 +0100
+++ new/mksusecd-1.49/layout.md 2017-04-05 16:57:14.000000000 +0200
@@ -0,0 +1,183 @@
+## isohybrid images done right
+
+'[isohybrid](http://www.syslinux.org/wiki/index.php?title=Isohybrid)'
+describes an image that can be both used as dvd (it has a valid
+[iso9660](https://en.wikipedia.org/wiki/ISO_9660) file system
+at offset 0) and as disk image (it also has a valid partition table).
+
+The partition table type
+([gpt](https://en.wikipedia.org/wiki/GUID_Partition_Table),
+[mbr](https://en.wikipedia.org/wiki/Master_boot_record),
+or even [apple](https://en.wikipedia.org/wiki/Apple_Partition_Map))
+doesn't matter - the
+iso fs leaves enough unassigned space at its start (32 kB) to accomodate any 
of those types.
+
+The catch is: Where should the data partition itself start? Obviously, at 
block 0
+would be a choice. But such a partition would again enclose the partition
+table itself and partitioning tools really don't like such a layout.
+
+Also, if the image should be
+[EFI 
bootable](https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface#Booting),
+the EFI boot image needs its own
+partition. You can of course create a partition pointing to the EFI image
+included in the iso fs but then you get overlapping partitions
+and partitioning tools will eat you for lunch - this time for sure.
+
+So, we do it differently. For isohybrid images we aim to create an image that
+
+1. looks like an iso fs **and**
+2. has a valid (sane) partition table with
+    - one partition containing the same fs as 1. and
+    - (optionally) another partition containing an EFI boot image
+
+### Using an iso9660 file system for the partition
+
+To achieve this, two [mkisofs](https://software.opensuse.org/package/mkisofs) 
runs are needed.
+To understand why the following works it's important to know that the iso fs 
layout starts with
+fs meta data, followed by directory data, followed by file data.
+
+Now imagine you manage to put valid iso meta/directory data into the first
+data file: this basically means you have an iso fs (excluding this file) that 
doesn't start at offset 0
+but at the offset of the first data file.
+
+Let's see how this works in detail.
+
+There are two special files in our iso fs we need below:
+
+- `efi`: (optional) EFI (fat-) boot image file (full path on x86_64 is 
`boot/x86_64/efi`)
+- `glump`: hidden(!) 2k-block containing a magic blob (as the file doesn't 
have a
+directory entry, we need the magic to find it in the image)
+
+`efi` must be the 1st file, `glump` the 2nd (mkisofs lets you force the file 
order
+easily).
+
+The fs layout looks like this after a 1st mkisofs run:
+
+```
+== 1st run ==
+iso meta/dir 1
+data 1
+  efi 1
+  glump 1
+    magic 1
+  other files 1
+```
+
+(Indentation is used to indicate 'contains'.)
+
+So, `glump` contains the magic blob, and `data` consists of `efi`, `glump`,
+and `other files`.
+
+The numbers are a reminder of the run the data was generated.
+
+Now we copy `iso meta/dir` ... `glump` (inclusive) into a new `glump` and run
+mkisofs on the same tree again. We get this layout:
+
+```
+== 2nd run ==
+ofs 0->   iso meta/dir 2
+          data 2
+part1->     efi 2
+part2->     glump 2
+              iso meta/dir 1
+              data 1
+                efi 1
+                glump 1
+                  magic 1
+            other files 2
+```
+
+Note that `other files 1` and `other files 2` are identical (we didn't change
+any data there).
+
+So, the result is:
+
+- a valid iso fs at offset 0
+- a valid iso fs at `glump 2` == `iso meta/dir 1`
+
+This means we can add a partition table where:
+
+- part1 points to the EFI boot partition
+- part2 points to a valid iso fs referencing the same files as via offset 0
+- part1 and part2 don't overlap
+
+Note that the EFI boot image exists twice - but `efi 1` is unused
+([El Torito](https://en.wikipedia.org/wiki/El_Torito_%28CD-ROM_standard%29)
+references `efi 2` for booting). It would technically be possible to exclude
+it in the 1st run (`efi 1` would then be gone) without loss of
+functionality. But this would mean the users see different things depending on
+whether they mount at offset 0 compared to partition 2. So, let's keep it
+and waste the few bytes.
+
+
+### Using a fat file system for the partition
+
+Why not have an iso fs at offset 0 but a differnt fs type in partition 2?
+
+The [fat](https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system) file 
system
+has a similar structure than iso fs: first fs meta data, then (mixed)
+directory and file data. But it's easy to disentangle directory and file data
+and ensure directories are first. So we can achieve the same basic fs layout 
and
+use the same trick as above again.
+
+Let's start by running mkisofs:
+
+```
+== 1st run ==
+iso meta/dir 1
+data 1
+  efi 1
+  glump 1
+    magic 1
+  other files 1
+```
+
+Now we need to prepare the content of `glump`. This is a bit more tricky
+than with the iso fs above - but possible.
+
+Here are the details:
+
+1. create a new fat fs, with desired size (enough for all files, at least)
+2. choose cluster size 2k, so files are aligned as in the iso fs (which also 
uses 2k blocks)
+3. but: fat meta data can still be non-2k aligned - for this we will later 
move the
+start of the whole file system so the start of the file data is 2k-aligned
+4. create all files in the order they are in the iso fs, but with size 0 -
+this will take care of creating all needed directory entries
+5. then truncate all files to the correct size
+6. while we do this, check if there are hidden files in the iso fs that would 
destroy
+the relative file alignment; if such a gap is detected, insert padding files 
into the fat fs
+7. delete any inserted padding files
+8. verify that the (relative) file offsets match the offsets in the iso fs
+9. determine the alignment blocks needed (as explained in step 3.)
+10. copy alignment blocks + fat fs up to the start of the file data into 
`glump`
+11. add `efi` (full 2k-blocks) to `glump`, if it exists
+
+Then, after a 2nd mkisofs run, the layout looks like this:
+
+```
+== 2nd run ==
+ofs 0->   iso meta/dir 2
+          data 2
+part1->     efi 2
+            glump 2
+              alignment
+part2->       fat meta/dir
+              efi
+            other files 2
+```
+
+So, the result is:
+
+- a valid iso fs at offset 0
+- a valid fat fs at `fat meta/dir`
+
+This means we can add a partition table where:
+
+- part1 points to the EFI boot partition
+- part2 points to a valid fat fs referencing the same files as via offset 0
+- part1 and part2 don't overlap
+
+Note that the fat fs is in fact **writable** but modifying any files will 
disrupt the
+iso fs side. This shouldn't cause any problems in real life as users
+probably don't copy the image onto a usb stick, use it for a while, and
+then later burn a dvd with it.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mksusecd-1.45/mksusecd new/mksusecd-1.49/mksusecd
--- old/mksusecd-1.45/mksusecd  2017-03-20 17:19:36.000000000 +0100
+++ new/mksusecd-1.49/mksusecd  2017-04-05 16:57:14.000000000 +0200
@@ -157,11 +157,13 @@
 sub rerun_mkisofs;
 sub run_isohybrid;
 sub run_isozipl;
+sub run_syslinux;
 sub run_createrepo;
 sub isols;
 sub find_magic;
 sub meta_iso;
 sub meta_fat;
+sub fat_data_start;
 sub create_initrd;
 sub get_kernel_initrd;
 sub update_kernel_initrd;
@@ -196,6 +198,7 @@
 sub new_products_xml;
 sub prepare_addon;
 sub check_mksquashfs_comp;
+sub eval_size;
 
 my %config;
 my $sudo;
@@ -236,6 +239,7 @@
 my $opt_addon_alias;
 my $opt_addon_prio = 60;
 my $opt_rebuild_initrd;
+my $opt_size;
 
 
 GetOptions(
@@ -258,6 +262,8 @@
   'hybrid'           => \$opt_hybrid,
   'no-hybrid'        => sub { $opt_hybrid = 0 },
   'hybrid-fs=s'      => sub { $opt_hybrid = 1; $opt_hybrid_fs = $_[1] },
+  'fat'              => sub { $opt_hybrid = 1; $opt_hybrid_fs = 'fat' },
+  'size=s'           => \$opt_size,
   'protective-mbr'   => sub { $opt_no_prot_mbr = 0 },
   'no-protective-mbr' => \$opt_no_prot_mbr,
   'mbr-code'         => sub { $opt_no_mbr_code = 0 },
@@ -298,6 +304,8 @@
 usage 1 if $opt_hybrid_fs !~ '^(|iso|fat)$';
 usage 1 if defined($opt_digest) && $opt_digest !~ 
'^(md5|sha1|sha224|sha256|sha384|sha512)$';
 
+$ENV{PATH} = "$LIBEXECDIR/mksusecd:/usr/bin:/bin:/usr/sbin:/sbin";
+
 if($opt_rebuild_initrd && $>) {
   die "mksusecd must be run with root permissions when --rebuild-initrd is 
used\n"
 }
@@ -355,17 +363,23 @@
 my $warned;
 my $read_write;
 my $mksquashfs_has_comp;
+my $image_size;
+my $syslinux_config;
 
 my $progress_start = 0;
 my $progress_end = 100;
 my $progress_txt = 'building:';
 
 $mkisofs->{command} = "/usr/bin/genisoimage" if ! -x $mkisofs->{command};
-
 die "mkisofs: command not found\n" if ! -x $mkisofs->{command};
 
 $mksquashfs_has_comp = check_mksquashfs_comp;
 
+if(defined $opt_size) {
+  $image_size = eval_size $opt_size;
+  die "$opt_size: invalid size\n" unless $image_size;
+}
+
 if($opt_create) {
 #  if(@opt_kernel_rpms) {
 #    die "Sorry, you must run mksusecd as root to replace kernel modules." if 
$>;
@@ -376,6 +390,8 @@
 
   $iso_file = $opt_dst;
 
+  die "$iso_file: block device not allowed\n" if -b $iso_file;
+
   for (@ARGV) {
     s#/*$##;
     next if $_ eq "";
@@ -467,7 +483,10 @@
   fix_catalog;
   relocate_catalog;
 
-  run_isohybrid if $opt_hybrid;
+  if($opt_hybrid) {
+    run_isohybrid;
+    run_syslinux if $opt_hybrid_fs eq 'fat';
+  }
   run_isozipl if $opt_zipl;
 
   if(defined $opt_digest) {
@@ -541,6 +560,13 @@
                                 image (partitioning tools don't really like 
this) or
                                 'iso' or 'fat' in which case you get a regular 
partition
                                 with an ISO960 or FAT file system (default: 
'iso').
+      --fat                     An alias for '--hybrid-fs fat'.
+      --size SIZE_SPEC          When using a FAT file system, you can set the 
intended size of
+                                the disk image.
+                                SIZE_SPEC can be a number, optionally followed 
by a unit ('b',
+                                'k', 'm', 'g', 't') indicating blocks, kiB, 
MiB, GiB, or TiB.
+                                But SIZE_SPEC can also be a device name like 
'/dev/sda', in
+                                which casee the size of the device is used.
       --zipl                    Make zIPL bootable (default on s390x).
       --no-zipl                 Don't make zIPL bootable (default except on 
s390x).
       --initrd DIR|RPM|DUD      Add directory DIR or package RPM or driver 
update DUD
@@ -1298,6 +1324,10 @@
 
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# rerun_mkisofs()
+#
+# Prepare hybrid image and run mkisofs again.
+#
 sub rerun_mkisofs
 {
   my $iso_file_list = isols;
@@ -1323,10 +1353,20 @@
 
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# run_isohybrid()
+#
+# Add a partition table to the iso image and, on x86, add boot code to the
+# partition table.
+#
 sub run_isohybrid
 {
   my $opt;
   my $ok;
+  my $part_type = $hybrid_part_type;
+
+  if($opt_hybrid_fs eq 'fat') {
+    $part_type = 0x0c if !$part_type;
+  }
 
   $opt .= " --uefi" if $has_efi;
   $opt .= " --gpt" if $opt_hybrid_gpt;
@@ -1334,14 +1374,11 @@
   $opt .= " --no-mbr" if $opt_no_prot_mbr;
   $opt .= " --no-code" if $opt_no_mbr_code;
   $opt .= " --no-chs" if $opt_no_mbr_chs;
-  $opt .= sprintf(" --type 0x%x", $hybrid_part_type) if $hybrid_part_type;
+  $opt .= sprintf(" --type 0x%x", $part_type) if $part_type;
   $opt .= " --offset $mkisofs->{partition_start}" if 
$mkisofs->{partition_start};
+  $opt .= " --size $image_size" if $image_size;
 
-  # prefer our own isohybrid variant
-  my $cmd = "$LIBEXECDIR/mksusecd/isohybrid";
-  $cmd = "isohybrid" unless -x $cmd;
-
-  $cmd .= "$opt $iso_file";
+  my $cmd = "isohybrid $opt '$iso_file'";
 
   print "running:\n$cmd\n" if $opt_verbose >= 1;
 
@@ -1360,16 +1397,45 @@
 
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# run_syslinux()
+#
+# Make fat partition bootable using syslinux. This requires the 'real'
+# syslinux package and does not work on non-x86 achitectures.
+#
+sub run_syslinux
+{
+  return unless $syslinux_config && $mkisofs->{partition_start};
+
+  my $mbr;
+  if(open my $f, "/usr/share/syslinux/mbr.bin") {
+    local $/;
+    $mbr = <$f>;
+    close $f;
+  }
+
+  if(!-x "/usr/bin/syslinux" || length($mbr) != 440) {
+    die "syslinux is needed to build a bootable FAT image, please install 
package 'syslinux'\n"
+  }
+
+  system "syslinux -t " . ($mkisofs->{partition_start} << 9) . " -d 
'$syslinux_config' -i '$iso_file'";
+
+  die "$iso_file: $!\n" unless open $iso_fh, "+<", $iso_file;
+  syswrite $iso_fh, $mbr;
+  close $iso_fh;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# run_isozipl()
+#
+# Make iso image zipl bootable.
+#
 sub run_isozipl
 {
   my $opt;
   my $ok;
 
-  # prefer our own isozipl variant
-  my $cmd = "$LIBEXECDIR/mksusecd/isozipl";
-  $cmd = "isozipl" unless -x $cmd;
-
-  $cmd .= " $iso_file";
+  my $cmd = "isozipl '$iso_file'";
 
   print "running:\n$cmd\n" if $opt_verbose >= 1;
 
@@ -1474,7 +1540,15 @@
 
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# find magic block
+# magic = find_magic(file_list)
+#
+# Find magic block.
+# - file_list: array ref with file names as produced by isols()
+# - magic: hash ref with offset of magic block ('block') and
+#   offset of first (with lowest start offset) file ('extra')
+#
+# Offsets are in 2k units (due to iso fs heritage).
+#
 sub find_magic
 {
   my $cnt;
@@ -1513,6 +1587,11 @@
 
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# metca_iso(magic)
+#
+# Prepare hybrid image using iso fs for partition.
+# - magic: hash ref as returned by find_magic()
+#
 sub meta_iso
 {
   my $magic = shift;
@@ -1538,6 +1617,33 @@
 
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# fat_mkfs(name, size, hidden)
+#
+# Create a fat file system image.
+# - name: image name
+# - size: size in blocks
+# - hidden: hidden blocks (aka planned partition offset)
+#
+sub fat_mkfs
+{
+  my ($name, $size, $hidden) = @_;
+
+  open my $fh, ">", $name;
+  close $fh;
+  truncate $name, $size << 9;
+  # try fat32 first
+  system "mformat -i '$name' -T $size -H $hidden -s 32 -h 64 -c 4 -F -d 1 -v 
'SUSEDISK' :: 2>/dev/null" and
+  system "mformat -i '$name' -T $size -H $hidden -s 32 -h 64 -c 4 -d 1 -v 
'SUSEDISK' ::";
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# meta_fat(magic, file_list)
+#
+# Prepare hybrid image using fat fs for partition.
+# - magic: hash ref as returned by find_magic()
+# - file_list: array ref with file names as produced by isols()
+#
 sub meta_fat
 {
   my $magic = shift;
@@ -1549,7 +1655,7 @@
 
   for (reverse @$iso_files) {
     next unless $_->{type} eq ' ';
-    $fat_size =  $_->{start} + (($_->{size} + 0x7ff) >> 11);
+    $fat_size = $_->{start} + (($_->{size} + 0x7ff) >> 11);
     last;
   }
 
@@ -1560,22 +1666,38 @@
    
   $fat_size += ($fat_size >> 8) + 4;
 
-  # add a bit free space (4MB)
-  $fat_size += 4 << 9;
+  # we want $fat_size to count 512 byte blocks, not 2k blocks as in iso fs
+  $fat_size *= 4;
+
+  # add a bit free space (4 MB)
+  $fat_size += 4 << 11;
 
   # and round up to full MB
-  my $fat_mb = ($fat_size + 511) >> 9;
+  my $fat_size = (($fat_size + 2047) >> 11) << 11;
 
-  $fat_size = $fat_mb << 9;
+  printf "fat_size (auto) = $fat_size\n" if $opt_verbose >= 2;
 
-  printf "fat_size = $fat_size\n" if $opt_verbose >= 2;
+  # disk size - partition offset - max alignment
+  my $user_fat_size = $image_size - ($magic->{block} << 2) - 3;
 
-  open my $fh, ">", $tmp_fat;
-  close $fh;
-  truncate $tmp_fat, $fat_mb << 20;
-  # try fat32 first
-  system "mformat -i '$tmp_fat|cylinders=" . $fat_mb * 4 . " heads=16 
sectors=32' -c 4 -F -v 'SUSEDVD' :: 2>/dev/null" and
-  system "mformat -i '$tmp_fat|cylinders=" . $fat_mb * 4 . " heads=16 
sectors=32' -c 4 -v 'SUSEDVD' ::";
+  # use user-specified value, if possible
+  $fat_size = $user_fat_size if $user_fat_size > $fat_size;
+
+  printf "fat_size (final) = $fat_size\n" if $opt_verbose >= 2;
+
+  fat_mkfs $tmp_fat, $fat_size, 0;
+
+  my $fat_data_start = fat_data_start $tmp_fat;
+
+  my $align = ($fat_data_start & 0x7ff) >> 9;
+  $align = (4 - $align) & 3;
+
+  print "fat fs alignment: $align blocks\n" if $opt_verbose >= 2;
+
+  $mkisofs->{partition_start} = ($magic->{block} << 2) + $align;
+
+  # remake, but with correct start offset stored in bpb
+  fat_mkfs $tmp_fat, $fat_size, $mkisofs->{partition_start};
 
   # 1.: directories
   for (@$iso_files) {
@@ -1651,18 +1773,23 @@
 
   print "last block: $last_block\n" if $opt_verbose >= 2;
 
-
-  my $data_start;
-  for (`dosfsck -v '$tmp_fat'`) {
-    if(/Data area starts at byte (\d+)/) {
-      $data_start = $1 + (($first - 2) << 11);
-      $last_block = ($1 >> 9) + (($last_block - 2) << 2);
+  # we're going to use syslinux instead of isolinux, so rename the config file
+  if($opt_hybrid_fs eq 'fat') {
+    for (@$iso_files) {
+      if($_->{name} =~ m#/isolinux.cfg$#) {
+        system "mren -i '$tmp_fat' '::$_->{name}' syslinux.cfg";
+        $syslinux_config = $_->{name};
+        $syslinux_config =~ s#^/##;
+        $syslinux_config =~ s#/[^/]+$##;
+        last;
+      }
     }
   }
 
-  printf "last_block = $last_block\n" if $opt_verbose >= 2;
+  my $data_start = $fat_data_start + (($first - 2) << 11);
+  $last_block = ($fat_data_start >> 9) + (($last_block - 2) << 2);
 
-  my $iso_pad = (($fat_size << 2) - $last_block) >> 2;
+  printf "last_block = $last_block\n" if $opt_verbose >= 2;
 
   die "$tmp_fat: oops, data start not found\n" unless $data_start;
 
@@ -1670,18 +1797,6 @@
 
   truncate $tmp_fat, $data_start;
 
-  my $align = ($data_start & 0x7ff) >> 9;
-  $align = (4 - $align) & 3;
-
-  if($align) {
-    print "alignment needed: $align\n" if $opt_verbose >= 2;
-    $iso_pad++;
-  }
-   
-  printf "iso_pad = $iso_pad\n" if $opt_verbose >= 2;
-
-  $mkisofs->{partition_start} = ($magic->{block} << 2) + $align;
-
   # now copy the fat
 
   open my $fh, ">", "$tmp_new/glump";
@@ -1720,6 +1835,29 @@
 
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# fat_data_start(fs_image_file)
+#
+# Returns the offset (in bytes) of the data area of the fat fs in
+# fs_image_file or not at all if there are problems detecting it.
+#
+sub fat_data_start
+{
+  my $data_start;
+
+  for (`dosfsck -v '$_[0]' 2>/dev/null`) {
+    if(/Data area starts at byte (\d+)/) {
+      $data_start = $1;
+      last;
+    }
+  }
+
+  die "error: dosfsck failed\n" unless $data_start;
+
+  return $data_start;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 sub create_initrd
 {
   return undef if !@opt_initrds;
@@ -3385,3 +3523,49 @@
   return $comp_ok;
 }
 
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# eval_size(size_string)
+#
+# Interpret size_string and return size in (512 byte)-blocks.
+#
+# size_string is either a numerical size like '64G' or a file or block
+# device name. In this case the size of the file or block device is used.
+#
+sub eval_size
+{
+  my $size = $_[0];
+  my $unit = { b => 9 - 9, k => 10 - 9, m => 20 - 9, g => 30 - 9, t => 40 - 9 
};
+
+  return undef unless $size;
+
+  if($size =~ /^(\d+)\s*([bkmgt]?)/i) {
+    $size <<= $unit->{"\L$2"} if $2;
+  }
+  elsif($size =~ m#/dev/#) {
+    my $s;
+    my $x = `readlink -f $size 2>/dev/null`;
+    if($x =~ m#/dev/([^/]+?)\s*$#) {
+      my $dev = $1;
+      for (</sys/block/$dev/size /sys/block/*/$dev/size>) {
+        if(open(my $f, $_)) {
+          $s = <$f> + 0;
+          close $f;
+          last;
+        }
+      }
+    }
+    $size = $s;
+  }
+  elsif(-s $size) {
+    $size = (-s _) >> 9;
+  }
+  else {
+    $size = undef;
+  }
+
+  printf "target image size: %.2f GiB ($size blocks)\n", $size / (1 << 21);
+
+  return $size;
+}
+


Reply via email to