~ubuntu-branches/ubuntu/intrepid/sg3-utils/intrepid

« back to all changes in this revision

Viewing changes to sg_map26.c

  • Committer: Bazaar Package Importer
  • Author(s): Luk Claes
  • Date: 2006-11-05 17:23:29 UTC
  • mfrom: (1.1.4 upstream) (3.1.2 edgy)
  • Revision ID: james.westby@ubuntu.com-20061105172329-l4loha00sk36qz6k
* Non-maintainer upload.
* Fix FTBFS due to old syscall usage (Closes: #395512).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2005-2006 Douglas Gilbert.
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
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.
 
15
 *
 
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
 
26
 * SUCH DAMAGE.
 
27
 *
 
28
 */
 
29
 
 
30
/* A utility program for the Linux OS SCSI subsystem.
 
31
 *
 
32
 *
 
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.
 
36
 */
 
37
 
 
38
/* #define _XOPEN_SOURCE 500 */
 
39
/* needed to see DT_REG and friends when compiled with: c99 pedantic */
 
40
#define _GNU_SOURCE
 
41
 
 
42
#include <unistd.h>
 
43
#include <fcntl.h>
 
44
#include <stdio.h>
 
45
#include <stdlib.h>
 
46
#include <string.h>
 
47
#include <ctype.h>
 
48
#include <errno.h>
 
49
#include <getopt.h>
 
50
#include <dirent.h>
 
51
#include <libgen.h>
 
52
#include <sys/ioctl.h>
 
53
#include <sys/types.h>
 
54
#include <sys/stat.h>
 
55
#include <linux/major.h>
 
56
 
 
57
#include "sg_lib.h"
 
58
 
 
59
static char * version_str = "1.03 20060623";
 
60
 
 
61
#define ME "sg_map26: "
 
62
 
 
63
#define NT_NO_MATCH 0
 
64
#define NT_SD 1
 
65
#define NT_SR 2
 
66
#define NT_HD 3
 
67
#define NT_ST 4
 
68
#define NT_OSST 5
 
69
#define NT_SG 6
 
70
#define NT_CH 7
 
71
#define NT_REG 8
 
72
#define NT_DIR 9
 
73
 
 
74
#define NAME_LEN_MAX 260
 
75
#define D_NAME_LEN_MAX 516
 
76
 
 
77
#ifndef SCSI_CHANGER_MAJOR
 
78
#define SCSI_CHANGER_MAJOR 86
 
79
#endif
 
80
#ifndef OSST_MAJOR
 
81
#define OSST_MAJOR 206
 
82
#endif
 
83
 
 
84
/* scandir() and stat() categories */
 
85
#define FT_OTHER 0
 
86
#define FT_REGULAR 1
 
87
#define FT_BLOCK 2
 
88
#define FT_CHAR 3
 
89
#define FT_DIR 4
 
90
 
 
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
 
101
#endif
 
102
 
 
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";
 
111
 
 
112
 
 
113
static struct option long_options[] = {
 
114
        {"dev_dir", 1, 0, 'd'},
 
115
        {"given_is", 1, 0, 'g'},
 
116
        {"help", 0, 0, 'h'},
 
117
        {"result", 1, 0, 'r'},
 
118
        {"symlink", 0, 0, 's'},
 
119
        {"verbose", 0, 0, 'v'},
 
120
        {"version", 0, 0, 'V'},
 
121
        {0, 0, 0, 0},
 
122
};
 
123
 
 
124
static const char * nt_names[] = {
 
125
        "No matching",
 
126
        "disk",
 
127
        "cd/dvd",
 
128
        "hd",
 
129
        "tape",
 
130
        "tape (osst)",
 
131
        "generic (sg)",
 
132
        "changer",
 
133
        "regular file",
 
134
        "directory",
 
135
};
 
136
 
 
137
static void usage()
 
138
{
 
139
        fprintf(stderr, "Usage: "
 
140
                "sg_map26   [--dev_dir=<dir>] [--given_is=<n>] [--help] "
 
141
                "[--result=<n>]\n"
 
142
                "                  [--symlink] [--verbose] [--version] "
 
143
                "<device>\n"
 
144
                "  where:\n"
 
145
                "         --dev_dir=<dir>|-d <dir>  search in <dir> for "
 
146
                "resulting special\n"
 
147
                "                              (def: directory of <device> "
 
148
                "or '/dev')\n"
 
149
                "         --given_is=<n>|-g <n>     variety of given "
 
150
                "<device>\n"
 
151
                "                              0->block or char special "
 
152
                "(or symlink to)\n"
 
153
                "                              1->sysfs device, 'dev' or "
 
154
                "parent\n"
 
155
                "         --help|-h       print out usage message\n"
 
156
                "         --result=<n>|-r <n>    variety of file(s) to "
 
157
                "find\n"
 
158
                "                              0->mapped block or char "
 
159
                "special(def)\n"
 
160
                "                              1->mapped sysfs parent\n"
 
161
                "                              2->matching block or char "
 
162
                "special\n"
 
163
                "                              3->matching sysfs parent\n"
 
164
                "         --symlink|-s    symlinks to special included in "
 
165
                "result\n"
 
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 "
 
169
                "vv)\n"
 
170
                );
 
171
}
 
172
 
 
173
 
 
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.
 
177
 */
 
178
 
 
179
static char safe_errbuf[64] = {'u', 'n', 'k', 'n', 'o', 'w', 'n', ' ',
 
180
                               'e', 'r', 'r', 'n', 'o', ':', ' ', 0};
 
181
 
 
182
static char * ssafe_strerror(int errnum)
 
183
{
 
184
        size_t len;
 
185
        char * errstr;
 
186
 
 
187
        errstr = strerror(errnum);
 
188
        if (NULL == errstr) {
 
189
                len = strlen(safe_errbuf);
 
190
                snprintf(safe_errbuf + len, sizeof(safe_errbuf) - len, "%i",
 
191
                         errnum);
 
192
                safe_errbuf[sizeof(safe_errbuf) - 1] = '\0';  /* bombproof */
 
193
                return safe_errbuf;
 
194
        }
 
195
        return errstr;
 
196
}
 
197
 
 
198
static int nt_typ_from_filename(const char * filename, int * majj, int * minn)
 
199
{
 
200
        struct stat st;
 
201
        int ma, mi;
 
202
 
 
203
        if (stat(filename, &st) < 0)
 
204
                return -errno;
 
205
        ma = major(st.st_rdev);
 
206
        mi = minor(st.st_rdev);
 
207
        if (majj)
 
208
                *majj = ma;
 
209
        if (minn)
 
210
                *minn = mi;
 
211
        if (S_ISCHR(st.st_mode)) {
 
212
                switch(ma) {
 
213
                case OSST_MAJOR:
 
214
                        return NT_OSST;
 
215
                case SCSI_GENERIC_MAJOR:
 
216
                        return NT_SG;
 
217
                case SCSI_TAPE_MAJOR:
 
218
                        return NT_ST;
 
219
                case SCSI_CHANGER_MAJOR:
 
220
                        return NT_CH;
 
221
                default:
 
222
                        return NT_NO_MATCH;
 
223
                }
 
224
        } else if (S_ISBLK(st.st_mode)) {
 
225
                switch(ma) {
 
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:
 
234
                        return NT_SD;
 
235
                case SCSI_CDROM_MAJOR:
 
236
                        return NT_SR;
 
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:
 
242
                        return NT_HD;
 
243
                default:
 
244
                        return NT_NO_MATCH;
 
245
                }
 
246
        } else if (S_ISREG(st.st_mode))
 
247
                return NT_REG;
 
248
        else if (S_ISDIR(st.st_mode))
 
249
                return NT_DIR;
 
250
        return NT_NO_MATCH;
 
251
}
 
252
 
 
253
static int nt_typ_from_major(int ma)
 
254
{
 
255
        switch(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:
 
264
                return NT_SD;
 
265
        case SCSI_CDROM_MAJOR:
 
266
                return NT_SR;
 
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:
 
272
                return NT_HD;
 
273
        case OSST_MAJOR:
 
274
                return NT_OSST;
 
275
        case SCSI_GENERIC_MAJOR:
 
276
                return NT_SG;
 
277
        case SCSI_TAPE_MAJOR:
 
278
                return NT_ST;
 
279
        case SCSI_CHANGER_MAJOR:
 
280
                return NT_CH;
 
281
        default:
 
282
                return NT_NO_MATCH;
 
283
        }
 
284
        return NT_NO_MATCH;
 
285
}
 
286
 
 
287
 
 
288
struct node_match_item {
 
289
        const char * dir_name;
 
290
        int file_type;
 
291
        int majj;
 
292
        int minn;
 
293
        int follow_symlink;
 
294
};
 
295
 
 
296
static struct node_match_item nd_match;
 
297
 
 
298
static int nd_match_scandir_select(const struct dirent * s)
 
299
{
 
300
        struct stat st;
 
301
        char name[D_NAME_LEN_MAX];
 
302
        int symlnk = 0;
 
303
 
 
304
        switch (s->d_type) {
 
305
        case DT_BLK:
 
306
                if (FT_BLOCK != nd_match.file_type)
 
307
                        return 0;
 
308
                break;
 
309
        case DT_CHR:
 
310
                if (FT_CHAR != nd_match.file_type)
 
311
                        return 0;
 
312
                break;
 
313
        case DT_DIR:
 
314
                return (FT_DIR == nd_match.file_type) ? 1 : 0;
 
315
        case DT_REG:
 
316
                return (FT_REGULAR == nd_match.file_type) ? 1 : 0;
 
317
        case DT_LNK:    /* follow symlinks */
 
318
                if (! nd_match.follow_symlink)
 
319
                        return 0;
 
320
                symlnk = 1;
 
321
                break;
 
322
        default:
 
323
                return 0;
 
324
        }
 
325
        if ((! symlnk) && (-1 == nd_match.majj) && (-1 == nd_match.minn))
 
326
                return 1;
 
327
        strncpy(name, nd_match.dir_name, NAME_LEN_MAX);
 
328
        strcat(name, "/");
 
329
        strncat(name, s->d_name, NAME_LEN_MAX);
 
330
        memset(&st, 0, sizeof(st));
 
331
        if (stat(name, &st) < 0)
 
332
                return 0;
 
333
        if (symlnk) {
 
334
                if (S_ISCHR(st.st_mode)) {
 
335
                        if (FT_CHAR != nd_match.file_type)
 
336
                                return 0;
 
337
                } else if (S_ISBLK(st.st_mode)) {
 
338
                        if (FT_BLOCK != nd_match.file_type)
 
339
                                return 0;
 
340
                } else
 
341
                        return 0;
 
342
        }
 
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)))
 
347
               ? 1 : 0;
 
348
}
 
349
 
 
350
static int list_matching_nodes(const char * dir_name, int file_type,
 
351
                               int majj, int minn, int follow_symlink,
 
352
                               int verbose)
 
353
{
 
354
        struct dirent ** namelist;
 
355
        int num, k;
 
356
 
 
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);
 
363
        if (num < 0) {
 
364
                if (verbose)
 
365
                        fprintf(stderr, "scandir: %s %s\n", dir_name,
 
366
                                ssafe_strerror(errno));
 
367
                return -errno;
 
368
        }
 
369
        for (k = 0; k < num; ++k) {
 
370
                printf("%s/%s\n", dir_name, namelist[k]->d_name);
 
371
                free(namelist[k]);
 
372
        }
 
373
        free(namelist);
 
374
        return num;
 
375
}
 
376
 
 
377
struct sg_item_t {
 
378
        char name[NAME_LEN_MAX];
 
379
        int ft;
 
380
        int nt;
 
381
};
 
382
 
 
383
static struct sg_item_t from_sg;
 
384
 
 
385
static int from_sg_scandir_select(const struct dirent * s)
 
386
{
 
387
        int len;
 
388
 
 
389
        if (FT_OTHER != from_sg.ft)
 
390
                return 0;
 
391
        if (DT_LNK != s->d_type)
 
392
                return 0;
 
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;
 
396
                from_sg.nt = NT_CH;
 
397
                return 1;
 
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;
 
401
                return 1;
 
402
        } else if (0 == strcmp("tape", s->d_name)) {
 
403
                strcpy(from_sg.name, s->d_name);
 
404
                from_sg.ft = FT_CHAR;
 
405
                from_sg.nt = NT_ST;
 
406
                return 1;
 
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;
 
413
                        from_sg.nt = NT_ST;
 
414
                        return 1;
 
415
                } else
 
416
                        return 0;
 
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;
 
421
                return 1;
 
422
        } else
 
423
                return 0;
 
424
}
 
425
 
 
426
static int from_sg_scan(const char * dir_name, int verbose)
 
427
{
 
428
        struct dirent ** namelist;
 
429
        int num, k;
 
430
 
 
431
        from_sg.ft = FT_OTHER;
 
432
        from_sg.nt = NT_NO_MATCH;
 
433
        num = scandir(dir_name, &namelist, from_sg_scandir_select, NULL);
 
434
        if (num < 0) {
 
435
                if (verbose)
 
436
                        fprintf(stderr, "scandir: %s %s\n", dir_name,
 
437
                                ssafe_strerror(errno));
 
438
                return -errno;
 
439
        }
 
440
        if (verbose) {
 
441
                for (k = 0; k < num; ++k)
 
442
                        fprintf(stderr, "    %s/%s\n", dir_name,
 
443
                                namelist[k]->d_name);
 
444
        }
 
445
        for (k = 0; k < num; ++k)
 
446
                free(namelist[k]);
 
447
        free(namelist);
 
448
        return num;
 
449
}
 
450
 
 
451
static struct sg_item_t to_sg;
 
452
 
 
453
static int to_sg_scandir_select(const struct dirent * s)
 
454
{
 
455
        if (FT_OTHER != to_sg.ft)
 
456
                return 0;
 
457
        if (DT_LNK != s->d_type)
 
458
                return 0;
 
459
        if (0 == strncmp("scsi_generic", s->d_name, 12)) {
 
460
                strncpy(to_sg.name, s->d_name, NAME_LEN_MAX);
 
461
                to_sg.ft = FT_CHAR;
 
462
                to_sg.nt = NT_SG;
 
463
                return 1;
 
464
        } else
 
465
                return 0;
 
466
}
 
467
 
 
468
static int to_sg_scan(const char * dir_name)
 
469
{
 
470
        struct dirent ** namelist;
 
471
        int num, k;
 
472
 
 
473
        to_sg.ft = FT_OTHER;
 
474
        to_sg.nt = NT_NO_MATCH;
 
475
        num = scandir(dir_name, &namelist, to_sg_scandir_select, NULL);
 
476
        if (num < 0)
 
477
                return -errno;
 
478
        for (k = 0; k < num; ++k)
 
479
                free(namelist[k]);
 
480
        free(namelist);
 
481
        return num;
 
482
}
 
483
 
 
484
/* Return 1 if directory, else 0 */
 
485
static int if_directory_chdir(const char * dir_name, const char * base_name)
 
486
{
 
487
        char buff[D_NAME_LEN_MAX];
 
488
        struct stat a_stat;
 
489
 
 
490
        strcpy(buff, dir_name);
 
491
        strcat(buff, "/");
 
492
        strcat(buff, base_name);
 
493
        if (stat(buff, &a_stat) < 0)
 
494
                return 0;
 
495
        if (S_ISDIR(a_stat.st_mode)) {
 
496
                if (chdir(buff) < 0)
 
497
                        return 0;
 
498
                return 1;
 
499
        }
 
500
        return 0;
 
501
}
 
502
 
 
503
/* Return 1 if directory, else 0 */
 
504
static int if_directory_ch2generic(const char * dir_name)
 
505
{
 
506
        char buff[NAME_LEN_MAX];
 
507
        struct stat a_stat;
 
508
        const char * old_name = "generic";
 
509
 
 
510
        strcpy(buff, dir_name);
 
511
        strcat(buff, "/");
 
512
        strcat(buff, old_name);
 
513
        if ((stat(buff, &a_stat) >= 0) && S_ISDIR(a_stat.st_mode)) {
 
514
                if (chdir(buff) < 0)
 
515
                        return 0;
 
516
                return 1;
 
517
        }
 
518
        /* No "generic", so now look for "scsi_generic:sg<n>" */
 
519
        if (1 != to_sg_scan(dir_name))
 
520
                return 0;
 
521
        strcpy(buff, dir_name);
 
522
        strcat(buff, "/");
 
523
        strcat(buff, to_sg.name);
 
524
        if (stat(buff, &a_stat) < 0)
 
525
                return 0;
 
526
        if (S_ISDIR(a_stat.st_mode)) {
 
527
                if (chdir(buff) < 0)
 
528
                        return 0;
 
529
                return 1;
 
530
        }
 
531
        return 0;
 
532
}
 
533
 
 
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)
 
537
{
 
538
        char buff[D_NAME_LEN_MAX];
 
539
        FILE * f;
 
540
        int len;
 
541
 
 
542
        if ((NULL == dir_name) && (NULL == base_name))
 
543
                return 0;
 
544
        if (dir_name) {
 
545
                strcpy(buff, dir_name);
 
546
                if (base_name && (strlen(base_name) > 0)) {
 
547
                        strcat(buff, "/");
 
548
                        strcat(buff, base_name);
 
549
                }
 
550
        } else
 
551
                strcpy(buff, base_name);
 
552
        if (NULL == (f = fopen(buff, "r"))) {
 
553
                return 0;
 
554
        }
 
555
        if (NULL == fgets(value, max_value_len, f)) {
 
556
                fclose(f);
 
557
                return 0;
 
558
        }
 
559
        len = strlen(value);
 
560
        if ((len > 0) && (value[len - 1] == '\n'))
 
561
                value[len - 1] = '\0';
 
562
        fclose(f);
 
563
        return 1;
 
564
}
 
565
 
 
566
static int map_hd(const char * device_dir, int ma, int mi, int result,
 
567
                  int follow_symlink, int verbose)
 
568
{
 
569
        char c, num;
 
570
 
 
571
        if (2 == result) {
 
572
                num = list_matching_nodes(device_dir, FT_BLOCK,
 
573
                                          ma, mi, follow_symlink,
 
574
                                          verbose);
 
575
                return (num > 0) ? 0 : 1;
 
576
        }
 
577
        switch (ma) {
 
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;
 
589
        }
 
590
        if (mi > 63)
 
591
                ++c;
 
592
        printf("%shd%c\n", sys_hd_dir, c);
 
593
        return 0;
 
594
}
 
595
 
 
596
static int map_sd(const char * device_name, const char * device_dir,
 
597
                  int ma, int mi, int result, int follow_symlink,
 
598
                  int verbose)
 
599
{
 
600
        int index, m_mi, m_ma, num;
 
601
        char value[D_NAME_LEN_MAX];
 
602
        char name[D_NAME_LEN_MAX];
 
603
 
 
604
        if (2 == result) {
 
605
                num = list_matching_nodes(device_dir, FT_BLOCK, ma, mi,
 
606
                                          follow_symlink, verbose);
 
607
                return (num > 0) ? 0 : 1;
 
608
        }
 
609
        if (SCSI_DISK0_MAJOR == ma)
 
610
                index = mi / 16;
 
611
        else if (ma >= SCSI_DISK8_MAJOR)
 
612
                index = (mi / 16) + 128 +
 
613
                        ((ma - SCSI_DISK8_MAJOR) * 16);
 
614
        else
 
615
                index = (mi / 16) + 16 +
 
616
                        ((ma - SCSI_DISK1_MAJOR) * 16);
 
617
        if (index < 26)
 
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",
 
622
                         sys_sd_dir,
 
623
                         'a' + index / 26 - 1,'a' + index % 26);
 
624
        else {
 
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;
 
628
 
 
629
                snprintf(name, sizeof(name), "%ssd%c%c%c",
 
630
                         sys_sd_dir, 'a' + m1, 'a' + m2, 'a' + m3);
 
631
        }
 
632
        if (3 == result) {
 
633
                printf("%s\n", name);
 
634
                return 0;
 
635
        }
 
636
        if (! get_value(name, "dev", value, sizeof(value))) {
 
637
                fprintf(stderr, "Couldn't find sysfs match for "
 
638
                        "device: %s\n", device_name);
 
639
                return 1;
 
640
        }
 
641
        if (verbose)
 
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",
 
645
                        device_name);
 
646
                return 1;
 
647
        }
 
648
        if (if_directory_ch2generic(".")) {
 
649
                if (1 == result) {
 
650
                        if (NULL == getcwd(value, sizeof(value)))
 
651
                                value[0] = '\0';
 
652
                        printf("%s\n", value);
 
653
                        return 0;
 
654
                }
 
655
                if (! get_value(".", "dev", value, sizeof(value))) {
 
656
                        fprintf(stderr, "Couldn't find sysfs generic"
 
657
                                "dev\n");
 
658
                        return 1;
 
659
                }
 
660
                if (verbose)
 
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 "
 
664
                                "dev\n");
 
665
                        return 1;
 
666
                }
 
667
                num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
 
668
                                          follow_symlink, verbose);
 
669
                return (num > 0) ? 0 : 1;
 
670
        } else {
 
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 "
 
674
                        "loaded\n");
 
675
                return 1;
 
676
        }
 
677
}
 
678
 
 
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)
 
681
{
 
682
        int m_mi, m_ma, num;
 
683
        char value[D_NAME_LEN_MAX];
 
684
        char name[D_NAME_LEN_MAX];
 
685
 
 
686
        if (2 == result) {
 
687
                num = list_matching_nodes(device_dir, FT_BLOCK, ma, mi,
 
688
                                          follow_symlink, verbose);
 
689
                return (num > 0) ? 0 : 1;
 
690
        }
 
691
        snprintf(name, sizeof(name), "%ssr%d", sys_sr_dir, mi);
 
692
        if (3 == result) {
 
693
                printf("%s\n", name);
 
694
                return 0;
 
695
        }
 
696
        if (! get_value(name, "dev", value, sizeof(value))) {
 
697
                fprintf(stderr, "Couldn't find sysfs match for "
 
698
                        "device: %s\n", device_name);
 
699
                return 1;
 
700
        }
 
701
        if (verbose)
 
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",
 
705
                        device_name);
 
706
                return 1;
 
707
        }
 
708
        if (if_directory_ch2generic(".")) {
 
709
                if (1 == result) {
 
710
                        if (NULL == getcwd(value, sizeof(value)))
 
711
                                value[0] = '\0';
 
712
                        printf("%s\n", value);
 
713
                        return 0;
 
714
                }
 
715
                if (! get_value(".", "dev", value, sizeof(value))) {
 
716
                        fprintf(stderr, "Couldn't find sysfs generic"
 
717
                                "dev\n");
 
718
                        return 1;
 
719
                }
 
720
                if (verbose)
 
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 "
 
724
                                "dev\n");
 
725
                        return 1;
 
726
                }
 
727
                num = list_matching_nodes(device_dir, FT_BLOCK, m_ma, m_mi,
 
728
                                          follow_symlink, verbose);
 
729
                return (num > 0) ? 0 : 1;
 
730
        } else {
 
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 "
 
734
                        "loaded\n");
 
735
                return 1;
 
736
        }
 
737
}
 
738
 
 
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)
 
741
{
 
742
        int m_mi, m_ma, num;
 
743
        char value[D_NAME_LEN_MAX];
 
744
        char name[D_NAME_LEN_MAX];
 
745
 
 
746
        if (2 == result) {
 
747
                num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
 
748
                                          follow_symlink, verbose);
 
749
                return (num > 0) ? 0 : 1;
 
750
        }
 
751
        snprintf(name, sizeof(name), "%sst%d", sys_st_dir,
 
752
                 (mi & 0x1f));
 
753
        if (3 == result) {
 
754
                printf("%s\n", name);
 
755
                return 0;
 
756
        }
 
757
        if (! get_value(name, "dev", value, sizeof(value))) {
 
758
                fprintf(stderr, "Couldn't find sysfs match for "
 
759
                        "device: %s\n", device_name);
 
760
                return 1;
 
761
        }
 
762
        if (verbose)
 
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",
 
766
                        device_name);
 
767
                return 1;
 
768
        }
 
769
        if (if_directory_ch2generic(".")) {
 
770
                if (1 == result) {
 
771
                        if (NULL == getcwd(value, sizeof(value)))
 
772
                                value[0] = '\0';
 
773
                        printf("%s\n", value);
 
774
                        return 0;
 
775
                }
 
776
                if (! get_value(".", "dev", value, sizeof(value))) {
 
777
                        fprintf(stderr, "Couldn't find sysfs generic"
 
778
                                "dev\n");
 
779
                        return 1;
 
780
                }
 
781
                if (verbose)
 
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 "
 
785
                                "dev\n");
 
786
                        return 1;
 
787
                }
 
788
                num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
 
789
                                          follow_symlink, verbose);
 
790
                return (num > 0) ? 0 : 1;
 
791
        } else {
 
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 "
 
795
                        "loaded\n");
 
796
                return 1;
 
797
        }
 
798
}
 
799
 
 
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)
 
802
{
 
803
        int m_mi, m_ma, num;
 
804
        char value[D_NAME_LEN_MAX];
 
805
        char name[D_NAME_LEN_MAX];
 
806
 
 
807
        if (2 == result) {
 
808
                num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
 
809
                                          follow_symlink, verbose);
 
810
                return (num > 0) ? 0 : 1;
 
811
        }
 
812
        snprintf(name, sizeof(name), "%sosst%d", sys_osst_dir,
 
813
                 (mi & 0x1f));
 
814
        if (3 == result) {
 
815
                printf("%s\n", name);
 
816
                return 0;
 
817
        }
 
818
        if (! get_value(name, "dev", value, sizeof(value))) {
 
819
                fprintf(stderr, "Couldn't find sysfs match for "
 
820
                        "device: %s\n", device_name);
 
821
                return 1;
 
822
        }
 
823
        if (verbose)
 
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",
 
827
                        device_name);
 
828
                return 1;
 
829
        }
 
830
        if (if_directory_ch2generic(".")) {
 
831
                if (1 == result) {
 
832
                        if (NULL == getcwd(value, sizeof(value)))
 
833
                                value[0] = '\0';
 
834
                        printf("%s\n", value);
 
835
                        return 0;
 
836
                }
 
837
                if (! get_value(".", "dev", value, sizeof(value))) {
 
838
                        fprintf(stderr, "Couldn't find sysfs generic"
 
839
                                "dev\n");
 
840
                        return 1;
 
841
                }
 
842
                if (verbose)
 
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 "
 
846
                                "dev\n");
 
847
                        return 1;
 
848
                }
 
849
                num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
 
850
                                          follow_symlink, verbose);
 
851
                return (num > 0) ? 0 : 1;
 
852
        } else {
 
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 "
 
856
                        "loaded\n");
 
857
                return 1;
 
858
        }
 
859
}
 
860
 
 
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)
 
863
{
 
864
        int m_mi, m_ma, num;
 
865
        char value[D_NAME_LEN_MAX];
 
866
        char name[D_NAME_LEN_MAX];
 
867
 
 
868
        if (2 == result) {
 
869
                num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
 
870
                                          follow_symlink, verbose);
 
871
                return (num > 0) ? 0 : 1;
 
872
        }
 
873
        snprintf(name, sizeof(name), "%ssch%d", sys_sch_dir, mi);
 
874
        if (3 == result) {
 
875
                printf("%s\n", name);
 
876
                return 0;
 
877
        }
 
878
        if (! get_value(name, "dev", value, sizeof(value))) {
 
879
                fprintf(stderr, "Couldn't find sysfs match for "
 
880
                        "device: %s\n", device_name);
 
881
                return 1;
 
882
        }
 
883
        if (verbose)
 
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",
 
887
                        device_name);
 
888
                return 1;
 
889
        }
 
890
        if (if_directory_ch2generic(".")) {
 
891
                if (1 == result) {
 
892
                        if (NULL == getcwd(value, sizeof(value)))
 
893
                                value[0] = '\0';
 
894
                        printf("%s\n", value);
 
895
                        return 0;
 
896
                }
 
897
                if (! get_value(".", "dev", value, sizeof(value))) {
 
898
                        fprintf(stderr, "Couldn't find sysfs generic"
 
899
                                "dev\n");
 
900
                        return 1;
 
901
                }
 
902
                if (verbose)
 
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 "
 
906
                                "dev\n");
 
907
                        return 1;
 
908
                }
 
909
                num = list_matching_nodes(device_dir, FT_CHAR, m_ma, m_mi,
 
910
                                          follow_symlink, verbose);
 
911
                return (num > 0) ? 0 : 1;
 
912
        } else {
 
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 "
 
916
                        "loaded\n");
 
917
                return 1;
 
918
        }
 
919
}
 
920
 
 
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)
 
923
{
 
924
        int m_mi, m_ma, num;
 
925
        char value[D_NAME_LEN_MAX];
 
926
        char name[D_NAME_LEN_MAX];
 
927
 
 
928
        if (2 == result) {
 
929
                num = list_matching_nodes(device_dir, FT_CHAR, ma, mi,
 
930
                                          follow_symlink, verbose);
 
931
                return (num > 0) ? 0 : 1;
 
932
        }
 
933
        snprintf(name, sizeof(name), "%ssg%d", sys_sg_dir, mi);
 
934
        if (3 == result) {
 
935
                printf("%s\n", name);
 
936
                return 0;
 
937
        }
 
938
        if (! get_value(name, "dev", value, sizeof(value))) {
 
939
                fprintf(stderr, "Couldn't find sysfs match for "
 
940
                        "device: %s\n", device_name);
 
941
                return 1;
 
942
        }
 
943
        if (verbose)
 
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",
 
947
                        device_name);
 
948
                return 1;
 
949
        }
 
950
        if ((1 == from_sg_scan(".", verbose)) &&
 
951
            (if_directory_chdir(".", from_sg.name))) {
 
952
                if (1 == result) {
 
953
                        if (NULL == getcwd(value, sizeof(value)))
 
954
                                value[0] = '\0';
 
955
                        printf("%s\n", value);
 
956
                        return 0;
 
957
                }
 
958
                if (! get_value(".", "dev", value, sizeof(value))) {
 
959
                        fprintf(stderr, "Couldn't find sysfs block "
 
960
                                "dev\n");
 
961
                        return 1;
 
962
                }
 
963
                if (verbose)
 
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 "
 
967
                                "dev\n");
 
968
                        return 1;
 
969
                }
 
970
                num = list_matching_nodes(device_dir, from_sg.ft, m_ma, m_mi,
 
971
                                          follow_symlink, verbose);
 
972
                return (num > 0) ? 0 : 1;
 
973
        } else {
 
974
                fprintf(stderr, "sg device: %s does not match any "
 
975
                        "other SCSI device\n", device_name);
 
976
                return 1;
 
977
        }
 
978
}
 
979
 
 
980
 
 
981
int main(int argc, char * argv[])
 
982
{
 
983
        int c, num, tt, cont, res;
 
984
        int do_dev_dir = 0;
 
985
        int given_is = -1;
 
986
        int result = 0;
 
987
        int follow_symlink = 0;
 
988
        int verbose = 0;
 
989
        char device_name[D_NAME_LEN_MAX];
 
990
        char device_dir[D_NAME_LEN_MAX];
 
991
        char value[D_NAME_LEN_MAX];
 
992
        int ret = 1;
 
993
        int ma, mi;
 
994
 
 
995
        memset(device_name, 0, sizeof(device_name));
 
996
        memset(device_dir, 0, sizeof(device_dir));
 
997
        while (1) {
 
998
                int option_index = 0;
 
999
 
 
1000
                c = getopt_long(argc, argv, "d:hg:r:svV", long_options,
 
1001
                                &option_index);
 
1002
                if (c == -1)
 
1003
                        break;
 
1004
 
 
1005
                switch (c) {
 
1006
                case 'd':
 
1007
                        strncpy(device_dir, optarg, sizeof(device_dir));
 
1008
                        do_dev_dir = 1;
 
1009
                        break;
 
1010
                case 'g':
 
1011
                        num = sscanf(optarg, "%d", &res);
 
1012
                        if ((1 == num) && ((0 == res) || (1 == res)))
 
1013
                                given_is = res;
 
1014
                        else {
 
1015
                                fprintf(stderr, "value for '--given_to=' "
 
1016
                                        "must be 0 or 1\n");
 
1017
                                return SG_LIB_SYNTAX_ERROR;
 
1018
                        }
 
1019
                        break;
 
1020
                case 'h':
 
1021
                case '?':
 
1022
                        usage();
 
1023
                        return 0;
 
1024
                case 'r':
 
1025
                        num = sscanf(optarg, "%d", &res);
 
1026
                        if ((1 == num) && (res >= 0) && (res < 4))
 
1027
                                result = res;
 
1028
                        else {
 
1029
                                fprintf(stderr, "value for '--result=' "
 
1030
                                        "must be 0..3\n");
 
1031
                                return SG_LIB_SYNTAX_ERROR;
 
1032
                        }
 
1033
                        break;
 
1034
                case 's':
 
1035
                        follow_symlink = 1;
 
1036
                        break;
 
1037
                case 'v':
 
1038
                        ++verbose;
 
1039
                        break;
 
1040
                case 'V':
 
1041
                        fprintf(stderr, ME "version: %s\n", version_str);
 
1042
                        return 0;
 
1043
                default:
 
1044
                        fprintf(stderr, "unrecognised switch code 0x%x ??\n",
 
1045
                                c);
 
1046
                        usage();
 
1047
                        return SG_LIB_SYNTAX_ERROR;
 
1048
                }
 
1049
        }
 
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';
 
1055
                        ++optind;
 
1056
                }
 
1057
                if (optind < argc) {
 
1058
                        for (; optind < argc; ++optind)
 
1059
                                fprintf(stderr, "Unexpected extra argument: "
 
1060
                                        "%s\n", argv[optind]);
 
1061
                        usage();
 
1062
                        return SG_LIB_SYNTAX_ERROR;
 
1063
                }
 
1064
        }
 
1065
 
 
1066
        if (0 == device_name[0]) {
 
1067
                fprintf(stderr, "missing device name!\n");
 
1068
                usage();
 
1069
                return SG_LIB_SYNTAX_ERROR;
 
1070
        }
 
1071
 
 
1072
        ma = 0;
 
1073
        mi = 0;
 
1074
        if (do_dev_dir) {
 
1075
                if (if_directory_chdir(".", device_dir)) {
 
1076
                        if (getcwd(device_dir, sizeof(device_dir)))
 
1077
                                device_dir[sizeof(device_dir) - 1] = '\0';
 
1078
                        else
 
1079
                                device_dir[0] = '\0';
 
1080
                        if (verbose > 1)
 
1081
                                fprintf(stderr, "Absolute path to "
 
1082
                                        "dev_dir: %s\n", device_dir);
 
1083
                } else {
 
1084
                        fprintf(stderr, "dev_dir: %s invalid\n", device_dir);
 
1085
                        return SG_LIB_FILE_ERROR;
 
1086
                }
 
1087
        } else {
 
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';
 
1093
                }
 
1094
        }
 
1095
        ret = nt_typ_from_filename(device_name, &ma, &mi);
 
1096
        if (ret < 0) {
 
1097
                fprintf(stderr, "stat failed on %s: %s\n", device_name,
 
1098
                        ssafe_strerror(-ret));
 
1099
                return SG_LIB_FILE_ERROR;
 
1100
        }
 
1101
        if (verbose)
 
1102
                fprintf(stderr, " %s: %s device [maj=%d, min=%d]\n",
 
1103
                        device_name, nt_names[ret], ma, mi);
 
1104
        res = 0;
 
1105
        switch (ret) {
 
1106
        case NT_SD:
 
1107
        case NT_SR:
 
1108
        case NT_HD:
 
1109
                if (given_is > 0) {
 
1110
                        fprintf(stderr, "block special but '--given_is=' "
 
1111
                                "suggested sysfs device\n");
 
1112
                        return SG_LIB_FILE_ERROR;
 
1113
                }
 
1114
                break;
 
1115
        case NT_ST:
 
1116
        case NT_OSST:
 
1117
        case NT_CH:
 
1118
        case NT_SG:
 
1119
                if (given_is > 0) {
 
1120
                        fprintf(stderr, "character special but '--given_is=' "
 
1121
                                "suggested sysfs device\n");
 
1122
                        return SG_LIB_FILE_ERROR;
 
1123
                }
 
1124
                break;
 
1125
        case NT_REG:
 
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;
 
1130
                }
 
1131
                strcpy(device_dir, def_dev_dir);
 
1132
                break;
 
1133
        case NT_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;
 
1138
                }
 
1139
                strcpy(device_dir, def_dev_dir);
 
1140
                break;
 
1141
        default:
 
1142
                break;
 
1143
        }
 
1144
 
 
1145
        tt = NT_NO_MATCH;
 
1146
        do {
 
1147
                cont = 0;
 
1148
                switch (ret) {
 
1149
                case NT_NO_MATCH:
 
1150
                        res = 1;
 
1151
                        break;
 
1152
                case NT_SD:
 
1153
                        res = map_sd(device_name, device_dir, ma, mi, result,
 
1154
                                     follow_symlink, verbose);
 
1155
                        break;
 
1156
                case NT_SR:
 
1157
                        res = map_sr(device_name, device_dir, ma, mi, result,
 
1158
                                     follow_symlink, verbose);
 
1159
                        break;
 
1160
                case NT_HD:
 
1161
                        if (result < 2) {
 
1162
                                fprintf(stderr, "a hd device does not map "
 
1163
                                        "to a sg device\n");
 
1164
                                return SG_LIB_FILE_ERROR;
 
1165
                        }
 
1166
                        res = map_hd(device_dir, ma, mi, result,
 
1167
                                     follow_symlink, verbose);
 
1168
                        break;
 
1169
                case NT_ST:
 
1170
                        res = map_st(device_name, device_dir, ma, mi, result,
 
1171
                                     follow_symlink, verbose);
 
1172
                        break;
 
1173
                case NT_OSST:
 
1174
                        res = map_osst(device_name, device_dir, ma, mi,
 
1175
                                       result, follow_symlink, verbose);
 
1176
                        break;
 
1177
                case NT_CH:
 
1178
                        res = map_ch(device_name, device_dir, ma, mi, result,
 
1179
                                     follow_symlink, verbose);
 
1180
                        break;
 
1181
                case NT_SG:
 
1182
                        res = map_sg(device_name, device_dir, ma, mi, result,
 
1183
                                     follow_symlink, verbose);
 
1184
                        break;
 
1185
                case NT_REG:
 
1186
                        if (! get_value(NULL, device_name, value,
 
1187
                                        sizeof(value))) {
 
1188
                                fprintf(stderr, "Couldn't fetch value "
 
1189
                                        "from: %s\n", device_name);
 
1190
                                return SG_LIB_FILE_ERROR;
 
1191
                        }
 
1192
                        if (verbose)
 
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;
 
1197
                        }
 
1198
                        tt = nt_typ_from_major(ma);
 
1199
                        cont = 1;
 
1200
                        break;
 
1201
                case NT_DIR:
 
1202
                        if (! get_value(device_name, "dev", value,
 
1203
                                        sizeof(value))) {
 
1204
                                fprintf(stderr, "Couldn't fetch value from: "
 
1205
                                        "%s/dev\n", device_name);
 
1206
                                return SG_LIB_FILE_ERROR;
 
1207
                        }
 
1208
                        if (verbose)
 
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;
 
1213
                        }
 
1214
                        tt = nt_typ_from_major(ma);
 
1215
                        cont = 1;
 
1216
                        break;
 
1217
                default:
 
1218
                        break;
 
1219
                }
 
1220
                ret = tt;
 
1221
        } while (cont);
 
1222
        return res;
 
1223
}