ftp.nice.ch/pub/next/unix/disk/vmount.0.6a.s.tar.gz#/vmount.0.6a.s/main.c

This is main.c in view mode; [Download] [Up]

/*
 * Name: main.c
 * Description: main() function and parameter parsing.
 * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
 * Date: 1996-11-14
 * Copyright: GNU-GPL
 * Tabsize: 4
 */

#include <libc.h>
#include <stdarg.h>
#include <ctype.h>
#include <syslog.h>
#include <pwd.h>
#include <grp.h>
#include "my_defines.h"

extern void	nfs_program_2();

typedef struct partition {
	unsigned char	boot_ind;		/* 0x80 - active */
	unsigned char	head;			/* starting head */
	unsigned char	sector;			/* starting sector */
	unsigned char	cyl;			/* starting cylinder */
	unsigned char	sys_ind;		/* What partition type */
	unsigned char	end_head;		/* end head */
	unsigned char	end_sector;		/* end sector */
	unsigned char	end_cyl;		/* end cylinder */
	unsigned char	start_sect[4];	/* starting sector counting from 0 */
	unsigned char	nr_sects[4];	/* nr of sectors in partition */
}partition_t;

typedef struct pinfo{
	unsigned int	start_sect;
	unsigned int	nr_sects;
	unsigned char	sys_ind;
}pinfo_t;

#define	SECTOR_SIZE		512	/* sector size on DOS partitioned disks */
#define EXTENDED		5	/* id of extended partitions */


/* ------------------------------------------------------------------------- */

char			*device_name;
int				my_fd;
int				wr_enable = 0;
int				had_fatal = 0;
int				probing_mode = 0;
int				use_syslog = 0;
unsigned long	part_offset = 0;
unsigned long	part_size = 0xffffffffUL;
int				debug_mode = 0;
char			*my_name;

/* ------------------------------------------------------------------------- */

static void	vlogprintf(int level, const char *format, va_list vlist)
{
char	buffer[32768];	/* should we alloc a larger chunk of virtual mem? */

	if(!probing_mode){
		if(use_syslog){
			vsprintf(buffer, format, vlist);
			syslog(level, "%s", buffer);
		}else{
			vfprintf(stderr, format, vlist);
		}
	}
}

/* ------------------------------------------------------------------------- */

void	dprintf(const char *format, ...)
{
va_list		vlist;

	va_start(vlist, format);
	vlogprintf(LOG_INFO, format, vlist);
	va_end(vlist);
}

/* ------------------------------------------------------------------------- */

void	eprintf(const char *format, ...)
{
va_list		vlist;

	va_start(vlist, format);
	vlogprintf(LOG_ERR, format, vlist);
	va_end(vlist);
}

/* ------------------------------------------------------------------------- */

void	fatal_error(const char *format, ...)
{
va_list		vlist;

	if(!had_fatal){
		if(wr_enable){
			close(my_fd);	/* reopen read only */
			my_fd = open(device_name, O_RDONLY);
			wr_enable = 0;
		}
		va_start(vlist, format);
		vlogprintf(LOG_ERR, format, vlist);
		va_end(vlist);
		had_fatal = 1;
	}
}

/* ------------------------------------------------------------------------- */

static inline unsigned	to_int(unsigned char *buf)
{
int		res;

	res = buf[0];
	res |= (unsigned)buf[1] << 8;
	res |= (unsigned)buf[2] << 16;
	res |= (unsigned)buf[3] << 24;
	return res;
}

/* ------------------------------------------------------------------------- */

static void	print_part(partition_t *p, int i, unsigned offset)
{
	fprintf(stderr, "%c %s %d 0x%02x start/sec=0x%08x size/sec=0x%08x\n",
		p->boot_ind ? '*' : ' ',
		i < 4 ? "primary" : "logical",
		i + 1,
		p->sys_ind,
		to_int(p->start_sect) + offset,
		to_int(p->nr_sects));
}

/* ------------------------------------------------------------------------- */

static pinfo_t	*get_part(int fd, unsigned *boot, unsigned offset, int *part_i, int info)
{
static pinfo_t	pinfo;
char			buffer[SECTOR_SIZE];
unsigned		my_boot = *boot;
int				i;
partition_t		*p;

	if(my_boot >= 0x00800000/SECTOR_SIZE * 512){
		fprintf(stderr, "partition table at sector 0x%x outside 4GB limit\n",
																	my_boot);
		fprintf(stderr, "aborting partition search.\n");
		return NULL;
	}
	if (lseek(fd, my_boot * SECTOR_SIZE, 0) == -1){
		perror("get_part() lseek()");
		exit(1);
	}
	if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE){
		perror("get_part() read()");
		exit(1);
	}
	for(*boot=i=0;i<4;i++){
		p = (struct partition *)(&buffer[0x1be] + i * sizeof(partition_t));
		if(p->sys_ind == 0){
			if(*part_i < 4)
				(*part_i)++;
			continue;
		}
		if(p->sys_ind == EXTENDED){
			if(*boot != 0){
				fprintf(stderr,
					"warning: one more extended partition in at index %d\n",
					*part_i);
			}
			*boot = to_int(p->start_sect) + offset;
			if(*part_i < 4)
				(*part_i)++;
		}else{
			if(*part_i == info){
				pinfo.start_sect = to_int(p->start_sect) + my_boot;
				pinfo.nr_sects = to_int(p->nr_sects);
				pinfo.sys_ind = p->sys_ind;
				return &pinfo;
			}
			if(info < 0)
				print_part(p, *part_i, my_boot);
			(*part_i)++;
		}
	}
	return NULL;
}

/* ------------------------------------------------------------------------- */

static pinfo_t	*partitions(int fd, int info)
{
unsigned	boot = 0, extbase;
int			part_i;
pinfo_t		*res;

	part_i = 0;
	if((res = get_part(fd, &boot, 0, &part_i, info)) != NULL)
		return res;
	extbase = boot;
	while(boot != 0){
		if((res = get_part(fd, &boot, extbase, &part_i, info)) != NULL)
			return res;
	}
	return NULL;
}

/* ------------------------------------------------------------------------- */

static void	print_valid_filesystems(int part, char *fs)
{
char	*p;

	while((p = strtok(fs, " ")) != NULL){
		fs = NULL;
		printf("%d/%s: -%c%d -t%s\n", part, p, part == 0 ? 'f' : 'p', part, p);
	}
}

/* ------------------------------------------------------------------------- */

static void	dump_info(int offset, int size, int part, int small_buffers)
{
pinfo_t		*p;
int			i;
char		*fsys;

	missing_init();
	buffer_initialize(small_buffers);
	fops_init();
	probing_mode = 1;
	if(offset == -1){
		if(part == -1){
			for(i=0;i<100;i++){
				p = partitions(my_fd, i);
				if(p == NULL){
					if(i < 4)
						continue;
					else
						break;
				}
				buffer_invalidate();
				part_offset = p->start_sect * SECTOR_SIZE;
				part_size = p->nr_sects * SECTOR_SIZE;
				dummies_init(device_name, SECTOR_SIZE, SECTOR_SIZE, part_size);
				fsys = valid_filesystems();
				if(fsys[0] != 0)
					print_valid_filesystems(i+1, fsys);
			}
		}else{
			if((p = partitions(my_fd, part-1)) != NULL){
				buffer_invalidate();
				part_offset = p->start_sect * SECTOR_SIZE;
				part_size = p->nr_sects * SECTOR_SIZE;
				dummies_init(device_name, SECTOR_SIZE, SECTOR_SIZE, part_size);
				fsys = valid_filesystems();
				if(fsys[0] != 0)
					print_valid_filesystems(part, fsys);
			}
		}
	}else{
		buffer_invalidate();
		part_offset = offset;
		part_size = size;
		dummies_init(device_name, SECTOR_SIZE, SECTOR_SIZE, part_size);
		fsys = valid_filesystems();
		if(fsys[0] != 0)
			print_valid_filesystems(0, fsys);
	}
	probing_mode = 0;
	exit(0);	/* must not continue after this kind of initialisation */
}

/* ------------------------------------------------------------------------- */

static void	print_help(char *name)
{
	fprintf(stderr, "Usage: %s [-i] -m<mount-point> -t<fs-type> [-f<offset> | -p<partition>]\n", name);
	fprintf(stderr, "\t\t[-s<partition-size>] [-w] [-o<options>] [-d<debug-mode>] [-v]\n");
	fprintf(stderr, "\t\t[-U<fixed-userid>] [-G<fixed-groupid>] [-S]\n");
	fprintf(stderr, "\t\t[-u <uid-translation-file>] [-g <gid-translation-file>] device\n");
	fprintf(stderr, "-w .... mount filesystem read/write (default: read only)\n");
	fprintf(stderr, "-i .... print partitioning and filesystem info\n");
	fprintf(stderr, "-S .... use small cache buffers\n");
	fprintf(stderr, "-v .... print version info and exit\n");
}

/* ------------------------------------------------------------------------- */

static void	print_version(char *name)
{
	fprintf(stderr, "%s: Version 0.6a (1997-06-06)\n", name);
	exit(0);
}

/* ------------------------------------------------------------------------- */

int	main(int argc, char **argv)
{
char			print_info = 0, read_only = 1, err = 0, *fs_name = NULL;
char			*name = NULL, *mountpoint = NULL, *mount_options = NULL;
int				c, part = -1, go_background = 1, use_small_buffer = 0;
long			offset = -1, size = -1;
char			mountpoint_abs[MAXPATHLEN + 1], *mtab_options = "";
struct passwd	*pwd;
struct group	*grp;
extern char		*optarg;
extern int		optind;
static char		root_fh[32] = {0};

	my_name = argv[0];
	openlog(my_name, LOG_PID, LOG_DAEMON);
	while ((c = getopt(argc, argv, "Svo:O:t:d:t:him:f:p:s:wu:g:U:G:")) != EOF){
		switch(c){
		case 'i':
			print_info = 1;
			break;
		case 'm':
			mountpoint = optarg;
			break;
		case 'f':
			offset = strtol(optarg, NULL, 0);
			break;
		case 'p':
			part = atoi(optarg);
			break;
		case 's':
			size = strtol(optarg, NULL, 0);
			break;
		case 'w':
			read_only = 0;
			break;
		case 'h':
			err = 1;
			break;
		case 'o':
			mount_options = optarg;
			break;
		case 'O':
			mtab_options = optarg;
			break;
		case 'd':
			debug_mode = strtol(optarg, NULL, 0);
			go_background = 0;
			break;
		case 't':
			fs_name = optarg;
			break;
		case 'u':
			load_translationfile(IDBUF_USR, optarg);
			break;
		case 'g':
			load_translationfile(IDBUF_GRP, optarg);
			break;
		case 'U':
			if(isdigit(optarg[0])){
				set_fixed_id(IDBUF_USR, atoi(optarg));
			}else{
				pwd = getpwnam(optarg);
				if(pwd == NULL){
					eprintf("Unknown user: %s\n", optarg);
					exit(1);
				}
				set_fixed_id(IDBUF_USR, pwd->pw_uid);
				set_fixed_id(IDBUF_GRP, pwd->pw_gid);
			}
			break;
		case 'G':
			if(isdigit(optarg[0])){
				set_fixed_id(IDBUF_GRP, atoi(optarg));
			}else{
				grp = getgrnam(optarg);
				if(grp == NULL){
					eprintf("Unknown group: %s\n", optarg);
					exit(1);
				}
				set_fixed_id(IDBUF_GRP, grp->gr_gid);
			}
			break;
		case 'v':
			print_version(argv[0]);
			break;
		case 'S':
			use_small_buffer = 1;
			break;
		default:
			err = 1;
			fprintf(stderr, "unknown option -%c\n", c);
			break;
		}
	}
	if(err){
		print_help(argv[0]);
		exit(1);
	}
	while(optind < argc){
		if(name == NULL)
			name = argv[optind];
		else{
			fprintf(stderr, "trailing superflous parameter ->%s<- ignored\n",
															argv[optind]);
		}
		optind++;
	}
	if(name == NULL){
		fprintf(stderr, "No device specified\n");
		exit(1);
	}
	device_name = name;
	dprintf("mounting read%s\n",(wr_enable = !read_only)!=0 ?"/write":" only");
	my_fd = open(name, wr_enable ? O_RDWR : O_RDONLY);
	if(my_fd < 0){
		perror("error opening device");
		exit(1);
	}
	if(print_info){		/* print partition tables */
		if(offset == -1)
			partitions(my_fd, -1);
		dump_info(offset, size, part, use_small_buffer);
		close(my_fd);
		exit(0);
	}
	if(fs_name == NULL){
		fprintf(stderr, "Option -t is mandatory\n");
		exit(1);
	}
	if(mountpoint == NULL){
		fprintf(stderr, "Option -m is mandatory!\n");
		exit(1);
	}
	if(offset != -1 && part != -1){
		fprintf(stderr, "Options -f and -p are exclusive!\n");
		exit(1);
	}
	if(part != -1){
		pinfo_t	*p;
		if(part < 1){
			fprintf(stderr, "Partition number is %d (< 1).\n", part);
			fprintf(stderr,"Partitions are counted from 1 in this version.\n");
			exit(1);
		}
		if((p = partitions(my_fd, part - 1)) == NULL){
			fprintf(stderr, "Partition %d does not exist on %s.\n", part,name);
			fprintf(stderr, "Use -i option to display partition table.\n");
			exit(1);
		}
		if(p->start_sect >= 0x00800000/SECTOR_SIZE*512
			|| (p->start_sect + p->nr_sects) >= 0x00800000/SECTOR_SIZE*512){
			fprintf(stderr, "Partition %d reaches out of 4GB limit\n", part);
			exit(1);
		}
		part_offset = p->start_sect * SECTOR_SIZE;
		part_size = p->nr_sects * SECTOR_SIZE;
	}else{
		if(offset != -1)
			part_offset = offset;
		if(size != -1)
			part_size = size;
	}
	missing_init();
	buffer_initialize(use_small_buffer);
	dummies_init(name, 512, 512, part_size);
	fops_init();
	if(my_mount(fs_name, wr_enable ? 0 : MNT_RONLY,
									mount_options, (int *)root_fh) != 0){
		close(my_fd);
		exit(1);
	}
	if(*mountpoint == '/'){		/* absolute path given? */
		strcpy(mountpoint_abs, mountpoint);
	}else{
		if(getwd(mountpoint_abs) == NULL){
			mountpoint_abs[0] = 0;
		}else{
			strcat(mountpoint_abs, "/");
		}
		strcat(mountpoint_abs, mountpoint);
	}
	mount_and_dispatch(mountpoint_abs, nfs_program_2, root_fh, go_background,
															mtab_options);
	close(my_fd);
	return 0;
}

/* ------------------------------------------------------------------------- */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.