diff options
author | kraxel <kraxel> | 2005-02-09 11:34:37 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2005-02-09 11:34:37 +0000 |
commit | 73671a2f4f0e6e03a509ff5a97ab70d7b0db12b1 (patch) | |
tree | d0099f50705e45392d9666c0aaa64bd69fc18b32 /autojuke.c | |
parent | 92a99fec1e7c0c05568a3abd647c9ae781acbd2f (diff) | |
download | scsi-changer-73671a2f4f0e6e03a509ff5a97ab70d7b0db12b1.tar.gz |
- add files to repository.
Diffstat (limited to 'autojuke.c')
-rw-r--r-- | autojuke.c | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/autojuke.c b/autojuke.c new file mode 100644 index 0000000..c27f135 --- /dev/null +++ b/autojuke.c @@ -0,0 +1,344 @@ +/* + * program "map-file" for linux autofs + * + * usage: /usr/sbin/automount /jukebox program /usr/sbin/autojuke + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <ctype.h> +#include <signal.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <asm/types.h> +#include <linux/cdrom.h> + +#include "chio.h" + +#define PROG "autojuke" +#define CHANGER "/dev/sch0" +#define CONFIG "/etc/autojuke.conf" + +#define DEBUG 0 /* set to 1 for debug output */ + +/* ---------------------------------------------------------------------- */ + +int +check_mtab(int n, char **devs) +{ + int i,res; + FILE *fp; + struct stat st; + char line[79],dev[32]; + int *fl; + + /* check for lock file */ + for (i = 0; i < 5; i++) { + if (-1 == stat("/etc/mtab~",&st)) + break; + sleep(1); + } + if (5 == i) { + fprintf(stderr,PROG ": /etc/mtab locked\n"); + exit(1); + } + + if (NULL == (fp = fopen("/etc/mtab", "r"))) { + perror(PROG ": open /etc/mtab"); + exit(1); + } + fl = malloc(n*sizeof(int)); + memset(fl,0,n*sizeof(int)); + while (NULL != fgets(line,79,fp)) { + sscanf(line," %31s",dev); + for (i = 0; i < n; i++) { + if (0 == strcmp(dev,devs[i])) + fl[i] = 1; + } + } + res = -1; + for (i = 0; i < n; i++) { + if (0 == fl[i]) + res = i; + } + free(fl); + fclose(fp); + return res; +} + +static int cdrom_tray(char *dev, int eject) +{ + int fd = -1; + + if (-1 == (fd = open(dev,O_RDONLY | O_NONBLOCK))) + goto err; + if (eject) { + if (-1 == ioctl(fd,CDROMEJECT,NULL)) + goto err; + } else { + if (-1 == ioctl(fd,CDROMCLOSETRAY,NULL)) + goto err; + } + close(fd); + return 0; + + err: + if (-1 != fd) + close(fd); + return -1; +} + +int +main(int argc, char *argv[]) +{ + struct changer_params params; + struct changer_get_element st; + struct changer_get_element *dt; + struct changer_move move; + char **devs,line[80],mopt[80],*h; + int fd,i,slot,drive; + int try_umount = 0; + int eject_cdrom = 0; + FILE *fp; + + if (argc != 2) { + fprintf(stderr,"Read the f*** manual!\n\n*plonk*\n\n"); + exit(1); + } + + if (-1 == (fd = open(CHANGER,O_RDONLY))) { + perror(PROG ": open " CHANGER); + exit(1); + } + + /* read changer status information */ + if (ioctl(fd,CHIOGPARAMS,¶ms)) { + perror(PROG ": ioctl CHIOGPARAMS"); + exit(1); + } +#if DEBUG + fprintf(stderr,PROG ": %d drives, %d slots\n", + params.cp_ndrives,params.cp_nslots); +#endif + + dt = malloc(sizeof(struct changer_get_element)*params.cp_ndrives); + for (i = 0; i < params.cp_ndrives; i++) { + dt[i].cge_type=CHET_DT; + dt[i].cge_unit=i; + if (ioctl(fd,CHIOGELEM,dt+i)) { + fprintf(stderr,PROG ":ioctl CHIOGELEM mt %d: %s\n", + i,strerror(errno)); + exit(1); + } + if (NULL != (h = strchr(dt[i].cge_pvoltag,' '))) *h = '\0'; + if (NULL != (h = strchr(dt[i].cge_avoltag,' '))) *h = '\0'; + } + + /* read config file */ + if (NULL == (fp = fopen(CONFIG, "r"))) { + perror(PROG ": open " CONFIG); + exit(1); + } + devs = malloc(sizeof(char*)*params.cp_ndrives); + for (i = 0; NULL != fgets(line,79,fp);) { + if (line[0] == '#' || line[0] == '\n') + continue; + if (sscanf(line,"try_umount= %d",&try_umount)) + continue; + if (sscanf(line,"eject_cdrom= %d",&eject_cdrom)) + continue; + if (line==strstr(line,"mopt=")) { + strncpy(mopt,line+5,79); + mopt[strlen(mopt)-1]='\0'; + continue; + } + + devs[i] = malloc(32); + if (!sscanf(line,"dev= %31s",devs[i])) { + fprintf(stderr,PROG ": config syntax error: %s",line); + exit(1); + } +#if DEBUG + fprintf(stderr,PROG ": drive %d: %s\n",i,devs[i]); +#endif + i++; + } + fclose(fp); + if (i != params.cp_ndrives) { + fprintf(stderr, + PROG ": number of drives (%d) does'nt match the\n" + PROG ": number of dev=... lines (%d) in " CONFIG "\n", + params.cp_ndrives,i); + exit(1); + } + + /* everything fine so far, lets check what key we got... */ + for (i = 0; argv[1][i];i++) + if (!isdigit(argv[1][i])) + break; + if (!argv[1][i]) { + /* we got a number */ + slot = atoi(argv[1]); + if (slot < 0 || slot >= params.cp_nslots) { + fprintf(stderr,PROG ": slot %d is out of range\n",slot); + exit(1); + } + + /* check drives */ + for (drive = -1, i = 0; i < params.cp_ndrives; i++) { + if ((dt[i].cge_status & CESTATUS_FULL) && + (dt[i].cge_flags & CGE_SRC) && + (dt[i].cge_srctype == CHET_ST) && + (dt[i].cge_srcunit == slot)) { + drive = i; + break; + } + } + + if (-1 != drive) { + /* Ha! requested media is still in a drive. Nothing to do :-) */ + printf("%s\t:%s\n",mopt,devs[drive]); + exit(0); + } + + st.cge_type=CHET_ST; + st.cge_unit=slot; + if (ioctl(fd,CHIOGELEM,&st)) { + fprintf(stderr,PROG ": ioctl CHIOGELEM st %d: %s\n", + slot,strerror(errno)); + exit(1); + } + + if (!(st.cge_status & CESTATUS_FULL)) { + fprintf(stderr,PROG ": slot %d has no media\n",slot); + exit(1); + } + } else { + + /* no number -- assume volume tag */ + + /* check drives */ + for (drive = -1, i = 0; i < params.cp_ndrives; i++) { + if ((dt[i].cge_status & CESTATUS_FULL) && + (dt[i].cge_flags & CGE_PVOLTAG) && + (0 == strcmp(argv[1],dt[i].cge_pvoltag))) { + drive = i; + break; + } + } + + if (-1 != drive) { + /* Ha! requested media is still in a drive. Nothing to do :-) */ + printf("%s\t:%s\n",mopt,devs[drive]); + exit(0); + } + + /* Find the tag */ + st.cge_type=CHET_ST; + for (slot = -1, i = 0; i < params.cp_nslots; i++) { + st.cge_unit=i; + if (ioctl(fd,CHIOGELEM,&st)) { + fprintf(stderr,PROG ": ioctl CHIOGELEM st %d: %s\n", + i,strerror(errno)); + exit(1); + } + + if (NULL != (h = strchr(st.cge_pvoltag,' '))) *h = '\0'; + if (NULL != (h = strchr(st.cge_avoltag,' '))) *h = '\0'; + + if ((st.cge_status & CESTATUS_FULL) && + (st.cge_flags & CGE_PVOLTAG) && + (0 == strcmp(argv[1],st.cge_pvoltag))) { + slot = i; + break; + } + } + + if (-1 == slot) { + fprintf(stderr,PROG ": volume tag %s not found\n",argv[1]); + exit(1); + } + } + + /* ok, requested media found, check where to put it now */ + + /* look for a empty drive first... */ + for (i = 0, drive = -1; i < params.cp_ndrives; i++) { + if (!(dt[i].cge_status & CESTATUS_FULL)) { + drive = i; + break; + } + } + + if (-1 == drive) + /* failing that, look for a unmounted drive */ + drive = check_mtab(params.cp_ndrives,devs); + + if (-1 == drive && try_umount) { + /* still no success -- tell automount to umount idle mount-points */ +#if DEBUG + fprintf(stderr,PROG ": sending SIGUSR1 to automount\n"); +#endif + kill(SIGUSR1,getppid()); + sleep(1); /* XXX */ + drive = check_mtab(params.cp_ndrives,devs); + } + + if (-1 == drive) { + /* bad luck */ + fprintf(stderr,PROG ": all drives busy, sorry\n"); + exit(1); + } + + if (eject_cdrom) { + if (0 != cdrom_tray(devs[drive],1)) + exit(1); + } + + if (dt[drive].cge_status & CESTATUS_FULL) { + /* Hmm, full. Ok, put back the old media ... */ + if (!(dt[drive].cge_flags & CGE_SRC)) { + fprintf(stderr,PROG ": source element for drive %d unknown\n", + drive); + goto close_error_exit; + } + memset(&move,0,sizeof(struct changer_move)); + move.cm_totype = dt[drive].cge_srctype; + move.cm_tounit = dt[drive].cge_srcunit; + move.cm_fromtype = CHET_DT; + move.cm_fromunit = drive; + if (ioctl(fd,CHIOMOVE,&move)) { + fprintf(stderr,PROG ": ioctl MOVE (unload): %s\n", + strerror(errno)); + goto close_error_exit; + } + } + + memset(&move,0,sizeof(struct changer_move)); + move.cm_totype = CHET_DT; + move.cm_tounit = drive; + move.cm_fromtype = CHET_ST; + move.cm_fromunit = slot; + if (ioctl(fd,CHIOMOVE,&move)) { + fprintf(stderr,PROG ": ioctl MOVE (load): %s\n", + strerror(errno)); + goto close_error_exit; + } + + if (eject_cdrom) + cdrom_tray(devs[drive],0); + + printf("%s\t:%s\n",mopt,devs[drive]); + exit(0); + + close_error_exit: + if (eject_cdrom) + cdrom_tray(devs[drive],0); + exit(1); +} |