Exemple #1
0
DLL_EXPORT
int w32_close_tape ( ufd_t  ufd )
{
    ifd_t  ifd  = W32STAPE_UFD2IFD( ufd );
    int    rc   = -1;
    errno       = EBADF;

    lock();

    if (1
            &&         ifd    >=  0
            &&         ifd    <   W32STAPE_MAX_FDNUMS
            && g_ifds[ ifd ]  !=  0
       )
    {
        // Deallocate resources

        HANDLE  hFile  = g_handles[ ifd ];
        char*   pName  = g_fnames [ ifd ];

        g_handles[ ifd ] = NULL;
        g_fnames [ ifd ] = NULL;
        g_fstats [ ifd ] = GMT_DR_OPEN (0xFFFFFFFF);
        g_BOTmsk [ ifd ] = 0xFFFFFFFF;
        g_BOTbot [ ifd ] = 0x00000000;

        VERIFY( w32_free_ifd( ifd ) == 0 );

        // Close the file...

        free( pName );

        errno  =  CloseHandle( hFile ) ? 0 : w32_trans_w32error( GetLastError() );
        rc     =  errno ? -1 : 0;
    }

    unlock();

    return rc;
}
Exemple #2
0
static
int w32_internal_rc ( U32* pStat )
{
    ASSERT( pStat );    // (sanity check)

    // PROGRAMMING NOTE: the 'door open' (no tape in drive) and the
    // 'write protected' statuses are "sticky" in that they never change
    // until a new/different tape is mounted. All the other statuses
    // however, change dynamically as one does i/o to the tape...

    if (0
            || ERROR_BUS_RESET            == errno // (See KB 111837: "ERROR_BUS_RESET May Be Benign")
            || ERROR_MEDIA_CHANGED        == errno
            || ERROR_DEVICE_NOT_CONNECTED == errno // (shouldn't occur but we'll check anyway)
            || ERROR_DEV_NOT_EXIST        == errno // (shouldn't occur but we'll check anyway)
            || ERROR_FILE_NOT_FOUND       == errno // (shouldn't occur but we'll check anyway)
       )
    {
        *pStat  &=  ~GMT_DR_OPEN (0xFFFFFFFF);
        *pStat  &=  ~GMT_WR_PROT (0xFFFFFFFF);
    }

    // (see PROGRAMMING NOTE above)

    *pStat  &=  ~GMT_BOT (0xFFFFFFFF);
    *pStat  &=  ~GMT_SM  (0xFFFFFFFF);
    *pStat  &=  ~GMT_EOF (0xFFFFFFFF);
    *pStat  &=  ~GMT_EOT (0xFFFFFFFF);
    *pStat  &=  ~GMT_EOD (0xFFFFFFFF);

    if (0
            || ERROR_BUS_RESET            == errno // (spurious error; retry)
            || ERROR_MEDIA_CHANGED        == errno // (spurious error; retry)
//      || ERROR_DEVICE_NOT_CONNECTED == errno // (PERM ERROR! NO RETRY!)
//      || ERROR_DEV_NOT_EXIST        == errno // (PERM ERROR! NO RETRY!)
//      || ERROR_FILE_NOT_FOUND       == errno // (PERM ERROR! NO RETRY!)
       )
    {
        return EINTR;   // (Interrupted system call; Retry)
    }

    // (see PROGRAMMING NOTE further above)

    switch (errno)
    {
    default:
        break;  // (leave errno set to whatever it already is)
    case NO_ERROR:
        errno = 0;
        break;  // (normal expected i/o result)

    case ERROR_BEGINNING_OF_MEDIA:
        *pStat |= GMT_BOT     (0xFFFFFFFF);
        errno = EIO;
        break;
    case ERROR_END_OF_MEDIA:
        *pStat |= GMT_EOT     (0xFFFFFFFF);
        errno = ENOSPC;
        break;

    //  "ERROR_END_OF_MEDIA"
    //
    //      Msg:   "The physical end of the tape has been reached."
    //
    //      The EOT warning reflector has been reached or passed (i.e. you're
    //      now/still in the "EOT Warning Zone" area). Writing additional data
    //      and/or tapemarks may still be possible depending on the size of the
    //      EOT Warning Zone (as set by a SetTapeParameters call with a non-zero
    //      EOTWarningZoneSize value (if supported; see further below)) and
    //      how much data you've already written to the EOT Warning Zone area
    //      (i.e. once you're in the warning area, this "error" occurs after
    //      EACH and EVERY I/O [in the warning zone area] until the ABSOLUTE
    //      physical end-of-tape (ERROR_EOM_OVERFLOW) is reached; see below).
    //
    //
    //                       ***********************
    //                       **  IMPORTANT NOTE!  **
    //                       ***********************
    //
    //                    This is NOT actually an "error"!!!
    //
    //
    //      When this "error" occurs, your "ReadFile" and/or "WriteFile" call
    //      returns 'FALSE' even though ALL of your requested data was actually
    //      written successfully!! This can be verified by checking to ensure
    //      the returned "number of bytes written" actually matches the amount
    //      you asked to be written. If they're the same (and they ALWAYS will
    //      be for this specific "error" code), then it means this "error" is
    //      NOT actually an error at all, but rather just a WARNING instead!!
    //      (Had it been an actual i/o error, the error code would have been
    //      some other DIFFERENT error code value instead!!)
    //
    //
    //                       ***********************
    //                       **  ALSO IMPORTANT!  **
    //                       ***********************
    //      See also:
    //
    //    http://fixunix.com/storage/205622-bug-dlttape-sys-no-eot-warning.html
    //
    //      for ADDITIONAL IMPORTANT INFORMATION regarding always having to
    //      specifically request that this "error" code be returned to you:
    //
    //      Even when a drive reports it does not support the setting of the
    //      the 'EOTWarningZoneSize' value (i.e. the FeaturesLow field of the
    //      GetTapeParameters call returns '0' for TAPE_DRIVE_SET_EOT_WZ_SIZE
    //      field), it may still be possible for "ERROR_END_OF_MEDIA" warnings
    //      to be generated anyway by simply calling SetTapeParameters with a
    //      non-zero 'EOTWarningZoneSize' value anyway.
    //
    //      The reason for this is because some drives may not allow CHANGING
    //      the value (thus the reason for it reporting that setting the value
    //      is not supported), but may nevertheless still support the ENABLING
    //      of their own hard-coded internal value. That is to say, while the
    //      size of the warning zone may not be modifiable (as it may be hard-
    //      coded and thus unchangeable), the drive may still have the ability
    //      to REPORT reaching the EOT Warning zone IF SPECIFICALLY REQUESTED
    //      TO DO SO! (which is presumably what requesting a non-zero Warning
    //      Zone size would end up doing: i.e. even though such calls APPEAR
    //      to fail, they actually DO succeed in accomplishing SOMETHING, just
    //      not what you originally/specifically requested).
    //
    //      Thus calling SetTapeParameters with a non-zero 'EOTWarningZoneSize'
    //      value might very well succeed anyway even though GetTapeParameters
    //      reports that doing so is not supported, and by so doing, may cause
    //      the drive to begin reporting of "ERROR_END_OF_MEDIA" (whereas not
    //      attempting to do so would end up leaving the drive in its default
    //      non-reporting mode. That is to say, you should ALWAYS try setting
    //      a non-zero 'EOTWarningZoneSize' value, ignoring any "unsupported"
    //      error code that may be returned from such a call.)

    case ERROR_EOM_OVERFLOW:
        *pStat |= GMT_EOT     (0xFFFFFFFF);
        errno = EIO;
        break;

    //  "ERROR_EOM_OVERFLOW"
    //
    //      Msg:   "Physical end of tape encountered."
    //
    //      This error code means that the actual physical end-of-media has been
    //      reached, and no more data can be written to the tape. This includes
    //      tapemarks as well.
    //
    //                       ***********************
    //                       **  IMPORTANT NOTE!  **
    //                       ***********************
    //
    //                 This is a HARD (UNRECOVERABLE) error!!
    //
    //      To be programmatically informed of when you are coming close to the
    //      physical end-of-the-tape (such that you could be assured room still
    //      remained to write logical end-of-volume labels for example), simply
    //      call SetTapeParameters with a non-zero 'EOTWarningZoneSize' value
    //      and treat any "ERROR_END_OF_MEDIA" "errors" received when writing
    //      as warnings instead. (See prior discussion of "ERROR_END_OF_MEDIA"
    //      return code further above)

    case ERROR_NO_DATA_DETECTED:
        *pStat |= GMT_EOD     (0xFFFFFFFF);
        errno = EIO;
        break;
    case ERROR_FILEMARK_DETECTED:
        *pStat |= GMT_EOF     (0xFFFFFFFF);
        errno = EIO;
        break;
    case ERROR_SETMARK_DETECTED:
        *pStat |= GMT_SM      (0xFFFFFFFF);
        errno = EIO;
        break;
    case ERROR_NOT_READY:
        *pStat |= GMT_DR_OPEN (0xFFFFFFFF);
        errno = ENOMEDIUM;
        break;
    case ERROR_NO_MEDIA_IN_DRIVE:
        *pStat |= GMT_DR_OPEN (0xFFFFFFFF);
        errno = ENOMEDIUM;
        break;
    case ERROR_WRITE_PROTECT:
        *pStat |= GMT_WR_PROT (0xFFFFFFFF);
        errno = EROFS;
        break;
    }
    return errno;
}
Exemple #3
0
static
int w32_internal_mtget ( HANDLE hFile, U32* pStat, struct mtget* mtget, ifd_t ifd )
{
    TAPE_GET_MEDIA_PARAMETERS   media_parms;
    DWORD                       dwRetCode, dwSize, dwLogicalPosition;

    ASSERT( pStat && mtget );

    mtget->mt_resid   =   0;            // (unknown/unsupported)
    mtget->mt_erreg   =   0;            // (unknown/unsupported)
    mtget->mt_fileno  =  -1;            // (unknown/unsupported)
    mtget->mt_blkno   =  -1;            // (unknown as of yet; set further below)
    mtget->mt_type    =  MT_ISSCSI2;    // "Generic ANSI SCSI-2 tape unit"
    mtget->mt_gstat   =  -1;            // (purposely invalid; set correctly below)

    // Reset the mounted status; it will get set further below...

    *pStat &= ~GMT_DR_OPEN (0xFFFFFFFF);

    // Attempt to retrieve the status of the tape-drive...

    dwRetCode = w32_get_tape_status( hFile );

    // Windows returns 'ERROR_NOT_READY' if no tape is mounted
    // instead of the usual expected 'ERROR_NO_MEDIA_IN_DRIVE'

    if ( ERROR_NOT_READY == dwRetCode )
        dwRetCode = ERROR_NO_MEDIA_IN_DRIVE;

    // If there is not tape mounted OR a new tape was mounted,
    // then the following status bits are now unknown/obsolete

    if (0
            || ERROR_NO_MEDIA_IN_DRIVE == dwRetCode
            || ERROR_MEDIA_CHANGED     == dwRetCode
       )
    {
        // (these statuse are now obsolete)
        *pStat  &=  ~GMT_WR_PROT (0xFFFFFFFF);
        *pStat  &=  ~GMT_BOT     (0xFFFFFFFF);
        *pStat  &=  ~GMT_EOT     (0xFFFFFFFF);
        *pStat  &=  ~GMT_EOD     (0xFFFFFFFF);
        *pStat  &=  ~GMT_EOF     (0xFFFFFFFF);
        *pStat  &=  ~GMT_SM      (0xFFFFFFFF);
    }

    // There's no sense trying to get media parameters
    // unless there's some media loaded on the drive!

    if ( ERROR_NO_MEDIA_IN_DRIVE == dwRetCode )
    {
        *pStat |= GMT_DR_OPEN (0xFFFFFFFF);     // (no tape mounted in drive)
        mtget->mt_gstat = *pStat;               // (return current status)
        return 0;                               // (nothing more we can do)
    }

    // A tape appears to be mounted on the drive...
    // Retrieve the media parameters information...

    dwSize = sizeof(media_parms);
    memset( &media_parms, 0, dwSize );
    dwRetCode = GetTapeParameters( hFile, GET_TAPE_MEDIA_INFORMATION, &dwSize, &media_parms );
    ASSERT( sizeof(media_parms) == dwSize );

    if ( NO_ERROR == dwRetCode )
    {
        mtget->mt_dsreg = media_parms.BlockSize;

        if (media_parms.WriteProtected)
            *pStat |=  GMT_WR_PROT (0xFFFFFFFF);
        else
            *pStat &= ~GMT_WR_PROT (0xFFFFFFFF);
    }
    else
        mtget->mt_dsreg = 0;    // (unknown; variable blocks presumed)

    // Lastly, attempt to determine if we are at BOT (i.e. load-point)...

    if ( 0 != ( errno = w32_internal_mtpos( hFile, pStat, &dwLogicalPosition, NULL, ifd ) ) )
    {
        mtget->mt_gstat = *pStat;
        return -1;
    }

    mtget->mt_blkno = dwLogicalPosition;

    if ( ( dwLogicalPosition & g_BOTmsk[ ifd ] ) == g_BOTbot[ ifd ] )
        *pStat |=  GMT_BOT (0xFFFFFFFF);
    else
        *pStat &= ~GMT_BOT (0xFFFFFFFF);

    mtget->mt_gstat = *pStat;
    return 0;
}
Exemple #4
0
/*      IOCTL routine called by kernel-interface code
 */
int _ftape_ioctl(unsigned int command, void *arg)
{
	TRACE_FUN(8, "ftape_ioctl");
	int result = EINVAL;
	union {
		struct mtop mtop;
		struct mtget mtget;
	} krnl_arg;
	int arg_size = (command & IOCSIZE_MASK) >> IOCSIZE_SHIFT;

	/* This check will only catch arguments that are too large !
	 */
	if ((command & IOC_INOUT) && arg_size > sizeof(krnl_arg)) {
		TRACEi(1, "bad argument size:", arg_size);
		TRACE_EXIT;
		return -EINVAL;
	}
	if (command & IOC_IN) {
		int error = verify_area(VERIFY_READ, arg, arg_size);
		if (error) {
			TRACE_EXIT;
			return error;
		}
		memcpy_fromfs(&krnl_arg.mtop, arg, arg_size);
	}
	TRACEx1(5, "called with ioctl command: 0x%08x", command);
	switch (command) {
		/* cpio compatibility
		 * mtrasx and mtreset are mt extension by Hennus Bergman
		 * mtseek and mttell are mt extension by eddy olk
		 */
	case MTIOCTOP:
		TRACEx1(5, "calling MTIOCTOP command: 0x%08x", krnl_arg.mtop.mt_op);
		switch (krnl_arg.mtop.mt_op) {
		case MTNOP:
			/* gnu mt calls MTNOP before MTIOCGET to set status */
			result = 0;
			break;
		case MTRESET:
			result = ftape_reset_drive();
			init_drive_needed = 1;
			if (result < 0 || ftape_offline) {
				break;
			}
			result = ftape_seek_to_bot();
			ftape_reset_position();
			break;
		case MTREW:
		case MTOFFL:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			ftape_flush_buffers();
			ftape_update_header_segments(NULL, 1);
			result = ftape_seek_to_bot();
			ftape_reset_position();
			if (krnl_arg.mtop.mt_op == MTOFFL) {
				going_offline = 1;
				TRACE(4, "Putting tape drive offline");
			}
			result = 0;
			break;
		case MTRETEN:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			result = ftape_seek_to_eot();
			if (result >= 0) {
				result = ftape_seek_to_bot();
			}
			ftape_reset_position();
			break;
		case MTERASE:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			result = ftape_erase();
			break;
		case MTEOM:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			result = ftape_seek_eom();
			break;
		case MTFSFM:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			eof_mark = 1;	/* position ready to extend */
		case MTFSF:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			result = ftape_seek_eof(krnl_arg.mtop.mt_count);
			break;
		case MTBSFM:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			eof_mark = 1;	/* position ready to extend */
		case MTBSF:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			result = ftape_seek_eof(-krnl_arg.mtop.mt_count);
			break;
		case MTFSR:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			tracing = krnl_arg.mtop.mt_count;
			TRACEx1(2, "tracing set to %d", tracing);
			result = 0;
			break;
		case MTBSR:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
#if 0
			result = ftape_fix();
#else
			result = 0;
#endif
			break;
		case MTWEOF:
			if (ftape_offline) {
				result = -EIO;
				break;
			}
			result = ftape_weof(krnl_arg.mtop.mt_count, ftape_seg_pos, 1);
			if (result >= 0) {
				ftape_seg_pos += krnl_arg.mtop.mt_count - 1;
			}
			break;
			/* MTRASx and MTRESET are mt extension by Hennus Bergman
			 */
		case MTRAS1:
		case MTRAS2:
		case MTRAS3:
		case MTSEEK:
		case MTTELL:
		default:
			TRACEi(1, "MTIOCTOP sub-command not implemented:", krnl_arg.mtop.mt_op);
			result = -EIO;
			break;
		}
		break;
	case MTIOCGET:
		krnl_arg.mtget.mt_type = drive_type.vendor_id + 0x800000;
		krnl_arg.mtget.mt_resid = 0;	/* not implemented */
		krnl_arg.mtget.mt_dsreg = 0;	/* status register */
		krnl_arg.mtget.mt_gstat =	/* device independent status */
		    ((ftape_offline) ? 0 : GMT_ONLINE(-1L)) |
		    ((write_protected) ? GMT_WR_PROT(-1L) : 0) |
		    ((no_tape) ? GMT_DR_OPEN(-1L) : 0);
		krnl_arg.mtget.mt_erreg = ftape_last_error;	/* error register */
		result = ftape_file_no(&krnl_arg.mtget.mt_fileno,
				       &krnl_arg.mtget.mt_blkno);
		break;
	case MTIOCPOS:
		TRACE(5, "Mag tape ioctl command: MTIOCPOS");
		TRACE(1, "MTIOCPOS command not implemented");
		break;
	default:
		result = -EINVAL;
		break;
	}
	if (command & IOC_OUT) {
		int error = verify_area(VERIFY_WRITE, arg, arg_size);
		if (error) {
			TRACE_EXIT;
			return error;
		}
		memcpy_tofs(arg, &krnl_arg, arg_size);
	}
	TRACE_EXIT;
	return result;
}
Exemple #5
0
/*
 * Return the status of the device.  This was meant
 * to be a generic routine. Unfortunately, it doesn't
 * seem possible (at least I do not know how to do it
 * currently), which means that for the moment, this
 * routine has very little value.
 *
 *   Returns: status
 */
uint32_t status_dev(DEVICE *dev)
{
   struct mtget mt_stat;
   uint32_t stat = 0;

   if (dev->state & (ST_EOT | ST_WEOT)) {
      stat |= BMT_EOD;
      Pmsg0(-20, " EOD");
   }
   if (dev->state & ST_EOF) {
      stat |= BMT_EOF;
      Pmsg0(-20, " EOF");
   }
   if (dev->is_tape()) {
      stat |= BMT_TAPE;
      Pmsg0(-20,_(" Bacula status:"));
      Pmsg2(-20,_(" file=%d block=%d\n"), dev->file, dev->block_num);
      if (dev->d_ioctl(dev->fd(), MTIOCGET, (char *)&mt_stat) < 0) {
         berrno be;
         dev->dev_errno = errno;
         Mmsg2(dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
            dev->print_name(), be.bstrerror());
         return 0;
      }
      Pmsg0(-20, _(" Device status:"));

#if defined(HAVE_LINUX_OS)
      if (GMT_EOF(mt_stat.mt_gstat)) {
         stat |= BMT_EOF;
         Pmsg0(-20, " EOF");
      }
      if (GMT_BOT(mt_stat.mt_gstat)) {
         stat |= BMT_BOT;
         Pmsg0(-20, " BOT");
      }
      if (GMT_EOT(mt_stat.mt_gstat)) {
         stat |= BMT_EOT;
         Pmsg0(-20, " EOT");
      }
      if (GMT_SM(mt_stat.mt_gstat)) {
         stat |= BMT_SM;
         Pmsg0(-20, " SM");
      }
      if (GMT_EOD(mt_stat.mt_gstat)) {
         stat |= BMT_EOD;
         Pmsg0(-20, " EOD");
      }
      if (GMT_WR_PROT(mt_stat.mt_gstat)) {
         stat |= BMT_WR_PROT;
         Pmsg0(-20, " WR_PROT");
      }
      if (GMT_ONLINE(mt_stat.mt_gstat)) {
         stat |= BMT_ONLINE;
         Pmsg0(-20, " ONLINE");
      }
      if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
         stat |= BMT_DR_OPEN;
         Pmsg0(-20, " DR_OPEN");
      }
      if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
         stat |= BMT_IM_REP_EN;
         Pmsg0(-20, " IM_REP_EN");
      }
#elif defined(HAVE_WIN32)
      if (GMT_EOF(mt_stat.mt_gstat)) {
         stat |= BMT_EOF;
         Pmsg0(-20, " EOF");
      }
      if (GMT_BOT(mt_stat.mt_gstat)) {
         stat |= BMT_BOT;
         Pmsg0(-20, " BOT");
      }
      if (GMT_EOT(mt_stat.mt_gstat)) {
         stat |= BMT_EOT;
         Pmsg0(-20, " EOT");
      }
      if (GMT_EOD(mt_stat.mt_gstat)) {
         stat |= BMT_EOD;
         Pmsg0(-20, " EOD");
      }
      if (GMT_WR_PROT(mt_stat.mt_gstat)) {
         stat |= BMT_WR_PROT;
         Pmsg0(-20, " WR_PROT");
      }
      if (GMT_ONLINE(mt_stat.mt_gstat)) {
         stat |= BMT_ONLINE;
         Pmsg0(-20, " ONLINE");
      }
      if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
         stat |= BMT_DR_OPEN;
         Pmsg0(-20, " DR_OPEN");
      }
      if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
         stat |= BMT_IM_REP_EN;
         Pmsg0(-20, " IM_REP_EN");
      }

#endif /* !SunOS && !OSF */
      if (dev->has_cap(CAP_MTIOCGET)) {
         Pmsg2(-20, _(" file=%d block=%d\n"), mt_stat.mt_fileno, mt_stat.mt_blkno);
      } else {
         Pmsg2(-20, _(" file=%d block=%d\n"), -1, -1);
      }
   } else {
      stat |= BMT_ONLINE | BMT_BOT;
   }
   return stat;
}
uint32_t generic_tape_device::status_dev()
{
   struct mtget mt_stat;
   uint32_t status = 0;

   if (state & (ST_EOT | ST_WEOT)) {
      status |= BMT_EOD;
      Pmsg0(-20, " EOD");
   }

   if (state & ST_EOF) {
      status |= BMT_EOF;
      Pmsg0(-20, " EOF");
   }

   status |= BMT_TAPE;
   Pmsg0(-20,_(" Bareos status:"));
   Pmsg2(-20,_(" file=%d block=%d\n"), file, block_num);
   if (d_ioctl(m_fd, MTIOCGET, (char *)&mt_stat) < 0) {
      berrno be;

      dev_errno = errno;
      Mmsg2(errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
            print_name(), be.bstrerror());
      return 0;
   }
   Pmsg0(-20, _(" Device status:"));

#if defined(HAVE_LINUX_OS)
   if (GMT_EOF(mt_stat.mt_gstat)) {
      status |= BMT_EOF;
      Pmsg0(-20, " EOF");
   }
   if (GMT_BOT(mt_stat.mt_gstat)) {
      status |= BMT_BOT;
      Pmsg0(-20, " BOT");
   }
   if (GMT_EOT(mt_stat.mt_gstat)) {
      status |= BMT_EOT;
      Pmsg0(-20, " EOT");
   }
   if (GMT_SM(mt_stat.mt_gstat)) {
      status |= BMT_SM;
      Pmsg0(-20, " SM");
   }
   if (GMT_EOD(mt_stat.mt_gstat)) {
      status |= BMT_EOD;
      Pmsg0(-20, " EOD");
   }
   if (GMT_WR_PROT(mt_stat.mt_gstat)) {
      status |= BMT_WR_PROT;
      Pmsg0(-20, " WR_PROT");
   }
   if (GMT_ONLINE(mt_stat.mt_gstat)) {
      status |= BMT_ONLINE;
      Pmsg0(-20, " ONLINE");
   }
   if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
      status |= BMT_DR_OPEN;
      Pmsg0(-20, " DR_OPEN");
   }
   if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
      status |= BMT_IM_REP_EN;
      Pmsg0(-20, " IM_REP_EN");
   }
#elif defined(HAVE_WIN32)
   if (GMT_EOF(mt_stat.mt_gstat)) {
      status |= BMT_EOF;
      Pmsg0(-20, " EOF");
   }
   if (GMT_BOT(mt_stat.mt_gstat)) {
      status |= BMT_BOT;
      Pmsg0(-20, " BOT");
   }
   if (GMT_EOT(mt_stat.mt_gstat)) {
      status |= BMT_EOT;
      Pmsg0(-20, " EOT");
   }
   if (GMT_EOD(mt_stat.mt_gstat)) {
      status |= BMT_EOD;
      Pmsg0(-20, " EOD");
   }
   if (GMT_WR_PROT(mt_stat.mt_gstat)) {
      status |= BMT_WR_PROT;
      Pmsg0(-20, " WR_PROT");
   }
   if (GMT_ONLINE(mt_stat.mt_gstat)) {
      status |= BMT_ONLINE;
      Pmsg0(-20, " ONLINE");
   }
   if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
      status |= BMT_DR_OPEN;
      Pmsg0(-20, " DR_OPEN");
   }
   if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
      status |= BMT_IM_REP_EN;
      Pmsg0(-20, " IM_REP_EN");
   }
#endif /* HAVE_LINUX_OS || HAVE_WIN32 */

   if (has_cap(CAP_MTIOCGET)) {
      Pmsg2(-20, _(" file=%d block=%d\n"), mt_stat.mt_fileno, mt_stat.mt_blkno);
   } else {
      Pmsg2(-20, _(" file=%d block=%d\n"), -1, -1);
   }

   return status;
}