diff options
Diffstat (limited to 'mover.c')
-rw-r--r-- | mover.c | 367 |
1 files changed, 367 insertions, 0 deletions
@@ -0,0 +1,367 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/ioctl.h> + +#include "chio.h" + +#define CHANGER "/dev/sch0" + +/* ---------------------------------------------------------------------- */ + +struct changer_params params; +struct changer_vendor_params vparams; + +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[]) +{ + int fd,rc; + + if (-1 == (fd = open(CHANGER,O_RDONLY))) { + perror("open"); + exit(1); + } + + rc = ioctl(fd,CHIOGPARAMS,¶ms); + if (rc) { + fprintf(stderr,"ioctl failed (GPARAMS): %s\n",strerror(errno)); + exit(1); + } else { + printf(CHANGER ": mt=%i st=%i ie=%i dt=%i\n", + 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(CHANGER ": v1=%d [%s]\n",vparams.cvp_n1,vparams.cvp_label1); + if (vparams.cvp_n2) + printf(CHANGER ": v2=%d [%s]\n",vparams.cvp_n2,vparams.cvp_label2); + if (vparams.cvp_n3) + printf(CHANGER ": v3=%d [%s]\n",vparams.cvp_n3,vparams.cvp_label3); + if (vparams.cvp_n4) + printf(CHANGER ": v4=%d [%s]\n",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); +} |