home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Utilities / vmount-0.6a-I / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-06  |  11.9 KB  |  491 lines

  1. /*
  2.  * Name: main.c
  3.  * Description: main() function and parameter parsing.
  4.  * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
  5.  * Date: 1996-11-14
  6.  * Copyright: GNU-GPL
  7.  * Tabsize: 4
  8.  */
  9.  
  10. #include <libc.h>
  11. #include <stdarg.h>
  12. #include <ctype.h>
  13. #include <syslog.h>
  14. #include <pwd.h>
  15. #include <grp.h>
  16. #include "my_defines.h"
  17.  
  18. extern void    nfs_program_2();
  19.  
  20. typedef struct partition {
  21.     unsigned char    boot_ind;        /* 0x80 - active */
  22.     unsigned char    head;            /* starting head */
  23.     unsigned char    sector;            /* starting sector */
  24.     unsigned char    cyl;            /* starting cylinder */
  25.     unsigned char    sys_ind;        /* What partition type */
  26.     unsigned char    end_head;        /* end head */
  27.     unsigned char    end_sector;        /* end sector */
  28.     unsigned char    end_cyl;        /* end cylinder */
  29.     unsigned char    start_sect[4];    /* starting sector counting from 0 */
  30.     unsigned char    nr_sects[4];    /* nr of sectors in partition */
  31. }partition_t;
  32.  
  33. typedef struct pinfo{
  34.     unsigned int    start_sect;
  35.     unsigned int    nr_sects;
  36.     unsigned char    sys_ind;
  37. }pinfo_t;
  38.  
  39. #define    SECTOR_SIZE        512    /* sector size on DOS partitioned disks */
  40. #define EXTENDED        5    /* id of extended partitions */
  41.  
  42.  
  43. /* ------------------------------------------------------------------------- */
  44.  
  45. char            *device_name;
  46. int                my_fd;
  47. int                wr_enable = 0;
  48. int                had_fatal = 0;
  49. int                probing_mode = 0;
  50. int                use_syslog = 0;
  51. unsigned long    part_offset = 0;
  52. unsigned long    part_size = 0xffffffffUL;
  53. int                debug_mode = 0;
  54. char            *my_name;
  55.  
  56. /* ------------------------------------------------------------------------- */
  57.  
  58. static void    vlogprintf(int level, const char *format, va_list vlist)
  59. {
  60. char    buffer[32768];    /* should we alloc a larger chunk of virtual mem? */
  61.  
  62.     if(!probing_mode){
  63.         if(use_syslog){
  64.             vsprintf(buffer, format, vlist);
  65.             syslog(level, "%s", buffer);
  66.         }else{
  67.             vfprintf(stderr, format, vlist);
  68.         }
  69.     }
  70. }
  71.  
  72. /* ------------------------------------------------------------------------- */
  73.  
  74. void    dprintf(const char *format, ...)
  75. {
  76. va_list        vlist;
  77.  
  78.     va_start(vlist, format);
  79.     vlogprintf(LOG_INFO, format, vlist);
  80.     va_end(vlist);
  81. }
  82.  
  83. /* ------------------------------------------------------------------------- */
  84.  
  85. void    eprintf(const char *format, ...)
  86. {
  87. va_list        vlist;
  88.  
  89.     va_start(vlist, format);
  90.     vlogprintf(LOG_ERR, format, vlist);
  91.     va_end(vlist);
  92. }
  93.  
  94. /* ------------------------------------------------------------------------- */
  95.  
  96. void    fatal_error(const char *format, ...)
  97. {
  98. va_list        vlist;
  99.  
  100.     if(!had_fatal){
  101.         if(wr_enable){
  102.             close(my_fd);    /* reopen read only */
  103.             my_fd = open(device_name, O_RDONLY);
  104.             wr_enable = 0;
  105.         }
  106.         va_start(vlist, format);
  107.         vlogprintf(LOG_ERR, format, vlist);
  108.         va_end(vlist);
  109.         had_fatal = 1;
  110.     }
  111. }
  112.  
  113. /* ------------------------------------------------------------------------- */
  114.  
  115. static inline unsigned    to_int(unsigned char *buf)
  116. {
  117. int        res;
  118.  
  119.     res = buf[0];
  120.     res |= (unsigned)buf[1] << 8;
  121.     res |= (unsigned)buf[2] << 16;
  122.     res |= (unsigned)buf[3] << 24;
  123.     return res;
  124. }
  125.  
  126. /* ------------------------------------------------------------------------- */
  127.  
  128. static void    print_part(partition_t *p, int i, unsigned offset)
  129. {
  130.     fprintf(stderr, "%c %s %d 0x%02x start/sec=0x%08x size/sec=0x%08x\n",
  131.         p->boot_ind ? '*' : ' ',
  132.         i < 4 ? "primary" : "logical",
  133.         i + 1,
  134.         p->sys_ind,
  135.         to_int(p->start_sect) + offset,
  136.         to_int(p->nr_sects));
  137. }
  138.  
  139. /* ------------------------------------------------------------------------- */
  140.  
  141. static pinfo_t    *get_part(int fd, unsigned *boot, unsigned offset, int *part_i, int info)
  142. {
  143. static pinfo_t    pinfo;
  144. char            buffer[SECTOR_SIZE];
  145. unsigned        my_boot = *boot;
  146. int                i;
  147. partition_t        *p;
  148.  
  149.     if(my_boot >= 0x00800000/SECTOR_SIZE * 512){
  150.         fprintf(stderr, "partition table at sector 0x%x outside 4GB limit\n",
  151.                                                                     my_boot);
  152.         fprintf(stderr, "aborting partition search.\n");
  153.         return NULL;
  154.     }
  155.     if (lseek(fd, my_boot * SECTOR_SIZE, 0) == -1){
  156.         perror("get_part() lseek()");
  157.         exit(1);
  158.     }
  159.     if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE){
  160.         perror("get_part() read()");
  161.         exit(1);
  162.     }
  163.     for(*boot=i=0;i<4;i++){
  164.         p = (struct partition *)(&buffer[0x1be] + i * sizeof(partition_t));
  165.         if(p->sys_ind == 0){
  166.             if(*part_i < 4)
  167.                 (*part_i)++;
  168.             continue;
  169.         }
  170.         if(p->sys_ind == EXTENDED){
  171.             if(*boot != 0){
  172.                 fprintf(stderr,
  173.                     "warning: one more extended partition in at index %d\n",
  174.                     *part_i);
  175.             }
  176.             *boot = to_int(p->start_sect) + offset;
  177.             if(*part_i < 4)
  178.                 (*part_i)++;
  179.         }else{
  180.             if(*part_i == info){
  181.                 pinfo.start_sect = to_int(p->start_sect) + my_boot;
  182.                 pinfo.nr_sects = to_int(p->nr_sects);
  183.                 pinfo.sys_ind = p->sys_ind;
  184.                 return &pinfo;
  185.             }
  186.             if(info < 0)
  187.                 print_part(p, *part_i, my_boot);
  188.             (*part_i)++;
  189.         }
  190.     }
  191.     return NULL;
  192. }
  193.  
  194. /* ------------------------------------------------------------------------- */
  195.  
  196. static pinfo_t    *partitions(int fd, int info)
  197. {
  198. unsigned    boot = 0, extbase;
  199. int            part_i;
  200. pinfo_t        *res;
  201.  
  202.     part_i = 0;
  203.     if((res = get_part(fd, &boot, 0, &part_i, info)) != NULL)
  204.         return res;
  205.     extbase = boot;
  206.     while(boot != 0){
  207.         if((res = get_part(fd, &boot, extbase, &part_i, info)) != NULL)
  208.             return res;
  209.     }
  210.     return NULL;
  211. }
  212.  
  213. /* ------------------------------------------------------------------------- */
  214.  
  215. static void    print_valid_filesystems(int part, char *fs)
  216. {
  217. char    *p;
  218.  
  219.     while((p = strtok(fs, " ")) != NULL){
  220.         fs = NULL;
  221.         printf("%d/%s: -%c%d -t%s\n", part, p, part == 0 ? 'f' : 'p', part, p);
  222.     }
  223. }
  224.  
  225. /* ------------------------------------------------------------------------- */
  226.  
  227. static void    dump_info(int offset, int size, int part, int small_buffers)
  228. {
  229. pinfo_t        *p;
  230. int            i;
  231. char        *fsys;
  232.  
  233.     missing_init();
  234.     buffer_initialize(small_buffers);
  235.     fops_init();
  236.     probing_mode = 1;
  237.     if(offset == -1){
  238.         if(part == -1){
  239.             for(i=0;i<100;i++){
  240.                 p = partitions(my_fd, i);
  241.                 if(p == NULL){
  242.                     if(i < 4)
  243.                         continue;
  244.                     else
  245.                         break;
  246.                 }
  247.                 buffer_invalidate();
  248.                 part_offset = p->start_sect * SECTOR_SIZE;
  249.                 part_size = p->nr_sects * SECTOR_SIZE;
  250.                 dummies_init(device_name, SECTOR_SIZE, SECTOR_SIZE, part_size);
  251.                 fsys = valid_filesystems();
  252.                 if(fsys[0] != 0)
  253.                     print_valid_filesystems(i+1, fsys);
  254.             }
  255.         }else{
  256.             if((p = partitions(my_fd, part-1)) != NULL){
  257.                 buffer_invalidate();
  258.                 part_offset = p->start_sect * SECTOR_SIZE;
  259.                 part_size = p->nr_sects * SECTOR_SIZE;
  260.                 dummies_init(device_name, SECTOR_SIZE, SECTOR_SIZE, part_size);
  261.                 fsys = valid_filesystems();
  262.                 if(fsys[0] != 0)
  263.                     print_valid_filesystems(part, fsys);
  264.             }
  265.         }
  266.     }else{
  267.         buffer_invalidate();
  268.         part_offset = offset;
  269.         part_size = size;
  270.         dummies_init(device_name, SECTOR_SIZE, SECTOR_SIZE, part_size);
  271.         fsys = valid_filesystems();
  272.         if(fsys[0] != 0)
  273.             print_valid_filesystems(0, fsys);
  274.     }
  275.     probing_mode = 0;
  276.     exit(0);    /* must not continue after this kind of initialisation */
  277. }
  278.  
  279. /* ------------------------------------------------------------------------- */
  280.  
  281. static void    print_help(char *name)
  282. {
  283.     fprintf(stderr, "Usage: %s [-i] -m<mount-point> -t<fs-type> [-f<offset> | -p<partition>]\n", name);
  284.     fprintf(stderr, "\t\t[-s<partition-size>] [-w] [-o<options>] [-d<debug-mode>] [-v]\n");
  285.     fprintf(stderr, "\t\t[-U<fixed-userid>] [-G<fixed-groupid>] [-S]\n");
  286.     fprintf(stderr, "\t\t[-u <uid-translation-file>] [-g <gid-translation-file>] device\n");
  287.     fprintf(stderr, "-w .... mount filesystem read/write (default: read only)\n");
  288.     fprintf(stderr, "-i .... print partitioning and filesystem info\n");
  289.     fprintf(stderr, "-S .... use small cache buffers\n");
  290.     fprintf(stderr, "-v .... print version info and exit\n");
  291. }
  292.  
  293. /* ------------------------------------------------------------------------- */
  294.  
  295. static void    print_version(char *name)
  296. {
  297.     fprintf(stderr, "%s: Version 0.6a (1997-06-06)\n", name);
  298.     exit(0);
  299. }
  300.  
  301. /* ------------------------------------------------------------------------- */
  302.  
  303. int    main(int argc, char **argv)
  304. {
  305. char            print_info = 0, read_only = 1, err = 0, *fs_name = NULL;
  306. char            *name = NULL, *mountpoint = NULL, *mount_options = NULL;
  307. int                c, part = -1, go_background = 1, use_small_buffer = 0;
  308. long            offset = -1, size = -1;
  309. char            mountpoint_abs[MAXPATHLEN + 1], *mtab_options = "";
  310. struct passwd    *pwd;
  311. struct group    *grp;
  312. extern char        *optarg;
  313. extern int        optind;
  314. static char        root_fh[32] = {0};
  315.  
  316.     my_name = argv[0];
  317.     openlog(my_name, LOG_PID, LOG_DAEMON);
  318.     while ((c = getopt(argc, argv, "Svo:O:t:d:t:him:f:p:s:wu:g:U:G:")) != EOF){
  319.         switch(c){
  320.         case 'i':
  321.             print_info = 1;
  322.             break;
  323.         case 'm':
  324.             mountpoint = optarg;
  325.             break;
  326.         case 'f':
  327.             offset = strtol(optarg, NULL, 0);
  328.             break;
  329.         case 'p':
  330.             part = atoi(optarg);
  331.             break;
  332.         case 's':
  333.             size = strtol(optarg, NULL, 0);
  334.             break;
  335.         case 'w':
  336.             read_only = 0;
  337.             break;
  338.         case 'h':
  339.             err = 1;
  340.             break;
  341.         case 'o':
  342.             mount_options = optarg;
  343.             break;
  344.         case 'O':
  345.             mtab_options = optarg;
  346.             break;
  347.         case 'd':
  348.             debug_mode = strtol(optarg, NULL, 0);
  349.             go_background = 0;
  350.             break;
  351.         case 't':
  352.             fs_name = optarg;
  353.             break;
  354.         case 'u':
  355.             load_translationfile(IDBUF_USR, optarg);
  356.             break;
  357.         case 'g':
  358.             load_translationfile(IDBUF_GRP, optarg);
  359.             break;
  360.         case 'U':
  361.             if(isdigit(optarg[0])){
  362.                 set_fixed_id(IDBUF_USR, atoi(optarg));
  363.             }else{
  364.                 pwd = getpwnam(optarg);
  365.                 if(pwd == NULL){
  366.                     eprintf("Unknown user: %s\n", optarg);
  367.                     exit(1);
  368.                 }
  369.                 set_fixed_id(IDBUF_USR, pwd->pw_uid);
  370.                 set_fixed_id(IDBUF_GRP, pwd->pw_gid);
  371.             }
  372.             break;
  373.         case 'G':
  374.             if(isdigit(optarg[0])){
  375.                 set_fixed_id(IDBUF_GRP, atoi(optarg));
  376.             }else{
  377.                 grp = getgrnam(optarg);
  378.                 if(grp == NULL){
  379.                     eprintf("Unknown group: %s\n", optarg);
  380.                     exit(1);
  381.                 }
  382.                 set_fixed_id(IDBUF_GRP, grp->gr_gid);
  383.             }
  384.             break;
  385.         case 'v':
  386.             print_version(argv[0]);
  387.             break;
  388.         case 'S':
  389.             use_small_buffer = 1;
  390.             break;
  391.         default:
  392.             err = 1;
  393.             fprintf(stderr, "unknown option -%c\n", c);
  394.             break;
  395.         }
  396.     }
  397.     if(err){
  398.         print_help(argv[0]);
  399.         exit(1);
  400.     }
  401.     while(optind < argc){
  402.         if(name == NULL)
  403.             name = argv[optind];
  404.         else{
  405.             fprintf(stderr, "trailing superflous parameter ->%s<- ignored\n",
  406.                                                             argv[optind]);
  407.         }
  408.         optind++;
  409.     }
  410.     if(name == NULL){
  411.         fprintf(stderr, "No device specified\n");
  412.         exit(1);
  413.     }
  414.     device_name = name;
  415.     dprintf("mounting read%s\n",(wr_enable = !read_only)!=0 ?"/write":" only");
  416.     my_fd = open(name, wr_enable ? O_RDWR : O_RDONLY);
  417.     if(my_fd < 0){
  418.         perror("error opening device");
  419.         exit(1);
  420.     }
  421.     if(print_info){        /* print partition tables */
  422.         if(offset == -1)
  423.             partitions(my_fd, -1);
  424.         dump_info(offset, size, part, use_small_buffer);
  425.         close(my_fd);
  426.         exit(0);
  427.     }
  428.     if(fs_name == NULL){
  429.         fprintf(stderr, "Option -t is mandatory\n");
  430.         exit(1);
  431.     }
  432.     if(mountpoint == NULL){
  433.         fprintf(stderr, "Option -m is mandatory!\n");
  434.         exit(1);
  435.     }
  436.     if(offset != -1 && part != -1){
  437.         fprintf(stderr, "Options -f and -p are exclusive!\n");
  438.         exit(1);
  439.     }
  440.     if(part != -1){
  441.         pinfo_t    *p;
  442.         if(part < 1){
  443.             fprintf(stderr, "Partition number is %d (< 1).\n", part);
  444.             fprintf(stderr,"Partitions are counted from 1 in this version.\n");
  445.             exit(1);
  446.         }
  447.         if((p = partitions(my_fd, part - 1)) == NULL){
  448.             fprintf(stderr, "Partition %d does not exist on %s.\n", part,name);
  449.             fprintf(stderr, "Use -i option to display partition table.\n");
  450.             exit(1);
  451.         }
  452.         if(p->start_sect >= 0x00800000/SECTOR_SIZE*512
  453.             || (p->start_sect + p->nr_sects) >= 0x00800000/SECTOR_SIZE*512){
  454.             fprintf(stderr, "Partition %d reaches out of 4GB limit\n", part);
  455.             exit(1);
  456.         }
  457.         part_offset = p->start_sect * SECTOR_SIZE;
  458.         part_size = p->nr_sects * SECTOR_SIZE;
  459.     }else{
  460.         if(offset != -1)
  461.             part_offset = offset;
  462.         if(size != -1)
  463.             part_size = size;
  464.     }
  465.     missing_init();
  466.     buffer_initialize(use_small_buffer);
  467.     dummies_init(name, 512, 512, part_size);
  468.     fops_init();
  469.     if(my_mount(fs_name, wr_enable ? 0 : MNT_RONLY,
  470.                                     mount_options, (int *)root_fh) != 0){
  471.         close(my_fd);
  472.         exit(1);
  473.     }
  474.     if(*mountpoint == '/'){        /* absolute path given? */
  475.         strcpy(mountpoint_abs, mountpoint);
  476.     }else{
  477.         if(getwd(mountpoint_abs) == NULL){
  478.             mountpoint_abs[0] = 0;
  479.         }else{
  480.             strcat(mountpoint_abs, "/");
  481.         }
  482.         strcat(mountpoint_abs, mountpoint);
  483.     }
  484.     mount_and_dispatch(mountpoint_abs, nfs_program_2, root_fh, go_background,
  485.                                                             mtab_options);
  486.     close(my_fd);
  487.     return 0;
  488. }
  489.  
  490. /* ------------------------------------------------------------------------- */
  491.