2
* Copyright (c) 2005-2006 Douglas Gilbert.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. The name of the author may not be used to endorse or promote products
14
* derived from this software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
/* A utility program for the Linux OS SCSI subsystem.
33
* This program maps a primary SCSI device node name to the corresponding
34
* SCSI generic device node name (or vice versa). Targets linux
35
* kernel 2.6 series. Sysfs device names can also be mapped.
38
/* #define _XOPEN_SOURCE 500 */
39
/* needed to see DT_REG and friends when compiled with: c99 pedantic */
52
#include <sys/ioctl.h>
53
#include <sys/types.h>
55
#include <linux/major.h>
59
static char * version_str = "1.03 20060623";
61
#define ME "sg_map26: "
74
#define NAME_LEN_MAX 260
75
#define D_NAME_LEN_MAX 516
77
#ifndef SCSI_CHANGER_MAJOR
78
#define SCSI_CHANGER_MAJOR 86
81
#define OSST_MAJOR 206
84
/* scandir() and stat() categories */
91
/* older major.h headers may not have these */
92
#ifndef SCSI_DISK8_MAJOR
93
#define SCSI_DISK8_MAJOR 128
94
#define SCSI_DISK9_MAJOR 129
95
#define SCSI_DISK10_MAJOR 130
96
#define SCSI_DISK11_MAJOR 131
97
#define SCSI_DISK12_MAJOR 132
98
#define SCSI_DISK13_MAJOR 133
99
#define SCSI_DISK14_MAJOR 134
100
#define SCSI_DISK15_MAJOR 135
103
static const char * sys_sg_dir = "/sys/class/scsi_generic/";
104
static const char * sys_sd_dir = "/sys/block/";
105
static const char * sys_sr_dir = "/sys/block/";
106
static const char * sys_hd_dir = "/sys/block/";
107
static const char * sys_st_dir = "/sys/class/scsi_tape/";
108
static const char * sys_sch_dir = "/sys/class/scsi_changer/";
109
static const char * sys_osst_dir = "/sys/class/onstream_tape/";
110
static const char * def_dev_dir = "/dev";
113
static struct option long_options[] = {
114
{"dev_dir", 1, 0, 'd'},
115
{"given_is", 1, 0, 'g'},
117
{"result", 1, 0, 'r'},
118
{"symlink", 0, 0, 's'},
119
{"verbose", 0, 0, 'v'},
120
{"version", 0, 0, 'V'},
124
static const char * nt_names[] = {
139
fprintf(stderr, "Usage: "
140
"sg_map26 [--dev_dir=<dir>] [--given_is=<n>] [--help] "
142
" [--symlink] [--verbose] [--version] "
145
" --dev_dir=<dir>|-d <dir> search in <dir> for "
146
"resulting special\n"
147
" (def: directory of <device> "
149
" --given_is=<n>|-g <n> variety of given "
151
" 0->block or char special "
153
" 1->sysfs device, 'dev' or "
155
" --help|-h print out usage message\n"
156
" --result=<n>|-r <n> variety of file(s) to "
158
" 0->mapped block or char "
160
" 1->mapped sysfs parent\n"
161
" 2->matching block or char "
163
" 3->matching sysfs parent\n"
164
" --symlink|-s symlinks to special included in "
166
" --verbose|-v set device identifier\n"
167
" --version|-V print version string and exit\n\n"
168
"Maps SCSI device node to corresponding generic node (and "
174
/* ssafe_strerror() contributed by Clayton Weaver <cgweav at email dot com>
175
Allows for situation in which strerror() is given a wild value (or the
176
C library is incomplete) and returns NULL. Still not thread safe.
179
static char safe_errbuf[64] = {'u', 'n', 'k', 'n', 'o', 'w', 'n', ' ',
180
'e', 'r', 'r', 'n', 'o', ':', ' ', 0};
182
static char * ssafe_strerror(int errnum)
187
errstr = strerror(errnum);
188
if (NULL == errstr) {
189
len = strlen(safe_errbuf);
190
snprintf(safe_errbuf + len, sizeof(safe_errbuf) - len, "%i",
192
safe_errbuf[sizeof(safe_errbuf) - 1] = '\0'; /* bombproof */
198
static int nt_typ_from_filename(const char * filename, int * majj, int * minn)
203
if (stat(filename, &st) < 0)
205
ma = major(st.st_rdev);
206
mi = minor(st.st_rdev);
211
if (S_ISCHR(st.st_mode)) {
215
case SCSI_GENERIC_MAJOR:
217
case SCSI_TAPE_MAJOR:
219
case SCSI_CHANGER_MAJOR:
224
} else if (S_ISBLK(st.st_mode)) {
226
case SCSI_DISK0_MAJOR: case SCSI_DISK1_MAJOR:
227
case SCSI_DISK2_MAJOR: case SCSI_DISK3_MAJOR:
228
case SCSI_DISK4_MAJOR: case SCSI_DISK5_MAJOR:
229
case SCSI_DISK6_MAJOR: case SCSI_DISK7_MAJOR:
230
case SCSI_DISK8_MAJOR: case SCSI_DISK9_MAJOR:
231
case SCSI_DISK10_MAJOR: case SCSI_DISK11_MAJOR:
232
case SCSI_DISK12_MAJOR: case SCSI_DISK13_MAJOR:
233
case SCSI_DISK14_MAJOR: case SCSI_DISK15_MAJOR:
235
case SCSI_CDROM_MAJOR:
237
case IDE0_MAJOR: case IDE1_MAJOR:
238
case IDE2_MAJOR: case IDE3_MAJOR:
239
case IDE4_MAJOR: case IDE5_MAJOR:
240
case IDE6_MAJOR: case IDE7_MAJOR:
241
case IDE8_MAJOR: case IDE9_MAJOR:
246
} else if (S_ISREG(st.st_mode))
248
else if (S_ISDIR(st.st_mode))
253
static int nt_typ_from_major(int ma)
256
case SCSI_DISK0_MAJOR: case SCSI_DISK1_MAJOR:
257
case SCSI_DISK2_MAJOR: case SCSI_DISK3_MAJOR:
258
case SCSI_DISK4_MAJOR: case SCSI_DISK5_MAJOR:
259
case SCSI_DISK6_MAJOR: case SCSI_DISK7_MAJOR:
260
case SCSI_DISK8_MAJOR: case SCSI_DISK9_MAJOR:
261
case SCSI_DISK10_MAJOR: case SCSI_DISK11_MAJOR:
262
case SCSI_DISK12_MAJOR: case SCSI_DISK13_MAJOR:
263
case SCSI_DISK14_MAJOR: case SCSI_DISK15_MAJOR:
265
case SCSI_CDROM_MAJOR:
267
case IDE0_MAJOR: case IDE1_MAJOR:
268
case IDE2_MAJOR: case IDE3_MAJOR:
269
case IDE4_MAJOR: case IDE5_MAJOR:
270
case IDE6_MAJOR: case IDE7_MAJOR:
271
case IDE8_MAJOR: case IDE9_MAJOR:
275
case SCSI_GENERIC_MAJOR:
277
case SCSI_TAPE_MAJOR:
279
case SCSI_CHANGER_MAJOR:
288
struct node_match_item {
289
const char * dir_name;
296
static struct node_match_item nd_match;
298
static int nd_match_scandir_select(const struct dirent * s)
301
char name[D_NAME_LEN_MAX];
306
if (FT_BLOCK != nd_match.file_type)
310
if (FT_CHAR != nd_match.file_type)
314
return (FT_DIR == nd_match.file_type) ? 1 : 0;
316
return (FT_REGULAR == nd_match.file_type) ? 1 : 0;
317
case DT_LNK: /* follow symlinks */
318
if (! nd_match.follow_symlink)
325
if ((! symlnk) && (-1 == nd_match.majj) && (-1 == nd_match.minn))
327
strncpy(name, nd_match.dir_name, NAME_LEN_MAX);
329
strncat(name, s->d_name, NAME_LEN_MAX);
330
memset(&st, 0, sizeof(st));
331
if (stat(name, &st) < 0)
334
if (S_ISCHR(st.st_mode)) {
335
if (FT_CHAR != nd_match.file_type)
337
} else if (S_ISBLK(st.st_mode)) {
338
if (FT_BLOCK != nd_match.file_type)
343
return (((-1 == nd_match.majj) ||
344
((unsigned)major(st.st_rdev) == (unsigned)nd_match.majj)) &&
345
((-1 == nd_match.minn) ||
346
((unsigned)minor(st.st_rdev) == (unsigned)nd_match.minn)))
350
static int list_matching_nodes(const char * dir_name, int file_type,
351
int majj, int minn, int follow_symlink,
354
struct dirent ** namelist;
357
nd_match.dir_name = dir_name;
358
nd_match.file_type = file_type;
359
nd_match.majj = majj;
360
nd_match.minn = minn;
361
nd_match.follow_symlink = follow_symlink;
362
num = scandir(dir_name, &namelist, nd_match_scandir_select, NULL);
365
fprintf(stderr, "scandir: %s %s\n", dir_name,
366
ssafe_strerror(errno));
369
for (k = 0; k < num; ++k) {
370
printf("%s/%s\n", dir_name, namelist[k]->d_name);
378
char name[NAME_LEN_MAX];
383
static struct sg_item_t from_sg;
385
static int from_sg_scandir_select(const struct dirent * s)
389
if (FT_OTHER != from_sg.ft)
391
if (DT_LNK != s->d_type)
393
if (0 == strncmp("scsi_changer", s->d_name, 12)) {
394
strncpy(from_sg.name, s->d_name, NAME_LEN_MAX);
395
from_sg.ft = FT_CHAR;
398
} else if (0 == strncmp("block", s->d_name, 5)) {
399
strncpy(from_sg.name, s->d_name, NAME_LEN_MAX);
400
from_sg.ft = FT_BLOCK;
402
} else if (0 == strcmp("tape", s->d_name)) {
403
strcpy(from_sg.name, s->d_name);
404
from_sg.ft = FT_CHAR;
407
} else if (0 == strncmp("scsi_tape:st", s->d_name, 12)) {
408
len = strlen(s->d_name);
409
if (isdigit(s->d_name[len - 1])) {
410
/* want 'st<num>' symlink only */
411
strcpy(from_sg.name, s->d_name);
412
from_sg.ft = FT_CHAR;
417
} else if (0 == strncmp("onstream_tape:os", s->d_name, 16)) {
418
strcpy(from_sg.name, s->d_name);
419
from_sg.ft = FT_CHAR;
420
from_sg.nt = NT_OSST;
426
static int from_sg_scan(const char * dir_name, int verbose)
428
struct dirent ** namelist;
431
from_sg.ft = FT_OTHER;
432
from_sg.nt = NT_NO_MATCH;
433
num = scandir(dir_name, &namelist, from_sg_scandir_select, NULL);
436
fprintf(stderr, "scandir: %s %s\n", dir_name,
437
ssafe_strerror(errno));
441
for (k = 0; k < num; ++k)
442
fprintf(stderr, " %s/%s\n", dir_name,
443
namelist[k]->d_name);
445
for (k = 0; k < num; ++k)
451
static struct sg_item_t to_sg;
453
static int to_sg_scandir_select(const struct dirent * s)
455
if (FT_OTHER != to_sg.ft)
457
if (DT_LNK != s->d_type)
459
if (0 == strncmp("scsi_generic", s->d_name, 12)) {
460
strncpy(to_sg.name, s->d_name, NAME_LEN_MAX);
468
static int to_sg_scan(const char * dir_name)
470
struct dirent ** namelist;
474
to_sg.nt = NT_NO_MATCH;
475
num = scandir(dir_name, &namelist, to_sg_scandir_select, NULL);
478
for (k = 0; k < num; ++k)
484
/* Return 1 if directory, else 0 */
485
static int if_directory_chdir(const char * dir_name, const char * base_name)
487
char buff[D_NAME_LEN_MAX];
490
strcpy(buff, dir_name);
492
strcat(buff, base_name);
493
if (stat(buff, &a_stat) < 0)
495
if (S_ISDIR(a_stat.st_mode)) {
503
/* Return 1 if directory, else 0 */
504
static int if_directory_ch2generic(const char * dir_name)
506
char buff[NAME_LEN_MAX];
508
const char * old_name = "generic";
510
strcpy(buff, dir_name);
512
strcat(buff, old_name);
513
if ((stat(buff, &a_stat) >= 0) && S_ISDIR(a_stat.st_mode)) {
518
/* No "generic", so now look for "scsi_generic:sg<n>" */
519
if (1 != to_sg_scan(dir_name))
521
strcpy(buff, dir_name);
523
strcat(buff, to_sg.name);
524
if (stat(buff, &a_stat) < 0)
526
if (S_ISDIR(a_stat.st_mode)) {
534
/* Return 1 if found, else 0 if problems */
535
static int get_value(const char * dir_name, const char * base_name,
536
char * value, int max_value_len)
538
char buff[D_NAME_LEN_MAX];
542
if ((NULL == dir_name) && (NULL == base_name))
545
strcpy(buff, dir_name);
546
if (base_name && (strlen(base_name) > 0)) {
548
strcat(buff, base_name);
551
strcpy(buff, base_name);
552
if (NULL == (f = fopen(buff, "r"))) {
555
if (NULL == fgets(value, max_value_len, f)) {
560
if ((len > 0) && (value[len - 1] == '\n'))
561
value[len - 1] = '\0';
566
static int map_hd(const char * device_dir, int ma, int mi, int result,
567
int follow_symlink, int verbose)
572
num = list_matching_nodes(device_dir, FT_BLOCK,
573
ma, mi, follow_symlink,
575
return (num > 0) ? 0 : 1;
578
case IDE0_MAJOR: c = 'a'; break;
579
case IDE1_MAJOR: c = 'c'; break;
580
case IDE2_MAJOR: c = 'e'; break;
581
case IDE3_MAJOR: c = 'g'; break;
582
case IDE4_MAJOR: c = 'i'; break;
583
case IDE5_MAJOR: c = 'k'; break;
584
case IDE6_MAJOR: c = 'm'; break;
585
case IDE7_MAJOR: c = 'o'; break;
586
case IDE8_MAJOR: c = 'q'; break;
587
case IDE9_MAJOR: c = 's'; break;
588
default: c = '?'; break;
592
printf("%shd%c\n", sys_hd_dir, c);
596
static int map_sd(const char * device_name, const char * device_dir,
597
int ma, int mi, int result, int follow_symlink,
600
int index, m_mi, m_ma, num;
601
char value[D_NAME_LEN_MAX];
602
char name[D_NAME_LEN_MAX];
605
num = list_matching_nodes(device_dir, FT_BLOCK, ma, mi,
606
follow_symlink, verbose);
607
return (num > 0) ? 0 : 1;
609
if (SCSI_DISK0_MAJOR == ma)
611
else if (ma >= SCSI_DISK8_MAJOR)
612
index = (mi / 16) + 128 +
613
((ma - SCSI_DISK8_MAJOR) * 16);
615
index = (mi / 16) + 16 +
616
((ma - SCSI_DISK1_MAJOR) * 16);
618
snprintf(name, sizeof(name), "%ssd%c",
619
sys_sd_dir, 'a' + index % 26);
620
else if (index < (26 + 1) * 26)
621
snprintf(name, sizeof(name), "%ssd%c%c",
623
'a' + index / 26 - 1,'a' + index % 26);
625
const unsigned int m1 = (index / 26 - 1) / 26 - 1;
626
const unsigned int m2 = (index / 26 - 1) % 26;
627
const unsigned int m3 = index % 26;
629
snprintf(name, sizeof(name), "%ssd%c%c%c",
630
sys_sd_dir, 'a' + m1, 'a' + m2, 'a' + m3);
633
printf("%s\n", name);
636
if (! get_value(name, "dev", value, sizeof(value))) {
637
fprintf(stderr, "Couldn't find sysfs match for "
638
"device: %s\n", device_name);
642
fprintf(stderr, "sysfs sd dev: %s\n", value);
643
if (! if_directory_chdir(name, "device")) {
644
fprintf(stderr, "sysfs problem with device: %s\n",
648
if (if_directory_ch2generic(".")) {
650
if (NULL == getcwd(value, sizeof(value)))
652
printf("%s\n", value);
655
if (! get_value(".", "dev", value, sizeof(value))) {
656
fprintf(stderr, "Couldn't find sysfs generic"
661
printf("matching dev: %s\n", value);
662
if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
663
fprintf(stderr, "Couldn't decode mapped "
667
num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
668
follow_symlink, verbose);
669
return (num > 0) ? 0 : 1;
671
fprintf(stderr, "sd device: %s does not match any "
672
"SCSI generic device\n", device_name);
673
fprintf(stderr, " perhaps sg module is not "
679
static int map_sr(const char * device_name, const char * device_dir, int ma,
680
int mi, int result, int follow_symlink, int verbose)
683
char value[D_NAME_LEN_MAX];
684
char name[D_NAME_LEN_MAX];
687
num = list_matching_nodes(device_dir, FT_BLOCK, ma, mi,
688
follow_symlink, verbose);
689
return (num > 0) ? 0 : 1;
691
snprintf(name, sizeof(name), "%ssr%d", sys_sr_dir, mi);
693
printf("%s\n", name);
696
if (! get_value(name, "dev", value, sizeof(value))) {
697
fprintf(stderr, "Couldn't find sysfs match for "
698
"device: %s\n", device_name);
702
fprintf(stderr, "sysfs sr dev: %s\n", value);
703
if (! if_directory_chdir(name, "device")) {
704
fprintf(stderr, "sysfs problem with device: %s\n",
708
if (if_directory_ch2generic(".")) {
710
if (NULL == getcwd(value, sizeof(value)))
712
printf("%s\n", value);
715
if (! get_value(".", "dev", value, sizeof(value))) {
716
fprintf(stderr, "Couldn't find sysfs generic"
721
printf("matching dev: %s\n", value);
722
if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
723
fprintf(stderr, "Couldn't decode mapped "
727
num = list_matching_nodes(device_dir, FT_BLOCK, m_ma, m_mi,
728
follow_symlink, verbose);
729
return (num > 0) ? 0 : 1;
731
fprintf(stderr, "sr device: %s does not match any "
732
"SCSI generic device\n", device_name);
733
fprintf(stderr, " perhaps sg module is not "
739
static int map_st(const char * device_name, const char * device_dir, int ma,
740
int mi, int result, int follow_symlink, int verbose)
743
char value[D_NAME_LEN_MAX];
744
char name[D_NAME_LEN_MAX];
747
num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
748
follow_symlink, verbose);
749
return (num > 0) ? 0 : 1;
751
snprintf(name, sizeof(name), "%sst%d", sys_st_dir,
754
printf("%s\n", name);
757
if (! get_value(name, "dev", value, sizeof(value))) {
758
fprintf(stderr, "Couldn't find sysfs match for "
759
"device: %s\n", device_name);
763
fprintf(stderr, "sysfs st dev: %s\n", value);
764
if (! if_directory_chdir(name, "device")) {
765
fprintf(stderr, "sysfs problem with device: %s\n",
769
if (if_directory_ch2generic(".")) {
771
if (NULL == getcwd(value, sizeof(value)))
773
printf("%s\n", value);
776
if (! get_value(".", "dev", value, sizeof(value))) {
777
fprintf(stderr, "Couldn't find sysfs generic"
782
printf("matching dev: %s\n", value);
783
if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
784
fprintf(stderr, "Couldn't decode mapped "
788
num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
789
follow_symlink, verbose);
790
return (num > 0) ? 0 : 1;
792
fprintf(stderr, "st device: %s does not match any "
793
"SCSI generic device\n", device_name);
794
fprintf(stderr, " perhaps sg module is not "
800
static int map_osst(const char * device_name, const char * device_dir, int ma,
801
int mi, int result, int follow_symlink, int verbose)
804
char value[D_NAME_LEN_MAX];
805
char name[D_NAME_LEN_MAX];
808
num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
809
follow_symlink, verbose);
810
return (num > 0) ? 0 : 1;
812
snprintf(name, sizeof(name), "%sosst%d", sys_osst_dir,
815
printf("%s\n", name);
818
if (! get_value(name, "dev", value, sizeof(value))) {
819
fprintf(stderr, "Couldn't find sysfs match for "
820
"device: %s\n", device_name);
824
fprintf(stderr, "sysfs osst dev: %s\n", value);
825
if (! if_directory_chdir(name, "device")) {
826
fprintf(stderr, "sysfs problem with device: %s\n",
830
if (if_directory_ch2generic(".")) {
832
if (NULL == getcwd(value, sizeof(value)))
834
printf("%s\n", value);
837
if (! get_value(".", "dev", value, sizeof(value))) {
838
fprintf(stderr, "Couldn't find sysfs generic"
843
printf("matching dev: %s\n", value);
844
if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
845
fprintf(stderr, "Couldn't decode mapped "
849
num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
850
follow_symlink, verbose);
851
return (num > 0) ? 0 : 1;
853
fprintf(stderr, "osst device: %s does not match any "
854
"SCSI generic device\n", device_name);
855
fprintf(stderr, " perhaps sg module is not "
861
static int map_ch(const char * device_name, const char * device_dir, int ma,
862
int mi, int result, int follow_symlink, int verbose)
865
char value[D_NAME_LEN_MAX];
866
char name[D_NAME_LEN_MAX];
869
num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
870
follow_symlink, verbose);
871
return (num > 0) ? 0 : 1;
873
snprintf(name, sizeof(name), "%ssch%d", sys_sch_dir, mi);
875
printf("%s\n", name);
878
if (! get_value(name, "dev", value, sizeof(value))) {
879
fprintf(stderr, "Couldn't find sysfs match for "
880
"device: %s\n", device_name);
884
fprintf(stderr, "sysfs sch dev: %s\n", value);
885
if (! if_directory_chdir(name, "device")) {
886
fprintf(stderr, "sysfs problem with device: %s\n",
890
if (if_directory_ch2generic(".")) {
892
if (NULL == getcwd(value, sizeof(value)))
894
printf("%s\n", value);
897
if (! get_value(".", "dev", value, sizeof(value))) {
898
fprintf(stderr, "Couldn't find sysfs generic"
903
printf("matching dev: %s\n", value);
904
if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
905
fprintf(stderr, "Couldn't decode mapped "
909
num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
910
follow_symlink, verbose);
911
return (num > 0) ? 0 : 1;
913
fprintf(stderr, "sch device: %s does not match any "
914
"SCSI generic device\n", device_name);
915
fprintf(stderr, " perhaps sg module is not "
921
static int map_sg(const char * device_name, const char * device_dir, int ma,
922
int mi, int result, int follow_symlink, int verbose)
925
char value[D_NAME_LEN_MAX];
926
char name[D_NAME_LEN_MAX];
929
num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
930
follow_symlink, verbose);
931
return (num > 0) ? 0 : 1;
933
snprintf(name, sizeof(name), "%ssg%d", sys_sg_dir, mi);
935
printf("%s\n", name);
938
if (! get_value(name, "dev", value, sizeof(value))) {
939
fprintf(stderr, "Couldn't find sysfs match for "
940
"device: %s\n", device_name);
944
fprintf(stderr, "sysfs sg dev: %s\n", value);
945
if (! if_directory_chdir(name, "device")) {
946
fprintf(stderr, "sysfs problem with device: %s\n",
950
if ((1 == from_sg_scan(".", verbose)) &&
951
(if_directory_chdir(".", from_sg.name))) {
953
if (NULL == getcwd(value, sizeof(value)))
955
printf("%s\n", value);
958
if (! get_value(".", "dev", value, sizeof(value))) {
959
fprintf(stderr, "Couldn't find sysfs block "
964
printf("matching dev: %s\n", value);
965
if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
966
fprintf(stderr, "Couldn't decode mapped "
970
num = list_matching_nodes(device_dir, from_sg.ft, m_ma, m_mi,
971
follow_symlink, verbose);
972
return (num > 0) ? 0 : 1;
974
fprintf(stderr, "sg device: %s does not match any "
975
"other SCSI device\n", device_name);
981
int main(int argc, char * argv[])
983
int c, num, tt, cont, res;
987
int follow_symlink = 0;
989
char device_name[D_NAME_LEN_MAX];
990
char device_dir[D_NAME_LEN_MAX];
991
char value[D_NAME_LEN_MAX];
995
memset(device_name, 0, sizeof(device_name));
996
memset(device_dir, 0, sizeof(device_dir));
998
int option_index = 0;
1000
c = getopt_long(argc, argv, "d:hg:r:svV", long_options,
1007
strncpy(device_dir, optarg, sizeof(device_dir));
1011
num = sscanf(optarg, "%d", &res);
1012
if ((1 == num) && ((0 == res) || (1 == res)))
1015
fprintf(stderr, "value for '--given_to=' "
1016
"must be 0 or 1\n");
1017
return SG_LIB_SYNTAX_ERROR;
1025
num = sscanf(optarg, "%d", &res);
1026
if ((1 == num) && (res >= 0) && (res < 4))
1029
fprintf(stderr, "value for '--result=' "
1031
return SG_LIB_SYNTAX_ERROR;
1041
fprintf(stderr, ME "version: %s\n", version_str);
1044
fprintf(stderr, "unrecognised switch code 0x%x ??\n",
1047
return SG_LIB_SYNTAX_ERROR;
1050
if (optind < argc) {
1051
if ('\0' == device_name[0]) {
1052
strncpy(device_name, argv[optind],
1053
sizeof(device_name) - 1);
1054
device_name[sizeof(device_name) - 1] = '\0';
1057
if (optind < argc) {
1058
for (; optind < argc; ++optind)
1059
fprintf(stderr, "Unexpected extra argument: "
1060
"%s\n", argv[optind]);
1062
return SG_LIB_SYNTAX_ERROR;
1066
if (0 == device_name[0]) {
1067
fprintf(stderr, "missing device name!\n");
1069
return SG_LIB_SYNTAX_ERROR;
1075
if (if_directory_chdir(".", device_dir)) {
1076
if (getcwd(device_dir, sizeof(device_dir)))
1077
device_dir[sizeof(device_dir) - 1] = '\0';
1079
device_dir[0] = '\0';
1081
fprintf(stderr, "Absolute path to "
1082
"dev_dir: %s\n", device_dir);
1084
fprintf(stderr, "dev_dir: %s invalid\n", device_dir);
1085
return SG_LIB_FILE_ERROR;
1088
strcpy(device_dir, device_name);
1089
dirname(device_dir);
1090
if (0 == strcmp(device_dir, device_name)) {
1091
if (NULL == getcwd(device_dir, sizeof(device_dir)))
1092
device_dir[0] = '\0';
1095
ret = nt_typ_from_filename(device_name, &ma, &mi);
1097
fprintf(stderr, "stat failed on %s: %s\n", device_name,
1098
ssafe_strerror(-ret));
1099
return SG_LIB_FILE_ERROR;
1102
fprintf(stderr, " %s: %s device [maj=%d, min=%d]\n",
1103
device_name, nt_names[ret], ma, mi);
1110
fprintf(stderr, "block special but '--given_is=' "
1111
"suggested sysfs device\n");
1112
return SG_LIB_FILE_ERROR;
1120
fprintf(stderr, "character special but '--given_is=' "
1121
"suggested sysfs device\n");
1122
return SG_LIB_FILE_ERROR;
1126
if (0 == given_is) {
1127
fprintf(stderr, "regular file but '--given_is=' "
1128
"suggested block or char special\n");
1129
return SG_LIB_FILE_ERROR;
1131
strcpy(device_dir, def_dev_dir);
1134
if (0 == given_is) {
1135
fprintf(stderr, "directory but '--given_is=' "
1136
"suggested block or char special\n");
1137
return SG_LIB_FILE_ERROR;
1139
strcpy(device_dir, def_dev_dir);
1153
res = map_sd(device_name, device_dir, ma, mi, result,
1154
follow_symlink, verbose);
1157
res = map_sr(device_name, device_dir, ma, mi, result,
1158
follow_symlink, verbose);
1162
fprintf(stderr, "a hd device does not map "
1163
"to a sg device\n");
1164
return SG_LIB_FILE_ERROR;
1166
res = map_hd(device_dir, ma, mi, result,
1167
follow_symlink, verbose);
1170
res = map_st(device_name, device_dir, ma, mi, result,
1171
follow_symlink, verbose);
1174
res = map_osst(device_name, device_dir, ma, mi,
1175
result, follow_symlink, verbose);
1178
res = map_ch(device_name, device_dir, ma, mi, result,
1179
follow_symlink, verbose);
1182
res = map_sg(device_name, device_dir, ma, mi, result,
1183
follow_symlink, verbose);
1186
if (! get_value(NULL, device_name, value,
1188
fprintf(stderr, "Couldn't fetch value "
1189
"from: %s\n", device_name);
1190
return SG_LIB_FILE_ERROR;
1193
fprintf(stderr, "value: %s\n", value);
1194
if (2 != sscanf(value, "%d:%d", &ma, &mi)) {
1195
fprintf(stderr, "Couldn't decode value\n");
1196
return SG_LIB_FILE_ERROR;
1198
tt = nt_typ_from_major(ma);
1202
if (! get_value(device_name, "dev", value,
1204
fprintf(stderr, "Couldn't fetch value from: "
1205
"%s/dev\n", device_name);
1206
return SG_LIB_FILE_ERROR;
1209
fprintf(stderr, "value: %s\n", value);
1210
if (2 != sscanf(value, "%d:%d", &ma, &mi)) {
1211
fprintf(stderr, "Couldn't decode value\n");
1212
return SG_LIB_FILE_ERROR;
1214
tt = nt_typ_from_major(ma);