~ubuntu-branches/ubuntu/vivid/sg3-utils/vivid-proposed

« back to all changes in this revision

Viewing changes to src/sg_write_same.c

  • Committer: Package Import Robot
  • Author(s): Ritesh Raj Sarraf
  • Date: 2013-06-23 16:08:01 UTC
  • mfrom: (1.2.7)
  • Revision ID: package-import@ubuntu.com-20130623160801-7rt7zb2dwk0ba7ut
Tags: 1.36-1
* [69e9dac] Imported Upstream version 1.36
* [cb75936] Add debian compat, level 7
* [68fed25] update README.source
* [3c724fc] Add build-dep autotools-dev
* [e4b9fdd] add destdir to install path
* [7cfff11] Simplify build with debhelper
* [f9a7540] Update symbols for 1.36 release
* [7b0b48d] Enable hardening build

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 2009-2011 Douglas Gilbert.
 
2
 * Copyright (c) 2009-2013 Douglas Gilbert.
3
3
 * All rights reserved.
4
4
 * Use of this source code is governed by a BSD-style
5
5
 * license that can be found in the BSD_LICENSE file.
26
26
#include "sg_cmds_basic.h"
27
27
#include "sg_cmds_extra.h"
28
28
 
29
 
static char * version_str = "0.99 20111117";
 
29
static const char * version_str = "1.02 20130516";
30
30
 
31
31
 
32
32
#define ME "sg_write_same: "
41
41
#define WRITE_SAME32_LEN 32
42
42
#define RCAP10_RESP_LEN 8
43
43
#define RCAP16_RESP_LEN 32
44
 
#define SENSE_BUFF_LEN 32       /* Arbitrary, could be larger */
 
44
#define SENSE_BUFF_LEN 64       /* Arbitrary, could be larger */
45
45
#define DEF_TIMEOUT_SECS 60
46
46
#define DEF_WS_CDB_SIZE WRITE_SAME10_LEN
47
47
#define DEF_WS_NUMBLOCKS 1
58
58
    {"in", required_argument, 0, 'i'},
59
59
    {"lba", required_argument, 0, 'l'},
60
60
    {"lbdata", no_argument, 0, 'L'},
 
61
    {"ndob", no_argument, 0, 'N'},
61
62
    {"num", required_argument, 0, 'n'},
62
63
    {"pbdata", no_argument, 0, 'P'},
63
64
    {"timeout", required_argument, 0, 'r'},
75
76
    char ifilename[256];
76
77
    uint64_t lba;
77
78
    int lbdata;
 
79
    int ndob;
78
80
    int numblocks;
79
81
    int pbdata;
80
82
    int timeout;
91
93
static void
92
94
usage()
93
95
{
94
 
  fprintf(stderr, "Usage: "
95
 
          "sg_write_same [--10] [--16] [--32] [--anchor] [--grpnum=GN] "
96
 
          "[--help]\n"
97
 
          "                     [--in=IF] [--lba=LBA] [--lbdata] "
98
 
          "[--num=NUM] [--pbdata]\n"
99
 
          "                     [--timeout=TO] [--unmap] [--verbose] "
100
 
          "[--version]\n"
101
 
          "                     [--wrprotect=WRP] [xferlen=LEN] DEVICE\n"
102
 
          "  where:\n"
103
 
          "    --10|-R              do WRITE SAME(10) (even if '--unmap' "
104
 
          "is given)\n"
105
 
          "    --16|-S              do WRITE SAME(16) (def: 10 unless "
106
 
          "'--unmap' given\n"
107
 
          "                         or LBA+NUM needs more than 32 bits)\n"
108
 
          "    --32|-T              do WRITE SAME(32) (def: 10 or 16)\n"
109
 
          "    --anchor|-a          set anchor field in cdb\n"
110
 
          "    --grpnum=GN|-g GN    GN is group number field (def: 0)\n"
111
 
          "    --help|-h            print out usage message\n"
112
 
          "    --in=IF|-i IF        IF is file to fetch one block of data "
113
 
          "from (use LEN\n"
114
 
          "                         bytes or whole file). Block written to "
115
 
          "DEVICE\n"
116
 
          "    --lba=LBA|-l LBA     LBA is the logical block address to "
117
 
          "start (def: 0)\n"
118
 
          "    --lbdata|-L          set LBDATA bit\n"
119
 
          "    --num=NUM|-n NUM     NUM is number of logical blocks to write "
120
 
          "(def: 1)\n"
121
 
          "                         [Beware NUM==0 means rest of device]\n"
122
 
          "    --pbdata|-P          set PBDATA bit\n"
123
 
          "    --timeout=TO|-t TO    command timeout (unit: seconds) (def: "
124
 
          "60)\n"
125
 
          "    --unmap|-U           set UNMAP bit\n"
126
 
          "    --verbose|-v         increase verbosity\n"
127
 
          "    --version|-V         print version string then exit\n"
128
 
          "    --wrprotect=WPR|-w WPR    WPR is the WRPROTECT field value "
129
 
          "(def: 0)\n"
130
 
          "    --xferlen=LEN|-x LEN    LEN is number of bytes from IF to "
131
 
          "send to\n"
132
 
          "                            DEVICE (def: IF file length)\n\n"
133
 
          "Performs a SCSI WRITE SAME (10, 16 or 32) command\n"
134
 
          );
 
96
    fprintf(stderr, "Usage: "
 
97
            "sg_write_same [--10] [--16] [--32] [--anchor] [--grpnum=GN] "
 
98
            "[--help]\n"
 
99
            "                     [--in=IF] [--lba=LBA] [--lbdata] "
 
100
            "[--ndob] [--num=NUM]\n"
 
101
            "                     [--pbdata] [--timeout=TO] [--unmap] "
 
102
            "[--verbose]\n"
 
103
            "                     [--version] [--wrprotect=WRP] "
 
104
            "[xferlen=LEN]\n"
 
105
            "                     DEVICE\n"
 
106
            "  where:\n"
 
107
            "    --10|-R              do WRITE SAME(10) (even if '--unmap' "
 
108
            "is given)\n"
 
109
            "    --16|-S              do WRITE SAME(16) (def: 10 unless "
 
110
            "'--unmap' given\n"
 
111
            "                         or LBA+NUM needs more than 32 bits)\n"
 
112
            "    --32|-T              do WRITE SAME(32) (def: 10 or 16)\n"
 
113
            "    --anchor|-a          set anchor field in cdb\n"
 
114
            "    --grpnum=GN|-g GN    GN is group number field (def: 0)\n"
 
115
            "    --help|-h            print out usage message\n"
 
116
            "    --in=IF|-i IF        IF is file to fetch one block of data "
 
117
            "from (use LEN\n"
 
118
            "                         bytes or whole file). Block written to "
 
119
            "DEVICE\n"
 
120
            "    --lba=LBA|-l LBA     LBA is the logical block address to "
 
121
            "start (def: 0)\n"
 
122
            "    --lbdata|-L          set LBDATA bit\n"
 
123
            "    --ndob|-N            set 'no data-out buffer' bit\n"
 
124
            "    --num=NUM|-n NUM     NUM is number of logical blocks to "
 
125
            "write (def: 1)\n"
 
126
            "                         [Beware NUM==0 means rest of device]\n"
 
127
            "    --pbdata|-P          set PBDATA bit\n"
 
128
            "    --timeout=TO|-t TO    command timeout (unit: seconds) (def: "
 
129
            "60)\n"
 
130
            "    --unmap|-U           set UNMAP bit\n"
 
131
            "    --verbose|-v         increase verbosity\n"
 
132
            "    --version|-V         print version string then exit\n"
 
133
            "    --wrprotect=WPR|-w WPR    WPR is the WRPROTECT field value "
 
134
            "(def: 0)\n"
 
135
            "    --xferlen=LEN|-x LEN    LEN is number of bytes from IF to "
 
136
            "send to\n"
 
137
            "                            DEVICE (def: IF file length)\n\n"
 
138
            "Performs a SCSI WRITE SAME (10, 16 or 32) command\n"
 
139
            );
135
140
}
136
141
 
137
142
static int
149
154
    if (WRITE_SAME10_LEN == cdb_len) {
150
155
        llba = optsp->lba + optsp->numblocks;
151
156
        if ((optsp->numblocks > 0xffff) || (llba > ULONG_MAX) ||
152
 
            (optsp->unmap && (0 == optsp->want_ws10))) {
 
157
            optsp->ndob || (optsp->unmap && (0 == optsp->want_ws10))) {
153
158
            cdb_len = WRITE_SAME16_LEN;
154
159
            if (optsp->verbose)
155
160
                fprintf(stderr, "do_write_same: use WRITE SAME(16) instead "
193
198
            wsCmdBlk[1] |= 0x4;
194
199
        if (optsp->lbdata)
195
200
            wsCmdBlk[1] |= 0x2;
 
201
        if (optsp->ndob)
 
202
            wsCmdBlk[1] |= 0x1;
196
203
        llba = optsp->lba;
197
204
        for (k = 7; k >= 0; --k) {
198
205
            wsCmdBlk[2 + k] = (llba & 0xff);
206
213
        wsCmdBlk[14] = (optsp->grpnum & 0x1f);
207
214
        break;
208
215
    case WRITE_SAME32_LEN:
 
216
        /* Note: In Linux at this time the sg driver does not support
 
217
         * cdb_s > 16 bytes long, but the bsg driver does. */
209
218
        wsCmdBlk[0] = VARIABLE_LEN_OP;
210
219
        wsCmdBlk[6] = (optsp->grpnum & 0x1f);
211
220
        wsCmdBlk[7] = WRITE_SAME32_ADD;
220
229
            wsCmdBlk[10] |= 0x4;
221
230
        if (optsp->lbdata)
222
231
            wsCmdBlk[10] |= 0x2;
 
232
        if (optsp->ndob)
 
233
            wsCmdBlk[10] |= 0x1;
223
234
        llba = optsp->lba;
224
235
        for (k = 7; k >= 0; --k) {
225
236
            wsCmdBlk[12 + k] = (llba & 0xff);
324
335
    while (1) {
325
336
        int option_index = 0;
326
337
 
327
 
        c = getopt_long(argc, argv, "ag:hi:l:Ln:PRSt:TUvVw:x:", long_options,
328
 
                        &option_index);
 
338
        c = getopt_long(argc, argv, "ag:hi:l:Ln:NPRSt:TUvVw:x:",
 
339
                        long_options, &option_index);
329
340
        if (c == -1)
330
341
            break;
331
342
 
368
379
            }
369
380
            num_given = 1;
370
381
            break;
 
382
        case 'N':
 
383
            ++opts.ndob;
 
384
            break;
371
385
        case 'P':
372
386
            ++opts.pbdata;
373
387
            break;
456
470
        return SG_LIB_SYNTAX_ERROR;
457
471
    }
458
472
 
459
 
    memset(&a_stat, 0, sizeof(a_stat));
460
 
    if (opts.ifilename[0]) {
 
473
    if (opts.ndob) {
 
474
        if (if_given) {
 
475
            fprintf(stderr, "Can't have both --ndob and '--in='\n");
 
476
            return SG_LIB_SYNTAX_ERROR;
 
477
        }
 
478
        if (0 != opts.xfer_len) {
 
479
            fprintf(stderr, "With --ndob only '--xferlen=0' (or not given) "
 
480
                    "is acceptable\n");
 
481
            return SG_LIB_SYNTAX_ERROR;
 
482
        }
 
483
    } else if (opts.ifilename[0]) {
461
484
        got_stdin = (0 == strcmp(opts.ifilename, "-")) ? 1 : 0;
462
485
        if (! got_stdin) {
 
486
            memset(&a_stat, 0, sizeof(a_stat));
463
487
            if (stat(opts.ifilename, &a_stat) < 0) {
464
488
                if (vb)
465
489
                    fprintf(stderr, "unable to stat(%s): %s\n",
470
494
                opts.xfer_len = (int)a_stat.st_size;
471
495
        }
472
496
    }
473
 
    
 
497
 
474
498
    sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, vb);
475
499
    if (sg_fd < 0) {
476
500
        fprintf(stderr, ME "open error: %s: %s\n", device_name,
478
502
        return SG_LIB_FILE_ERROR;
479
503
    }
480
504
 
481
 
    prot_en = 0;
482
 
    if (0 == opts.xfer_len) {
483
 
        res = sg_ll_readcap_16(sg_fd, 0 /* pmi */, 0 /* llba */, resp_buff,
484
 
                               RCAP16_RESP_LEN, 0, (vb ? (vb - 1): 0));
485
 
        if (0 == res) {
486
 
            if (vb > 3)
487
 
                dStrHex((const char *)resp_buff, RCAP16_RESP_LEN, 1);
488
 
            block_size = ((resp_buff[8] << 24) |
489
 
                          (resp_buff[9] << 16) |
490
 
                          (resp_buff[10] << 8) |
491
 
                          resp_buff[11]);
492
 
            prot_en = !!(resp_buff[12] & 0x1);
493
 
            opts.xfer_len = block_size;
494
 
            if (prot_en && (opts.wrprotect > 0))
495
 
                opts.xfer_len += 8;
496
 
        } else if ((SG_LIB_CAT_INVALID_OP == res) ||
497
 
                   (SG_LIB_CAT_ILLEGAL_REQ == res)) {
498
 
            if (vb)
499
 
                fprintf(stderr, "Read capacity(16) not supported, try Read "
500
 
                        "capacity(10)\n");
501
 
            res = sg_ll_readcap_10(sg_fd, 0 /* pmi */, 0 /* lba */, resp_buff,
502
 
                                   RCAP10_RESP_LEN, 0, (vb ? (vb - 1): 0));
 
505
    if (! opts.ndob) {
 
506
        prot_en = 0;
 
507
        if (0 == opts.xfer_len) {
 
508
            res = sg_ll_readcap_16(sg_fd, 0 /* pmi */, 0 /* llba */, resp_buff,
 
509
                                   RCAP16_RESP_LEN, 0, (vb ? (vb - 1): 0));
503
510
            if (0 == res) {
504
511
                if (vb > 3)
505
 
                    dStrHex((const char *)resp_buff, RCAP10_RESP_LEN, 1);
506
 
                block_size = ((resp_buff[4] << 24) |
507
 
                              (resp_buff[5] << 16) |
508
 
                              (resp_buff[6] << 8) |
509
 
                              resp_buff[7]);
 
512
                    dStrHex((const char *)resp_buff, RCAP16_RESP_LEN, 1);
 
513
                block_size = ((resp_buff[8] << 24) |
 
514
                              (resp_buff[9] << 16) |
 
515
                              (resp_buff[10] << 8) |
 
516
                              resp_buff[11]);
 
517
                prot_en = !!(resp_buff[12] & 0x1);
510
518
                opts.xfer_len = block_size;
 
519
                if (prot_en && (opts.wrprotect > 0))
 
520
                    opts.xfer_len += 8;
 
521
            } else if ((SG_LIB_CAT_INVALID_OP == res) ||
 
522
                       (SG_LIB_CAT_ILLEGAL_REQ == res)) {
 
523
                if (vb)
 
524
                    fprintf(stderr, "Read capacity(16) not supported, try "
 
525
                            "Read capacity(10)\n");
 
526
                res = sg_ll_readcap_10(sg_fd, 0 /* pmi */, 0 /* lba */,
 
527
                                       resp_buff, RCAP10_RESP_LEN, 0,
 
528
                                       (vb ? (vb - 1): 0));
 
529
                if (0 == res) {
 
530
                    if (vb > 3)
 
531
                        dStrHex((const char *)resp_buff, RCAP10_RESP_LEN, 1);
 
532
                    block_size = ((resp_buff[4] << 24) |
 
533
                                  (resp_buff[5] << 16) |
 
534
                                  (resp_buff[6] << 8) |
 
535
                                  resp_buff[7]);
 
536
                    opts.xfer_len = block_size;
 
537
                }
 
538
            } else if (vb)
 
539
                fprintf(stderr, "Read capacity(16) failed. Unable to "
 
540
                        "calculate block size\n");
 
541
            if (res)
 
542
                fprintf(stderr, "Read capacity(10) failed. Unable to "
 
543
                        "calculate block size\n");
 
544
        }
 
545
        if (opts.xfer_len < 1) {
 
546
            fprintf(stderr, "unable to deduce block size, please give "
 
547
                    "'--xferlen=' argument\n");
 
548
            ret = SG_LIB_SYNTAX_ERROR;
 
549
            goto err_out;
 
550
        }
 
551
        if (opts.xfer_len > MAX_XFER_LEN) {
 
552
            fprintf(stderr, "'--xferlen=%d is out of range ( want <= %d)\n",
 
553
                    opts.xfer_len, MAX_XFER_LEN);
 
554
            ret = SG_LIB_SYNTAX_ERROR;
 
555
            goto err_out;
 
556
        }
 
557
        wBuff = (unsigned char*)calloc(opts.xfer_len, 1);
 
558
        if (NULL == wBuff) {
 
559
            fprintf(stderr, "unable to allocate %d bytes of memory with "
 
560
                    "calloc()\n", opts.xfer_len);
 
561
            ret = SG_LIB_SYNTAX_ERROR;
 
562
            goto err_out;
 
563
        }
 
564
        if (opts.ifilename[0]) {
 
565
            if (got_stdin) {
 
566
                infd = STDIN_FILENO;
 
567
                if (sg_set_binary_mode(STDIN_FILENO) < 0)
 
568
                    perror("sg_set_binary_mode");
 
569
            } else {
 
570
                if ((infd = open(opts.ifilename, O_RDONLY)) < 0) {
 
571
                    snprintf(ebuff, EBUFF_SZ, ME "could not open %s for "
 
572
                             "reading", opts.ifilename);
 
573
                    perror(ebuff);
 
574
                    ret = SG_LIB_FILE_ERROR;
 
575
                    goto err_out;
 
576
                } else if (sg_set_binary_mode(infd) < 0)
 
577
                    perror("sg_set_binary_mode");
511
578
            }
512
 
        } else if (vb)
513
 
            fprintf(stderr, "Read capacity(16) failed. Unable to calculate "
514
 
                    "block size\n");
515
 
        if (res)
516
 
            fprintf(stderr, "Read capacity(10) failed. Unable to calculate "
517
 
                    "block size\n");
518
 
    }
519
 
    if (opts.xfer_len < 1) {
520
 
        fprintf(stderr, "unable to deduce block size, please give "
521
 
                "'--xferlen=' argument\n");
522
 
        ret = SG_LIB_SYNTAX_ERROR;
523
 
        goto err_out;
524
 
    }
525
 
    if (opts.xfer_len > MAX_XFER_LEN) {
526
 
        fprintf(stderr, "'--xferlen=%d is out of range ( want <= %d)\n",
527
 
                opts.xfer_len, MAX_XFER_LEN);
528
 
        ret = SG_LIB_SYNTAX_ERROR;
529
 
        goto err_out;
530
 
    }
531
 
    wBuff = (unsigned char*)calloc(opts.xfer_len, 1);
532
 
    if (NULL == wBuff) {
533
 
        fprintf(stderr, "unable to allocate %d bytes of memory with "
534
 
                "calloc()\n", opts.xfer_len);
535
 
        ret = SG_LIB_SYNTAX_ERROR;
536
 
        goto err_out;
537
 
    }
538
 
    if (opts.ifilename[0]) {
539
 
        if (got_stdin) {
540
 
            infd = STDIN_FILENO;
541
 
            if (sg_set_binary_mode(STDIN_FILENO) < 0)
542
 
                perror("sg_set_binary_mode");
543
 
        } else {
544
 
            if ((infd = open(opts.ifilename, O_RDONLY)) < 0) {
545
 
                snprintf(ebuff, EBUFF_SZ,
546
 
                         ME "could not open %s for reading", opts.ifilename);
 
579
            res = read(infd, wBuff, opts.xfer_len);
 
580
            if (res < 0) {
 
581
                snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %s",
 
582
                         opts.ifilename);
547
583
                perror(ebuff);
 
584
                if (! got_stdin)
 
585
                    close(infd);
548
586
                ret = SG_LIB_FILE_ERROR;
549
587
                goto err_out;
550
 
            } else if (sg_set_binary_mode(infd) < 0)
551
 
                perror("sg_set_binary_mode");
552
 
        }
553
 
        res = read(infd, wBuff, opts.xfer_len);
554
 
        if (res < 0) {
555
 
            snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %s",
556
 
                     opts.ifilename);
557
 
            perror(ebuff);
 
588
            }
 
589
            if (res < opts.xfer_len) {
 
590
                fprintf(stderr, "tried to read %d bytes from %s, got %d "
 
591
                        "bytes\n", opts.xfer_len, opts.ifilename, res);
 
592
                fprintf(stderr, "  so pad with 0x0 bytes and continue\n");
 
593
            }
558
594
            if (! got_stdin)
559
595
                close(infd);
560
 
            ret = SG_LIB_FILE_ERROR;
561
 
            goto err_out;
562
 
        }
563
 
        if (res < opts.xfer_len) {
564
 
            fprintf(stderr, "tried to read %d bytes from %s, got %d "
565
 
                    "bytes\n", opts.xfer_len, opts.ifilename, res);
566
 
            fprintf(stderr, "  so pad with 0x0 bytes and continue\n");
567
 
        }
568
 
        if (! got_stdin)
569
 
            close(infd);
570
 
    } else {
571
 
        if (vb)
572
 
            fprintf(stderr, "Default data-out buffer set to %d zeros\n",
573
 
                    opts.xfer_len);
574
 
        if (prot_en && (opts.wrprotect > 0)) {
575
 
           /* default for protection is 0xff, rest get 0x0 */
576
 
            memset(wBuff + opts.xfer_len - 8, 0xff, 8);
 
596
        } else {
577
597
            if (vb)
578
 
                fprintf(stderr, " ... apart from last 8 bytes which are set "
579
 
                        "to 0xff\n");
 
598
                fprintf(stderr, "Default data-out buffer set to %d zeros\n",
 
599
                        opts.xfer_len);
 
600
            if (prot_en && (opts.wrprotect > 0)) {
 
601
               /* default for protection is 0xff, rest get 0x0 */
 
602
                memset(wBuff + opts.xfer_len - 8, 0xff, 8);
 
603
                if (vb)
 
604
                    fprintf(stderr, " ... apart from last 8 bytes which are "
 
605
                            "set to 0xff\n");
 
606
            }
580
607
        }
581
608
    }
582
609