STIOC_READ_POSITION_EX

This IOCTL returns tape position with support for the short, long, and extended formats. The definitions and data structures that are used for this IOCTL follow. See the READ_POSITION section of your tape drive’s SCSI documentation for details on the short_data_format, long_data_format, and extended_data_format structures.

#define RP_SHORT_FORM (0x00)
#define RP_LONG_FORM (0x06)
#define RP_EXTENDED_FORM (0x08)

struct short_data_format {
#if defined __LITTLE_ENDIAN
        unchar bpew : 1;
        unchar perr : 1;
        unchar lolu : 1;
        unchar rsvd : 1;
        unchar bycu : 1;
        unchar locu : 1;
        unchar eop : 1;
        unchar bop : 1;
#elif defined __BIG_ENDIAN
        unchar bop : 1;
        unchar eop : 1;
        unchar locu : 1;
        unchar bycu : 1;unchar rsvd : 1;
        unchar lolu : 1;
        unchar perr : 1;
        unchar bpew : 1;
#else
                error
#endif
        unchar active_partition;
        char reserved[2];
        unchar first_logical_obj_position[4];
        unchar last_logical_obj_position[4];
        unchar num_buffer_logical_obj[4];
        unchar num_buffer_bytes[4];
        char reserved1;
};

struct long_data_format {
#if defined __LITTLE_ENDIAN
        unchar bpew : 1;
        unchar rsvd2 : 1;
        unchar lonu : 1;
        unchar mpu : 1;
        unchar rsvd1 : 2;
        unchar eop : 1;
        unchar bop : 1;
#elif defined __BIG_ENDIAN
        unchar bop : 1;
        unchar eop : 1;
        unchar rsvd1 : 2;
        unchar mpu : 1;
        unchar lonu : 1;
        unchar rsvd2 : 1;
        unchar bpew : 1;
#else
                error
#endif
        char reserved[6];
        unchar active_partition;
        unchar logical_obj_number[8];
        unchar logical_file_id[8];
        unchar obsolete[8];
};

struct extended_data_format {
#if defined __LITTLE_ENDIAN
        unchar bpew : 1;
        unchar perr : 1;
        unchar lolu : 1;
        unchar rsvd : 1;
        unchar bycu : 1;
        unchar locu : 1;
        unchar eop : 1;
        unchar bop : 1;
#elif defined __BIG_ENDIAN
        unchar bop : 1;
        unchar eop : 1;
        unchar locu : 1;
        unchar bycu : 1;
        unchar rsvd : 1;
        unchar lolu : 1;
        unchar perr : 1;
        unchar bpew : 1;
#else
                error
#endif
        unchar active_partition;
        unchar additional_length[2];
        unchar num_buffer_logical_obj[4];
        unchar first_logical_obj_position[8];
        unchar last_logical_obj_position[8];
        unchar num_buffer_bytes[8];
        unchar reserved;
};

struct read_tape_position {
        unchar data_format;
        union {
                struct short_data_format rp_short;
                struct long_data_format rp_long;
                struct extended_data_format rp_extended;
        } rp_data;
};
data_format is the format in which you want to receive your data, as defined here. It can take the value RP_SHORT_FORM, RP_LONG_FORM, or RP_EXTENDED_FORM. When the IOCTL finishes, data is returned to the corresponding structure within the rp_data union.
An example of the use of the STIOC_READ_POSITION_EX IOCTL is
int stioc_read_position_ex(void)
{
        int rc = 0;
        char* input = NULL;
        struct read_tape_position rp = {0};

        printf("Note: only supported on LTO 5 and higher drives\n");
        input = malloc(DEF_BUF_SIZE / 16);
        if(!input) {
                rc = ENOMEM;
                goto EXIT_LABEL;
        } /* if */
        memset(input, '\0', DEF_BUF_SIZE / 16);

        while(input[0] == '\0' || atoi(input) &lt 0 || atoi(input) > 3) {
                printf("0) Cancel\n");
                printf("1) Short Form\n");
                printf("2) Long Form\n");
                printf("3) Extended Form\n");

                printf("\nPlease select: ");

                fgets(input, DEF_BUF_SIZE / 16, stdin);
                if(!atoi(input)) {
                        rc = 0;
                        goto EXIT_LABEL;
                } /* if */
        } /* while */

        memset(&rp, '\0', sizeof(struct read_tape_position));

        switch(atoi(input)) {
        case 1:
                 rp.data_format = RP_SHORT_FORM;
                 break;
        case 2:
                 rp.data_format = RP_LONG_FORM;
                 break;
        case 3:
                 rp.data_format = RP_EXTENDED_FORM;
                 break;
        default:
                 rc = EINVAL;
                 goto EXIT_LABEL;
        } /* switch */

        rc = ioctl(fd, STIOC_READ_POSITION_EX, &rp);

        if(rc) {
                 printf("Cannot get position: %d\n", rc = errno);
                 goto EXIT_LABEL;
        } /* if */

        print_read_position_ex(&rp);

  EXIT_LABEL:
        if(input) free(input);
        return rc;
 } /* stioc_read_position_ex() */