ia64/xen-unstable

changeset 9111:dfa7ba9c1296

Many fixes and cleanups for lomount:
- Fixed several overflows, off-by-one, and uninitialized variables.
- Added well-defined exit codes.
- Proper handling of system()'s return value.
- Errors parsing partition table cause it to stop now.
- etcetera...

Tested on 32 and 64 bit, with valgrind, with physical disks and disk
images.

Signed-off-by: Charles Coffing <ccoffing@novell.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Mar 02 21:35:17 2006 +0100 (2006-03-02)
parents fd102a15436f
children 316fafc6d743
files tools/misc/lomount/lomount.c
line diff
     1.1 --- a/tools/misc/lomount/lomount.c	Thu Mar 02 21:34:16 2006 +0100
     1.2 +++ b/tools/misc/lomount/lomount.c	Thu Mar 02 21:35:17 2006 +0100
     1.3 @@ -24,16 +24,33 @@
     1.4   * THE SOFTWARE.
     1.5   */
     1.6  
     1.7 +/*
     1.8 + *  Return code:
     1.9 + *
    1.10 + *  bit 7 set:		lomount wrapper failed
    1.11 + *  bit 7 clear:	lomount wrapper ok; mount's return code in low 7 bits
    1.12 + *  0			success
    1.13 + */
    1.14 +
    1.15 +enum
    1.16 +{
    1.17 +	ERR_USAGE = 0x80,	// Incorrect usage
    1.18 +	ERR_PART_PARSE,		// Failed to parse partition table
    1.19 +	ERR_NO_PART,		// No such partition
    1.20 +	ERR_NO_EPART,		// No such extended partition
    1.21 +	ERR_MOUNT		// Other failure of mount command
    1.22 +};
    1.23 +
    1.24  #include <unistd.h>
    1.25  #include <stdio.h>
    1.26  #include <stdlib.h>
    1.27  #include <string.h>
    1.28  #include <strings.h>
    1.29 +#include <sys/wait.h>
    1.30  #include <errno.h>
    1.31  
    1.32  #define BUF 4096
    1.33  
    1.34 -//#define SECSIZE 4096    /* arbitrarilly large (it's probably just 512) */
    1.35  #define SECSIZE 512
    1.36  
    1.37  struct pentry 
    1.38 @@ -50,30 +67,32 @@ struct pentry
    1.39  	unsigned long no_of_sectors_abs;
    1.40  };
    1.41  
    1.42 -char * progname;
    1.43 -
    1.44 -int loadptable(const char *argv, struct pentry parttbl[], struct pentry **exttbl)
    1.45 +int loadptable(const char *diskimage, struct pentry parttbl[], struct pentry **exttbl, int * valid)
    1.46  {
    1.47 -	FILE *fd; 
    1.48 -	int i, valid, total_known_sectors = 0;
    1.49 +	FILE *fd;
    1.50 +	size_t size;
    1.51 +	int fail = 1;
    1.52 +	int i, total_known_sectors = 0;
    1.53  	unsigned char *pi; 
    1.54  	unsigned char data [SECSIZE]; 
    1.55  	unsigned long extent = 0, old_extent = 0, e_count = 1;
    1.56  	struct pentry exttbls[4];
    1.57  
    1.58 -	fd = fopen(argv, "r");
    1.59 +	*valid = 0;
    1.60 +
    1.61 +	fd = fopen(diskimage, "r");
    1.62  	if (fd == NULL)
    1.63  	{
    1.64 -		perror ("lomount"); 
    1.65 -		return 1;
    1.66 +		perror(diskimage);
    1.67 +		goto done;
    1.68  	}
    1.69 -	i = fread (&data, 1, sizeof (data), fd); 
    1.70 -	if (i < SECSIZE)
    1.71 +	size = fread (&data, 1, sizeof(data), fd);
    1.72 +	if (size < (size_t)sizeof(data))
    1.73  	{
    1.74 -		fprintf (stderr, "%s: could not read the entire first sector\n", progname); 
    1.75 -		return 1;
    1.76 +		fprintf(stderr, "Could not read the entire first sector of %s.\n", diskimage);
    1.77 +		goto done;
    1.78  	}
    1.79 -	for (i = 0;i < 4;i++)
    1.80 +	for (i = 0; i < 4; i++)
    1.81  	{
    1.82  		pi = &data [446 + 16 * i];
    1.83  		parttbl [i].bootable = *pi; 
    1.84 @@ -95,7 +114,7 @@ int loadptable(const char *argv, struct 
    1.85  			old_extent = extent;
    1.86  		}
    1.87  	}
    1.88 -	valid = (data [510] == 0x55 && data [511] == 0xaa) ? 1 : 0;
    1.89 +	*valid = (data [510] == 0x55 && data [511] == 0xaa) ? 1 : 0;
    1.90  	for (i = 0; i < 4; i++)
    1.91  	{
    1.92  		total_known_sectors += parttbl[i].no_of_sectors_abs;
    1.93 @@ -105,7 +124,7 @@ int loadptable(const char *argv, struct 
    1.94  #ifdef DEBUG
    1.95  	if (extent != 0)
    1.96  	{
    1.97 -		printf("extended partition detected at offset %d\n", extent);
    1.98 +		printf("extended partition detected at offset %ld\n", extent);
    1.99  	}
   1.100  #endif
   1.101  	while (extent != 0)
   1.102 @@ -113,14 +132,14 @@ int loadptable(const char *argv, struct 
   1.103  /* according to realloc(3) passing NULL as pointer is same as calling malloc() */
   1.104  		exttbl[0] = realloc(exttbl[0], e_count * sizeof(struct pentry));
   1.105  		fseek(fd, extent, SEEK_SET);
   1.106 -		i = fread (&data, 1, sizeof (data), fd); 
   1.107 -		if (i < SECSIZE)
   1.108 +		size = fread (&data, 1, sizeof(data), fd);
   1.109 +		if (size < (size_t)sizeof(data))
   1.110  		{
   1.111 -			fprintf (stderr, "%s: could not read the entire first sector\n", progname); 
   1.112 -			return 1;
   1.113 +			fprintf(stderr, "Could not read extended partition of %s.", diskimage);
   1.114 +			goto done;
   1.115  		}
   1.116  	/* only first 2 entrys are used in extented partition tables */
   1.117 -		for (i = 0;i < 2;i++)
   1.118 +		for (i = 0; i < 2; i++)
   1.119  		{
   1.120  			pi = &data [446 + 16 * i];
   1.121  			exttbls [i].bootable = *pi; 
   1.122 @@ -152,7 +171,7 @@ int loadptable(const char *argv, struct 
   1.123  			/* adjust for start of image instead of start of ext partition */
   1.124  				exttbl[0][e_count-1].start_sector_abs += (extent/SECSIZE);
   1.125  #ifdef DEBUG
   1.126 -				printf("extent %d start_sector_abs %d\n", extent, exttbl[0][e_count-1].start_sector_abs);
   1.127 +				printf("extent %ld start_sector_abs %ld\n", extent, exttbl[0][e_count-1].start_sector_abs);
   1.128  #endif
   1.129  			//else if (parttbl[i].system == 0x5)
   1.130  			}
   1.131 @@ -165,53 +184,71 @@ int loadptable(const char *argv, struct 
   1.132  		}
   1.133  		e_count ++;
   1.134  	}
   1.135 -	//fclose (fd);
   1.136 -	//the above segfaults (?!!!)
   1.137  #ifdef DEBUG
   1.138 -	printf("e_count = %d\n", e_count);
   1.139 +	printf("e_count = %ld\n", e_count);
   1.140  #endif
   1.141 -	return valid;
   1.142 +	fail = 0;
   1.143 +
   1.144 +done:
   1.145 +	if (fd)
   1.146 +		fclose(fd);
   1.147 +	return fail;
   1.148 +}
   1.149 +
   1.150 +void usage()
   1.151 +{
   1.152 +	fprintf(stderr, "You must specify at least -diskimage and -partition.\n");
   1.153 +	fprintf(stderr, "All other arguments are passed through to 'mount'.\n");
   1.154 +	fprintf(stderr, "ex. lomount -t fs-type -diskimage hda.img -partition 1 /mnt\n");
   1.155 +	exit(ERR_USAGE);
   1.156  }
   1.157  
   1.158  int main(int argc, char ** argv)
   1.159  {
   1.160 +	int status;
   1.161  	struct pentry perttbl [4];
   1.162  	struct pentry *exttbl[1], *parttbl;
   1.163 -	char buf[BUF], argv2[BUF], diskimage[BUF];
   1.164 -	int partition = 1, sec, num = 0, pnum = 0, len = BUF, i, f = 0, valid;
   1.165 -	progname = argv[0];
   1.166 +	char buf[BUF], argv2[BUF];
   1.167 +	const char * diskimage = 0;
   1.168 +	int partition = 0, sec, num = 0, pnum = 0, i, valid;
   1.169 +	size_t argv2_len = sizeof(argv2);
   1.170 +	argv2[0] = '\0';
   1.171  	exttbl[0] = NULL;
   1.172 +
   1.173  	for (i = 1; i < argc; i ++)
   1.174  	{
   1.175 -		if (strncmp(argv[i], "-diskimage", BUF)==0)
   1.176 +		if (strcmp(argv[i], "-diskimage")==0)
   1.177  		{
   1.178 -			strncpy(diskimage, argv[i+1], BUF);
   1.179 -			i++; f = 1;
   1.180 +			if (i == argc-1)
   1.181 +				usage();
   1.182 +			i++;
   1.183 +			diskimage = argv[i];
   1.184  		}
   1.185 -		else if (strncmp(argv[i], "-partition", BUF)==0)
   1.186 +		else if (strcmp(argv[i], "-partition")==0)
   1.187  		{
   1.188 -			partition = atoi(argv[i+1]);
   1.189 +			if (i == argc-1)
   1.190 +				usage();
   1.191  			i++;
   1.192 -			if (partition < 1) partition = 1;
   1.193 +			partition = atoi(argv[i]);
   1.194  		}
   1.195  		else
   1.196  		{
   1.197 -			strncat(argv2, argv[i], len);
   1.198 -			strncat(argv2, " ", len-1);
   1.199 -			len -= strlen(argv[i]);
   1.200 -			len--;
   1.201 +			size_t len = strlen(argv[i]);
   1.202 +			if (len >= argv2_len-1)
   1.203 +				usage();
   1.204 +			strcat(argv2, argv[i]);
   1.205 +			strcat(argv2, " ");
   1.206 +			len -= (len+1);
   1.207  		}
   1.208  	}
   1.209 -	if (!f)
   1.210 -	{
   1.211 -		printf("You must specify -diskimage and -partition\n");
   1.212 -		printf("ex. lomount -t fs-type -diskimage hda.img -partition 1 /mnt\n");
   1.213 -		return 0;
   1.214 -	}
   1.215 -	valid = loadptable(diskimage, perttbl, exttbl);
   1.216 +	if (! diskimage || partition < 1)
   1.217 +		usage();
   1.218 +
   1.219 +	if (loadptable(diskimage, perttbl, exttbl, &valid))
   1.220 +		return ERR_PART_PARSE;
   1.221  	if (!valid)
   1.222  	{
   1.223 -		printf("Warning: disk image does not appear to describe a valid partition table.\n");
   1.224 +		fprintf(stderr, "Warning: disk image does not appear to describe a valid partition table.\n");
   1.225  	}
   1.226  	/* NOTE: need to make sure this always rounds down */
   1.227  	//sec = total_known_sectors / sizeof_diskimage;
   1.228 @@ -228,14 +265,14 @@ off by (larger than) a value less than o
   1.229  	{
   1.230  		if (exttbl[0] == NULL)
   1.231  		{
   1.232 -		    printf("No extended partitions were found in %s.\n", diskimage);
   1.233 -		    return 2;
   1.234 +		    fprintf(stderr, "No extended partitions were found in %s.\n", diskimage);
   1.235 +		    return ERR_NO_EPART;
   1.236  		}
   1.237  		parttbl = exttbl[0];
   1.238  		if (parttbl[partition-5].no_of_sectors_abs == 0)
   1.239  		{
   1.240 -			printf("Partition %d was not found in %s.\n", partition, diskimage);
   1.241 -			return 3;
   1.242 +			fprintf(stderr, "Partition %d was not found in %s.\n", partition, diskimage);
   1.243 +			return ERR_NO_PART;
   1.244  		}
   1.245  		partition -= 4;
   1.246  	}
   1.247 @@ -244,8 +281,8 @@ off by (larger than) a value less than o
   1.248  		parttbl = perttbl;
   1.249  		if (parttbl[partition-1].no_of_sectors_abs == 0)
   1.250  		{
   1.251 -			printf("Partition %d was not found in %s.\n", partition, diskimage);
   1.252 -			return 3;
   1.253 +			fprintf(stderr, "Partition %d was not found in %s.\n", partition, diskimage);
   1.254 +			return ERR_NO_PART;
   1.255  		}
   1.256  	}
   1.257  	num = parttbl[partition-1].start_sector_abs;
   1.258 @@ -253,10 +290,14 @@ off by (larger than) a value less than o
   1.259  #ifdef DEBUG
   1.260  	printf("offset = %d\n", pnum);
   1.261  #endif
   1.262 -	snprintf(buf, BUF, "mount -oloop,offset=%d %s %s", pnum, diskimage, argv2);
   1.263 +	snprintf(buf, sizeof(buf), "mount -oloop,offset=%d %s %s", pnum, diskimage, argv2);
   1.264  #ifdef DEBUG
   1.265  	printf("%s\n", buf);
   1.266  #endif
   1.267 -	system(buf);
   1.268 -	return 0;
   1.269 +	status = system(buf);
   1.270 +	if (WIFEXITED(status))
   1.271 +		status = WEXITSTATUS(status);
   1.272 +	else
   1.273 +		status = ERR_MOUNT;
   1.274 +	return status;
   1.275  }