WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] lomount: Major rewrite: handle large file

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] lomount: Major rewrite: handle large files and GPT partition.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 14 Jul 2006 17:40:46 +0000
Delivery-date: Fri, 14 Jul 2006 10:45:10 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID fa143f374f3deac2c63b4f9585bb7e89d2d9614b
# Parent  ef8d08aa2072b187a865f0827dc152fcc7afaf1d
lomount: Major rewrite: handle large files and GPT partition.
Signed-off-by: Tristan Gingold <tristan.gingold@xxxxxxxx>
---
 tools/misc/lomount/lomount.c |  430 ++++++++++++++++++++++++++++---------------
 1 files changed, 282 insertions(+), 148 deletions(-)

diff -r ef8d08aa2072 -r fa143f374f3d tools/misc/lomount/lomount.c
--- a/tools/misc/lomount/lomount.c      Fri Jul 14 12:00:02 2006 +0100
+++ b/tools/misc/lomount/lomount.c      Fri Jul 14 13:53:59 2006 +0100
@@ -4,6 +4,9 @@
  * Copyright (c) 2004 Jim Brown
  * Copyright (c) 2004 Brad Watson
  * Copyright (c) 2004 Mulyadi Santosa
+ * Major rewrite by Tristan Gingold:
+ *  - Handle GPT partitions
+ *  - Handle large files 
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to 
deal
@@ -41,6 +44,8 @@ enum
        ERR_MOUNT               // Other failure of mount command
 };
 
+#define _LARGEFILE_SOURCE
+#define _FILE_OFFSET_BITS 64
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -63,22 +68,69 @@ struct pentry
        unsigned char end_head;
        unsigned int  end_cylinder;
        unsigned char end_sector;
-       unsigned long start_sector_abs;
-       unsigned long no_of_sectors_abs;
+       unsigned long long start_sector_abs;
+       unsigned long long no_of_sectors_abs;
 };
 
-int loadptable(const char *diskimage, struct pentry parttbl[], struct pentry 
**exttbl, int * valid)
+static void
+disp_entry (struct pentry *p)
+{
+       printf ("%10llu - %10llu: %02x %x\n",
+               SECSIZE * p->start_sector_abs,
+               SECSIZE * (p->start_sector_abs + p->no_of_sectors_abs - 1),
+               p->system,
+               p->bootable);
+}
+
+static unsigned long
+read_le4 (unsigned char *p)
+{
+       return (unsigned long) p[0]
+               | ((unsigned long) p[1] << 8)
+               | ((unsigned long) p[2] << 16)
+               | ((unsigned long) p[3] << 24);
+}
+
+static unsigned long long
+read_le8 (unsigned char *p)
+{
+       return (unsigned long long) p[0]
+               | ((unsigned long long) p[1] << 8)
+               | ((unsigned long long) p[2] << 16)
+               | ((unsigned long long) p[3] << 24)
+               | ((unsigned long long) p[4] << 32)
+               | ((unsigned long long) p[5] << 40)
+               | ((unsigned long long) p[6] << 48)
+               | ((unsigned long long) p[7] << 56);
+}
+
+/* Return true if the partition table is a GPT protective MBR.  */
+static int
+check_gpt (struct pentry *part, int nbr_part)
+{
+       if (nbr_part != 4)
+               return 0;
+       if (part[0].system == 0xee
+           && part[1].no_of_sectors_abs == 0
+           && part[2].no_of_sectors_abs == 0
+           && part[3].no_of_sectors_abs == 0)
+               return 1;
+       return 0;
+}
+
+static int
+load_gpt (const char *diskimage, struct pentry *parttbl[])
 {
        FILE *fd;
        size_t size;
-       int fail = 1;
-       int i, total_known_sectors = 0;
-       unsigned char *pi; 
-       unsigned char data [SECSIZE]; 
-       unsigned long extent = 0, old_extent = 0, e_count = 1;
-       struct pentry exttbls[4];
-
-       *valid = 0;
+       int fail = -1;
+       unsigned char data[SECSIZE];
+       unsigned long long entries_lba;
+       unsigned long entry_size;
+       struct pentry *part;
+       int nbr_part;
+       unsigned long long off;
+       int i;
 
        fd = fopen(diskimage, "r");
        if (fd == NULL)
@@ -86,108 +138,72 @@ int loadptable(const char *diskimage, st
                perror(diskimage);
                goto done;
        }
+       fseeko (fd, SECSIZE, SEEK_SET);
        size = fread (&data, 1, sizeof(data), fd);
        if (size < (size_t)sizeof(data))
        {
-               fprintf(stderr, "Could not read the entire first sector of 
%s.\n", diskimage);
-               goto done;
-       }
-       for (i = 0; i < 4; i++)
-       {
-               pi = &data [446 + 16 * i];
-               parttbl [i].bootable = *pi; 
-               parttbl [i].start_head  = *(pi + 1); 
-               parttbl [i].start_cylinder = *(pi + 3) | ((*(pi + 2) << 2) & 
0x300);
-               parttbl [i].start_sector = *(pi + 2) & 0x3f;
-               parttbl [i].system = *(pi + 4);
-               parttbl [i].end_head = *(pi + 5);
-               parttbl [i].end_cylinder = *(pi + 7) | ((*(pi + 6) << 2) & 
0x300);
-               parttbl [i].end_sector = *(pi + 6) & 0x3f;
-               parttbl [i].start_sector_abs = 
-                       (unsigned long) *(pi + 8) | ((unsigned long) *(pi + 9) 
<< 8) | ((unsigned long) *(pi + 10) << 16) | ((unsigned long) *(pi + 11) << 24);
-               parttbl [i].no_of_sectors_abs = 
-                       (unsigned long) *(pi + 12) | ((unsigned long) *(pi + 
13) << 8) | ((unsigned long) *(pi + 14) << 16) | ((unsigned long) *(pi + 15) << 
24);
-               if (parttbl[i].system == 0xF || parttbl[i].system == 0x5)
-               {
-                       extent = parttbl[i].start_sector_abs * SECSIZE;
-                       /* save the location of the "real" extended partition */
-                       old_extent = extent;
-               }
-       }
-       *valid = (data [510] == 0x55 && data [511] == 0xaa) ? 1 : 0;
-       for (i = 0; i < 4; i++)
-       {
-               total_known_sectors += parttbl[i].no_of_sectors_abs;
-       }
-       /* Extended Partition layout format was obtained from
-       http://wigner.cped.ornl.gov/the-gang/att-0520/03-Partition.htm */
+               fprintf(stderr, "Could not read the GPT header of %s.\n",
+                       diskimage);
+               goto done;
+       }
+
+       if (memcmp (data, "EFI PART", 8) != 0)
+       {
+               fprintf (stderr, "Bad GPT signature\n");
+               goto done;
+       }
+
+       entries_lba = read_le8 (&data[72]);
+       nbr_part = read_le4 (&data[80]);
+       entry_size = read_le4 (&data[84]);
+
 #ifdef DEBUG
-       if (extent != 0)
-       {
-               printf("extended partition detected at offset %ld\n", extent);
-       }
+       fprintf(stderr, "lba entries: %lu, nbr_part: %u, entry_size: %lu\n",
+               entries_lba, nbr_part, entry_size);
 #endif
-       while (extent != 0)
-       {
-/* according to realloc(3) passing NULL as pointer is same as calling malloc() 
*/
-               exttbl[0] = realloc(exttbl[0], e_count * sizeof(struct pentry));
-               fseek(fd, extent, SEEK_SET);
-               size = fread (&data, 1, sizeof(data), fd);
-               if (size < (size_t)sizeof(data))
-               {
-                       fprintf(stderr, "Could not read extended partition of 
%s.", diskimage);
+       part = malloc (nbr_part * sizeof (struct pentry));
+       if (part == NULL)
+       {
+               fprintf(stderr,"Cannot allocate memory\n");
+               goto done;
+       }
+       memset (part, 0, nbr_part * sizeof (struct pentry));
+       *parttbl = part;
+
+       off = entries_lba * SECSIZE;
+       for (i = 0; i < nbr_part; i++)
+       {
+               static const char unused_guid[16] = {0};
+               fseeko (fd, off, SEEK_SET);
+               size = fread (&data, 1, 128, fd);
+               if (size < 128)
+               {
+                       fprintf(stderr, "Could not read a GPT entry of %s.\n",
+                               diskimage);
                        goto done;
                }
-       /* only first 2 entrys are used in extented partition tables */
-               for (i = 0; i < 2; i++)
-               {
-                       pi = &data [446 + 16 * i];
-                       exttbls [i].bootable = *pi; 
-                       exttbls [i].start_head  = *(pi + 1); 
-                       exttbls [i].start_cylinder = *(pi + 3) | ((*(pi + 2) << 
2) & 0x300);
-                       exttbls [i].start_sector = *(pi + 2) & 0x3f;
-                       exttbls [i].system = *(pi + 4);
-                       exttbls [i].end_head = *(pi + 5);
-                       exttbls [i].end_cylinder = *(pi + 7) | ((*(pi + 6) << 
2) & 0x300);
-                       exttbls [i].end_sector = *(pi + 6) & 0x3f;
-                       exttbls [i].start_sector_abs = 
-                               (unsigned long) *(pi + 8) | ((unsigned long) 
*(pi + 9) << 8) | ((unsigned long) *(pi + 10) << 16) | ((unsigned long) *(pi + 
11) << 24);
-                       exttbls [i].no_of_sectors_abs = 
-                               (unsigned long) *(pi + 12) | ((unsigned long) 
*(pi + 13) << 8) | ((unsigned long) *(pi + 14) << 16) | ((unsigned long) *(pi + 
15) << 24);
-                       if (i == 0)
-                       {
-                               //memmove((void *)exttbl[e_count-1], (void 
*)exttbls[i], sizeof(struct pentry));
-                               //memmove() seems broken!
-                               exttbl[0][e_count-1].bootable = exttbls 
[i].bootable;
-                               exttbl[0][e_count-1].start_head  = exttbls 
[i].start_head;
-                               exttbl[0][e_count-1].start_cylinder = exttbls 
[i].start_cylinder;
-                               exttbl[0][e_count-1].start_sector = exttbls 
[i].start_sector;
-                               exttbl[0][e_count-1].system = exttbls 
[i].system;
-                               exttbl[0][e_count-1].end_head = exttbls 
[i].end_head;
-                               exttbl[0][e_count-1].end_cylinder = exttbls 
[i].end_cylinder;
-                               exttbl[0][e_count-1].end_sector = exttbls 
[i].end_sector;
-                               exttbl[0][e_count-1].start_sector_abs = exttbls 
[i].start_sector_abs;
-                               exttbl[0][e_count-1].no_of_sectors_abs = 
exttbls [i].no_of_sectors_abs;
-                       /* adjust for start of image instead of start of ext 
partition */
-                               exttbl[0][e_count-1].start_sector_abs += 
(extent/SECSIZE);
+               if (memcmp (&data[0], unused_guid, 16) == 0)
+               {
+                       part[i].start_sector_abs = 0;
+                       part[i].no_of_sectors_abs = 0;
+               }
+               else
+               {
+                       part[i].start_sector_abs = read_le8 (&data[32]);
+                       part[i].no_of_sectors_abs = read_le8 (&data[40]);
 #ifdef DEBUG
-                               printf("extent %ld start_sector_abs %ld\n", 
extent, exttbl[0][e_count-1].start_sector_abs);
+                       fprintf (stderr, "%d: %llu - %llu\n", i,
+                                part[i].start_sector_abs,
+                                part[i].no_of_sectors_abs);
 #endif
-                       //else if (parttbl[i].system == 0x5)
-                       }
-                       else if (i == 1)
-                       {
-                               extent = (exttbls[i].start_sector_abs * 
SECSIZE);
-                               if (extent)
-                                       extent += old_extent;
-                       }
-               }
-               e_count ++;
-       }
-#ifdef DEBUG
-       printf("e_count = %ld\n", e_count);
-#endif
-       fail = 0;
+                       /* Convert end to a number.  */
+                       part[i].no_of_sectors_abs -=
+                               part[i].start_sector_abs - 1;
+               }
+               off += entry_size;
+       }
+               
+       fail = nbr_part;
 
 done:
        if (fd)
@@ -195,10 +211,115 @@ done:
        return fail;
 }
 
+/* Read an MBR entry.  */
+static void
+read_mbr_record (unsigned char pi[16], struct pentry *res)
+{
+       res->bootable = *pi; 
+       res->start_head  = *(pi + 1); 
+       res->start_cylinder = *(pi + 3) | ((*(pi + 2) << 2) & 0x300);
+       res->start_sector = *(pi + 2) & 0x3f;
+       res->system = *(pi + 4);
+       res->end_head = *(pi + 5);
+       res->end_cylinder = *(pi + 7) | ((*(pi + 6) << 2) & 0x300);
+       res->end_sector = *(pi + 6) & 0x3f;
+       res->start_sector_abs = read_le4 (&pi[8]);
+       res->no_of_sectors_abs = read_le4 (&pi[12]);
+}
+
+/* Returns the number of partitions, -1 in case of failure.  */
+int load_mbr(const char *diskimage, struct pentry *parttbl[])
+{
+       FILE *fd;
+       size_t size;
+       int fail = -1;
+       int nbr_part;
+       int i;
+       unsigned char *pi; 
+       unsigned char data [SECSIZE]; 
+       unsigned long long extent;
+       struct pentry *part;
+
+       nbr_part = 0;
+
+       fd = fopen(diskimage, "r");
+       if (fd == NULL)
+       {
+               perror(diskimage);
+               goto done;
+       }
+       size = fread (&data, 1, sizeof(data), fd);
+       if (size < (size_t)sizeof(data))
+       {
+               fprintf(stderr, "Could not read the entire first sector of 
%s.\n", diskimage);
+               goto done;
+       }
+
+       if (data [510] != 0x55 || data [511] != 0xaa)
+       {
+               fprintf(stderr,"MBR signature mismatch (invalid partition 
table?)\n");
+               goto done;
+       }
+
+       /* There is at most 4*4 + 4 = 20 entries, also there should be only
+          one extended partition.  */
+       part = malloc (20 * sizeof (struct pentry));
+       if (part == NULL)
+       {
+               fprintf(stderr,"Cannot allocate memory\n");
+               goto done;
+       }
+       *parttbl = part;
+
+       /* Read MBR.  */
+       nbr_part = 4;
+       for (i = 0; i < 4; i++)
+       {
+               pi = &data [446 + 16 * i];
+               read_mbr_record (pi, &part[i]);
+       }
+
+       /* Read extended partitions.  */
+       for (i = 0; i < 4; i++)
+       {
+               if (part[i].system == 0xF || part[i].system == 0x5)
+               {
+                       int j;
+
+                       extent = part[i].start_sector_abs * SECSIZE;
+
+                       fseeko (fd, extent, SEEK_SET);
+                       size = fread (&data, 1, sizeof(data), fd);
+                       if (size < (size_t)sizeof(data))
+                       {
+                               fprintf(stderr, "Could not read extended 
partition of %s.", diskimage);
+                               goto done;
+                       }
+
+                       for (j = 0; j < 4; j++)
+                       {
+                               int n;
+                               pi = &data [446 + 16 * j];
+                               n = nbr_part + j;
+                               read_mbr_record (pi, &part[n]);
+                       }
+
+                       nbr_part += 4;
+               }
+       }
+
+       fail = nbr_part;
+
+done:
+       if (fd)
+               fclose(fd);
+       return fail;
+}
+
 void usage(void)
 {
-       fprintf(stderr, "You must specify at least -diskimage and 
-partition.\n");
-       fprintf(stderr, "All other arguments are passed through to 'mount'.\n");
+       fprintf(stderr, "Usage: lomount [-verbose] [OPTIONS] -diskimage FILE 
-partition NUM [OPTIONS]\n");
+       fprintf(stderr, "All OPTIONS are passed through to 'mount'.\n");
        fprintf(stderr, "ex. lomount -t fs-type -diskimage hda.img -partition 1 
/mnt\n");
        exit(ERR_USAGE);
 }
@@ -206,14 +327,17 @@ int main(int argc, char ** argv)
 int main(int argc, char ** argv)
 {
        int status;
-       struct pentry perttbl [4];
-       struct pentry *exttbl[1], *parttbl;
+       int nbr_part;
+       struct pentry *parttbl;
        char buf[BUF], argv2[BUF];
-       const char * diskimage = 0;
-       int partition = 0, sec, num = 0, pnum = 0, i, valid;
+       const char * diskimage = NULL;
+       int partition = 0;
+       unsigned long long sec, num, pnum;
+       int i;
        size_t argv2_len = sizeof(argv2);
+       int verbose = 0;
+
        argv2[0] = '\0';
-       exttbl[0] = NULL;
 
        for (i = 1; i < argc; i ++)
        {
@@ -230,6 +354,10 @@ int main(int argc, char ** argv)
                                usage();
                        i++;
                        partition = atoi(argv[i]);
+               }
+               else if (strcmp(argv[i], "-verbose")==0)
+               {
+                       verbose++;
                }
                else
                {
@@ -241,59 +369,65 @@ int main(int argc, char ** argv)
                        len -= (len+1);
                }
        }
-       if (! diskimage || partition < 1)
+       if (! diskimage || partition < 0)
                usage();
 
-       if (loadptable(diskimage, perttbl, exttbl, &valid))
+       nbr_part = load_mbr(diskimage, &parttbl);
+       if (check_gpt (parttbl, nbr_part)) {
+               free (parttbl);
+               nbr_part = load_gpt (diskimage, &parttbl);
+       }
+       if (nbr_part < 0)
                return ERR_PART_PARSE;
-       if (!valid)
-       {
-               fprintf(stderr, "Warning: disk image does not appear to 
describe a valid partition table.\n");
+       if (partition == 0)
+       {
+               printf("Please specify a partition number.  Table is:\n");
+               printf("Num      Start -        End  OS Bootable\n");
+               for (i = 0; i < nbr_part; i++)
+               {
+                       if (parttbl[i].no_of_sectors_abs != 0)
+                       {
+                               printf ("%2d: ", i + 1);
+                               disp_entry (&parttbl[i]);
+                       }
+               }
+               if (partition == 0)
+                       return 0;
        }
        /* NOTE: need to make sure this always rounds down */
        //sec = total_known_sectors / sizeof_diskimage;
-/* The above doesn't work unless the disk image is completely filled by
-partitions ... unused space will thrown off the sector size. The calculation
-assumes the disk image is completely filled, and that the few sectors used
-to store the partition table/MBR are few enough that the calculated value is
-off by (larger than) a value less than one. */
+       /* The above doesn't work unless the disk image is completely
+          filled by partitions ... unused space will thrown off the
+          sector size. The calculation assumes the disk image is
+          completely filled, and that the few sectors used to store
+          the partition table/MBR are few enough that the calculated
+          value is off by (larger than) a value less than one. */
        sec = 512; /* TODO: calculate real sector size */
 #ifdef DEBUG
        printf("sec: %d\n", sec);
 #endif
-       if (partition > 4)
-       {
-               if (exttbl[0] == NULL)
-               {
-                   fprintf(stderr, "No extended partitions were found in 
%s.\n", diskimage);
-                   return ERR_NO_EPART;
-               }
-               parttbl = exttbl[0];
-               if (parttbl[partition-5].no_of_sectors_abs == 0)
-               {
-                       fprintf(stderr, "Partition %d was not found in %s.\n", 
partition, diskimage);
-                       return ERR_NO_PART;
-               }
-               partition -= 4;
-       }
-       else
-       {
-               parttbl = perttbl;
-               if (parttbl[partition-1].no_of_sectors_abs == 0)
-               {
-                       fprintf(stderr, "Partition %d was not found in %s.\n", 
partition, diskimage);
-                       return ERR_NO_PART;
-               }
+       if (partition > nbr_part)
+       {
+               fprintf(stderr, "Bad partition number\n");
+               return ERR_NO_EPART;
        }
        num = parttbl[partition-1].start_sector_abs;
+       if (num == 0)
+       {
+               fprintf(stderr, "Partition %d was not found in %s.\n",
+                       partition, diskimage);
+               return ERR_NO_PART;
+       }
+
        pnum = sec * num;
 #ifdef DEBUG
        printf("offset = %d\n", pnum);
 #endif
-       snprintf(buf, sizeof(buf), "mount -oloop,offset=%d %s %s", pnum, 
diskimage, argv2);
-#ifdef DEBUG
-       printf("%s\n", buf);
-#endif
+       snprintf(buf, sizeof(buf), "mount -oloop,offset=%lld %s %s",
+                pnum, diskimage, argv2);
+       if (verbose)
+               printf("%s\n", buf);
+
        status = system(buf);
        if (WIFEXITED(status))
                status = WEXITSTATUS(status);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] lomount: Major rewrite: handle large files and GPT partition., Xen patchbot-unstable <=