"Fossies" - the Fresh Open Source Software Archive

Member "scsiadd-1.97/scsiadd.c" (16 Jun 2009, 7513 Bytes) of package /linux/misc/old/scsiadd-1.97.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "scsiadd.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2   scsiadd - add/remove scsi devices from the linux scsi subsystem
    3   ----------------------------------------------------------------
    4   Copyright (C) 2000..2009 by Dirk Jagdmann <doj@cubic.org>
    5 
    6   This program is free software; you can redistribute it and/or
    7   modify it under the terms of the GNU General Public License
    8   as published by the Free Software Foundation; either version 2
    9   of the License, or (at your option) any later version.
   10 
   11   This program is distributed in the hope that it will be useful,
   12   but WITHOUT ANY WARRANTY; without even the implied warranty of
   13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14   GNU General Public License for more details.
   15 
   16   You should have received a copy of the GNU General Public License
   17   along with this program; if not, write to the Free Software
   18   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   19 */
   20 
   21 #include <errno.h>
   22 #include <fcntl.h>
   23 #include <stdio.h>
   24 #include <stdlib.h>
   25 #include <string.h>
   26 #include <sys/stat.h>
   27 #include <sys/types.h>
   28 #include <unistd.h>
   29 
   30 //#define DEBUG
   31 
   32 /// maximum SCSI ID which is scanned
   33 static int maxid = 15;
   34 
   35 /// the modes in which the program should operate
   36 typedef enum
   37   {
   38     SINGLE,
   39     SCAN
   40   } scsiaddmode_t;
   41 
   42 /// action the program should commit
   43 typedef enum
   44   {
   45     ADD,
   46     REMOVE
   47   } scsiaddaction_t;
   48 
   49 /// print the help message and terminate program
   50 static void help()
   51 {
   52   printf(
   53      "scsiadd " VER " - add and remove devices from the scsi subsystem\n"
   54      "---------------------------------------------------------------\n"
   55      "syntax: scsiadd {-a|-r} <id>\n"
   56      "        scsiadd {-a|-r} <id> <lun>\n"
   57      "        scsiadd {-a|-r} <host> <id> <lun>\n"
   58      "        scsiadd {-a|-r} <host> <channel> <id> <lun>\n"
   59      "        scsiadd [-i maxid] -s <host>\n"
   60      "        scsiadd [-i maxid] -s <host> <channel>\n"
   61          "        scsiadd -p\n"
   62      "parameters not given are assumed 0\n"
   63      "-a: add a device (default if no command given)\n"
   64      "-r: remove device\n"
   65      "-s: scan for devices\n"
   66          "-p: print scsi status\n"
   67          "-h: print this help message\n"
   68          "-i: maximum SCSI ID which is scanned\n"
   69          "\nhttp://llg.cubic.org/tools - ftp://ftp.cubic.org/pub/llg\n"
   70      );
   71 
   72   exit(1);
   73 }
   74 
   75 /**
   76     check if the calling user is root. If not try to make the program run as root.
   77     If program can not be made root, terminate.
   78 */
   79 void becomeRoot()
   80 {
   81   uid_t me;
   82 
   83   me = getuid();
   84   if(me!=0)
   85     {
   86 #ifdef DEBUG
   87       fprintf(stderr, "Aha, I am not root. Therefore I will now try to become root\n");
   88 #endif
   89       if(geteuid()!=0)
   90     {
   91       fprintf(stderr,
   92           "I can not become root. scsiadd was most likely started by a normal user.\n"
   93           "If you want to make this program suid root use make install-suidroot when\n"
   94           "installing or (as root) type: chmod +s %s\n",
   95           PATH
   96           );
   97       exit(1);
   98     }
   99       setuid(0);
  100     }
  101 }
  102 
  103 /**
  104     perform the command to add/remove a scsi device.
  105     @param action action that will be performed. currently supported are ADD and REMOVE.
  106     @param host host number
  107     @param channel channel number
  108     @param id id number
  109     @param lun lun number
  110     @return 0 on success. -1 on error
  111 */
  112 static int scsiadd(const scsiaddaction_t action,
  113            const int host,
  114            const int channel,
  115            const int id,
  116            const int lun)
  117 {
  118   char *actionstr, buf[128];
  119   int fd, len, ret=0, w;
  120 
  121   switch(action)
  122     {
  123     case ADD:
  124       actionstr="add";
  125       break;
  126     case REMOVE:
  127       actionstr="remove";
  128       break;
  129     default:
  130       fprintf(stderr, "scsiadd:scsiadd(): oops, action error\n");
  131       return -1;
  132     }
  133 
  134   snprintf(buf, sizeof(buf), "scsi %s-single-device %i %i %i %i\n", actionstr, host, channel, id, lun);
  135   len=strlen(buf);
  136 
  137   fd=open("/proc/scsi/scsi", O_WRONLY);
  138   if(fd < 0)
  139     {
  140       perror("scsiadd:scsiadd(): could not open /proc/scsi/scsi (w)");
  141       return -1;
  142     }
  143 
  144   errno=0;
  145   w=write(fd, buf, len);
  146   /* check if the command did not succeed */
  147   if(errno && w != len)
  148     {
  149       /* ignore errors in IDs > 8 and EINVAL, which are triggered in scan mode on adapters not support Wide adressing */
  150       if(!(id>=9 && errno==EINVAL))
  151     {
  152       fprintf(stderr, "could not %s device %i %i %i %i : %s\n", actionstr, host, channel, id, lun, strerror(errno));
  153       ret=-1;
  154     }
  155     }
  156 
  157   if(close(fd) < 0)
  158     {
  159 #ifdef DEBUG
  160       perror("scsiadd:scsiadd():could not close /proc/scsi/scsi (w)");
  161 #endif
  162     }
  163 
  164   return ret;
  165 }
  166 
  167 /**
  168     prints the contents of /proc/scsi/scsi to output stream
  169     @param os the Output Stream
  170     @return 0 on success. -1 on error
  171 */
  172 static int scsidump(FILE *os)
  173 {
  174   FILE *f=0;
  175 
  176   if(os==NULL)
  177     return -1;
  178 
  179   f=fopen("/proc/scsi/scsi", "r");
  180   if(f == NULL)
  181     {
  182       perror("scsiadd:scsidump():could not open /proc/scsi/scsi (r)");
  183       return -1;
  184     }
  185 
  186   while(!feof(f))
  187     {
  188       char buf[129];
  189       int i=fread(buf, 1, sizeof(buf)-1, f);
  190       buf[i]=0;
  191       fprintf(os, "%s", buf);
  192     }
  193 
  194   if(fclose(f) < 0)
  195     {
  196 #ifdef DEBUG
  197       perror("scsiadd:scsidump():could not close /proc/scsi/scsi (r)");
  198 #endif
  199     }
  200 
  201   return 0;
  202 }
  203 
  204 static int full_atoi(const char *str)
  205 {
  206   char *end = NULL;
  207   int ret;
  208 
  209   errno = 0;
  210   ret = strtol(str, &end, 10);
  211   if(errno || end == str || *end)
  212     {
  213       fprintf(stderr, "scsiadd: not a valid number: %s\n", str);
  214       exit(1);
  215     }
  216 
  217   return ret;
  218 }
  219 
  220 /**
  221    main function.
  222    @param argc number of command line items
  223    @param argv pointer to command line items
  224    @return 0 on success. 1 on error
  225 */
  226 int main(int argc, char **argv)
  227 {
  228   int host=0, channel=0, id=0, lun=0;
  229   scsiaddmode_t scanmode=SINGLE;
  230   scsiaddaction_t mode=ADD;
  231   int ret=0;
  232   int c=0;
  233   int i=0;
  234 
  235   // parse command line
  236   while((c=getopt(argc, argv, "ahi:prs"))!=EOF)
  237     {
  238       switch(c)
  239     {
  240     case 'a': mode=ADD; break;
  241     case 'p': scsidump(stdout); return 0;
  242     case 'r': mode=REMOVE; break;
  243     case 's': scanmode=SCAN; break;
  244     case 'i':
  245       if(optarg==NULL) break;
  246       maxid=strtol(optarg, NULL, 0);
  247       if(maxid<0)
  248         {
  249           fprintf(stderr, "error: max SCSI ID < 0\n");
  250           return 1;
  251         }
  252       break;
  253     case '?':
  254     case 'h':
  255     default: help();
  256     }
  257     }
  258 
  259   // convert the supplied numbers
  260   switch(scanmode)
  261     {
  262     case SINGLE:
  263       switch(argc-optind)
  264     {
  265     case 1:
  266       id=full_atoi(argv[optind]);
  267       break;
  268     case 2:
  269       id=full_atoi(argv[optind]);
  270       lun=full_atoi(argv[optind+1]);
  271       break;
  272     case 3:
  273       host=full_atoi(argv[optind]);
  274       id=full_atoi(argv[optind+1]);
  275       lun=full_atoi(argv[optind+2]);
  276       break;
  277     case 4:
  278       host=full_atoi(argv[optind]);
  279       channel=full_atoi(argv[optind+1]);
  280       id=full_atoi(argv[optind+2]);
  281       lun=full_atoi(argv[optind+3]);
  282       break;
  283     default:
  284       help();
  285     }
  286       break;
  287     case SCAN:
  288       switch(argc-optind)
  289     {
  290     case 1:
  291       host=full_atoi(argv[optind]);
  292       break;
  293     case 2:
  294       host=full_atoi(argv[optind]);
  295       channel=full_atoi(argv[optind+1]);
  296       break;
  297     }
  298       break;
  299     default:
  300       fprintf(stderr, "scsiadd: oops! scanmode error.\n");
  301       return 1;
  302     }
  303 
  304 #ifdef DEBUG
  305   printf("command args: %i %i %i %i %i\n", mode, host, channel, id, lun);
  306 #endif
  307 
  308   becomeRoot();
  309 
  310   switch(scanmode)
  311     {
  312     case SINGLE:
  313       ret=scsiadd(mode, host, channel, id, lun);
  314       break;
  315     case SCAN:
  316       for(i=0; i<maxid; i++)
  317     {
  318 #ifdef DEBUG
  319       printf("scan: %i %i %i %i %i\n", mode, host, channel, id, lun);
  320 #endif
  321       ret=scsiadd(mode, host, channel, i, lun);
  322     }
  323       break;
  324     default:
  325       fprintf(stderr, "scsiadd: oops! scanmode error\n");
  326       return 1;
  327     }
  328 
  329   if(ret>=0)
  330     ret=scsidump(stdout);
  331 
  332   return -ret;
  333 }