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.