1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche * Copyright (c) 2005-2022 Douglas Gilbert.
3*44704f69SBart Van Assche * All rights reserved.
4*44704f69SBart Van Assche * Use of this source code is governed by a BSD-style
5*44704f69SBart Van Assche * license that can be found in the BSD_LICENSE file.
6*44704f69SBart Van Assche *
7*44704f69SBart Van Assche * SPDX-License-Identifier: BSD-2-Clause
8*44704f69SBart Van Assche */
9*44704f69SBart Van Assche
10*44704f69SBart Van Assche /* A utility program for the Linux OS SCSI subsystem.
11*44704f69SBart Van Assche *
12*44704f69SBart Van Assche *
13*44704f69SBart Van Assche * This program maps a primary SCSI device node name to the corresponding
14*44704f69SBart Van Assche * SCSI generic device node name (or vice versa). Targets Linux
15*44704f69SBart Van Assche * kernel 2.6, 3 and 4 series. Sysfs device names can also be mapped.
16*44704f69SBart Van Assche */
17*44704f69SBart Van Assche
18*44704f69SBart Van Assche /* #define _XOPEN_SOURCE 500 */
19*44704f69SBart Van Assche /* needed to see DT_REG and friends when compiled with: c99 pedantic */
20*44704f69SBart Van Assche #ifndef _GNU_SOURCE
21*44704f69SBart Van Assche #define _GNU_SOURCE 1
22*44704f69SBart Van Assche #endif
23*44704f69SBart Van Assche
24*44704f69SBart Van Assche #include <unistd.h>
25*44704f69SBart Van Assche #include <fcntl.h>
26*44704f69SBart Van Assche #include <stdio.h>
27*44704f69SBart Van Assche #include <stdlib.h>
28*44704f69SBart Van Assche #include <stdarg.h>
29*44704f69SBart Van Assche #include <stdbool.h>
30*44704f69SBart Van Assche #include <string.h>
31*44704f69SBart Van Assche #include <ctype.h>
32*44704f69SBart Van Assche #include <errno.h>
33*44704f69SBart Van Assche #include <limits.h>
34*44704f69SBart Van Assche #include <getopt.h>
35*44704f69SBart Van Assche #include <dirent.h>
36*44704f69SBart Van Assche #include <libgen.h>
37*44704f69SBart Van Assche #include <sys/ioctl.h>
38*44704f69SBart Van Assche #include <sys/stat.h>
39*44704f69SBart Van Assche #include <sys/sysmacros.h> /* new location for major + minor */
40*44704f69SBart Van Assche #ifndef major
41*44704f69SBart Van Assche #include <sys/types.h>
42*44704f69SBart Van Assche #endif
43*44704f69SBart Van Assche #include <linux/major.h>
44*44704f69SBart Van Assche
45*44704f69SBart Van Assche #ifdef HAVE_CONFIG_H
46*44704f69SBart Van Assche #include "config.h"
47*44704f69SBart Van Assche #endif
48*44704f69SBart Van Assche #include "sg_lib.h"
49*44704f69SBart Van Assche
50*44704f69SBart Van Assche static const char * version_str = "1.19 20220117";
51*44704f69SBart Van Assche
52*44704f69SBart Van Assche #define ME "sg_map26: "
53*44704f69SBart Van Assche
54*44704f69SBart Van Assche #define NT_NO_MATCH 0
55*44704f69SBart Van Assche #define NT_SD 1
56*44704f69SBart Van Assche #define NT_SR 2
57*44704f69SBart Van Assche #define NT_HD 3
58*44704f69SBart Van Assche #define NT_ST 4
59*44704f69SBart Van Assche #define NT_OSST 5
60*44704f69SBart Van Assche #define NT_SG 6
61*44704f69SBart Van Assche #define NT_CH 7
62*44704f69SBart Van Assche #define NT_REG 8
63*44704f69SBart Van Assche #define NT_DIR 9
64*44704f69SBart Van Assche
65*44704f69SBart Van Assche #define NAME_LEN_MAX 256
66*44704f69SBart Van Assche #define D_NAME_LEN_MAX 520
67*44704f69SBart Van Assche
68*44704f69SBart Van Assche #ifndef SCSI_CHANGER_MAJOR
69*44704f69SBart Van Assche #define SCSI_CHANGER_MAJOR 86
70*44704f69SBart Van Assche #endif
71*44704f69SBart Van Assche #ifndef OSST_MAJOR
72*44704f69SBart Van Assche #define OSST_MAJOR 206
73*44704f69SBart Van Assche #endif
74*44704f69SBart Van Assche
75*44704f69SBart Van Assche /* scandir() and stat() categories */
76*44704f69SBart Van Assche #define FT_OTHER 0
77*44704f69SBart Van Assche #define FT_REGULAR 1
78*44704f69SBart Van Assche #define FT_BLOCK 2
79*44704f69SBart Van Assche #define FT_CHAR 3
80*44704f69SBart Van Assche #define FT_DIR 4
81*44704f69SBart Van Assche
82*44704f69SBart Van Assche /* older major.h headers may not have these */
83*44704f69SBart Van Assche #ifndef SCSI_DISK8_MAJOR
84*44704f69SBart Van Assche #define SCSI_DISK8_MAJOR 128
85*44704f69SBart Van Assche #define SCSI_DISK9_MAJOR 129
86*44704f69SBart Van Assche #define SCSI_DISK10_MAJOR 130
87*44704f69SBart Van Assche #define SCSI_DISK11_MAJOR 131
88*44704f69SBart Van Assche #define SCSI_DISK12_MAJOR 132
89*44704f69SBart Van Assche #define SCSI_DISK13_MAJOR 133
90*44704f69SBart Van Assche #define SCSI_DISK14_MAJOR 134
91*44704f69SBart Van Assche #define SCSI_DISK15_MAJOR 135
92*44704f69SBart Van Assche #endif
93*44704f69SBart Van Assche
94*44704f69SBart Van Assche /* st minor decodes from Kai Makisara 20081008 */
95*44704f69SBart Van Assche #define ST_NBR_MODE_BITS 2
96*44704f69SBart Van Assche #define ST_MODE_SHIFT (7 - ST_NBR_MODE_BITS)
97*44704f69SBart Van Assche #define TAPE_NR(minor) ( (((minor) & ~255) >> (ST_NBR_MODE_BITS + 1)) | \
98*44704f69SBart Van Assche ((minor) & ~(UINT_MAX << ST_MODE_SHIFT)) )
99*44704f69SBart Van Assche
100*44704f69SBart Van Assche static const char * sys_sg_dir = "/sys/class/scsi_generic/";
101*44704f69SBart Van Assche static const char * sys_sd_dir = "/sys/block/";
102*44704f69SBart Van Assche static const char * sys_sr_dir = "/sys/block/";
103*44704f69SBart Van Assche static const char * sys_hd_dir = "/sys/block/";
104*44704f69SBart Van Assche static const char * sys_st_dir = "/sys/class/scsi_tape/";
105*44704f69SBart Van Assche static const char * sys_sch_dir = "/sys/class/scsi_changer/";
106*44704f69SBart Van Assche static const char * sys_osst_dir = "/sys/class/onstream_tape/";
107*44704f69SBart Van Assche static const char * def_dev_dir = "/dev";
108*44704f69SBart Van Assche
109*44704f69SBart Van Assche
110*44704f69SBart Van Assche static struct option long_options[] = {
111*44704f69SBart Van Assche {"dev_dir", required_argument, 0, 'd'},
112*44704f69SBart Van Assche {"given_is", required_argument, 0, 'g'},
113*44704f69SBart Van Assche {"help", no_argument, 0, 'h'},
114*44704f69SBart Van Assche {"result", required_argument, 0, 'r'},
115*44704f69SBart Van Assche {"symlink", no_argument, 0, 's'},
116*44704f69SBart Van Assche {"verbose", no_argument, 0, 'v'},
117*44704f69SBart Van Assche {"version", no_argument, 0, 'V'},
118*44704f69SBart Van Assche {0, 0, 0, 0},
119*44704f69SBart Van Assche };
120*44704f69SBart Van Assche
121*44704f69SBart Van Assche static const char * nt_names[] = {
122*44704f69SBart Van Assche "No matching",
123*44704f69SBart Van Assche "disk",
124*44704f69SBart Van Assche "cd/dvd",
125*44704f69SBart Van Assche "hd",
126*44704f69SBart Van Assche "tape",
127*44704f69SBart Van Assche "tape (osst)",
128*44704f69SBart Van Assche "generic (sg)",
129*44704f69SBart Van Assche "changer",
130*44704f69SBart Van Assche "regular file",
131*44704f69SBart Van Assche "directory",
132*44704f69SBart Van Assche };
133*44704f69SBart Van Assche
134*44704f69SBart Van Assche #if defined(__GNUC__) || defined(__clang__)
135*44704f69SBart Van Assche static int pr2serr(const char * fmt, ...)
136*44704f69SBart Van Assche __attribute__ ((format (printf, 1, 2)));
137*44704f69SBart Van Assche #else
138*44704f69SBart Van Assche static int pr2serr(const char * fmt, ...);
139*44704f69SBart Van Assche #endif
140*44704f69SBart Van Assche
141*44704f69SBart Van Assche
142*44704f69SBart Van Assche static int
pr2serr(const char * fmt,...)143*44704f69SBart Van Assche pr2serr(const char * fmt, ...)
144*44704f69SBart Van Assche {
145*44704f69SBart Van Assche va_list args;
146*44704f69SBart Van Assche int n;
147*44704f69SBart Van Assche
148*44704f69SBart Van Assche va_start(args, fmt);
149*44704f69SBart Van Assche n = vfprintf(stderr, fmt, args);
150*44704f69SBart Van Assche va_end(args);
151*44704f69SBart Van Assche return n;
152*44704f69SBart Van Assche }
153*44704f69SBart Van Assche
154*44704f69SBart Van Assche static void
usage()155*44704f69SBart Van Assche usage()
156*44704f69SBart Van Assche {
157*44704f69SBart Van Assche pr2serr("Usage: sg_map26 [--dev_dir=DIR] [--given_is=0...1] [--help] "
158*44704f69SBart Van Assche "[--result=0...3]\n"
159*44704f69SBart Van Assche " [--symlink] [--verbose] [--version] "
160*44704f69SBart Van Assche "DEVICE\n"
161*44704f69SBart Van Assche " where:\n"
162*44704f69SBart Van Assche " --dev_dir=DIR | -d DIR search in DIR for "
163*44704f69SBart Van Assche "resulting special\n"
164*44704f69SBart Van Assche " (def: directory of DEVICE "
165*44704f69SBart Van Assche "or '/dev')\n"
166*44704f69SBart Van Assche " --given_is=0...1 | -g 0...1 variety of given "
167*44704f69SBart Van Assche "DEVICE\n"
168*44704f69SBart Van Assche " 0->block or char special "
169*44704f69SBart Van Assche "(or symlink to)\n"
170*44704f69SBart Van Assche " 1->sysfs device, 'dev' or "
171*44704f69SBart Van Assche "parent\n"
172*44704f69SBart Van Assche " --help | -h print out usage message\n"
173*44704f69SBart Van Assche " --result=0...3 | -r 0...3 variety of file(s) to "
174*44704f69SBart Van Assche "find\n"
175*44704f69SBart Van Assche " 0->mapped block or char "
176*44704f69SBart Van Assche "special(def)\n"
177*44704f69SBart Van Assche " 1->mapped sysfs path\n"
178*44704f69SBart Van Assche " 2->matching block or "
179*44704f69SBart Van Assche "char special\n"
180*44704f69SBart Van Assche " 3->matching sysfs "
181*44704f69SBart Van Assche "path\n"
182*44704f69SBart Van Assche " --symlink | -s symlinks to special included in "
183*44704f69SBart Van Assche "result\n"
184*44704f69SBart Van Assche " --verbose | -v increase verbosity of output\n"
185*44704f69SBart Van Assche " --version | -V print version string and exit\n\n"
186*44704f69SBart Van Assche "Maps SCSI device node to corresponding generic node (and "
187*44704f69SBart Van Assche "vv)\n"
188*44704f69SBart Van Assche );
189*44704f69SBart Van Assche }
190*44704f69SBart Van Assche
191*44704f69SBart Van Assche
192*44704f69SBart Van Assche /* ssafe_strerror() contributed by Clayton Weaver <cgweav at email dot com>
193*44704f69SBart Van Assche Allows for situation in which strerror() is given a wild value (or the
194*44704f69SBart Van Assche C library is incomplete) and returns NULL. Still not thread safe.
195*44704f69SBart Van Assche */
196*44704f69SBart Van Assche
197*44704f69SBart Van Assche static char safe_errbuf[64] = {'u', 'n', 'k', 'n', 'o', 'w', 'n', ' ',
198*44704f69SBart Van Assche 'e', 'r', 'r', 'n', 'o', ':', ' ', 0};
199*44704f69SBart Van Assche
200*44704f69SBart Van Assche static char *
ssafe_strerror(int errnum)201*44704f69SBart Van Assche ssafe_strerror(int errnum)
202*44704f69SBart Van Assche {
203*44704f69SBart Van Assche size_t len;
204*44704f69SBart Van Assche char * errstr;
205*44704f69SBart Van Assche
206*44704f69SBart Van Assche errstr = strerror(errnum);
207*44704f69SBart Van Assche if (NULL == errstr) {
208*44704f69SBart Van Assche len = strlen(safe_errbuf);
209*44704f69SBart Van Assche snprintf(safe_errbuf + len, sizeof(safe_errbuf) - len, "%i",
210*44704f69SBart Van Assche errnum);
211*44704f69SBart Van Assche safe_errbuf[sizeof(safe_errbuf) - 1] = '\0'; /* bombproof */
212*44704f69SBart Van Assche return safe_errbuf;
213*44704f69SBart Van Assche }
214*44704f69SBart Van Assche return errstr;
215*44704f69SBart Van Assche }
216*44704f69SBart Van Assche
217*44704f69SBart Van Assche static int
nt_typ_from_filename(const char * filename,int * majj,int * minn)218*44704f69SBart Van Assche nt_typ_from_filename(const char * filename, int * majj, int * minn)
219*44704f69SBart Van Assche {
220*44704f69SBart Van Assche struct stat st;
221*44704f69SBart Van Assche int ma, mi;
222*44704f69SBart Van Assche
223*44704f69SBart Van Assche if (stat(filename, &st) < 0)
224*44704f69SBart Van Assche return -errno;
225*44704f69SBart Van Assche ma = major(st.st_rdev);
226*44704f69SBart Van Assche mi = minor(st.st_rdev);
227*44704f69SBart Van Assche if (majj)
228*44704f69SBart Van Assche *majj = ma;
229*44704f69SBart Van Assche if (minn)
230*44704f69SBart Van Assche *minn = mi;
231*44704f69SBart Van Assche if (S_ISCHR(st.st_mode)) {
232*44704f69SBart Van Assche switch(ma) {
233*44704f69SBart Van Assche case OSST_MAJOR:
234*44704f69SBart Van Assche return NT_OSST;
235*44704f69SBart Van Assche case SCSI_GENERIC_MAJOR:
236*44704f69SBart Van Assche return NT_SG;
237*44704f69SBart Van Assche case SCSI_TAPE_MAJOR:
238*44704f69SBart Van Assche return NT_ST;
239*44704f69SBart Van Assche case SCSI_CHANGER_MAJOR:
240*44704f69SBart Van Assche return NT_CH;
241*44704f69SBart Van Assche default:
242*44704f69SBart Van Assche return NT_NO_MATCH;
243*44704f69SBart Van Assche }
244*44704f69SBart Van Assche } else if (S_ISBLK(st.st_mode)) {
245*44704f69SBart Van Assche switch(ma) {
246*44704f69SBart Van Assche case SCSI_DISK0_MAJOR: case SCSI_DISK1_MAJOR:
247*44704f69SBart Van Assche case SCSI_DISK2_MAJOR: case SCSI_DISK3_MAJOR:
248*44704f69SBart Van Assche case SCSI_DISK4_MAJOR: case SCSI_DISK5_MAJOR:
249*44704f69SBart Van Assche case SCSI_DISK6_MAJOR: case SCSI_DISK7_MAJOR:
250*44704f69SBart Van Assche case SCSI_DISK8_MAJOR: case SCSI_DISK9_MAJOR:
251*44704f69SBart Van Assche case SCSI_DISK10_MAJOR: case SCSI_DISK11_MAJOR:
252*44704f69SBart Van Assche case SCSI_DISK12_MAJOR: case SCSI_DISK13_MAJOR:
253*44704f69SBart Van Assche case SCSI_DISK14_MAJOR: case SCSI_DISK15_MAJOR:
254*44704f69SBart Van Assche return NT_SD;
255*44704f69SBart Van Assche case SCSI_CDROM_MAJOR:
256*44704f69SBart Van Assche return NT_SR;
257*44704f69SBart Van Assche case IDE0_MAJOR: case IDE1_MAJOR:
258*44704f69SBart Van Assche case IDE2_MAJOR: case IDE3_MAJOR:
259*44704f69SBart Van Assche case IDE4_MAJOR: case IDE5_MAJOR:
260*44704f69SBart Van Assche case IDE6_MAJOR: case IDE7_MAJOR:
261*44704f69SBart Van Assche case IDE8_MAJOR: case IDE9_MAJOR:
262*44704f69SBart Van Assche return NT_HD;
263*44704f69SBart Van Assche default:
264*44704f69SBart Van Assche return NT_NO_MATCH;
265*44704f69SBart Van Assche }
266*44704f69SBart Van Assche } else if (S_ISREG(st.st_mode))
267*44704f69SBart Van Assche return NT_REG;
268*44704f69SBart Van Assche else if (S_ISDIR(st.st_mode))
269*44704f69SBart Van Assche return NT_DIR;
270*44704f69SBart Van Assche return NT_NO_MATCH;
271*44704f69SBart Van Assche }
272*44704f69SBart Van Assche
273*44704f69SBart Van Assche static int
nt_typ_from_major(int ma)274*44704f69SBart Van Assche nt_typ_from_major(int ma)
275*44704f69SBart Van Assche {
276*44704f69SBart Van Assche switch(ma) {
277*44704f69SBart Van Assche case SCSI_DISK0_MAJOR: case SCSI_DISK1_MAJOR:
278*44704f69SBart Van Assche case SCSI_DISK2_MAJOR: case SCSI_DISK3_MAJOR:
279*44704f69SBart Van Assche case SCSI_DISK4_MAJOR: case SCSI_DISK5_MAJOR:
280*44704f69SBart Van Assche case SCSI_DISK6_MAJOR: case SCSI_DISK7_MAJOR:
281*44704f69SBart Van Assche case SCSI_DISK8_MAJOR: case SCSI_DISK9_MAJOR:
282*44704f69SBart Van Assche case SCSI_DISK10_MAJOR: case SCSI_DISK11_MAJOR:
283*44704f69SBart Van Assche case SCSI_DISK12_MAJOR: case SCSI_DISK13_MAJOR:
284*44704f69SBart Van Assche case SCSI_DISK14_MAJOR: case SCSI_DISK15_MAJOR:
285*44704f69SBart Van Assche return NT_SD;
286*44704f69SBart Van Assche case SCSI_CDROM_MAJOR:
287*44704f69SBart Van Assche return NT_SR;
288*44704f69SBart Van Assche case IDE0_MAJOR: case IDE1_MAJOR:
289*44704f69SBart Van Assche case IDE2_MAJOR: case IDE3_MAJOR:
290*44704f69SBart Van Assche case IDE4_MAJOR: case IDE5_MAJOR:
291*44704f69SBart Van Assche case IDE6_MAJOR: case IDE7_MAJOR:
292*44704f69SBart Van Assche case IDE8_MAJOR: case IDE9_MAJOR:
293*44704f69SBart Van Assche return NT_HD;
294*44704f69SBart Van Assche case OSST_MAJOR:
295*44704f69SBart Van Assche return NT_OSST;
296*44704f69SBart Van Assche case SCSI_GENERIC_MAJOR:
297*44704f69SBart Van Assche return NT_SG;
298*44704f69SBart Van Assche case SCSI_TAPE_MAJOR:
299*44704f69SBart Van Assche return NT_ST;
300*44704f69SBart Van Assche case SCSI_CHANGER_MAJOR:
301*44704f69SBart Van Assche return NT_CH;
302*44704f69SBart Van Assche default:
303*44704f69SBart Van Assche return NT_NO_MATCH;
304*44704f69SBart Van Assche }
305*44704f69SBart Van Assche return NT_NO_MATCH;
306*44704f69SBart Van Assche }
307*44704f69SBart Van Assche
308*44704f69SBart Van Assche
309*44704f69SBart Van Assche struct node_match_item {
310*44704f69SBart Van Assche bool follow_symlink;
311*44704f69SBart Van Assche int file_type;
312*44704f69SBart Van Assche int majj;
313*44704f69SBart Van Assche int minn;
314*44704f69SBart Van Assche char dir_name[D_NAME_LEN_MAX];
315*44704f69SBart Van Assche };
316*44704f69SBart Van Assche
317*44704f69SBart Van Assche static struct node_match_item nd_match;
318*44704f69SBart Van Assche
319*44704f69SBart Van Assche static int
nd_match_scandir_select(const struct dirent * s)320*44704f69SBart Van Assche nd_match_scandir_select(const struct dirent * s)
321*44704f69SBart Van Assche {
322*44704f69SBart Van Assche bool symlnk = false;
323*44704f69SBart Van Assche struct stat st;
324*44704f69SBart Van Assche char name[D_NAME_LEN_MAX];
325*44704f69SBart Van Assche
326*44704f69SBart Van Assche switch (s->d_type) {
327*44704f69SBart Van Assche case DT_BLK:
328*44704f69SBart Van Assche if (FT_BLOCK != nd_match.file_type)
329*44704f69SBart Van Assche return 0;
330*44704f69SBart Van Assche break;
331*44704f69SBart Van Assche case DT_CHR:
332*44704f69SBart Van Assche if (FT_CHAR != nd_match.file_type)
333*44704f69SBart Van Assche return 0;
334*44704f69SBart Van Assche break;
335*44704f69SBart Van Assche case DT_DIR:
336*44704f69SBart Van Assche return (FT_DIR == nd_match.file_type) ? 1 : 0;
337*44704f69SBart Van Assche case DT_REG:
338*44704f69SBart Van Assche return (FT_REGULAR == nd_match.file_type) ? 1 : 0;
339*44704f69SBart Van Assche case DT_LNK: /* follow symlinks */
340*44704f69SBart Van Assche if (! nd_match.follow_symlink)
341*44704f69SBart Van Assche return 0;
342*44704f69SBart Van Assche symlnk = true;
343*44704f69SBart Van Assche break;
344*44704f69SBart Van Assche default:
345*44704f69SBart Van Assche return 0;
346*44704f69SBart Van Assche }
347*44704f69SBart Van Assche if ((! symlnk) && (-1 == nd_match.majj) && (-1 == nd_match.minn))
348*44704f69SBart Van Assche return 1;
349*44704f69SBart Van Assche snprintf(name, sizeof(name), "%.*s/%.*s", NAME_LEN_MAX,
350*44704f69SBart Van Assche nd_match.dir_name, NAME_LEN_MAX, s->d_name);
351*44704f69SBart Van Assche memset(&st, 0, sizeof(st));
352*44704f69SBart Van Assche if (stat(name, &st) < 0)
353*44704f69SBart Van Assche return 0;
354*44704f69SBart Van Assche if (symlnk) {
355*44704f69SBart Van Assche if (S_ISCHR(st.st_mode)) {
356*44704f69SBart Van Assche if (FT_CHAR != nd_match.file_type)
357*44704f69SBart Van Assche return 0;
358*44704f69SBart Van Assche } else if (S_ISBLK(st.st_mode)) {
359*44704f69SBart Van Assche if (FT_BLOCK != nd_match.file_type)
360*44704f69SBart Van Assche return 0;
361*44704f69SBart Van Assche } else
362*44704f69SBart Van Assche return 0;
363*44704f69SBart Van Assche }
364*44704f69SBart Van Assche return (((-1 == nd_match.majj) ||
365*44704f69SBart Van Assche ((unsigned)major(st.st_rdev) == (unsigned)nd_match.majj)) &&
366*44704f69SBart Van Assche ((-1 == nd_match.minn) ||
367*44704f69SBart Van Assche ((unsigned)minor(st.st_rdev) == (unsigned)nd_match.minn)))
368*44704f69SBart Van Assche ? 1 : 0;
369*44704f69SBart Van Assche }
370*44704f69SBart Van Assche
371*44704f69SBart Van Assche static int
list_matching_nodes(const char * dir_name,int file_type,int majj,int minn,bool follow_symlink,int verbose)372*44704f69SBart Van Assche list_matching_nodes(const char * dir_name, int file_type, int majj, int minn,
373*44704f69SBart Van Assche bool follow_symlink, int verbose)
374*44704f69SBart Van Assche {
375*44704f69SBart Van Assche struct dirent ** namelist;
376*44704f69SBart Van Assche int num, k;
377*44704f69SBart Van Assche
378*44704f69SBart Van Assche strncpy(nd_match.dir_name, dir_name, D_NAME_LEN_MAX - 1);
379*44704f69SBart Van Assche nd_match.file_type = file_type;
380*44704f69SBart Van Assche nd_match.majj = majj;
381*44704f69SBart Van Assche nd_match.minn = minn;
382*44704f69SBart Van Assche nd_match.follow_symlink = follow_symlink;
383*44704f69SBart Van Assche num = scandir(dir_name, &namelist, nd_match_scandir_select, NULL);
384*44704f69SBart Van Assche if (num < 0) {
385*44704f69SBart Van Assche if (verbose)
386*44704f69SBart Van Assche pr2serr("scandir: %s %s\n", dir_name,
387*44704f69SBart Van Assche ssafe_strerror(errno));
388*44704f69SBart Van Assche return -errno;
389*44704f69SBart Van Assche }
390*44704f69SBart Van Assche for (k = 0; k < num; ++k) {
391*44704f69SBart Van Assche printf("%s/%s\n", dir_name, namelist[k]->d_name);
392*44704f69SBart Van Assche free(namelist[k]);
393*44704f69SBart Van Assche }
394*44704f69SBart Van Assche free(namelist);
395*44704f69SBart Van Assche return num;
396*44704f69SBart Van Assche }
397*44704f69SBart Van Assche
398*44704f69SBart Van Assche struct sg_item_t {
399*44704f69SBart Van Assche char name[NAME_LEN_MAX + 2];
400*44704f69SBart Van Assche int ft;
401*44704f69SBart Van Assche int nt;
402*44704f69SBart Van Assche int d_type;
403*44704f69SBart Van Assche };
404*44704f69SBart Van Assche
405*44704f69SBart Van Assche static struct sg_item_t for_first;
406*44704f69SBart Van Assche
407*44704f69SBart Van Assche static int
first_scandir_select(const struct dirent * s)408*44704f69SBart Van Assche first_scandir_select(const struct dirent * s)
409*44704f69SBart Van Assche {
410*44704f69SBart Van Assche if (FT_OTHER != for_first.ft)
411*44704f69SBart Van Assche return 0;
412*44704f69SBart Van Assche if ((DT_LNK != s->d_type) &&
413*44704f69SBart Van Assche ((DT_DIR != s->d_type) || ('.' == s->d_name[0])))
414*44704f69SBart Van Assche return 0;
415*44704f69SBart Van Assche strncpy(for_first.name, s->d_name, NAME_LEN_MAX);
416*44704f69SBart Van Assche for_first.ft = FT_CHAR; /* dummy */
417*44704f69SBart Van Assche for_first.d_type = s->d_type;
418*44704f69SBart Van Assche return 1;
419*44704f69SBart Van Assche }
420*44704f69SBart Van Assche
421*44704f69SBart Van Assche /* scan for directory entry that is either a symlink or a directory */
422*44704f69SBart Van Assche static int
scan_for_first(const char * dir_name,int verbose)423*44704f69SBart Van Assche scan_for_first(const char * dir_name, int verbose)
424*44704f69SBart Van Assche {
425*44704f69SBart Van Assche char name[NAME_LEN_MAX];
426*44704f69SBart Van Assche struct dirent ** namelist;
427*44704f69SBart Van Assche int num, k;
428*44704f69SBart Van Assche
429*44704f69SBart Van Assche for_first.ft = FT_OTHER;
430*44704f69SBart Van Assche num = scandir(dir_name, &namelist, first_scandir_select, NULL);
431*44704f69SBart Van Assche if (num < 0) {
432*44704f69SBart Van Assche if (verbose > 0) {
433*44704f69SBart Van Assche snprintf(name, NAME_LEN_MAX, "scandir: %s", dir_name);
434*44704f69SBart Van Assche perror(name);
435*44704f69SBart Van Assche }
436*44704f69SBart Van Assche return -1;
437*44704f69SBart Van Assche }
438*44704f69SBart Van Assche for (k = 0; k < num; ++k)
439*44704f69SBart Van Assche free(namelist[k]);
440*44704f69SBart Van Assche free(namelist);
441*44704f69SBart Van Assche return num;
442*44704f69SBart Van Assche }
443*44704f69SBart Van Assche
444*44704f69SBart Van Assche static struct sg_item_t from_sg;
445*44704f69SBart Van Assche
446*44704f69SBart Van Assche static int
from_sg_scandir_select(const struct dirent * s)447*44704f69SBart Van Assche from_sg_scandir_select(const struct dirent * s)
448*44704f69SBart Van Assche {
449*44704f69SBart Van Assche int len;
450*44704f69SBart Van Assche
451*44704f69SBart Van Assche if (FT_OTHER != from_sg.ft)
452*44704f69SBart Van Assche return 0;
453*44704f69SBart Van Assche if ((DT_LNK != s->d_type) &&
454*44704f69SBart Van Assche ((DT_DIR != s->d_type) || ('.' == s->d_name[0])))
455*44704f69SBart Van Assche return 0;
456*44704f69SBart Van Assche from_sg.d_type = s->d_type;
457*44704f69SBart Van Assche if (0 == strncmp("scsi_changer", s->d_name, 12)) {
458*44704f69SBart Van Assche strncpy(from_sg.name, s->d_name, NAME_LEN_MAX);
459*44704f69SBart Van Assche from_sg.ft = FT_CHAR;
460*44704f69SBart Van Assche from_sg.nt = NT_CH;
461*44704f69SBart Van Assche return 1;
462*44704f69SBart Van Assche } else if (0 == strncmp("block", s->d_name, 5)) {
463*44704f69SBart Van Assche strncpy(from_sg.name, s->d_name, NAME_LEN_MAX);
464*44704f69SBart Van Assche from_sg.ft = FT_BLOCK;
465*44704f69SBart Van Assche return 1;
466*44704f69SBart Van Assche } else if (0 == strcmp("tape", s->d_name)) {
467*44704f69SBart Van Assche strcpy(from_sg.name, s->d_name);
468*44704f69SBart Van Assche from_sg.ft = FT_CHAR;
469*44704f69SBart Van Assche from_sg.nt = NT_ST;
470*44704f69SBart Van Assche return 1;
471*44704f69SBart Van Assche } else if (0 == strncmp("scsi_tape:st", s->d_name, 12)) {
472*44704f69SBart Van Assche len = strlen(s->d_name);
473*44704f69SBart Van Assche if (isdigit(s->d_name[len - 1])) {
474*44704f69SBart Van Assche /* want 'st<num>' symlink only */
475*44704f69SBart Van Assche strcpy(from_sg.name, s->d_name);
476*44704f69SBart Van Assche from_sg.ft = FT_CHAR;
477*44704f69SBart Van Assche from_sg.nt = NT_ST;
478*44704f69SBart Van Assche return 1;
479*44704f69SBart Van Assche } else
480*44704f69SBart Van Assche return 0;
481*44704f69SBart Van Assche } else if (0 == strncmp("onstream_tape:os", s->d_name, 16)) {
482*44704f69SBart Van Assche strcpy(from_sg.name, s->d_name);
483*44704f69SBart Van Assche from_sg.ft = FT_CHAR;
484*44704f69SBart Van Assche from_sg.nt = NT_OSST;
485*44704f69SBart Van Assche return 1;
486*44704f69SBart Van Assche } else
487*44704f69SBart Van Assche return 0;
488*44704f69SBart Van Assche }
489*44704f69SBart Van Assche
490*44704f69SBart Van Assche static int
from_sg_scan(const char * dir_name,int verbose)491*44704f69SBart Van Assche from_sg_scan(const char * dir_name, int verbose)
492*44704f69SBart Van Assche {
493*44704f69SBart Van Assche struct dirent ** namelist;
494*44704f69SBart Van Assche int num, k;
495*44704f69SBart Van Assche
496*44704f69SBart Van Assche from_sg.ft = FT_OTHER;
497*44704f69SBart Van Assche from_sg.nt = NT_NO_MATCH;
498*44704f69SBart Van Assche num = scandir(dir_name, &namelist, from_sg_scandir_select, NULL);
499*44704f69SBart Van Assche if (num < 0) {
500*44704f69SBart Van Assche if (verbose)
501*44704f69SBart Van Assche pr2serr("scandir: %s %s\n", dir_name,
502*44704f69SBart Van Assche ssafe_strerror(errno));
503*44704f69SBart Van Assche return -errno;
504*44704f69SBart Van Assche }
505*44704f69SBart Van Assche if (verbose) {
506*44704f69SBart Van Assche for (k = 0; k < num; ++k)
507*44704f69SBart Van Assche pr2serr(" %s/%s\n", dir_name,
508*44704f69SBart Van Assche namelist[k]->d_name);
509*44704f69SBart Van Assche }
510*44704f69SBart Van Assche for (k = 0; k < num; ++k)
511*44704f69SBart Van Assche free(namelist[k]);
512*44704f69SBart Van Assche free(namelist);
513*44704f69SBart Van Assche return num;
514*44704f69SBart Van Assche }
515*44704f69SBart Van Assche
516*44704f69SBart Van Assche static struct sg_item_t to_sg;
517*44704f69SBart Van Assche
518*44704f69SBart Van Assche static int
to_sg_scandir_select(const struct dirent * s)519*44704f69SBart Van Assche to_sg_scandir_select(const struct dirent * s)
520*44704f69SBart Van Assche {
521*44704f69SBart Van Assche if (FT_OTHER != to_sg.ft)
522*44704f69SBart Van Assche return 0;
523*44704f69SBart Van Assche if (DT_LNK != s->d_type)
524*44704f69SBart Van Assche return 0;
525*44704f69SBart Van Assche if (0 == strncmp("scsi_generic", s->d_name, 12)) {
526*44704f69SBart Van Assche strncpy(to_sg.name, s->d_name, NAME_LEN_MAX);
527*44704f69SBart Van Assche to_sg.ft = FT_CHAR;
528*44704f69SBart Van Assche to_sg.nt = NT_SG;
529*44704f69SBart Van Assche return 1;
530*44704f69SBart Van Assche } else
531*44704f69SBart Van Assche return 0;
532*44704f69SBart Van Assche }
533*44704f69SBart Van Assche
534*44704f69SBart Van Assche static int
to_sg_scan(const char * dir_name)535*44704f69SBart Van Assche to_sg_scan(const char * dir_name)
536*44704f69SBart Van Assche {
537*44704f69SBart Van Assche struct dirent ** namelist;
538*44704f69SBart Van Assche int num, k;
539*44704f69SBart Van Assche
540*44704f69SBart Van Assche to_sg.ft = FT_OTHER;
541*44704f69SBart Van Assche to_sg.nt = NT_NO_MATCH;
542*44704f69SBart Van Assche num = scandir(dir_name, &namelist, to_sg_scandir_select, NULL);
543*44704f69SBart Van Assche if (num < 0)
544*44704f69SBart Van Assche return -errno;
545*44704f69SBart Van Assche for (k = 0; k < num; ++k)
546*44704f69SBart Van Assche free(namelist[k]);
547*44704f69SBart Van Assche free(namelist);
548*44704f69SBart Van Assche return num;
549*44704f69SBart Van Assche }
550*44704f69SBart Van Assche
551*44704f69SBart Van Assche /* Return 1 if directory, else 0 */
552*44704f69SBart Van Assche static int
if_directory_chdir(const char * dir_name,const char * base_name)553*44704f69SBart Van Assche if_directory_chdir(const char * dir_name, const char * base_name)
554*44704f69SBart Van Assche {
555*44704f69SBart Van Assche char buff[D_NAME_LEN_MAX];
556*44704f69SBart Van Assche struct stat a_stat;
557*44704f69SBart Van Assche
558*44704f69SBart Van Assche strcpy(buff, dir_name);
559*44704f69SBart Van Assche strcat(buff, "/");
560*44704f69SBart Van Assche strcat(buff, base_name);
561*44704f69SBart Van Assche if (stat(buff, &a_stat) < 0)
562*44704f69SBart Van Assche return 0;
563*44704f69SBart Van Assche if (S_ISDIR(a_stat.st_mode)) {
564*44704f69SBart Van Assche if (chdir(buff) < 0)
565*44704f69SBart Van Assche return 0;
566*44704f69SBart Van Assche return 1;
567*44704f69SBart Van Assche }
568*44704f69SBart Van Assche return 0;
569*44704f69SBart Van Assche }
570*44704f69SBart Van Assche
571*44704f69SBart Van Assche /* Return 1 if directory, else 0 */
572*44704f69SBart Van Assche static int
if_directory_ch2generic(const char * dir_name)573*44704f69SBart Van Assche if_directory_ch2generic(const char * dir_name)
574*44704f69SBart Van Assche {
575*44704f69SBart Van Assche char buff[NAME_LEN_MAX];
576*44704f69SBart Van Assche struct stat a_stat;
577*44704f69SBart Van Assche const char * old_name = "generic";
578*44704f69SBart Van Assche
579*44704f69SBart Van Assche strcpy(buff, dir_name);
580*44704f69SBart Van Assche strcat(buff, "/");
581*44704f69SBart Van Assche strcat(buff, old_name);
582*44704f69SBart Van Assche if ((stat(buff, &a_stat) >= 0) && S_ISDIR(a_stat.st_mode)) {
583*44704f69SBart Van Assche if (chdir(buff) < 0)
584*44704f69SBart Van Assche return 0;
585*44704f69SBart Van Assche return 1;
586*44704f69SBart Van Assche }
587*44704f69SBart Van Assche /* No "generic", so now look for "scsi_generic:sg<n>" */
588*44704f69SBart Van Assche if (1 != to_sg_scan(dir_name))
589*44704f69SBart Van Assche return 0;
590*44704f69SBart Van Assche strcpy(buff, dir_name);
591*44704f69SBart Van Assche strcat(buff, "/");
592*44704f69SBart Van Assche strcat(buff, to_sg.name);
593*44704f69SBart Van Assche if (stat(buff, &a_stat) < 0)
594*44704f69SBart Van Assche return 0;
595*44704f69SBart Van Assche if (S_ISDIR(a_stat.st_mode)) {
596*44704f69SBart Van Assche if (chdir(buff) < 0)
597*44704f69SBart Van Assche return 0;
598*44704f69SBart Van Assche return 1;
599*44704f69SBart Van Assche }
600*44704f69SBart Van Assche return 0;
601*44704f69SBart Van Assche }
602*44704f69SBart Van Assche
603*44704f69SBart Van Assche /* Return 1 if found, else 0 if problems */
604*44704f69SBart Van Assche static int
get_value(const char * dir_name,const char * base_name,char * value,int max_value_len)605*44704f69SBart Van Assche get_value(const char * dir_name, const char * base_name, char * value,
606*44704f69SBart Van Assche int max_value_len)
607*44704f69SBart Van Assche {
608*44704f69SBart Van Assche char buff[D_NAME_LEN_MAX];
609*44704f69SBart Van Assche FILE * f;
610*44704f69SBart Van Assche int len;
611*44704f69SBart Van Assche
612*44704f69SBart Van Assche if ((NULL == dir_name) && (NULL == base_name))
613*44704f69SBart Van Assche return 0;
614*44704f69SBart Van Assche if (dir_name) {
615*44704f69SBart Van Assche strcpy(buff, dir_name);
616*44704f69SBart Van Assche if (base_name && (strlen(base_name) > 0)) {
617*44704f69SBart Van Assche strcat(buff, "/");
618*44704f69SBart Van Assche strcat(buff, base_name);
619*44704f69SBart Van Assche }
620*44704f69SBart Van Assche } else
621*44704f69SBart Van Assche strcpy(buff, base_name);
622*44704f69SBart Van Assche if (NULL == (f = fopen(buff, "r"))) {
623*44704f69SBart Van Assche return 0;
624*44704f69SBart Van Assche }
625*44704f69SBart Van Assche if (NULL == fgets(value, max_value_len, f)) {
626*44704f69SBart Van Assche fclose(f);
627*44704f69SBart Van Assche return 0;
628*44704f69SBart Van Assche }
629*44704f69SBart Van Assche len = strlen(value);
630*44704f69SBart Van Assche if ((len > 0) && (value[len - 1] == '\n'))
631*44704f69SBart Van Assche value[len - 1] = '\0';
632*44704f69SBart Van Assche fclose(f);
633*44704f69SBart Van Assche return 1;
634*44704f69SBart Van Assche }
635*44704f69SBart Van Assche
636*44704f69SBart Van Assche static int
map_hd(const char * device_dir,int ma,int mi,int result,bool follow_symlink,int verbose)637*44704f69SBart Van Assche map_hd(const char * device_dir, int ma, int mi, int result,
638*44704f69SBart Van Assche bool follow_symlink, int verbose)
639*44704f69SBart Van Assche {
640*44704f69SBart Van Assche char c, num;
641*44704f69SBart Van Assche
642*44704f69SBart Van Assche if (2 == result) {
643*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_BLOCK,
644*44704f69SBart Van Assche ma, mi, follow_symlink,
645*44704f69SBart Van Assche verbose);
646*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
647*44704f69SBart Van Assche }
648*44704f69SBart Van Assche switch (ma) {
649*44704f69SBart Van Assche case IDE0_MAJOR: c = 'a'; break;
650*44704f69SBart Van Assche case IDE1_MAJOR: c = 'c'; break;
651*44704f69SBart Van Assche case IDE2_MAJOR: c = 'e'; break;
652*44704f69SBart Van Assche case IDE3_MAJOR: c = 'g'; break;
653*44704f69SBart Van Assche case IDE4_MAJOR: c = 'i'; break;
654*44704f69SBart Van Assche case IDE5_MAJOR: c = 'k'; break;
655*44704f69SBart Van Assche case IDE6_MAJOR: c = 'm'; break;
656*44704f69SBart Van Assche case IDE7_MAJOR: c = 'o'; break;
657*44704f69SBart Van Assche case IDE8_MAJOR: c = 'q'; break;
658*44704f69SBart Van Assche case IDE9_MAJOR: c = 's'; break;
659*44704f69SBart Van Assche default: c = '?'; break;
660*44704f69SBart Van Assche }
661*44704f69SBart Van Assche if (mi > 63)
662*44704f69SBart Van Assche ++c;
663*44704f69SBart Van Assche printf("%shd%c\n", sys_hd_dir, c);
664*44704f69SBart Van Assche return 0;
665*44704f69SBart Van Assche }
666*44704f69SBart Van Assche
667*44704f69SBart Van Assche static int
map_sd(const char * device_name,const char * device_dir,int ma,int mi,int result,bool follow_symlink,int verbose)668*44704f69SBart Van Assche map_sd(const char * device_name, const char * device_dir, int ma, int mi,
669*44704f69SBart Van Assche int result, bool follow_symlink, int verbose)
670*44704f69SBart Van Assche {
671*44704f69SBart Van Assche int index, m_mi, m_ma, num;
672*44704f69SBart Van Assche char value[D_NAME_LEN_MAX];
673*44704f69SBart Van Assche char name[D_NAME_LEN_MAX];
674*44704f69SBart Van Assche
675*44704f69SBart Van Assche if (2 == result) {
676*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_BLOCK, ma, mi,
677*44704f69SBart Van Assche follow_symlink, verbose);
678*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
679*44704f69SBart Van Assche }
680*44704f69SBart Van Assche if (SCSI_DISK0_MAJOR == ma)
681*44704f69SBart Van Assche index = mi / 16;
682*44704f69SBart Van Assche else if (ma >= SCSI_DISK8_MAJOR)
683*44704f69SBart Van Assche index = (mi / 16) + 128 +
684*44704f69SBart Van Assche ((ma - SCSI_DISK8_MAJOR) * 16);
685*44704f69SBart Van Assche else
686*44704f69SBart Van Assche index = (mi / 16) + 16 +
687*44704f69SBart Van Assche ((ma - SCSI_DISK1_MAJOR) * 16);
688*44704f69SBart Van Assche if (index < 26)
689*44704f69SBart Van Assche snprintf(name, sizeof(name), "%ssd%c",
690*44704f69SBart Van Assche sys_sd_dir, 'a' + index % 26);
691*44704f69SBart Van Assche else if (index < (26 + 1) * 26)
692*44704f69SBart Van Assche snprintf(name, sizeof(name), "%ssd%c%c",
693*44704f69SBart Van Assche sys_sd_dir,
694*44704f69SBart Van Assche 'a' + index / 26 - 1,'a' + index % 26);
695*44704f69SBart Van Assche else {
696*44704f69SBart Van Assche const unsigned int m1 = (index / 26 - 1) / 26 - 1;
697*44704f69SBart Van Assche const unsigned int m2 = (index / 26 - 1) % 26;
698*44704f69SBart Van Assche const unsigned int m3 = index % 26;
699*44704f69SBart Van Assche
700*44704f69SBart Van Assche snprintf(name, sizeof(name), "%ssd%c%c%c",
701*44704f69SBart Van Assche sys_sd_dir, 'a' + m1, 'a' + m2, 'a' + m3);
702*44704f69SBart Van Assche }
703*44704f69SBart Van Assche if (3 == result) {
704*44704f69SBart Van Assche printf("%s\n", name);
705*44704f69SBart Van Assche return 0;
706*44704f69SBart Van Assche }
707*44704f69SBart Van Assche if (! get_value(name, "dev", value, sizeof(value))) {
708*44704f69SBart Van Assche pr2serr("Couldn't find sysfs match for device: %s\n",
709*44704f69SBart Van Assche device_name);
710*44704f69SBart Van Assche return 1;
711*44704f69SBart Van Assche }
712*44704f69SBart Van Assche if (verbose)
713*44704f69SBart Van Assche pr2serr("sysfs sd dev: %s\n", value);
714*44704f69SBart Van Assche if (! if_directory_chdir(name, "device")) {
715*44704f69SBart Van Assche pr2serr("sysfs problem with device: %s\n", device_name);
716*44704f69SBart Van Assche return 1;
717*44704f69SBart Van Assche }
718*44704f69SBart Van Assche if (if_directory_ch2generic(".")) {
719*44704f69SBart Van Assche if (1 == result) {
720*44704f69SBart Van Assche if (NULL == getcwd(value, sizeof(value)))
721*44704f69SBart Van Assche value[0] = '\0';
722*44704f69SBart Van Assche printf("%s\n", value);
723*44704f69SBart Van Assche return 0;
724*44704f69SBart Van Assche }
725*44704f69SBart Van Assche if (! get_value(".", "dev", value, sizeof(value))) {
726*44704f69SBart Van Assche pr2serr("Couldn't find sysfs generic dev\n");
727*44704f69SBart Van Assche return 1;
728*44704f69SBart Van Assche }
729*44704f69SBart Van Assche if (verbose)
730*44704f69SBart Van Assche printf("matching dev: %s\n", value);
731*44704f69SBart Van Assche if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
732*44704f69SBart Van Assche pr2serr("Couldn't decode mapped dev\n");
733*44704f69SBart Van Assche return 1;
734*44704f69SBart Van Assche }
735*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
736*44704f69SBart Van Assche follow_symlink, verbose);
737*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
738*44704f69SBart Van Assche } else {
739*44704f69SBart Van Assche pr2serr("sd device: %s does not match any SCSI generic "
740*44704f69SBart Van Assche "device\n", device_name);
741*44704f69SBart Van Assche pr2serr(" perhaps sg module is not loaded\n");
742*44704f69SBart Van Assche return 1;
743*44704f69SBart Van Assche }
744*44704f69SBart Van Assche }
745*44704f69SBart Van Assche
746*44704f69SBart Van Assche static int
map_sr(const char * device_name,const char * device_dir,int ma,int mi,int result,bool follow_symlink,int verbose)747*44704f69SBart Van Assche map_sr(const char * device_name, const char * device_dir, int ma, int mi,
748*44704f69SBart Van Assche int result, bool follow_symlink, int verbose)
749*44704f69SBart Van Assche {
750*44704f69SBart Van Assche int m_mi, m_ma, num;
751*44704f69SBart Van Assche char value[D_NAME_LEN_MAX];
752*44704f69SBart Van Assche char name[D_NAME_LEN_MAX];
753*44704f69SBart Van Assche
754*44704f69SBart Van Assche if (2 == result) {
755*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_BLOCK, ma, mi,
756*44704f69SBart Van Assche follow_symlink, verbose);
757*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
758*44704f69SBart Van Assche }
759*44704f69SBart Van Assche snprintf(name, sizeof(name), "%ssr%d", sys_sr_dir, mi);
760*44704f69SBart Van Assche if (3 == result) {
761*44704f69SBart Van Assche printf("%s\n", name);
762*44704f69SBart Van Assche return 0;
763*44704f69SBart Van Assche }
764*44704f69SBart Van Assche if (! get_value(name, "dev", value, sizeof(value))) {
765*44704f69SBart Van Assche pr2serr("Couldn't find sysfs match for device: %s\n",
766*44704f69SBart Van Assche device_name);
767*44704f69SBart Van Assche return 1;
768*44704f69SBart Van Assche }
769*44704f69SBart Van Assche if (verbose)
770*44704f69SBart Van Assche pr2serr("sysfs sr dev: %s\n", value);
771*44704f69SBart Van Assche if (! if_directory_chdir(name, "device")) {
772*44704f69SBart Van Assche pr2serr("sysfs problem with device: %s\n", device_name);
773*44704f69SBart Van Assche return 1;
774*44704f69SBart Van Assche }
775*44704f69SBart Van Assche if (if_directory_ch2generic(".")) {
776*44704f69SBart Van Assche if (1 == result) {
777*44704f69SBart Van Assche if (NULL == getcwd(value, sizeof(value)))
778*44704f69SBart Van Assche value[0] = '\0';
779*44704f69SBart Van Assche printf("%s\n", value);
780*44704f69SBart Van Assche return 0;
781*44704f69SBart Van Assche }
782*44704f69SBart Van Assche if (! get_value(".", "dev", value, sizeof(value))) {
783*44704f69SBart Van Assche pr2serr("Couldn't find sysfs generic dev\n");
784*44704f69SBart Van Assche return 1;
785*44704f69SBart Van Assche }
786*44704f69SBart Van Assche if (verbose)
787*44704f69SBart Van Assche printf("matching dev: %s\n", value);
788*44704f69SBart Van Assche if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
789*44704f69SBart Van Assche pr2serr("Couldn't decode mapped dev\n");
790*44704f69SBart Van Assche return 1;
791*44704f69SBart Van Assche }
792*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_BLOCK, m_ma, m_mi,
793*44704f69SBart Van Assche follow_symlink, verbose);
794*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
795*44704f69SBart Van Assche } else {
796*44704f69SBart Van Assche pr2serr("sr device: %s does not match any SCSI generic "
797*44704f69SBart Van Assche "device\n", device_name);
798*44704f69SBart Van Assche pr2serr(" perhaps sg module is not loaded\n");
799*44704f69SBart Van Assche return 1;
800*44704f69SBart Van Assche }
801*44704f69SBart Van Assche }
802*44704f69SBart Van Assche
803*44704f69SBart Van Assche static int
map_st(const char * device_name,const char * device_dir,int ma,int mi,int result,bool follow_symlink,int verbose)804*44704f69SBart Van Assche map_st(const char * device_name, const char * device_dir, int ma, int mi,
805*44704f69SBart Van Assche int result, bool follow_symlink, int verbose)
806*44704f69SBart Van Assche {
807*44704f69SBart Van Assche int m_mi, m_ma, num;
808*44704f69SBart Van Assche char value[D_NAME_LEN_MAX];
809*44704f69SBart Van Assche char name[D_NAME_LEN_MAX];
810*44704f69SBart Van Assche
811*44704f69SBart Van Assche if (2 == result) {
812*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
813*44704f69SBart Van Assche follow_symlink, verbose);
814*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
815*44704f69SBart Van Assche }
816*44704f69SBart Van Assche snprintf(name, sizeof(name), "%sst%d", sys_st_dir,
817*44704f69SBart Van Assche TAPE_NR(mi));
818*44704f69SBart Van Assche if (3 == result) {
819*44704f69SBart Van Assche printf("%s\n", name);
820*44704f69SBart Van Assche return 0;
821*44704f69SBart Van Assche }
822*44704f69SBart Van Assche if (! get_value(name, "dev", value, sizeof(value))) {
823*44704f69SBart Van Assche pr2serr("Couldn't find sysfs match for device: %s\n",
824*44704f69SBart Van Assche device_name);
825*44704f69SBart Van Assche return 1;
826*44704f69SBart Van Assche }
827*44704f69SBart Van Assche if (verbose)
828*44704f69SBart Van Assche pr2serr("sysfs st dev: %s\n", value);
829*44704f69SBart Van Assche if (! if_directory_chdir(name, "device")) {
830*44704f69SBart Van Assche pr2serr("sysfs problem with device: %s\n", device_name);
831*44704f69SBart Van Assche return 1;
832*44704f69SBart Van Assche }
833*44704f69SBart Van Assche if (if_directory_ch2generic(".")) {
834*44704f69SBart Van Assche if (1 == result) {
835*44704f69SBart Van Assche if (NULL == getcwd(value, sizeof(value)))
836*44704f69SBart Van Assche value[0] = '\0';
837*44704f69SBart Van Assche printf("%s\n", value);
838*44704f69SBart Van Assche return 0;
839*44704f69SBart Van Assche }
840*44704f69SBart Van Assche if (! get_value(".", "dev", value, sizeof(value))) {
841*44704f69SBart Van Assche pr2serr("Couldn't find sysfs generic dev\n");
842*44704f69SBart Van Assche return 1;
843*44704f69SBart Van Assche }
844*44704f69SBart Van Assche if (verbose)
845*44704f69SBart Van Assche printf("matching dev: %s\n", value);
846*44704f69SBart Van Assche if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
847*44704f69SBart Van Assche pr2serr("Couldn't decode mapped dev\n");
848*44704f69SBart Van Assche return 1;
849*44704f69SBart Van Assche }
850*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
851*44704f69SBart Van Assche follow_symlink, verbose);
852*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
853*44704f69SBart Van Assche } else {
854*44704f69SBart Van Assche pr2serr("st device: %s does not match any SCSI generic "
855*44704f69SBart Van Assche "device\n", device_name);
856*44704f69SBart Van Assche pr2serr(" perhaps sg module is not loaded\n");
857*44704f69SBart Van Assche return 1;
858*44704f69SBart Van Assche }
859*44704f69SBart Van Assche }
860*44704f69SBart Van Assche
861*44704f69SBart Van Assche static int
map_osst(const char * device_name,const char * device_dir,int ma,int mi,int result,bool follow_symlink,int verbose)862*44704f69SBart Van Assche map_osst(const char * device_name, const char * device_dir, int ma, int mi,
863*44704f69SBart Van Assche int result, bool follow_symlink, int verbose)
864*44704f69SBart Van Assche {
865*44704f69SBart Van Assche int m_mi, m_ma, num;
866*44704f69SBart Van Assche char value[D_NAME_LEN_MAX];
867*44704f69SBart Van Assche char name[D_NAME_LEN_MAX];
868*44704f69SBart Van Assche
869*44704f69SBart Van Assche if (2 == result) {
870*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
871*44704f69SBart Van Assche follow_symlink, verbose);
872*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
873*44704f69SBart Van Assche }
874*44704f69SBart Van Assche snprintf(name, sizeof(name), "%sosst%d", sys_osst_dir,
875*44704f69SBart Van Assche TAPE_NR(mi));
876*44704f69SBart Van Assche if (3 == result) {
877*44704f69SBart Van Assche printf("%s\n", name);
878*44704f69SBart Van Assche return 0;
879*44704f69SBart Van Assche }
880*44704f69SBart Van Assche if (! get_value(name, "dev", value, sizeof(value))) {
881*44704f69SBart Van Assche pr2serr("Couldn't find sysfs match for device: %s\n",
882*44704f69SBart Van Assche device_name);
883*44704f69SBart Van Assche return 1;
884*44704f69SBart Van Assche }
885*44704f69SBart Van Assche if (verbose)
886*44704f69SBart Van Assche pr2serr("sysfs osst dev: %s\n", value);
887*44704f69SBart Van Assche if (! if_directory_chdir(name, "device")) {
888*44704f69SBart Van Assche pr2serr("sysfs problem with device: %s\n", device_name);
889*44704f69SBart Van Assche return 1;
890*44704f69SBart Van Assche }
891*44704f69SBart Van Assche if (if_directory_ch2generic(".")) {
892*44704f69SBart Van Assche if (1 == result) {
893*44704f69SBart Van Assche if (NULL == getcwd(value, sizeof(value)))
894*44704f69SBart Van Assche value[0] = '\0';
895*44704f69SBart Van Assche printf("%s\n", value);
896*44704f69SBart Van Assche return 0;
897*44704f69SBart Van Assche }
898*44704f69SBart Van Assche if (! get_value(".", "dev", value, sizeof(value))) {
899*44704f69SBart Van Assche pr2serr("Couldn't find sysfs generic dev\n");
900*44704f69SBart Van Assche return 1;
901*44704f69SBart Van Assche }
902*44704f69SBart Van Assche if (verbose)
903*44704f69SBart Van Assche printf("matching dev: %s\n", value);
904*44704f69SBart Van Assche if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
905*44704f69SBart Van Assche pr2serr("Couldn't decode mapped dev\n");
906*44704f69SBart Van Assche return 1;
907*44704f69SBart Van Assche }
908*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
909*44704f69SBart Van Assche follow_symlink, verbose);
910*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
911*44704f69SBart Van Assche } else {
912*44704f69SBart Van Assche pr2serr("osst device: %s does not match any SCSI generic "
913*44704f69SBart Van Assche "device\n", device_name);
914*44704f69SBart Van Assche pr2serr(" perhaps sg module is not loaded\n");
915*44704f69SBart Van Assche return 1;
916*44704f69SBart Van Assche }
917*44704f69SBart Van Assche }
918*44704f69SBart Van Assche
919*44704f69SBart Van Assche static int
map_ch(const char * device_name,const char * device_dir,int ma,int mi,int result,bool follow_symlink,int verbose)920*44704f69SBart Van Assche map_ch(const char * device_name, const char * device_dir, int ma, int mi,
921*44704f69SBart Van Assche int result, bool follow_symlink, int verbose)
922*44704f69SBart Van Assche {
923*44704f69SBart Van Assche int m_mi, m_ma, num;
924*44704f69SBart Van Assche char value[D_NAME_LEN_MAX];
925*44704f69SBart Van Assche char name[D_NAME_LEN_MAX];
926*44704f69SBart Van Assche
927*44704f69SBart Van Assche if (2 == result) {
928*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
929*44704f69SBart Van Assche follow_symlink, verbose);
930*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
931*44704f69SBart Van Assche }
932*44704f69SBart Van Assche snprintf(name, sizeof(name), "%ssch%d", sys_sch_dir, mi);
933*44704f69SBart Van Assche if (3 == result) {
934*44704f69SBart Van Assche printf("%s\n", name);
935*44704f69SBart Van Assche return 0;
936*44704f69SBart Van Assche }
937*44704f69SBart Van Assche if (! get_value(name, "dev", value, sizeof(value))) {
938*44704f69SBart Van Assche pr2serr("Couldn't find sysfs match for device: %s\n",
939*44704f69SBart Van Assche device_name);
940*44704f69SBart Van Assche return 1;
941*44704f69SBart Van Assche }
942*44704f69SBart Van Assche if (verbose)
943*44704f69SBart Van Assche pr2serr("sysfs sch dev: %s\n", value);
944*44704f69SBart Van Assche if (! if_directory_chdir(name, "device")) {
945*44704f69SBart Van Assche pr2serr("sysfs problem with device: %s\n", device_name);
946*44704f69SBart Van Assche return 1;
947*44704f69SBart Van Assche }
948*44704f69SBart Van Assche if (if_directory_ch2generic(".")) {
949*44704f69SBart Van Assche if (1 == result) {
950*44704f69SBart Van Assche if (NULL == getcwd(value, sizeof(value)))
951*44704f69SBart Van Assche value[0] = '\0';
952*44704f69SBart Van Assche printf("%s\n", value);
953*44704f69SBart Van Assche return 0;
954*44704f69SBart Van Assche }
955*44704f69SBart Van Assche if (! get_value(".", "dev", value, sizeof(value))) {
956*44704f69SBart Van Assche pr2serr("Couldn't find sysfs generic dev\n");
957*44704f69SBart Van Assche return 1;
958*44704f69SBart Van Assche }
959*44704f69SBart Van Assche if (verbose)
960*44704f69SBart Van Assche printf("matching dev: %s\n", value);
961*44704f69SBart Van Assche if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
962*44704f69SBart Van Assche pr2serr("Couldn't decode mapped dev\n");
963*44704f69SBart Van Assche return 1;
964*44704f69SBart Van Assche }
965*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
966*44704f69SBart Van Assche follow_symlink, verbose);
967*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
968*44704f69SBart Van Assche } else {
969*44704f69SBart Van Assche pr2serr("sch device: %s does not match any SCSI generic "
970*44704f69SBart Van Assche "device\n", device_name);
971*44704f69SBart Van Assche pr2serr(" perhaps sg module is not loaded\n");
972*44704f69SBart Van Assche return 1;
973*44704f69SBart Van Assche }
974*44704f69SBart Van Assche }
975*44704f69SBart Van Assche
976*44704f69SBart Van Assche static int
map_sg(const char * device_name,const char * device_dir,int ma,int mi,int result,bool follow_symlink,int verbose)977*44704f69SBart Van Assche map_sg(const char * device_name, const char * device_dir, int ma, int mi,
978*44704f69SBart Van Assche int result, bool follow_symlink, int verbose)
979*44704f69SBart Van Assche {
980*44704f69SBart Van Assche int m_mi, m_ma, num;
981*44704f69SBart Van Assche char value[D_NAME_LEN_MAX];
982*44704f69SBart Van Assche char name[D_NAME_LEN_MAX];
983*44704f69SBart Van Assche
984*44704f69SBart Van Assche if (2 == result) {
985*44704f69SBart Van Assche num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
986*44704f69SBart Van Assche follow_symlink, verbose);
987*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
988*44704f69SBart Van Assche }
989*44704f69SBart Van Assche snprintf(name, sizeof(name), "%ssg%d", sys_sg_dir, mi);
990*44704f69SBart Van Assche if (3 == result) {
991*44704f69SBart Van Assche printf("%s\n", name);
992*44704f69SBart Van Assche return 0;
993*44704f69SBart Van Assche }
994*44704f69SBart Van Assche if (! get_value(name, "dev", value, sizeof(value))) {
995*44704f69SBart Van Assche pr2serr("Couldn't find sysfs match for device: %s\n",
996*44704f69SBart Van Assche device_name);
997*44704f69SBart Van Assche return 1;
998*44704f69SBart Van Assche }
999*44704f69SBart Van Assche if (verbose)
1000*44704f69SBart Van Assche pr2serr("sysfs sg dev: %s\n", value);
1001*44704f69SBart Van Assche if (! if_directory_chdir(name, "device")) {
1002*44704f69SBart Van Assche pr2serr("sysfs problem with device: %s\n", device_name);
1003*44704f69SBart Van Assche return 1;
1004*44704f69SBart Van Assche }
1005*44704f69SBart Van Assche if ((1 == from_sg_scan(".", verbose)) &&
1006*44704f69SBart Van Assche (if_directory_chdir(".", from_sg.name))) {
1007*44704f69SBart Van Assche if (DT_DIR == from_sg.d_type) {
1008*44704f69SBart Van Assche if ((1 == scan_for_first(".", verbose)) &&
1009*44704f69SBart Van Assche (if_directory_chdir(".", for_first.name))) {
1010*44704f69SBart Van Assche ;
1011*44704f69SBart Van Assche } else {
1012*44704f69SBart Van Assche pr2serr("unexpected scan_for_first error\n");
1013*44704f69SBart Van Assche }
1014*44704f69SBart Van Assche }
1015*44704f69SBart Van Assche if (1 == result) {
1016*44704f69SBart Van Assche if (NULL == getcwd(value, sizeof(value)))
1017*44704f69SBart Van Assche value[0] = '\0';
1018*44704f69SBart Van Assche printf("%s\n", value);
1019*44704f69SBart Van Assche return 0;
1020*44704f69SBart Van Assche }
1021*44704f69SBart Van Assche if (! get_value(".", "dev", value, sizeof(value))) {
1022*44704f69SBart Van Assche pr2serr("Couldn't find sysfs block dev\n");
1023*44704f69SBart Van Assche return 1;
1024*44704f69SBart Van Assche }
1025*44704f69SBart Van Assche if (verbose)
1026*44704f69SBart Van Assche printf("matching dev: %s\n", value);
1027*44704f69SBart Van Assche if (2 != sscanf(value, "%d:%d", &m_ma, &m_mi)) {
1028*44704f69SBart Van Assche pr2serr("Couldn't decode mapped dev\n");
1029*44704f69SBart Van Assche return 1;
1030*44704f69SBart Van Assche }
1031*44704f69SBart Van Assche num = list_matching_nodes(device_dir, from_sg.ft, m_ma, m_mi,
1032*44704f69SBart Van Assche follow_symlink, verbose);
1033*44704f69SBart Van Assche return (num > 0) ? 0 : 1;
1034*44704f69SBart Van Assche } else {
1035*44704f69SBart Van Assche pr2serr("sg device: %s does not match any other SCSI "
1036*44704f69SBart Van Assche "device\n", device_name);
1037*44704f69SBart Van Assche return 1;
1038*44704f69SBart Van Assche }
1039*44704f69SBart Van Assche }
1040*44704f69SBart Van Assche
1041*44704f69SBart Van Assche
1042*44704f69SBart Van Assche int
main(int argc,char * argv[])1043*44704f69SBart Van Assche main(int argc, char * argv[])
1044*44704f69SBart Van Assche {
1045*44704f69SBart Van Assche bool cont;
1046*44704f69SBart Van Assche int c, num, tt, res;
1047*44704f69SBart Van Assche int given_is = -1;
1048*44704f69SBart Van Assche int result = 0;
1049*44704f69SBart Van Assche int verbose = 0;
1050*44704f69SBart Van Assche int ret = 1;
1051*44704f69SBart Van Assche int ma, mi;
1052*44704f69SBart Van Assche bool do_dev_dir = false;
1053*44704f69SBart Van Assche bool follow_symlink = false;
1054*44704f69SBart Van Assche char device_name[D_NAME_LEN_MAX];
1055*44704f69SBart Van Assche char device_dir[D_NAME_LEN_MAX];
1056*44704f69SBart Van Assche char value[D_NAME_LEN_MAX];
1057*44704f69SBart Van Assche
1058*44704f69SBart Van Assche memset(device_name, 0, sizeof(device_name));
1059*44704f69SBart Van Assche memset(device_dir, 0, sizeof(device_dir));
1060*44704f69SBart Van Assche while (1) {
1061*44704f69SBart Van Assche int option_index = 0;
1062*44704f69SBart Van Assche
1063*44704f69SBart Van Assche c = getopt_long(argc, argv, "d:hg:r:svV", long_options,
1064*44704f69SBart Van Assche &option_index);
1065*44704f69SBart Van Assche if (c == -1)
1066*44704f69SBart Van Assche break;
1067*44704f69SBart Van Assche
1068*44704f69SBart Van Assche switch (c) {
1069*44704f69SBart Van Assche case 'd':
1070*44704f69SBart Van Assche strncpy(device_dir, optarg, sizeof(device_dir) - 1);
1071*44704f69SBart Van Assche do_dev_dir = true;
1072*44704f69SBart Van Assche break;
1073*44704f69SBart Van Assche case 'g':
1074*44704f69SBart Van Assche num = sscanf(optarg, "%d", &res);
1075*44704f69SBart Van Assche if ((1 == num) && ((0 == res) || (1 == res)))
1076*44704f69SBart Van Assche given_is = res;
1077*44704f69SBart Van Assche else {
1078*44704f69SBart Van Assche pr2serr("value for '--given_to=' must be 0 "
1079*44704f69SBart Van Assche "or 1\n");
1080*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1081*44704f69SBart Van Assche }
1082*44704f69SBart Van Assche break;
1083*44704f69SBart Van Assche case 'h':
1084*44704f69SBart Van Assche case '?':
1085*44704f69SBart Van Assche usage();
1086*44704f69SBart Van Assche return 0;
1087*44704f69SBart Van Assche case 'r':
1088*44704f69SBart Van Assche num = sscanf(optarg, "%d", &res);
1089*44704f69SBart Van Assche if ((1 == num) && (res >= 0) && (res < 4))
1090*44704f69SBart Van Assche result = res;
1091*44704f69SBart Van Assche else {
1092*44704f69SBart Van Assche pr2serr("value for '--result=' must be "
1093*44704f69SBart Van Assche "0..3\n");
1094*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1095*44704f69SBart Van Assche }
1096*44704f69SBart Van Assche break;
1097*44704f69SBart Van Assche case 's':
1098*44704f69SBart Van Assche follow_symlink = true;
1099*44704f69SBart Van Assche break;
1100*44704f69SBart Van Assche case 'v':
1101*44704f69SBart Van Assche ++verbose;
1102*44704f69SBart Van Assche break;
1103*44704f69SBart Van Assche case 'V':
1104*44704f69SBart Van Assche pr2serr(ME "version: %s\n", version_str);
1105*44704f69SBart Van Assche return 0;
1106*44704f69SBart Van Assche default:
1107*44704f69SBart Van Assche pr2serr("unrecognised option code 0x%x ??\n", c);
1108*44704f69SBart Van Assche usage();
1109*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1110*44704f69SBart Van Assche }
1111*44704f69SBart Van Assche }
1112*44704f69SBart Van Assche if (optind < argc) {
1113*44704f69SBart Van Assche if ('\0' == device_name[0]) {
1114*44704f69SBart Van Assche strncpy(device_name, argv[optind],
1115*44704f69SBart Van Assche sizeof(device_name) - 1);
1116*44704f69SBart Van Assche device_name[sizeof(device_name) - 1] = '\0';
1117*44704f69SBart Van Assche ++optind;
1118*44704f69SBart Van Assche }
1119*44704f69SBart Van Assche if (optind < argc) {
1120*44704f69SBart Van Assche for (; optind < argc; ++optind)
1121*44704f69SBart Van Assche pr2serr("Unexpected extra argument: %s\n",
1122*44704f69SBart Van Assche argv[optind]);
1123*44704f69SBart Van Assche usage();
1124*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1125*44704f69SBart Van Assche }
1126*44704f69SBart Van Assche }
1127*44704f69SBart Van Assche
1128*44704f69SBart Van Assche if (0 == device_name[0]) {
1129*44704f69SBart Van Assche pr2serr("missing device name!\n");
1130*44704f69SBart Van Assche usage();
1131*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1132*44704f69SBart Van Assche }
1133*44704f69SBart Van Assche
1134*44704f69SBart Van Assche ma = 0;
1135*44704f69SBart Van Assche mi = 0;
1136*44704f69SBart Van Assche if (do_dev_dir) {
1137*44704f69SBart Van Assche if (if_directory_chdir(".", device_dir)) {
1138*44704f69SBart Van Assche if (getcwd(device_dir, sizeof(device_dir)))
1139*44704f69SBart Van Assche device_dir[sizeof(device_dir) - 1] = '\0';
1140*44704f69SBart Van Assche else
1141*44704f69SBart Van Assche device_dir[0] = '\0';
1142*44704f69SBart Van Assche if (verbose > 1)
1143*44704f69SBart Van Assche pr2serr("Absolute path to dev_dir: %s\n",
1144*44704f69SBart Van Assche device_dir);
1145*44704f69SBart Van Assche } else {
1146*44704f69SBart Van Assche pr2serr("dev_dir: %s invalid\n", device_dir);
1147*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1148*44704f69SBart Van Assche }
1149*44704f69SBart Van Assche } else {
1150*44704f69SBart Van Assche strcpy(device_dir, device_name);
1151*44704f69SBart Van Assche dirname(device_dir);
1152*44704f69SBart Van Assche if (0 == strcmp(device_dir, device_name)) {
1153*44704f69SBart Van Assche if (NULL == getcwd(device_dir, sizeof(device_dir)))
1154*44704f69SBart Van Assche device_dir[0] = '\0';
1155*44704f69SBart Van Assche }
1156*44704f69SBart Van Assche }
1157*44704f69SBart Van Assche ret = nt_typ_from_filename(device_name, &ma, &mi);
1158*44704f69SBart Van Assche if (ret < 0) {
1159*44704f69SBart Van Assche pr2serr("stat failed on %s: %s\n", device_name,
1160*44704f69SBart Van Assche ssafe_strerror(-ret));
1161*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1162*44704f69SBart Van Assche }
1163*44704f69SBart Van Assche if (verbose)
1164*44704f69SBart Van Assche pr2serr(" %s: %s device [maj=%d, min=%d]\n", device_name,
1165*44704f69SBart Van Assche nt_names[ret], ma, mi);
1166*44704f69SBart Van Assche res = 0;
1167*44704f69SBart Van Assche switch (ret) {
1168*44704f69SBart Van Assche case NT_SD:
1169*44704f69SBart Van Assche case NT_SR:
1170*44704f69SBart Van Assche case NT_HD:
1171*44704f69SBart Van Assche if (given_is > 0) {
1172*44704f69SBart Van Assche pr2serr("block special but '--given_is=' suggested "
1173*44704f69SBart Van Assche "sysfs device\n");
1174*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1175*44704f69SBart Van Assche }
1176*44704f69SBart Van Assche break;
1177*44704f69SBart Van Assche case NT_ST:
1178*44704f69SBart Van Assche case NT_OSST:
1179*44704f69SBart Van Assche case NT_CH:
1180*44704f69SBart Van Assche case NT_SG:
1181*44704f69SBart Van Assche if (given_is > 0) {
1182*44704f69SBart Van Assche pr2serr("character special but '--given_is=' "
1183*44704f69SBart Van Assche "suggested sysfs device\n");
1184*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1185*44704f69SBart Van Assche }
1186*44704f69SBart Van Assche break;
1187*44704f69SBart Van Assche case NT_REG:
1188*44704f69SBart Van Assche if (0 == given_is) {
1189*44704f69SBart Van Assche pr2serr("regular file but '--given_is=' suggested "
1190*44704f69SBart Van Assche "block or char special\n");
1191*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1192*44704f69SBart Van Assche }
1193*44704f69SBart Van Assche strcpy(device_dir, def_dev_dir);
1194*44704f69SBart Van Assche break;
1195*44704f69SBart Van Assche case NT_DIR:
1196*44704f69SBart Van Assche if (0 == given_is) {
1197*44704f69SBart Van Assche pr2serr("directory but '--given_is=' suggested "
1198*44704f69SBart Van Assche "block or char special\n");
1199*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1200*44704f69SBart Van Assche }
1201*44704f69SBart Van Assche strcpy(device_dir, def_dev_dir);
1202*44704f69SBart Van Assche break;
1203*44704f69SBart Van Assche default:
1204*44704f69SBart Van Assche break;
1205*44704f69SBart Van Assche }
1206*44704f69SBart Van Assche
1207*44704f69SBart Van Assche tt = NT_NO_MATCH;
1208*44704f69SBart Van Assche do {
1209*44704f69SBart Van Assche cont = false;
1210*44704f69SBart Van Assche switch (ret) {
1211*44704f69SBart Van Assche case NT_NO_MATCH:
1212*44704f69SBart Van Assche res = 1;
1213*44704f69SBart Van Assche break;
1214*44704f69SBart Van Assche case NT_SD:
1215*44704f69SBart Van Assche res = map_sd(device_name, device_dir, ma, mi, result,
1216*44704f69SBart Van Assche follow_symlink, verbose);
1217*44704f69SBart Van Assche break;
1218*44704f69SBart Van Assche case NT_SR:
1219*44704f69SBart Van Assche res = map_sr(device_name, device_dir, ma, mi, result,
1220*44704f69SBart Van Assche follow_symlink, verbose);
1221*44704f69SBart Van Assche break;
1222*44704f69SBart Van Assche case NT_HD:
1223*44704f69SBart Van Assche if (result < 2) {
1224*44704f69SBart Van Assche pr2serr("a hd device does not map to a sg "
1225*44704f69SBart Van Assche "device\n");
1226*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1227*44704f69SBart Van Assche }
1228*44704f69SBart Van Assche res = map_hd(device_dir, ma, mi, result,
1229*44704f69SBart Van Assche follow_symlink, verbose);
1230*44704f69SBart Van Assche break;
1231*44704f69SBart Van Assche case NT_ST:
1232*44704f69SBart Van Assche res = map_st(device_name, device_dir, ma, mi, result,
1233*44704f69SBart Van Assche follow_symlink, verbose);
1234*44704f69SBart Van Assche break;
1235*44704f69SBart Van Assche case NT_OSST:
1236*44704f69SBart Van Assche res = map_osst(device_name, device_dir, ma, mi,
1237*44704f69SBart Van Assche result, follow_symlink, verbose);
1238*44704f69SBart Van Assche break;
1239*44704f69SBart Van Assche case NT_CH:
1240*44704f69SBart Van Assche res = map_ch(device_name, device_dir, ma, mi, result,
1241*44704f69SBart Van Assche follow_symlink, verbose);
1242*44704f69SBart Van Assche break;
1243*44704f69SBart Van Assche case NT_SG:
1244*44704f69SBart Van Assche res = map_sg(device_name, device_dir, ma, mi, result,
1245*44704f69SBart Van Assche follow_symlink, verbose);
1246*44704f69SBart Van Assche break;
1247*44704f69SBart Van Assche case NT_REG:
1248*44704f69SBart Van Assche if (! get_value(NULL, device_name, value,
1249*44704f69SBart Van Assche sizeof(value))) {
1250*44704f69SBart Van Assche pr2serr("Couldn't fetch value from: %s\n",
1251*44704f69SBart Van Assche device_name);
1252*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1253*44704f69SBart Van Assche }
1254*44704f69SBart Van Assche if (verbose)
1255*44704f69SBart Van Assche pr2serr("value: %s\n", value);
1256*44704f69SBart Van Assche if (2 != sscanf(value, "%d:%d", &ma, &mi)) {
1257*44704f69SBart Van Assche pr2serr("Couldn't decode value\n");
1258*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1259*44704f69SBart Van Assche }
1260*44704f69SBart Van Assche tt = nt_typ_from_major(ma);
1261*44704f69SBart Van Assche cont = true;
1262*44704f69SBart Van Assche break;
1263*44704f69SBart Van Assche case NT_DIR:
1264*44704f69SBart Van Assche if (! get_value(device_name, "dev", value,
1265*44704f69SBart Van Assche sizeof(value))) {
1266*44704f69SBart Van Assche pr2serr("Couldn't fetch value from: %s/dev\n",
1267*44704f69SBart Van Assche device_name);
1268*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1269*44704f69SBart Van Assche }
1270*44704f69SBart Van Assche if (verbose)
1271*44704f69SBart Van Assche pr2serr("value: %s\n", value);
1272*44704f69SBart Van Assche if (2 != sscanf(value, "%d:%d", &ma, &mi)) {
1273*44704f69SBart Van Assche pr2serr("Couldn't decode value\n");
1274*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
1275*44704f69SBart Van Assche }
1276*44704f69SBart Van Assche tt = nt_typ_from_major(ma);
1277*44704f69SBart Van Assche cont = true;
1278*44704f69SBart Van Assche break;
1279*44704f69SBart Van Assche default:
1280*44704f69SBart Van Assche break;
1281*44704f69SBart Van Assche }
1282*44704f69SBart Van Assche ret = tt;
1283*44704f69SBart Van Assche } while (cont);
1284*44704f69SBart Van Assche return res;
1285*44704f69SBart Van Assche }
1286