Ejemplo n.º 1
0
/*
 * Toggle tray.
 *
 * Written by Benjamin Schwenk <*****@*****.**> and
 * Sybren Stuvel <*****@*****.**>
 *
 * Not supported by older kernels because it might use
 * CloseTray().
 *
 */
static void toggle_tray(int fd)
{
#ifdef CDROM_DRIVE_STATUS
	/* First ask the CDROM for info, otherwise fall back to manual.  */
	switch (ioctl(fd, CDROM_DRIVE_STATUS)) {
	case CDS_TRAY_OPEN:
		close_tray(fd);
		return;

	case CDS_NO_DISC:
	case CDS_DISC_OK:
		if (!eject_cdrom(fd))
			err(EXIT_FAILURE, _("CD-ROM eject command failed"));
		return;
	case CDS_NO_INFO:
		warnx(_("no CD-ROM information available"));
		return;
	case CDS_DRIVE_NOT_READY:
		warnx(_("CD-ROM drive is not ready"));
		return;
	default:
		abort();
	}
#else
	struct timeval time_start, time_stop;
	int time_elapsed;

	/* Try to open the CDROM tray and measure the time therefor
	 * needed.  In my experience the function needs less than 0.05
	 * seconds if the tray was already open, and at least 1.5 seconds
	 * if it was closed.  */
	gettime_monotonic(&time_start);

	/* Send the CDROMEJECT command to the device. */
	if (!eject_cdrom(fd))
		err(EXIT_FAILURE, _("CD-ROM eject command failed"));

	/* Get the second timestamp, to measure the time needed to open
	 * the tray.  */
	gettime_monotonic(&time_stop);

	time_elapsed = (time_stop.tv_sec * 1000000 + time_stop.tv_usec) -
		(time_start.tv_sec * 1000000 + time_start.tv_usec);

	/* If the tray "opened" too fast, we can be nearly sure, that it
	 * was already open. In this case, close it now. Else the tray was
	 * closed before. This would mean that we are done.  */
	if (time_elapsed < TRAY_WAS_ALREADY_OPEN_USECS)
		close_tray(fd);
#endif
}
Ejemplo n.º 2
0
/*
 * Wait for the top of a clock tick by reading /dev/rtc in a busy loop
 * until we see it. This function is used for rtc drivers without ioctl
 * interrupts. This is typical on an Alpha, where the Hardware Clock
 * interrupts are used by the kernel for the system clock, so aren't at
 * the user's disposal.
 */
static int busywait_for_rtc_clock_tick(const struct hwclock_control *ctl,
				       const int rtc_fd)
{
	struct tm start_time;
	/* The time when we were called (and started waiting) */
	struct tm nowtime;
	int rc;
	struct timeval begin, now;

	if (ctl->verbose) {
		printf("ioctl(%d, RTC_UIE_ON, 0): %s\n",
		       rtc_fd, strerror(errno));
		printf(_("Waiting in loop for time from %s to change\n"),
		       rtc_dev_name);
	}

	if (do_rtc_read_ioctl(rtc_fd, &start_time))
		return 1;

	/*
	 * Wait for change.  Should be within a second, but in case
	 * something weird happens, we have a time limit (1.5s) on this loop
	 * to reduce the impact of this failure.
	 */
	gettime_monotonic(&begin);
	do {
		rc = do_rtc_read_ioctl(rtc_fd, &nowtime);
		if (rc || start_time.tm_sec != nowtime.tm_sec)
			break;
		gettime_monotonic(&now);
		if (time_diff(now, begin) > 1.5) {
			warnx(_("Timed out waiting for time change."));
			return 1;
		}
	} while (1);

	if (rc)
		return 1;
	return 0;
}
Ejemplo n.º 3
0
/*
  pim_time_monotonic_sec():
  number of seconds since some unspecified starting point
*/
int64_t pim_time_monotonic_sec()
{
  struct timeval now_tv;

  if (gettime_monotonic(&now_tv)) {
    zlog_err("%s: gettime_monotonic() failure: errno=%d: %s",
	     __PRETTY_FUNCTION__,
	     errno, safe_strerror(errno));
    return -1;
  }

  return now_tv.tv_sec;
}
Ejemplo n.º 4
0
static void write_output(struct script_control *ctl, char *obuf,
			    ssize_t bytes)
{
	DBG(IO, ul_debug(" writing output"));

	if (ctl->timing && ctl->timingfp) {
		struct timeval now, delta;

		DBG(IO, ul_debug("  writing timing info"));

		gettime_monotonic(&now);
		timersub(&now, &ctl->oldtime, &delta);
		fprintf(ctl->timingfp, "%ld.%06ld %zd\n", delta.tv_sec, delta.tv_usec, bytes);
		if (ctl->flush)
			fflush(ctl->timingfp);
		ctl->oldtime = now;
	}

	DBG(IO, ul_debug("  writing to script file"));

	if (fwrite_all(obuf, 1, bytes, ctl->typescriptfp)) {
		warn(_("cannot write script file"));
		fail(ctl);
	}
	if (ctl->flush)
		fflush(ctl->typescriptfp);

	DBG(IO, ul_debug("  writing to output"));

	if (write_all(STDOUT_FILENO, obuf, bytes)) {
		DBG(IO, ul_debug("  writing output *failed*"));
		warn(_("write failed"));
		fail(ctl);
	}

	DBG(IO, ul_debug("  writing output *done*"));
}
Ejemplo n.º 5
0
int main(int argc, char **argv)
{
	char *path;
	int c, fd, verbose = 0, secure = 0, secsize;
	uint64_t end, blksize, step, range[2], stats[2];
	struct stat sb;
	struct timeval now, last;

	static const struct option longopts[] = {
	    { "help",      0, 0, 'h' },
	    { "version",   0, 0, 'V' },
	    { "offset",    1, 0, 'o' },
	    { "length",    1, 0, 'l' },
	    { "step",      1, 0, 'p' },
	    { "secure",    0, 0, 's' },
	    { "verbose",   0, 0, 'v' },
	    { NULL,        0, 0, 0 }
	};

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

	range[0] = 0;
	range[1] = ULLONG_MAX;
	step = 0;

	while ((c = getopt_long(argc, argv, "hVsvo:l:p:", longopts, NULL)) != -1) {
		switch(c) {
		case 'h':
			usage(stdout);
			break;
		case 'V':
			printf(UTIL_LINUX_VERSION);
			return EXIT_SUCCESS;
		case 'l':
			range[1] = strtosize_or_err(optarg,
					_("failed to parse length"));
			break;
		case 'o':
			range[0] = strtosize_or_err(optarg,
					_("failed to parse offset"));
			break;
		case 'p':
			step = strtosize_or_err(optarg,
					_("failed to parse step"));
			break;
		case 's':
			secure = 1;
			break;
		case 'v':
			verbose = 1;
			break;
		default:
			usage(stderr);
			break;
		}
	}

	if (optind == argc)
		errx(EXIT_FAILURE, _("no device specified"));

	path = argv[optind++];

	if (optind != argc) {
		warnx(_("unexpected number of arguments"));
		usage(stderr);
	}

	fd = open(path, O_WRONLY);
	if (fd < 0)
		err(EXIT_FAILURE, _("cannot open %s"), path);

	if (fstat(fd, &sb) == -1)
		err(EXIT_FAILURE, _("stat failed %s"), path);
	if (!S_ISBLK(sb.st_mode))
		errx(EXIT_FAILURE, _("%s: not a block device"), path);

	if (ioctl(fd, BLKGETSIZE64, &blksize))
		err(EXIT_FAILURE, _("%s: BLKGETSIZE64 ioctl failed"), path);
	if (ioctl(fd, BLKSSZGET, &secsize))
		err(EXIT_FAILURE, _("%s: BLKSSZGET ioctl failed"), path);

	/* check offset alignment to the sector size */
	if (range[0] % secsize)
		errx(EXIT_FAILURE, _("%s: offset %" PRIu64 " is not aligned "
			 "to sector size %i"), path, range[0], secsize);

	/* is the range end behind the end of the device ?*/
	if (range[0] > blksize)
		errx(EXIT_FAILURE, _("%s: offset is greater than device size"), path);
	end = range[0] + range[1];
	if (end < range[0] || end > blksize)
		end = blksize;

	range[1] = (step > 0) ? step : end - range[0];

	/* check length alignment to the sector size */
	if (range[1] % secsize)
		errx(EXIT_FAILURE, _("%s: length %" PRIu64 " is not aligned "
			 "to sector size %i"), path, range[1], secsize);

	stats[0] = range[0], stats[1] = 0;
	gettime_monotonic(&last);

	for (range[0] = range[0]; range[0] < end; range[0] += range[1]) {
		if (range[0] + range[1] > end)
			range[1] = end - range[0];

		if (secure) {
			if (ioctl(fd, BLKSECDISCARD, &range))
				err(EXIT_FAILURE, _("%s: BLKSECDISCARD ioctl failed"), path);
		} else {
			if (ioctl(fd, BLKDISCARD, &range))
				err(EXIT_FAILURE, _("%s: BLKDISCARD ioctl failed"), path);
		}

		/* reporting progress */
		if (verbose && step) {
			gettime_monotonic(&now);
			if (last.tv_sec < now.tv_sec) {
				print_stats(path, stats);
				stats[0] = range[0], stats[1] = 0;
				last = now;
			}
		}

		stats[1] += range[1];
	}

	if (verbose)
		print_stats(path, stats);

	close(fd);
	return EXIT_SUCCESS;
}