diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2007-06-27 02:58:48 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2007-06-27 02:58:48 +0000 |
commit | 1f7410c00c57dcc2c6b0d64a33431e2298a7c87b (patch) | |
tree | cf20d39db1f13f940c98910a2248af147dc09b55 /archive | |
parent | cc763ae132f3fa5b74bfb17819c64939f5b9b2cf (diff) | |
download | sg3_utils-1f7410c00c57dcc2c6b0d64a33431e2298a7c87b.tar.gz |
To prepare to load sg3_utils-1.07 into trunk/, perform 2 renames.
* trunk//archive/scsi_devfs_scan.8: Renamed from
trunk//scsi_devfs_scan.8.
* trunk//archive/scsi_devfs_scan.c: Renamed from
trunk//scsi_devfs_scan.c.
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@38 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'archive')
-rw-r--r-- | archive/scsi_devfs_scan.8 | 42 | ||||
-rw-r--r-- | archive/scsi_devfs_scan.c | 354 |
2 files changed, 396 insertions, 0 deletions
diff --git a/archive/scsi_devfs_scan.8 b/archive/scsi_devfs_scan.8 new file mode 100644 index 00000000..c371b24c --- /dev/null +++ b/archive/scsi_devfs_scan.8 @@ -0,0 +1,42 @@ +.TH SG_DEVFS_SCAN "8" "April 2003" "sg3_utils-1.03" SG3_UTILS +.SH NAME +sg_devfs_scan \- Scan SCSI devices within a devfs tree +.SH SYNOPSIS +.B sg_devfs_scan +[\fI-d <dir>\fR] +[\fI-i\fR] +[\fI-ide\fR] +[\fI-l [-x]\fR] +[\fI-q\fR] +<\fIgeneric device\fR> +.SH DESCRIPTION +.\" Add any additional description here +.PP +scsi_devfs_scan is a utility for doing a directory scan on a system +running devfs to identify SCSI (and optionally IDE) devices. Various +information (including an INQUIRY) can be listed for each found device. +.TP +-d <dir> +location of devfs [default: /dev ] +.TP +-i +show INQUIRY data for each SCSI device +.TP +-ide +show scan of IDE devices after SCSI ones +.TP +-l +show device file names in leaf directory +.TP +-x +add (major,minor) information to '-l' +.TP +-q +just output host, bus, target, lun numbers +.SH AUTHORS +Written by D. Gilbert +.SH COPYRIGHT +Copyright \(co 2001 Douglas Gilbert +.br +This software is distributed under the GPL version 2. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/archive/scsi_devfs_scan.c b/archive/scsi_devfs_scan.c new file mode 100644 index 00000000..20f273d1 --- /dev/null +++ b/archive/scsi_devfs_scan.c @@ -0,0 +1,354 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <dirent.h> +#include <errno.h> +#include <unistd.h> +#include "sg_include.h" +#include "sg_err.h" + +/* Code for scanning for SCSI devices within a Linux device pseudo file + system. + * Copyright (C) 2001 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. + + This program scans the /dev directory structure looking for the + devfs "primary" scsi (and optionally IDE) device names. + + Version 0.13 20030430 +*/ + +void usage() +{ + printf("Usage: 'scsi_devfs_scan [-d <dir>] [-i] [-ide] [-l [-x]] " + "[-q]'\n"); + printf(" where: -d <dir> location of devfs [default: /dev ]\n"); + printf(" -i show INQUIRY data for each SCSI device\n"); + printf(" -ide show scan of IDE devices after SCSI devices\n"); + printf(" -l show device file names in leaf directory\n"); + printf(" -q just output host, bus, target, lun numbers\n"); + printf(" -x add (major,minor) information to '-l'\n"); +} + +#define NAME_LEN_MAX 256 +#define LEVELS 4 + +#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */ +#define INQUIRY_CMD 0x12 +#define INQUIRY_CMDLEN 6 + +static const char * level_arr[LEVELS] = {"host", "bus", "target", "lun"}; + +static int do_ide = 0; +static int do_inq = 0; +static int do_leaf = 0; +static int do_extra = 0; +static int do_quiet = 0; +static int checked_sg = 0; + +static void dStrHex(const char* str, int len) +{ + const char* p = str; + unsigned char c; + char buff[82]; + int a = 0; + const int bpstart = 5; + const int cpstart = 60; + int cpos = cpstart; + int bpos = bpstart; + int i, k; + + if (len <= 0) return; + memset(buff,' ',80); + buff[80]='\0'; + k = sprintf(buff + 1, "%.2x", a); + buff[k + 1] = ' '; + if (bpos >= ((bpstart + (9 * 3)))) + bpos++; + + for(i = 0; i < len; i++) + { + c = *p++; + bpos += 3; + if (bpos == (bpstart + (9 * 3))) + bpos++; + sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c); + buff[bpos + 2] = ' '; + if ((c < ' ') || (c >= 0x7f)) + c='.'; + buff[cpos++] = c; + if (cpos > (cpstart+15)) + { + printf("%s\n", buff); + bpos = bpstart; + cpos = cpstart; + a += 16; + memset(buff,' ',80); + k = sprintf(buff + 1, "%.2x", a); + buff[k + 1] = ' '; + } + } + if (cpos > cpstart) + { + printf("%s\n", buff); + } +} + +static int do_inquiry(int sg_fd, void * resp, int mx_resp_len) +{ + int res; + unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0}; + unsigned char sense_b[SENSE_BUFF_LEN]; + sg_io_hdr_t io_hdr; + + inqCmdBlk[4] = (unsigned char)mx_resp_len; + memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); + io_hdr.interface_id = 'S'; + io_hdr.cmd_len = sizeof(inqCmdBlk); + io_hdr.mx_sb_len = sizeof(sense_b); + io_hdr.dxfer_direction = SG_DXFER_TO_FROM_DEV; + io_hdr.dxfer_len = mx_resp_len; + io_hdr.dxferp = resp; + io_hdr.cmdp = inqCmdBlk; + io_hdr.timeout = DEF_TIMEOUT; + + if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { + perror("SG_IO (inquiry) error"); + return -1; + } + res = sg_err_category3(&io_hdr); + switch (res) { + case SG_ERR_CAT_CLEAN: + case SG_ERR_CAT_RECOVERED: + return 0; + default: + sg_chk_n_print3("Failed INQUIRY", &io_hdr); + return -1; + } +} + +void leaf_dir(const char * lf, unsigned int * larr) +{ + char name[NAME_LEN_MAX * 2]; + int res; + + if (do_quiet) { + printf("%u\t%u\t%u\t%u\n", larr[0], larr[1], larr[2], larr[3]); + return; + } + printf("%u\t%u\t%u\t%u\t%s\n", larr[0], larr[1], larr[2], larr[3], lf); + if (do_leaf) { + struct dirent * de_entry; + struct dirent * de_result; + DIR * sdir; + int outpos; + + if (NULL == (sdir = opendir(lf))) { + fprintf(stderr, "leaf_dir: opendir of %s: failed\n", lf); + return; + } + de_entry = (struct dirent *)malloc(sizeof(struct dirent) + + NAME_LEN_MAX); + if (NULL == de_entry) + return; + res = 0; + printf("\t"); + outpos = 8; + while (1) { + res = readdir_r(sdir, de_entry, &de_result); + if (0 != res) { + fprintf(stderr, "leaf_dir: readdir_r of %s: %s\n", + lf, strerror(res)); + res = -2; + break; + } + if (de_result == NULL) + break; + strncpy(name, de_entry->d_name, NAME_LEN_MAX * 2); + if ((0 == strcmp("..", name)) ||(0 == strcmp(".", name))) + continue; + if (do_extra) { + struct stat st; + char devname[NAME_LEN_MAX * 2]; + + strncpy(devname, lf, NAME_LEN_MAX * 2); + strcat(devname, "/"); + strcat(devname, name); + if (stat(devname, &st) < 0) + return; + if (S_ISCHR(st.st_mode)) { + strcat(name, "(c "); + sprintf(name + strlen(name), "%d %d)", major(st.st_rdev), + minor(st.st_rdev)); + } + else if (S_ISBLK(st.st_mode)) { + strcat(name, "(b "); + sprintf(name + strlen(name), "%d %d)", major(st.st_rdev), + minor(st.st_rdev)); + } + } + res = strlen(name); + if ((outpos + res + 2) > 80) { + printf("\n\t"); + outpos = 8; + } + printf("%s ", name); + outpos += res + 2; + } + printf("\n"); + } + if (do_inq) { + int sg_fd; + char buff[64]; + + memset(buff, 0, sizeof(buff)); + strncpy(name, lf, NAME_LEN_MAX * 2); + strcat(name, "/generic"); + if ((sg_fd = open(name, O_RDONLY)) < 0) { + if (! checked_sg) { + checked_sg = 1; + if ((sg_fd = open("/dev/sg0", O_RDONLY)) >= 0) + close(sg_fd); /* try and get sg module loaded */ + sg_fd = open(name, O_RDONLY); + } + if (sg_fd < 0) { + printf("Unable to open sg device: %s, %s\n", name, + strerror(errno)); + return; + } + } + if (0 != do_inquiry(sg_fd, buff, 64)) + return; + close(sg_fd); + dStrHex(buff, 64); + } +} + +/* Return 0 -> ok, -1 -> opendir() error, -2 -> readdir_r error, + -3 -> malloc error */ +int hbtl_scan(const char * path, int level, unsigned int *larr) +{ + struct dirent * de_entry; + struct dirent * de_result; + char new_path[NAME_LEN_MAX * 2]; + DIR * sdir; + int res; + size_t level_slen; + + level_slen = strlen(level_arr[level]); + if (NULL == (sdir = opendir(path))) { + fprintf(stderr, "hbtl_scan: opendir of %s: failed\n", path); + return -1; + } + de_entry = (struct dirent *)malloc(sizeof(struct dirent) + NAME_LEN_MAX); + if (NULL == de_entry) + return -3; + res = 0; + while (1) { + res = readdir_r(sdir, de_entry, &de_result); + if (0 != res) { + fprintf(stderr, "hbtl_scan: readdir_r of %s: %s\n", + path, strerror(res)); + res = -2; + break; + } + if (de_result == NULL) + break; + if (0 == strncmp(level_arr[level], de_entry->d_name, level_slen)) { + if (1 != sscanf(de_entry->d_name + level_slen, "%u", larr + level)) + larr[level] = UINT_MAX; + strncpy(new_path, path, NAME_LEN_MAX * 2); + strcat(new_path, "/"); + strcat(new_path, de_entry->d_name); + if ((level + 1) < LEVELS) { + res = hbtl_scan(new_path, level + 1, larr); + if (res < 0) + break; + } + else + leaf_dir(new_path, larr); + } + } + free(de_entry); + closedir(sdir); + return res; +} + +#define D_ROOT_SZ 512 + + +int main(int argc, char * argv[]) +{ + int k, res; + char ds_root[D_ROOT_SZ]; + char di_root[D_ROOT_SZ]; + unsigned int larr[LEVELS]; + struct stat st; + + strncpy(ds_root, "/dev", D_ROOT_SZ); + for (k = 1; k < argc; ++k) { + if (0 == strcmp("-ide", argv[k])) + do_ide = 1; + else if (0 == strcmp("-i", argv[k])) + do_inq = 1; + else if (0 == strcmp("-l", argv[k])) + do_leaf = 1; + else if (0 == strcmp("-x", argv[k])) + do_extra = 1; + else if (0 == strcmp("-q", argv[k])) + do_quiet = 1; + else if (0 == strncmp("-d", argv[k], 2)) { + if (strlen(argv[k]) > 2) + strncpy(ds_root, argv[k] + 2, D_ROOT_SZ); + else if (++k < argc) + strncpy(ds_root, argv[k], D_ROOT_SZ); + } + else if ((0 == strcmp("-?", argv[k])) || + (0 == strncmp("-h", argv[k], 2))) { + printf("Scan SCSI devices within a devfs tree\n\n"); + usage(); + return 1; + } + else if (*argv[k] == '-') { + printf("Unknown switch: %s\n", argv[k]); + usage(); + return 1; + } + else if (*argv[k] != '-') { + printf("Unknown argument\n"); + usage(); + return 1; + } + } + strncpy(di_root, ds_root, D_ROOT_SZ); + strcat(di_root, "/.devfsd"); + if (stat(di_root, &st) < 0) + printf("Didn't find %s so perhaps devfs is not present," + " continuing ...\n", di_root); + strncpy(di_root, ds_root, D_ROOT_SZ); + strcat(ds_root, "/scsi"); + strcat(di_root, "/ide"); + + if (do_ide) + printf("SCSI scan:\n"); + res = hbtl_scan(ds_root, 0, larr); + if (res < 0) + printf("main: scsi hbtl_scan res=%d\n", res); + do_inq = 0; /* won't try SCSI INQUIRY on IDE devices */ + if (do_ide) { + printf("\nIDE scan:\n"); + res = hbtl_scan(di_root, 0, larr); + if (res < 0) + printf("main: ide hbtl_scan res=%d\n", res); + } + return 0; +} |