home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / mtools_3.6.src.lzh / MTOOLS_3.6 / mzip.c < prev    next >
Text File  |  1997-11-12  |  8KB  |  347 lines

  1. /*
  2.  * mzip.c
  3.  * Iomega Zip/Jaz drive tool
  4.  * change protection mode and eject disk
  5.  */
  6.  
  7. /* mzip.c by Markus Gyger <mgyger@itr.ch> */
  8. /* This code is based on ftp://gear.torque.net/pub/ziptool.c */
  9. /* by Grant R. Guenther with the following copyright notice: */
  10.  
  11. /*  (c) 1996   Grant R. Guenther,  based on work of Itai Nahshon  */
  12. /*  http://www.torque.net/ziptool.html  */
  13.  
  14. #include "sysincludes.h"
  15. #include "mtools.h"
  16. #include "scsi.h"
  17.  
  18. #ifndef _PASSWORD_LEN
  19. #define _PASSWORD_LEN 33
  20. #endif
  21.  
  22. #ifdef linux
  23. #include <linux/fs.h>
  24. #endif
  25.  
  26. static void usage(void)
  27. {
  28.     fprintf(stderr, 
  29.         "Mtools version %s, dated %s\n", 
  30.         mversion, mdate);
  31.     fprintf(stderr, 
  32.         "Usage: %s [-V] [-q] [-e] [-r|-w|-p|-x] [drive:]\n"
  33.         "\t-q print status\n"
  34.         "\t-e eject disk\n"
  35.         "\t-f eject disk even when mounted\n"
  36.         "\t-r write protected (read-only)\n"
  37.         "\t-w not write-protected (read-write)\n"
  38.         "\t-p password write protected\n"
  39.         "\t-x password protected\n", 
  40.         progname);
  41.     exit(1);
  42. }
  43.  
  44.  
  45. static int get_zip_status(int fd)
  46. {
  47.     unsigned char status[128];
  48.     unsigned char cdb[6] = { 0x06, 0, 0x02, 0, sizeof status, 0 };
  49.     
  50.     if (scsi_cmd(fd, cdb, 6, SCSI_IO_READ, 
  51.              status, sizeof status) == -1) {
  52.         perror("status: ");
  53.         exit(1);
  54.     }
  55.     return status[21] & 0xf;
  56. }
  57.  
  58.  
  59. static int short_command(int fd, int cmd1, int cmd2, int cmd3, char *data)
  60. {
  61.     unsigned char cdb[6] = { 0, 0, 0, 0, 0, 0 };
  62.  
  63.     cdb[0] = cmd1;
  64.     cdb[1] = cmd2;
  65.     cdb[4] = cmd3;
  66.  
  67.     return scsi_cmd(fd, cdb, 6, SCSI_IO_WRITE, 
  68.             data, data ? strlen(data) : 0);
  69. }
  70.  
  71.  
  72. static int iomega_command(int fd, int mode, char *data)
  73. {
  74.     return short_command(fd, 
  75.                  SCSI_IOMEGA, mode, data ? strlen(data) : 0,
  76.                  data);
  77. }
  78.  
  79. static int door_command(int fd, int cmd1, int cmd2)
  80. {
  81.     return short_command(fd, cmd1, 0, cmd2, 0);
  82. }
  83.  
  84. void mzip(int argc, char **argv, int type)
  85. {
  86.     int c;
  87.     char drive;
  88.     device_t *dev;
  89.     int fd = -1;
  90.     char name[EXPAND_BUF];
  91.     enum { ZIP_NIX    =      0,
  92.            ZIP_STATUS = 1 << 0,
  93.            ZIP_EJECT  = 1 << 1,
  94.            ZIP_RW     = 1 << 2,
  95.            ZIP_RO     = 1 << 3,
  96.            ZIP_RO_PW  = 1 << 4,
  97.            ZIP_PW     = 1 << 5,
  98.            ZIP_FORCE  = 1 << 6
  99.     } request = ZIP_NIX;
  100.     
  101.     /* get command line options */
  102.     while ((c = getopt(argc, argv, "efpqrwx")) != EOF) {
  103.         switch (c) {
  104.             case 'f':
  105.                 request |= ZIP_FORCE;
  106.                 break;
  107.             case 'e': /* eject */
  108.                 request |= ZIP_EJECT;
  109.                 break;
  110.             case 'p': /* password read-only */
  111.                 request |= ZIP_RO_PW;
  112.                 break;
  113.             case 'q': /* status query */
  114.                 request |= ZIP_STATUS;
  115.                 break;
  116.             case 'r': /* read-only */
  117.                 request |= ZIP_RO;
  118.                 break;
  119.             case 'w': /* read-write */
  120.                 request |= ZIP_RW;
  121.                 break;
  122.             case 'x': /* password protected */
  123.                 request |= ZIP_PW;
  124.                 break;
  125.             default:  /* unrecognized */
  126.                 usage();
  127.         }
  128.     }
  129.     
  130.     if (request == ZIP_NIX) request = ZIP_STATUS;  /* default action */
  131.  
  132.     if(!!(request & ZIP_RW) + !!(request & ZIP_RO) +
  133.        !!(request & ZIP_RO_PW) + !!(request & ZIP_PW) > 1)
  134.         usage();
  135.     
  136.     if (argc - optind > 1 || 
  137.         (argc - optind == 1 &&
  138.          (!argv[optind][0] || argv[optind][1] != ':')))
  139.         usage();
  140.     
  141.     drive = toupper(argc - optind == 1 ? argv[argc - 1][0] : 'a');
  142.     
  143.     for (dev = devices; dev->name; dev++) {
  144.         unsigned char cdb[6] = { 0, 0, 0, 0, 0, 0 };
  145.         struct {
  146.             char    type,
  147.                 type_modifier,
  148.                 scsi_version,
  149.                 data_format,
  150.                 length,
  151.                 reserved1[2],
  152.                 capabilities,
  153.                 vendor[8],
  154.                 product[16],
  155.                 revision[4],
  156.                 vendor_specific[20],
  157.                 reserved2[40];
  158.         } inq_data;
  159.  
  160.         if (dev->drive != drive) 
  161.             continue;
  162.         expand(dev->name, name);
  163.         precmd(dev);
  164.  
  165.         if(dev->privileged)
  166.             reclaim_privs();
  167.         fd = open(name, O_RDONLY | dev->mode); 
  168.         if(dev->privileged)
  169.             drop_privs();
  170.  
  171.         /* need readonly, else we can't
  172.          * open the drive on Solaris if
  173.          * write-protected */        
  174.         if (fd == -1) 
  175.             continue;
  176.         closeExec(fd);
  177.  
  178.  
  179.         if (!(request & (ZIP_RW | ZIP_RO | ZIP_RO_PW | 
  180.                  ZIP_PW | ZIP_STATUS)))
  181.             /* if no mode change or ZIP specific status is
  182.              * involved, the command (eject) is applicable
  183.              * on all drives */
  184.             break;
  185.  
  186.         cdb[0] = SCSI_INQUIRY;
  187.         cdb[4] = sizeof inq_data;
  188.         if (scsi_cmd(fd, cdb, 6, SCSI_IO_READ, 
  189.                  &inq_data, sizeof inq_data) != 0) {
  190.             close(fd);
  191.             continue;
  192.         }
  193.         
  194. #ifdef DEBUG
  195.         fprintf(stderr, "device: %s\n\tvendor: %.8s\n\tproduct: %.16s\n"
  196.             "\trevision: %.4s\n", name, inq_data.vendor,
  197.             inq_data.product, inq_data.revision);
  198. #endif /* DEBUG */
  199.         
  200.         if (strncasecmp("IOMEGA  ", inq_data.vendor, 
  201.                 sizeof inq_data.vendor) ||
  202.             (strncasecmp("ZIP 100         ", 
  203.                  inq_data.product, sizeof inq_data.product) &&
  204.              strncasecmp("JAZ 1GB         ", 
  205.                  inq_data.product, sizeof inq_data.product))) {
  206.             
  207.             /* debugging */
  208.             fprintf(stderr,"Skipping drive with vendor='");
  209.             fwrite(inq_data.vendor,1, sizeof(inq_data.vendor), 
  210.                    stderr);
  211.             fprintf(stderr,"' product='");
  212.             fwrite(inq_data.product,1, sizeof(inq_data.product), 
  213.                    stderr);
  214.             fprintf(stderr,"'\n");
  215.             /* end debugging */
  216.             close(fd);
  217.             continue;
  218.         }
  219.         break;  /* found Zip/Jaz drive */
  220.     }
  221.     
  222.     if (dev->drive == 0) {
  223.         fprintf(stderr, "%s: drive '%c:' is not a Zip or Jaz drive\n",
  224.             argv[0], drive);
  225.         exit(1);
  226.     }
  227.     
  228.     if (request & (ZIP_RW | ZIP_RO | ZIP_RO_PW | ZIP_PW)) {
  229.         int ret;
  230.         char *passwd, dummy[1];
  231.         int newmode;
  232.         
  233.         if (get_zip_status(fd) & 0x01) {  /* unlock first */
  234.             char *s, *passwd;
  235.             passwd = getpass("Password: ");
  236.             if ((s = strchr(passwd, '\n'))) *s = '\0';  /* chomp */
  237.             if((ret=iomega_command(fd, 0, passwd))){
  238.                 if (ret == -1) perror("passwd: ");
  239.                 else fprintf(stderr, "wrong password\n");
  240.                 exit(1);
  241.             }
  242.             if(get_zip_status(fd) & 0x01) {
  243.                 fprintf(stderr, "wrong password\n");
  244.                 exit(1);
  245.             }
  246.         }
  247.         
  248.         if (request & (ZIP_RO_PW | ZIP_PW)) {            
  249.             char first_try[_PASSWORD_LEN];
  250.             
  251.             passwd = getpass("Enter new password:");
  252.             strncpy(first_try, passwd,_PASSWORD_LEN);
  253.             passwd = getpass("Re-type new password:");
  254.             if(strncmp(first_try, passwd, _PASSWORD_LEN)) {
  255.                 fprintf(stderr,
  256.                     "You mispelled it. Password not set.\n");
  257.                 exit(1);
  258.             }
  259.         } else {
  260.             passwd = dummy;
  261.             dummy[0] = '\0';
  262.         }
  263.             
  264.         switch (request & 
  265.             (ZIP_RW | ZIP_RO | ZIP_RO_PW | ZIP_PW)) {
  266.             case ZIP_RW:    
  267.                 newmode = 0x00;
  268.                 break;
  269.             case ZIP_RO:   
  270.                 newmode = 0x02;
  271.                 break;
  272.             case ZIP_RO_PW:
  273.                 newmode = 0x03;
  274.                 break;
  275.             case ZIP_PW:  
  276.                 newmode = 0x05;
  277.                 break;
  278.             default:
  279.                 newmode = 0;
  280.                 break;
  281.         }
  282.             
  283.         if((ret=iomega_command(fd, newmode, passwd))){
  284.             if (ret == -1) perror("set passwd: ");
  285.             else fprintf(stderr, "password not changed\n");
  286.             exit(1);
  287.         }
  288. #ifdef linux
  289.         ioctl(fd, BLKRRPART); /* revalidate the disk, so that the
  290.                      kernel notices that its writable
  291.                      status has changed */
  292. #endif
  293.     }
  294.     
  295.     if (request & ZIP_STATUS) {
  296.         int status;
  297.         
  298.         switch (status = get_zip_status(fd)) {
  299.             case 0:  
  300.                 printf("Drive '%c:' is not write-protected\n", 
  301.                        drive);
  302.                 break;
  303.             case 2:
  304.                 printf("Drive '%c:' is write-protected\n",
  305.                        drive);
  306.                 break;
  307.             case 3: 
  308.                 printf("Drive '%c:' is password write-protected\n", 
  309.                        drive);
  310.                 break;
  311.             case 5:  
  312.                 printf("Drive '%c:' is password protected\n", 
  313.                        drive);
  314.                 break;
  315.             default: 
  316.                 printf("Unknown protection mode %d of drive '%c:'\n",
  317.                        status, drive);
  318.                 break;                
  319.         }        
  320.     }
  321.     
  322.     if (request & ZIP_EJECT) {
  323.         if(request & ZIP_FORCE)
  324.             if(door_command(fd, SCSI_ALLOW_MEDIUM_REMOVAL, 0) < 0) {
  325.                 perror("door unlock: ");
  326.                 exit(1);
  327.             }
  328.  
  329.         if(door_command(fd, SCSI_START_STOP, 1) < 0) {
  330.             perror("stop motor: ");
  331.             exit(1);
  332.         }
  333.  
  334.         if(door_command(fd, SCSI_START_STOP, 2) < 0) {
  335.             perror("eject: ");
  336.             exit(1);
  337.         }
  338.         if(door_command(fd, SCSI_START_STOP, 2) < 0) {
  339.             perror("second eject: ");
  340.             exit(1);
  341.         }
  342.     }
  343.     
  344.     close(fd);
  345.     exit(0);
  346. }
  347.