aboutsummaryrefslogtreecommitdiff
path: root/src/sg_turs.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2007-09-10 00:54:57 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2007-09-10 00:54:57 +0000
commit7b165064d3d22cf8e699935bccef0e728857c4eb (patch)
treeec1fd18a51e9cef40fb333366a13796592bdceda /src/sg_turs.c
parent6716cee810f1680cefe477e0b8e191c3321cd3b7 (diff)
downloadsg3_utils-7b165064d3d22cf8e699935bccef0e728857c4eb.tar.gz
rearrange files into include, src, lib and doc directories
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@100 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src/sg_turs.c')
-rw-r--r--src/sg_turs.c370
1 files changed, 370 insertions, 0 deletions
diff --git a/src/sg_turs.c b/src/sg_turs.c
new file mode 100644
index 00000000..ee65dc25
--- /dev/null
+++ b/src/sg_turs.c
@@ -0,0 +1,370 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef SG3_UTILS_MINGW
+#include <sys/time.h>
+#endif
+
+#include "sg_lib.h"
+#include "sg_cmds_basic.h"
+
+/* This program sends a user specified number of TEST UNIT READY commands
+ to the given sg device. Since TUR is a simple command involing no
+ data transfer (and no REQUEST SENSE command iff the unit is ready)
+ then this can be used for timing per SCSI command overheads.
+
+ * Copyright (C) 2000-2007 D. Gilbert
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+
+ */
+
+static char * version_str = "3.26 20070714";
+
+#if defined(MSC_VER) || defined(__MINGW32__)
+#define HAVE_MS_SLEEP
+#endif
+
+#ifdef HAVE_MS_SLEEP
+#include <windows.h>
+#define sleep_for(seconds) Sleep( (seconds) * 1000)
+#else
+#define sleep_for(seconds) sleep(seconds)
+#endif
+
+static struct option long_options[] = {
+ {"help", 0, 0, 'h'},
+ {"new", 0, 0, 'N'},
+ {"number", 1, 0, 'n'},
+ {"old", 0, 0, 'O'},
+ {"progress", 0, 0, 'p'},
+ {"time", 0, 0, 't'},
+ {"verbose", 0, 0, 'v'},
+ {"version", 0, 0, 'V'},
+ {0, 0, 0, 0},
+};
+
+struct opts_t {
+ int do_help;
+ int do_number;
+ int do_progress;
+ int do_time;
+ int do_verbose;
+ int do_version;
+ const char * device_name;
+ int opt_new;
+};
+
+
+static void usage()
+{
+ printf("Usage: sg_turs [--help] [--number=NUM] [--progress] [--time] "
+ "[--verbose]\n"
+ " [--version] DEVICE\n"
+ " where:\n"
+ " --help|-h print usage message then exit\n"
+ " --number=NUM|-n NUM number of test_unit_ready commands "
+ "(def: 1)\n"
+ " --progress|-p outputs progress indication (percentage) "
+ "if available\n"
+ " --time|-t outputs total duration and commands per "
+ "second\n"
+ " --verbose|-v increase verbosity\n"
+ " --version|-V print version string then exit\n\n"
+ "Performs a SCSI TEST UNIT READY command (or many of them)\n");
+}
+
+static void usage_old()
+{
+ printf("Usage: sg_turs [-n=NUM] [-p] [-t] [-v] [-V] "
+ "DEVICE\n"
+ " where:\n"
+ " -n=NUM number of test_unit_ready commands "
+ "(def: 1)\n"
+ " -p outputs progress indication (percentage) "
+ "if available\n"
+ " -t outputs total duration and commands per "
+ "second\n"
+ " -v increase verbosity\n"
+ " -V print version string then exit\n\n"
+ "Performs a SCSI TEST UNIT READY command (or many of them)\n");
+}
+
+static void usage_for(const struct opts_t * optsp)
+{
+ if (optsp->opt_new)
+ usage();
+ else
+ usage_old();
+}
+
+static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
+{
+ int c, n;
+
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "hn:NOptvV", long_options,
+ &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ case '?':
+ ++optsp->do_help;
+ break;
+ case 'n':
+ n = sg_get_num(optarg);
+ if (n < 0) {
+ fprintf(stderr, "bad argument to '--number='\n");
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ optsp->do_number = n;
+ break;
+ case 'N':
+ break; /* ignore */
+ case 'O':
+ optsp->opt_new = 0;
+ return 0;
+ case 'p':
+ ++optsp->do_progress;
+ break;
+ case 't':
+ ++optsp->do_time;
+ break;
+ case 'v':
+ ++optsp->do_verbose;
+ break;
+ case 'V':
+ ++optsp->do_version;
+ break;
+ default:
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
+ if (optsp->do_help)
+ break;
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ if (optind < argc) {
+ if (NULL == optsp->device_name) {
+ optsp->device_name = argv[optind];
+ ++optind;
+ }
+ if (optind < argc) {
+ for (; optind < argc; ++optind)
+ fprintf(stderr, "Unexpected extra argument: %s\n",
+ argv[optind]);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ return 0;
+}
+
+static int process_cl_old(struct opts_t * optsp, int argc, char * argv[])
+{
+ int k, jmp_out, plen;
+ const char * cp;
+
+ for (k = 1; k < argc; ++k) {
+ cp = argv[k];
+ plen = strlen(cp);
+ if (plen <= 0)
+ continue;
+ if ('-' == *cp) {
+ for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) {
+ switch (*cp) {
+ case 'N':
+ optsp->opt_new = 1;
+ return 0;
+ case 'O':
+ break;
+ case 'p':
+ ++optsp->do_progress;
+ break;
+ case 't':
+ ++optsp->do_time;
+ break;
+ case 'v':
+ ++optsp->do_verbose;
+ break;
+ case 'V':
+ ++optsp->do_verbose;
+ break;
+ case '?':
+ usage_old();
+ return 0;
+ default:
+ jmp_out = 1;
+ break;
+ }
+ if (jmp_out)
+ break;
+ }
+ if (plen <= 0)
+ continue;
+ if (0 == strncmp("n=", cp, 2)) {
+ optsp->do_number = sg_get_num(cp + 2);
+ if (optsp->do_number <= 0) {
+ printf("Couldn't decode number after 'n=' option\n");
+ usage_old();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ } else if (0 == strncmp("-old", cp, 4))
+ ;
+ else if (jmp_out) {
+ fprintf(stderr, "Unrecognized option: %s\n", cp);
+ usage_old();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ } else if (0 == optsp->device_name)
+ optsp->device_name = cp;
+ else {
+ fprintf(stderr, "too many arguments, got: %s, not expecting: "
+ "%s\n", optsp->device_name, cp);
+ usage_old();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ return 0;
+}
+
+static int process_cl(struct opts_t * optsp, int argc, char * argv[])
+{
+ int res;
+ char * cp;
+
+ cp = getenv("SG3_UTILS_OLD_OPTS");
+ if (cp) {
+ optsp->opt_new = 0;
+ res = process_cl_old(optsp, argc, argv);
+ if ((0 == res) && optsp->opt_new)
+ res = process_cl_new(optsp, argc, argv);
+ } else {
+ optsp->opt_new = 1;
+ res = process_cl_new(optsp, argc, argv);
+ if ((0 == res) && (0 == optsp->opt_new))
+ res = process_cl_old(optsp, argc, argv);
+ }
+ return res;
+}
+
+int main(int argc, char * argv[])
+{
+ int sg_fd, k, res, progress;
+ int num_errs = 0;
+ int reported = 0;
+ int ret = 0;
+#ifndef SG3_UTILS_MINGW
+ struct timeval start_tm, end_tm;
+#endif
+ struct opts_t opts;
+
+ memset(&opts, 0, sizeof(opts));
+ opts.do_number = 1;
+ res = process_cl(&opts, argc, argv);
+ if (res)
+ return SG_LIB_SYNTAX_ERROR;
+ if (opts.do_help) {
+ usage_for(&opts);
+ return 0;
+ }
+ if (opts.do_version) {
+ fprintf(stderr, "Version string: %s\n", version_str);
+ return 0;
+ }
+
+ if (NULL == opts.device_name) {
+ fprintf(stderr, "No DEVICE argument given\n");
+ usage_for(&opts);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+
+ if ((sg_fd = sg_cmds_open_device(opts.device_name, 1 /* ro */,
+ opts.do_verbose)) < 0) {
+ fprintf(stderr, "sg_turs: error opening file: %s: %s\n",
+ opts.device_name, safe_strerror(-sg_fd));
+ return SG_LIB_FILE_ERROR;
+ }
+ if (opts.do_progress) {
+ for (k = 0; k < opts.do_number; ++k) {
+ if (k > 0)
+ sleep_for(30);
+ progress = -1;
+ res = sg_ll_test_unit_ready_progress(sg_fd, k, &progress,
+ ((1 == opts.do_number) ? 1 : 0), opts.do_verbose);
+ if (progress < 0) {
+ ret = res;
+ break;
+ } else
+ printf("Progress indication: %d%% done\n",
+ (progress * 100) / 65536);
+ }
+ if (opts.do_number > 1)
+ printf("Completed %d Test Unit Ready commands\n",
+ ((k < opts.do_number) ? k + 1 : k));
+ } else {
+#ifndef SG3_UTILS_MINGW
+ if (opts.do_time) {
+ start_tm.tv_sec = 0;
+ start_tm.tv_usec = 0;
+ gettimeofday(&start_tm, NULL);
+ }
+#endif
+ for (k = 0; k < opts.do_number; ++k) {
+ res = sg_ll_test_unit_ready(sg_fd, k, 0, opts.do_verbose);
+ if (res) {
+ ++num_errs;
+ ret = res;
+ if ((1 == opts.do_number) && (SG_LIB_CAT_NOT_READY == res)) {
+ printf("device not ready\n");
+ reported = 1;
+ break;
+ }
+ }
+ }
+#ifndef SG3_UTILS_MINGW
+ if ((opts.do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
+ struct timeval res_tm;
+ double a, b;
+
+ gettimeofday(&end_tm, NULL);
+ res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec;
+ res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec;
+ if (res_tm.tv_usec < 0) {
+ --res_tm.tv_sec;
+ res_tm.tv_usec += 1000000;
+ }
+ a = res_tm.tv_sec;
+ a += (0.000001 * res_tm.tv_usec);
+ b = (double)opts.do_number;
+ printf("time to perform commands was %d.%06d secs",
+ (int)res_tm.tv_sec, (int)res_tm.tv_usec);
+ if (a > 0.00001)
+ printf("; %.2f operations/sec\n", b / a);
+ else
+ printf("\n");
+ }
+#endif
+
+ if (((opts.do_number > 1) || (num_errs > 0)) && (! reported))
+ printf("Completed %d Test Unit Ready commands with %d errors\n",
+ opts.do_number, num_errs);
+ }
+ sg_cmds_close_device(sg_fd);
+ return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
+}