static void check_tape(int boot_flag)
{
size_t status, buflen;
int action;
static char *fid = "check_tape";

    MUTEX_LOCK(&Status->lock);
        Status->output.state = ISP_OUTPUT_CHECK;
    MUTEX_UNLOCK(&Status->lock);

/* Check for data by trying to read from the tape */

    if (mtio_rew(tp) < 0) {
        util_log(1, "%s: mtio_rew: %s", fid, syserrmsg(errno));
        eject_tape(0);
        return;
    }

    status = mtio_read(tp, tmpbuf, MAXBUFLEN);

    if (mtio_rew(tp) < 0) {
        util_log(1, "%s: mtio_rew: %s", fid, syserrmsg(errno));
        eject_tape(0);
        return;
    }

    if (status > 0) {
        util_log(1, "tape contains data", fid);
        if (boot_flag) {
            action = ISP_MEDIA_APPEND;
        } else {
            action = media_alert(0);
        }
        switch (action) {
          case ISP_MEDIA_EJECT:
            eject_tape(0);
            break;
          case ISP_MEDIA_OVERWRITE:
            util_log(1, "OVERWRITTING TAPE");
            MUTEX_LOCK(&Status->lock);
                Status->output.state = ISP_OUTPUT_ONLINE;
            MUTEX_UNLOCK(&Status->lock);
            break;
          default:
            util_log(1, "skipping to end of data");
            MUTEX_LOCK(&Status->lock);
                Status->output.state = ISP_OUTPUT_SKIP;
            MUTEX_UNLOCK(&Status->lock);
            mtio_eom(tp);
            MUTEX_LOCK(&Status->lock);
                Status->output.state = ISP_OUTPUT_ONLINE;
            MUTEX_UNLOCK(&Status->lock);
            break;
        }
    }

    return;
}
void check_eject_flag()
{
    MUTEX_LOCK(&mp);
        if (eject_flag) eject_tape(0);
        eject_flag = 0;
    MUTEX_UNLOCK(&mp);
}
Exemple #3
0
/* main program */
int main(int argc, char **argv)
{
	char *device = NULL;
	char *disk = NULL;
	char *mountpoint = NULL;
	int worked = 0;    /* set to 1 when successfully ejected */
	int fd;            /* file descriptor for device */

	setlocale(LC_ALL,"");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	atexit(close_stdout);

	/* parse the command line arguments */
	parse_args(argc, argv, &device);

	/* handle -d option */
	if (d_option) {
		info(_("default device: `%s'"), EJECT_DEFAULT_DEVICE);
		return EXIT_SUCCESS;
	}

	if (!device) {
		device = mnt_resolve_path(EJECT_DEFAULT_DEVICE, NULL);
		verbose(_("using default device `%s'"), device);
	} else {
		char *p;

		if (device[strlen(device)-1] == '/')
			device[strlen(device)-1] = '\0';

		/* figure out full device or mount point name */
		p = find_device(device);
		if (p)
			free(device);
		else
			p = device;

		device = mnt_resolve_spec(p, NULL);
		free(p);
	}

	if (!device)
		errx(EXIT_FAILURE, _("%s: unable to find device"), device);

	verbose(_("device name is `%s'"), device);

	device_get_mountpoint(&device, &mountpoint);
	if (mountpoint)
		verbose(_("%s: mounted on %s"), device, mountpoint);
	else
		verbose(_("%s: not mounted"), device);

	disk = get_disk_devname(device);
	if (disk) {
		verbose(_("%s: disc device: %s (disk device will be used for eject)"), device, disk);
		free(device);
		device = disk;
		disk = NULL;
	} else {
		struct stat st;

		if (stat(device, &st) != 0 || !S_ISBLK(st.st_mode))
			errx(EXIT_FAILURE, _("%s: not found mountpoint or device "
					"with the given name"), device);

		verbose(_("%s: is whole-disk device"), device);
	}

	if (F_option == 0 && is_hotpluggable(device) == 0)
		errx(EXIT_FAILURE, _("%s: is not hot-pluggable device"), device);

	/* handle -n option */
	if (n_option) {
		info(_("device is `%s'"), device);
		verbose(_("exiting due to -n/--noop option"));
		return EXIT_SUCCESS;
	}

	/* handle -i option */
	if (i_option) {
		fd = open_device(device);
		manual_eject(fd, i_arg);
		return EXIT_SUCCESS;
	}

	/* handle -a option */
	if (a_option) {
		if (a_arg)
			verbose(_("%s: enabling auto-eject mode"), device);
		else
			verbose(_("%s: disabling auto-eject mode"), device);
		fd = open_device(device);
		auto_eject(fd, a_arg);
		return EXIT_SUCCESS;
	}

	/* handle -t option */
	if (t_option) {
		verbose(_("%s: closing tray"), device);
		fd = open_device(device);
		close_tray(fd);
		set_device_speed(device);
		return EXIT_SUCCESS;
	}

	/* handle -T option */
	if (T_option) {
		verbose(_("%s: toggling tray"), device);
		fd = open_device(device);
		toggle_tray(fd);
		set_device_speed(device);
		return EXIT_SUCCESS;
	}

	/* handle -X option */
	if (X_option) {
		verbose(_("%s: listing CD-ROM speed"), device);
		fd = open_device(device);
		list_speeds(device, fd);
		return EXIT_SUCCESS;
	}

	/* handle -x option only */
	if (!c_option)
		set_device_speed(device);


	/*
	 * Unmount all partitions if -m is not specified; or umount given
	 * mountpoint if -M is specified, otherwise print error of another
	 * partition is mounted.
	 */
	if (!m_option) {
		int ct = umount_partitions(device, M_option);

		if (ct == 0 && mountpoint)
			umount_one(mountpoint); /* probably whole-device */

		if (M_option) {
			if (ct == 1 && mountpoint)
				umount_one(mountpoint);
			else if (ct)
				errx(EXIT_FAILURE, _("error: %s: device in use"), device);
		}
	}

	/* handle -c option */
	if (c_option) {
		verbose(_("%s: selecting CD-ROM disc #%ld"), device, c_arg);
		fd = open_device(device);
		changer_select(fd, c_arg);
		set_device_speed(device);
		return EXIT_SUCCESS;
	}

	/* if user did not specify type of eject, try all four methods */
	if (r_option + s_option + f_option + q_option == 0)
		r_option = s_option = f_option = q_option = 1;

	/* open device */
	fd = open_device(device);

	/* try various methods of ejecting until it works */
	if (r_option) {
		verbose(_("%s: trying to eject using CD-ROM eject command"), device);
		worked = eject_cdrom(fd);
		verbose(worked ? _("CD-ROM eject command succeeded") :
				 _("CD-ROM eject command failed"));
	}

	if (s_option && !worked) {
		verbose(_("%s: trying to eject using SCSI commands"), device);
		worked = eject_scsi(fd);
		verbose(worked ? _("SCSI eject succeeded") :
				 _("SCSI eject failed"));
	}

	if (f_option && !worked) {
		verbose(_("%s: trying to eject using floppy eject command"), device);
		worked = eject_floppy(fd);
		verbose(worked ? _("floppy eject command succeeded") :
				 _("floppy eject command failed"));
	}

	if (q_option && !worked) {
		verbose(_("%s: trying to eject using tape offline command"), device);
		worked = eject_tape(fd);
		verbose(worked ? _("tape offline command succeeded") :
				 _("tape offline command failed"));
	}

	if (!worked)
		errx(EXIT_FAILURE, _("unable to eject"));

	/* cleanup */
	close(fd);
	free(device);
	free(mountpoint);

	mnt_unref_table(mtab);

	return EXIT_SUCCESS;
}
static THREAD_FUNC TapeWriteThread(void *dummy)
{
int status;
size_t blen, remain, want, put, nrec;
char *ptr;
OLD_MSGQ_MSG *obuf;
static char *fid = "TapeWriteThread";

    blen = Params->bfact * IDA_BUFSIZ; /* IDA10 OK */
    MUTEX_LOCK(&mp);
        ioerr = 0;
    MUTEX_UNLOCK(&mp);

    while (1) {

        obuf = msgq_get(&Q->obuf, OLD_MSGQ_WAITFOREVER);
        if (!msgq_chkmsg2(fid, obuf)) {
            util_log(1, "%s: corrupt message received", fid);
            ispd_die(MY_MOD_ID + 1);
        }
        nrec = *((size_t *) obuf->data);
        util_log(1, "dumping %ld records to %s", nrec, Params->odev);

        ptr = obuf->data + sizeof(size_t);
        remain = nrec * IDA_BUFSIZ; /* IDA10 OK */

        while (remain > 0) {
            want = remain > blen ? blen : remain;
            nrec = want / IDA_BUFSIZ; /* IDA10 OK */
            do {
                lock_device();
                    put = mtio_write(tp, ptr, want);
                    if (put == want) {
                        MUTEX_LOCK(&Status->lock);
                            Status->output.nrec += nrec;
                            status = Status->output.state;
                        MUTEX_UNLOCK(&Status->lock);
                        ptr += put;
                        if (ioerr) {
                            clear_alarm(ISP_ALARM_IOERR);
                            ioerr = 0;
                        }
                    } else {
                        if (put != 0) {
                            if (++ioerr == 1) {
                                set_alarm(ISP_ALARM_IOERR);
                                util_log(1, "%s: %s",
                                    Params->odev, syserrmsg(errno)
                                );
                            }
                            MUTEX_LOCK(&Status->lock);
                                ++Status->output.err;
                            MUTEX_UNLOCK(&Status->lock);
                            eject_tape(0);
                        }
                    }
                release_device();
                if (put != want) {
                    if (shutting_down()) {
                        complete_shutdown();
                        THREAD_EXIT(0);
                    } else {
                        sleep(5);
                    }
                }
            } while (put != want);
            remain -= put;
        }
        util_log(1, "tape dump completed OK");

        if (shutting_down()) {
            complete_shutdown();
            THREAD_EXIT(0);
        }

        MUTEX_LOCK(&mp);
            if (eject_flag) eject_tape(0);
            eject_flag = 0;
        MUTEX_UNLOCK(&mp);

        msgq_put(&Heap->obuf, obuf);
    }
}
Exemple #5
0
int
main(
    int		argc,
    char **	argv)
{
  int loaded;
  int target = -1;
  int oldtarget;
  command com;   /* a little DOS joke */
  
  /*
   * drive_num really should be something from the config file, but..
   * for now, it is set to zero, since most of the common changers
   * used by amanda only have one drive ( until someone wants to 
   * use an EXB60/120, or a Breece Hill Q45.. )
   */
  int    drive_num = 0;
  int need_eject = 0; /* Does the drive need an eject command ? */
  unsigned need_sleep = 0; /* How many seconds to wait for the drive to get ready */
  int clean_slot = -1;
  int maxclean = 0;
  char *clean_file=NULL;
  char *time_file=NULL;

  int use_slots;
  int slot_offset;
  int confnum;

  int fd, slotcnt, drivecnt;
  int endstatus = 0;
  char *changer_dev = NULL;
  char *tape_device = NULL;
  char *changer_file = NULL;
  char *scsitapedevice = NULL;

  /*
   * Configure program for internationalization:
   *   1) Only set the message locale for now.
   *   2) Set textdomain for all amanda related programs to "amanda"
   *      We don't want to be forced to support dozens of message catalogs.
   */  
  setlocale(LC_MESSAGES, "C");
  textdomain("amanda"); 

  set_pname("chg-scsi");

  /* Don't die when child closes pipe */
  signal(SIGPIPE, SIG_IGN);

  dbopen(DBG_SUBDIR_SERVER);
  parse_args(argc,argv,&com);

  changer = alloc(SIZEOF(changer_t));
  config_init(CONFIG_INIT_USE_CWD, NULL);

  if (config_errors(NULL) >= CFGERR_WARNINGS) {
    config_print_errors();
    if (config_errors(NULL) >= CFGERR_ERRORS) {
      g_critical(_("errors processing config file"));
    }
  }

  changer_dev = getconf_str(CNF_CHANGERDEV);
  changer_file = getconf_str(CNF_CHANGERFILE);
  tape_device = getconf_str(CNF_TAPEDEV);

  /* Get the configuration parameters */

  if (strlen(tape_device)==1){
    read_config(changer_file, changer);
    confnum=atoi(tape_device);
    use_slots    = changer->conf[confnum].end-changer->conf[confnum].start+1;
    slot_offset  = changer->conf[confnum].start;
    drive_num    = changer->conf[confnum].drivenum;
    need_eject   = changer->eject;
    need_sleep   = changer->sleep;
    clean_file   = stralloc(changer->conf[confnum].cleanfile);
    clean_slot   = changer->conf[confnum].cleanslot;
    maxclean     = changer->cleanmax;
    if (NULL != changer->conf[confnum].timefile)
      time_file = stralloc(changer->conf[confnum].timefile);
    if (NULL != changer->conf[confnum].slotfile)
      changer_file = stralloc(changer->conf[confnum].slotfile);
    else
      changer_file = NULL;
    if (NULL != changer->conf[confnum].device)
      tape_device  = stralloc(changer->conf[confnum].device);
    if (NULL != changer->device)
      changer_dev  = stralloc(changer->device); 
    if (NULL != changer->conf[confnum].scsitapedev)
      scsitapedevice = stralloc(changer->conf[confnum].scsitapedev);
    if (NULL != changer->conf[confnum].tapestatfile)
      tapestatfile = stralloc(changer->conf[confnum].tapestatfile);
    dump_changer_struct(changer);
    /* get info about the changer */
    fd = OpenDevice(INDEX_CHANGER , changer_dev,
			"changer_dev", changer->conf[confnum].changerident);
    if (fd == -1) {
      int localerr = errno;
      g_fprintf(stderr, _("%s: open: %s: %s\n"), get_pname(), 
              changer_dev, strerror(localerr));
      g_printf(_("%s open: %s: %s\n"), "<none>", changer_dev, strerror(localerr));
      dbprintf(_("open: %s: %s\n"), changer_dev, strerror(localerr));
      return 2;
    }

    if (tape_device == NULL)
      {
        tape_device = stralloc(changer_dev);
      }

    if (scsitapedevice == NULL)
      {
         scsitapedevice = stralloc(tape_device);
      }

    if ((changer->conf[confnum].end == -1) || (changer->conf[confnum].start == -1)){
      slotcnt = get_slot_count(fd);
      use_slots    = slotcnt;
      slot_offset  = 0;
    }
    free_changer_struct(&changer);
  } else {
    /* get info about the changer */
    confnum = 0;
    fd = OpenDevice(INDEX_CHANGER , changer_dev,
			"changer_dev", changer->conf[confnum].changerident);
    if (fd == -1) {
      int localerr = errno;
      g_fprintf(stderr, _("%s: open: %s: %s\n"), get_pname(), 
              changer_dev, strerror(localerr));
      g_printf(_("%s open: %s: %s\n"), _("<none>"), changer_dev, strerror(localerr));
      dbprintf(_("open: %s: %s\n"), changer_dev, strerror(localerr));
      return 2;
    }
    slotcnt = get_slot_count(fd);
    use_slots    = slotcnt;
    slot_offset  = 0;
    drive_num    = 0;
    need_eject   = 0;
    need_sleep   = 0;
  }

  drivecnt = get_drive_count(fd);

  if (drive_num > drivecnt) {
    g_printf(_("%s drive number error (%d > %d)\n"), _("<none>"), 
           drive_num, drivecnt);
    g_fprintf(stderr, _("%s: requested drive number (%d) greater than "
            "number of supported drives (%d)\n"), get_pname(), 
            drive_num, drivecnt);
    dbprintf(_("requested drive number (%d) greater than "
              "number of supported drives (%d)\n"), drive_num, drivecnt);
    CloseDevice("", fd);
    return 2;
  }

  loaded = drive_loaded(fd, drive_num);

  switch(com.command_code) {
  case COM_SLOT:  /* slot changing command */
    if (is_positive_number(com.parameter)) {
      if ((target = atoi(com.parameter))>=use_slots) {
        g_printf(_("<none> no slot `%d'\n"),target);
        close(fd);
        endstatus = 2;
        break;
      } else {
        target = target+slot_offset;
      }
    } else
      target=get_relative_target(fd, use_slots,
                                 com.parameter,
                                 loaded, 
                                 changer_file,slot_offset,slot_offset+use_slots);
    if (loaded) {
      if (changer_file != NULL)
        {
          oldtarget=get_current_slot(changer_file);
        } else {
          oldtarget = GetCurrentSlot(fd, drive_num);
        }
      if ((oldtarget)!=target) {
        if (need_eject)
          eject_tape(scsitapedevice, need_eject);
        (void)unload(fd, drive_num, oldtarget);
        if (ask_clean(scsitapedevice))
          clean_tape(fd,tape_device,clean_file,drive_num,
                     clean_slot,maxclean,time_file);
        loaded=0;
      }
    }
    if (changer_file != NULL)
      {
      put_current_slot(changer_file, target);
    }
    if (!loaded && isempty(fd, target)) {
      g_printf(_("%d slot %d is empty\n"),target-slot_offset,
             target-slot_offset);
      close(fd);
      endstatus = 1;
      break;
    }
    if (!loaded)
      if (load(fd, drive_num, target) != 0) {
        g_printf(_("%d slot %d move failed\n"),target-slot_offset,
               target-slot_offset);  
        close(fd);
        endstatus = 2;
        break;
      }
    if (need_sleep)
      Tape_Ready1(scsitapedevice, need_sleep);
    g_printf(_("%d %s\n"), target-slot_offset, tape_device);
    break;

  case COM_INFO:
    if (changer_file != NULL)
      {
        g_printf("%d ", get_current_slot(changer_file)-slot_offset);
      } else {
        g_printf("%d ", GetCurrentSlot(fd, drive_num)-slot_offset);
      }
    g_printf("%d 1\n", use_slots);
    break;

  case COM_RESET:
    if (changer_file != NULL)
      {
        target=get_current_slot(changer_file);
      } else {
        target = GetCurrentSlot(fd, drive_num);
      }
    if (loaded) {
      if (!isempty(fd, target))
        target=find_empty(fd,0 ,0);
      if (need_eject)
        eject_tape(scsitapedevice, need_eject);
      (void)unload(fd, drive_num, target);
      if (ask_clean(scsitapedevice))
        clean_tape(fd,tape_device,clean_file,drive_num,clean_slot,
                   maxclean,time_file);
    }

    if (isempty(fd, slot_offset)) {
      g_printf(_("0 slot 0 is empty\n"));
      close(fd);
      endstatus = 1;
      break;
    }

    if (load(fd, drive_num, slot_offset) != 0) {
      g_printf(_("%d slot %d move failed\n"),slot_offset,
             slot_offset);  
      close(fd);
      endstatus = 2;
      break;
    }
    if (changer_file != NULL)
    {
      put_current_slot(changer_file, slot_offset);
    }
    if (need_sleep)
      Tape_Ready1(scsitapedevice, need_sleep);
    if (changer_file != NULL)
      {
        g_printf("%d %s\n", get_current_slot(changer_file), tape_device);
      } else {
        g_printf("%d %s\n", GetCurrentSlot(fd, drive_num), tape_device);
      }
    break;

  case COM_EJECT:
    if (loaded) {
      if (changer_file != NULL)
        {
          target=get_current_slot(changer_file);
        } else {
          target = GetCurrentSlot(fd, drive_num);
        }
      if (need_eject)
        eject_tape(scsitapedevice, need_eject);
      (void)unload(fd, drive_num, target);
      if (ask_clean(scsitapedevice))
        clean_tape(fd,tape_device,clean_file,drive_num,clean_slot,
                   maxclean,time_file);
      g_printf("%d %s\n", target, tape_device);
    } else {
      g_printf(_("%d drive was not loaded\n"), target);
      endstatus = 1;
    }
    break;
  case COM_CLEAN:
    if (loaded) {
      if (changer_file  != NULL)
        {
          target=get_current_slot(changer_file);
        } else {
          target = GetCurrentSlot(fd, drive_num);
        }
      if (need_eject)
        eject_tape(scsitapedevice, need_eject);
      (void)unload(fd, drive_num, target);
    } 
    clean_tape(fd,tape_device,clean_file,drive_num,clean_slot,
               maxclean,time_file);
    g_printf(_("%s cleaned\n"), tape_device);
    break;
  };

  CloseDevice("", 0);
  dbclose();
  return endstatus;
}