/* This is a utility program for listing SCSI devices and hosts (HBAs)
* in the Linux operating system. It is applicable to kernel versions
* 2.6.1 and greater.
* Copyright (C) 2003-2012 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.
*/
#define _XOPEN_SOURCE 600
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <libgen.h>
#include <linux/major.h>
#include <time.h>
static const char * version_str = "0.26 2012/01/31 [svn: r97]";
#define NAME_LEN_MAX 260
#define FT_OTHER 0
#define FT_BLOCK 1
#define FT_CHAR 2
#define TRANSPORT_UNKNOWN 0
#define TRANSPORT_SPI 1
#define TRANSPORT_FC 2
#define TRANSPORT_SAS 3
#define TRANSPORT_SAS_CLASS 4
#define TRANSPORT_ISCSI 5
#define TRANSPORT_SBP 6
#define TRANSPORT_USB 7
#define TRANSPORT_ATA 8 /* probably PATA, could be SATA */
#define TRANSPORT_SATA 9 /* most likely SATA */
#define TRANSPORT_FCOE 10
static int transport_id = TRANSPORT_UNKNOWN;
static const char * sysfsroot = "/sys";
static const char * bus_scsi_devs = "/bus/scsi/devices";
static const char * class_scsi_dev = "/class/scsi_device/";
static const char * scsi_host = "/class/scsi_host/";
static const char * spi_host = "/class/spi_host/";
static const char * spi_transport = "/class/spi_transport/";
static const char * sas_host = "/class/sas_host/";
static const char * sas_phy = "/class/sas_phy/";
static const char * sas_port = "/class/sas_port/";
static const char * sas_device = "/class/sas_device/";
static const char * sas_end_device = "/class/sas_end_device/";
static const char * fc_host = "/class/fc_host/";
static const char * fc_transport = "/class/fc_transport/";
static const char * fc_remote_ports = "/class/fc_remote_ports/";
static const char * iscsi_host = "/class/iscsi_host/";
static const char * iscsi_session = "/class/iscsi_session/";
static const char * dev_dir = "/dev";
static const char * dev_disk_byid_dir = "/dev/disk/by-id";
struct addr_hctl {
int h;
int c;
int t;
int l;
};
struct addr_hctl filter;
static int filter_active = 0;
struct lsscsi_opt_coll {
int long_opt; /* --long */
int classic;
int generic;
int dev_maj_min; /* --device */
int kname;
int protection; /* data integrity */
int protmode; /* data integrity */
int size;
int transport;
int verbose;
int wwn;
};
static const char * scsi_device_types[] =
{
"Direct-Access",
"Sequential-Access",
"Printer",
"Processor",
"Write-once",
"CD-ROM",
"Scanner",
"Optical memory",
"Medium Changer",
"Communications",
"Unknown (0xa)",
"Unknown (0xb)",
"Storage array",
"Enclosure",
"Simplified direct-access",
"Optical card read/writer",
"Bridge controller",
"Object based storage",
"Automation Drive interface",
"Reserved (0x13)", "Reserved (0x14)",
"Reserved (0x15)", "Reserved (0x16)", "Reserved (0x17)",
"Reserved (0x18)", "Reserved (0x19)", "Reserved (0x1a)",
"Reserved (0x1b)", "Reserved (0x1c)", "Reserved (0x1e)",
"Well known LU",
"No device",
};
static const char * scsi_short_device_types[] =
{
"disk ", "tape ", "printer", "process", "worm ", "cd/dvd ",
"scanner", "optical", "mediumx", "comms ", "(0xa) ", "(0xb) ",
"storage", "enclosu", "sim dsk", "opti rd", "bridge ", "osd ",
"adi ", "(0x13) ", "(0x14) ", "(0x15) ", "(0x16) ", "(0x17) ",
"(0x18) ", "(0x19) ", "(0x1a) ", "(0x1b) ", "(0x1c) ", "(0x1e) ",
"wlun ", "no dev ",
};
/* '--name' ('-n') option removed in version 0.11 and can now be reused */
static struct option long_options[] = {
{"classic", 0, 0, 'c'},
{"device", 0, 0, 'd'},
{"generic", 0, 0, 'g'},
{"help", 0, 0, 'h'},
{"hosts", 0, 0, 'H'},
{"kname", 0, 0, 'k'},
{"long", 0, 0, 'l'},
{"list", 0, 0, 'L'},
{"protection", 0, 0, 'p'},
{"protmode", 0, 0, 'P'},
{"size", 0, 0, 's'},
{"sysfsroot", 1, 0, 'y'},
{"transport", 0, 0, 't'},
{"verbose", 0, 0, 'v'},
{"version", 0, 0, 'V'},
{"wwn", 0, 0, 'w'},
{0, 0, 0, 0}
};
/* Device node list: contains the information needed to match a node with a
sysfs class device. */
#define DEV_NODE_LIST_ENTRIES 16
enum dev_type { BLK_DEV, CHR_DEV};
struct dev_node_list {
struct dev_node_list *next;
unsigned int count;
struct dev_node_entry {
unsigned int maj, min;
enum dev_type type;
time_t mtime;
char name [ NAME_MAX + 1];
} nodes[DEV_NODE_LIST_ENTRIES];
};
static struct dev_node_list* dev_node_listhead = NULL;
#define DISK_WWN_NODE_LIST_ENTRIES 16
struct disk_wwn_node_list {
struct disk_wwn_node_list *next;
unsigned int count;
struct disk_wwn_node_entry {
char wwn[32];
char disk_bname[12];
} nodes[DISK_WWN_NODE_LIST_ENTRIES];
};
static struct disk_wwn_node_list * disk_wwn_node_listhead = NULL;
struct item_t {
char name[NAME_LEN_MAX];
int ft;
int d_type;
};
static struct item_t non_sg;
static struct item_t aa_sg;
static struct item_t aa_first;
static struct item_t enclosure_device;
static char sas_low_phy[NAME_LEN_MAX];
static char sas_hold_end_device[NAME_LEN_MAX];
static const char * iscsi_dir_name;
static const struct addr_hctl * iscsi_target_hct;
static int iscsi_tsession_num;
static const char * usage_message =
"Usage: lsscsi [--classic] [--device] [--generic] [--help] [--hosts]\n"
"\t\t[--kname] [--list] [--long] [--protection] [--size]\n"
"\t\t[--sysfsroot=PATH] [--transport] [--verbose] [--version]\n"
"\t\t[--wwn] [<h:c:t:l>]\n"
" where:\n"
" --classic|-c alternate output similar to 'cat /proc/scsi/scsi'\n"
" --device|-d show device node's major + minor numbers\n"
" --generic|-g show scsi generic device name\n"
" --help|-h this usage information\n"
" --hosts|-H lists scsi hosts rather than scsi devices\n"
" --kname|-k show kernel name instead of device node name\n"
" --list|-L additional information output one\n"
" attribute=value per line\n"
" --long|-l additional information output\n"
" --protection|-p show target and initiator protection information\n"
" --protmode|-P show negotiated protection information mode\n"
" --size|-s show disk size\n"
" --sysfsroot=PATH|-y PATH set sysfs mount point to PATH (def: /sys)\n"
" --transport|-t transport information for target or, if '--hosts'\n"
" given, for initiator\n"
" --verbose|-v output path names where data is found\n"
" --version|-V output version string and exit\n"
" --wwn|-w output WWN for disks (from /dev/disk/by-id/wwn*)\n"
" <h:c:t:l> filter output list (def: '- - - -' (all))\n\n"
"List SCSI devices or hosts, optionally with additional information\n";
static void
usage(void)
{
fprintf(stderr, "%s", usage_message);
}
/* Returns remainder (*np % base) and replaces *np with (*np / base).
* base needs to be > 0 */
static unsigned int
do_div_rem(uint64_t * np, unsigned int base)
{
unsigned int res;
res = *np % base;
*np /= base;
return res;
}
enum string_size_units {
评论0
最新资源