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.