#include #include #include #include #include #include #include #include "chio.h" #define CHANGER "/dev/sch0" /* ---------------------------------------------------------------------- */ struct changer_params params; struct changer_vendor_params vparams; static int parse_arg(char *arg, int *type, int *nr) { char t; if (NULL == arg) return -1; if (2 != sscanf(arg,"%c%i",&t,nr)) return -1; switch (t) { case 'm': case 'M': *type = CHET_MT; break; case 's': case 'S': *type = CHET_ST; break; case 'e': case 'E': *type = CHET_IE; break; case 'd': case 'D': *type = CHET_DT; break; case 'v': case 'V': *type = CHET_V1; break; case 'w': case 'W': *type = CHET_V2; break; case 'x': case 'X': *type = CHET_V3; break; case 'y': case 'Y': *type = CHET_V4; break; default: return -1; } return 0; } static void print_stat(int fd, int type, int count) { struct changer_element_status ces; struct changer_get_element elinfo; int i,rc; switch (type) { case CHET_MT: printf("medium transport\n"); break; case CHET_ST: printf("storage\n"); break; case CHET_IE: printf("import/export\n"); break; case CHET_DT: printf("data transfer\n"); break; case CHET_V1: printf("vendor specific #1 [%s]\n",vparams.cvp_label1); break; case CHET_V2: printf("vendor specific #2 [%s]\n",vparams.cvp_label2); break; case CHET_V3: printf("vendor specific #3 [%s]\n",vparams.cvp_label3); break; case CHET_V4: printf("vendor specific #4 [%s]\n",vparams.cvp_label4); break; } ces.ces_type = type; ces.ces_data = malloc(count); rc = ioctl(fd,CHIOGSTATUS,&ces); if (rc) { fprintf(stderr,"ioctl failed (GSTATUS): %s\n",strerror(errno)); exit(1); } for (i = 0; i < count; i++) { printf(" %2d: ",i); if (ces.ces_data[i] & CESTATUS_INENAB) printf("inenab "); if (ces.ces_data[i] & CESTATUS_EXENAB) printf("exenab "); if (ces.ces_data[i] & CESTATUS_ACCESS) printf("access "); if (ces.ces_data[i] & CESTATUS_EXCEPT) printf("except "); if (ces.ces_data[i] & CESTATUS_IMPEXP) printf("impexp "); if (ces.ces_data[i] & CESTATUS_FULL) printf("full "); memset(&elinfo,0,sizeof(elinfo)); elinfo.cge_type = type; elinfo.cge_unit = i; rc = ioctl(fd,CHIOGELEM,&elinfo); if (rc) { fprintf(stderr,"ioctl failed (GELEM): %s\n",strerror(errno)); exit(1); } if (elinfo.cge_flags & CGE_PVOLTAG && strlen(elinfo.cge_pvoltag) > 0 ) { printf("\ttag: '%s'",elinfo.cge_pvoltag); } else if (ces.ces_data[i] & CESTATUS_FULL) printf("\t(no volume tag)"); printf("\n"); } free(ces.ces_data); } /* ---------------------------------------------------------------------- */ int main(int argc, char *argv[]) { char *changer; int fd,rc; if (!(changer = getenv("CHANGER"))) { changer = CHANGER; } if (-1 == (fd = open(changer,O_RDONLY))) { fprintf(stderr,"open %s: %s\n",changer,strerror(errno)); exit(1); } rc = ioctl(fd,CHIOGPARAMS,¶ms); if (rc) { fprintf(stderr,"ioctl failed (GPARAMS): %s\n",strerror(errno)); exit(1); } else { printf("%s: mt=%i st=%i ie=%i dt=%i\n", changer, params.cp_npickers,params.cp_nslots, params.cp_nportals,params.cp_ndrives); } rc = ioctl(fd,CHIOGVPARAMS,&vparams); if (rc) { fprintf(stderr,"ioctl failed (VPARAMS): %s\n",strerror(errno)); } else { if (vparams.cvp_n1) printf("%s: v1=%d [%s]\n",changer,vparams.cvp_n1,vparams.cvp_label1); if (vparams.cvp_n2) printf("%s: v2=%d [%s]\n",changer,vparams.cvp_n2,vparams.cvp_label2); if (vparams.cvp_n3) printf("%s: v3=%d [%s]\n",changer,vparams.cvp_n3,vparams.cvp_label3); if (vparams.cvp_n4) printf("%s: v4=%d [%s]\n",changer,vparams.cvp_n4,vparams.cvp_label4); } if (argc == 1 || 0 == strcasecmp(argv[1],"status")) { /* no args, so print some status informations */ print_stat(fd,CHET_MT,params.cp_npickers); print_stat(fd,CHET_ST,params.cp_nslots); print_stat(fd,CHET_IE,params.cp_nportals); print_stat(fd,CHET_DT,params.cp_ndrives); if (vparams.cvp_n1) print_stat(fd,CHET_V1,vparams.cvp_n1); if (vparams.cvp_n2) print_stat(fd,CHET_V2,vparams.cvp_n2); if (vparams.cvp_n3) print_stat(fd,CHET_V3,vparams.cvp_n3); if (vparams.cvp_n4) print_stat(fd,CHET_V4,vparams.cvp_n4); exit(0); } if (0 == strcasecmp(argv[1],"pos")) { struct changer_position pos; memset(&pos,0,sizeof(pos)); if (-1 == parse_arg(argv[2],&pos.cp_type,&pos.cp_unit)) { fprintf(stderr,"slot arg parse error (POSITION)\n"); exit(1); } if (argc > 3) pos.cp_flags = atoi(argv[3]); rc = ioctl(fd,CHIOPOSITION,&pos); if (rc) { fprintf(stderr,"ioctl failed (POSITION): %s\n", strerror(errno)); exit(1); } } else if (0 == strcasecmp(argv[1],"load") || 0 == strcasecmp(argv[1],"unload")) { struct changer_move move; memset(&move,0,sizeof(move)); if (0 == strcasecmp(argv[1],"load")) { move.cm_fromtype = CHET_ST; move.cm_fromunit = atoi(argv[2]); move.cm_totype = CHET_DT; move.cm_tounit = 0; } else { if (argc > 2) { move.cm_totype = CHET_ST; move.cm_tounit = atoi(argv[2]); } else { struct changer_get_element elinfo; memset(&elinfo,0,sizeof(elinfo)); elinfo.cge_type = CHET_DT; elinfo.cge_unit = 0; rc = ioctl(fd,CHIOGELEM,&elinfo); if (rc) { fprintf(stderr,"ioctl failed (GELEM): %s\n", strerror(errno)); exit(1); } if (!(elinfo.cge_flags & CGE_SRC)) { fprintf(stderr,"element source info not available\n"); exit(1); } move.cm_totype = elinfo.cge_srctype; move.cm_tounit = elinfo.cge_srcunit; if (elinfo.cge_flags & CGE_INVERT) move.cm_flags |= CE_INVERT1; } move.cm_fromtype = CHET_DT; move.cm_fromunit = 0; } rc = ioctl(fd,CHIOMOVE,&move); if (rc) { fprintf(stderr,"ioctl failed (MOVE): %s\n", strerror(errno)); exit(1); } } else if (0 == strcasecmp(argv[1],"mv")) { struct changer_move move; memset(&move,0,sizeof(move)); if (-1 == parse_arg(argv[2],&move.cm_fromtype,&move.cm_fromunit) || -1 == parse_arg(argv[3],&move.cm_totype, &move.cm_tounit )) { fprintf(stderr,"slot arg parse error (MOVE)\n"); exit(1); } if (argc > 4) move.cm_flags = atoi(argv[4]); rc = ioctl(fd,CHIOMOVE,&move); if (rc) { fprintf(stderr,"ioctl failed (MOVE): %s\n", strerror(errno)); exit(1); } } else if (0 == strcasecmp(argv[1],"ex")) { struct changer_exchange xchg; memset(&xchg,0,sizeof(xchg)); if (-1 == parse_arg(argv[2],&xchg.ce_srctype, &xchg.ce_srcunit ) || -1 == parse_arg(argv[3],&xchg.ce_fdsttype,&xchg.ce_fdstunit) || -1 == parse_arg(argv[4],&xchg.ce_sdsttype,&xchg.ce_sdstunit)) { fprintf(stderr,"slot arg parse error (EXCHANGE)\n"); exit(1); } if (argc > 5) xchg.ce_flags = atoi(argv[5]); rc = ioctl(fd,CHIOEXCHANGE,&xchg); if (rc) { fprintf(stderr,"ioctl failed (EXCHANGE): %s\n", strerror(errno)); exit(1); } } else if (0 == strcasecmp(argv[1],"info")) { struct changer_get_element elinfo; memset(&elinfo,0,sizeof(elinfo)); if (-1 == parse_arg(argv[2],&elinfo.cge_type, &elinfo.cge_unit)) { fprintf(stderr,"slot arg parse error (INFO)\n"); exit(1); } rc = ioctl(fd,CHIOGELEM,&elinfo); if (rc) { fprintf(stderr,"ioctl failed (INFO): %s\n", strerror(errno)); exit(1); } printf("status : "); if (elinfo.cge_status & CESTATUS_INENAB) printf("inenab "); if (elinfo.cge_status & CESTATUS_EXENAB) printf("exenab "); if (elinfo.cge_status & CESTATUS_ACCESS) printf("access "); if (elinfo.cge_status & CESTATUS_EXCEPT) printf("except "); if (elinfo.cge_status & CESTATUS_IMPEXP) printf("impexp "); if (elinfo.cge_status & CESTATUS_FULL) printf("full "); printf("\n"); if (elinfo.cge_flags & CGE_ERRNO) { printf("error : %s\n",strerror(elinfo.cge_errno)); } if (elinfo.cge_flags & CGE_SRC) { printf("source : "); switch (elinfo.cge_srctype) { case CHET_MT: printf("m"); break; case CHET_ST: printf("s"); break; case CHET_IE: printf("e"); break; case CHET_DT: printf("d"); break; case CHET_V1: printf("v"); break; case CHET_V2: printf("w"); break; case CHET_V3: printf("x"); break; case CHET_V4: printf("y"); break; } printf("%d",elinfo.cge_srcunit); if (elinfo.cge_flags & CGE_INVERT) printf(" (rotated)"); printf("\n"); } if (elinfo.cge_flags & CGE_IDLUN) { printf("scsi id : %d\n",elinfo.cge_id); printf("scsi lun: %d\n",elinfo.cge_lun); } if (elinfo.cge_flags & CGE_PVOLTAG) { printf("pvoltag : %32.32s\n",elinfo.cge_pvoltag); } if (elinfo.cge_flags & CGE_AVOLTAG) { printf("avoltag : %32.32s\n",elinfo.cge_avoltag); } } else if (0 == strcasecmp(argv[1],"init")) { rc = ioctl(fd,CHIOINITELEM,NULL); if (rc) { fprintf(stderr,"ioctl failed (INITELEM): %s\n", strerror(errno)); exit(1); } } else if (0 == strcasecmp(argv[1],"settag") || 0 == strcasecmp(argv[1],"cleartag")) { struct changer_set_voltag tag; memset(&tag,0,sizeof(tag)); if (-1 == parse_arg(argv[2],&tag.csv_type,&tag.csv_unit)) { fprintf(stderr,"slot arg parse error (SVOLTAG)\n"); exit(1); } if (argc <= 3) { fprintf(stderr,"no type (pri | alt) given\n"); exit(1); } if (0 == strcasecmp(argv[3],"pri")) tag.csv_flags |= CSV_PVOLTAG; if (0 == strcasecmp(argv[3],"alt")) tag.csv_flags |= CSV_AVOLTAG; if (0 == strcasecmp(argv[1],"cleartag")) { tag.csv_flags |= CSV_CLEARTAG; } else { if (argc <= 4) { fprintf(stderr,"no volume tag given\n"); exit(1); } strncpy(tag.csv_voltag,argv[4],32); } rc = ioctl(fd,CHIOSVOLTAG,&tag); if (rc) { fprintf(stderr,"ioctl failed (SVOLTAG): %s\n", strerror(errno)); exit(1); } } else { printf("%s: unknown argument\n",argv[1]); exit(1); } close(fd); exit(0); }