* errno.cc (errmap): Handle ERROR_BUS_RESET.
* fhandler.h (fhandler_dev_raw::write_file): New method, created from former static function. (fhandler_dev_raw::read_file): Ditto. (reset_devbuf): New inline method. (class fhandler_dev_tape): Add TAPE_GET_DRIVE_PARAMETERS member `dp'. (fhandler_dev_tape::write_file): New method. (fhandler_dev_tape::read_file): Ditto. (fhandler_dev_tape::tape_get_feature): Convert to inline method. (fhandler_dev_tape::tape_error): New method, created from former static function. (fhandler_dev_tape::tape_get_blocksize): Remove declaration. * fhandler_raw.cc (fhandler_dev_raw::write_file): New method, created from former static function. (fhandler_dev_raw::read_file): Ditto. (fhandler_dev_raw::writebuf): Accomodate the fact that no devbuf exists under variable block size condition. (fhandler_dev_raw::raw_read): Ditto. Add local p pointer to simplify pointer arithmetic. (fhandler_dev_raw::raw_write): Always set devbufend to 0 when starting with writing. Accomodate the fact that no devbuf exists under variable block size condition. * fhandler_tape.cc: Various formatting changes. (TAPE_FUNC): New macro. Use throughout as tape function loop. (get_ll): Convert into macro. (IS_EOM): New macro. (IS_EOF): New macro. (fhandler_dev_tape::is_eom): Use IS_EOM macro. (fhandler_dev_tape::is_eof): Use IS_EOF macro. (fhandler_dev_tape::write_file): New method. (fhandler_dev_tape::read_file): New method. (fhandler_dev_tape::open): Get drive information block here once. (fhandler_dev_tape::lseek): Remove unneeded duplicate code. (fhandler_dev_tape::dup): Duplicate drive information block. (fhandler_dev_tape::ioctl): Remove drvbuf in variable block size mode. Return ERROR_INVALID_BLOCK_LENGTH instead of ERROR_MORE_DATA if buffer contains data which would get lost on buffer size changing. Use absolute tape positioning also if drive only supports logical block positioning. (fhandler_dev_tape::tape_error): New method, created from former static function. (fhandler_dev_tape::tape_get_pos): Allow logical block reporting. Workaround tape driver bug. (fhandler_dev_tape::_tape_set_pos): Reset device buffer and flags after successful repositioning. (fhandler_dev_tape::tape_set_pos): Allow logical block positioning. Workaround tape driver bug. (fhandler_dev_tape::tape_erase): Use dp instead of calling GetTapeParameters. (fhandler_dev_tape::tape_prepare): Ditto. (fhandler_dev_tape::tape_get_blocksize): Remove. (fhandler_dev_tape::tape_set_blocksize): Don't call tape_get_blocksize. Error handling already done in fhandler_dev_tape::ioctl. (fhandler_dev_tape::tape_status): Remove local `dp' variable. Accomodate logical tape reporting. Call tape_get_feature instead of accessing feature words directly. (fhandler_dev_tape::tape_compression): Use dp instead of calling GetTapeParameters. Fix resetting datcompression.
This commit is contained in:
		| @@ -1,3 +1,65 @@ | ||||
| 2004-03-12  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* errno.cc (errmap): Handle ERROR_BUS_RESET. | ||||
| 	* fhandler.h (fhandler_dev_raw::write_file): New method, created | ||||
| 	from former static function. | ||||
| 	(fhandler_dev_raw::read_file): Ditto. | ||||
| 	(reset_devbuf): New inline method. | ||||
| 	(class fhandler_dev_tape): Add TAPE_GET_DRIVE_PARAMETERS | ||||
| 	member `dp'. | ||||
| 	(fhandler_dev_tape::write_file): New method. | ||||
| 	(fhandler_dev_tape::read_file): Ditto. | ||||
| 	(fhandler_dev_tape::tape_get_feature): Convert to inline method. | ||||
| 	(fhandler_dev_tape::tape_error): New method, created from former | ||||
| 	static function.  | ||||
| 	(fhandler_dev_tape::tape_get_blocksize): Remove declaration. | ||||
| 	* fhandler_raw.cc (fhandler_dev_raw::write_file): New method, created | ||||
| 	from former static function. | ||||
| 	(fhandler_dev_raw::read_file): Ditto. | ||||
| 	(fhandler_dev_raw::writebuf): Accomodate the fact that no devbuf | ||||
| 	exists under variable block size condition. | ||||
| 	(fhandler_dev_raw::raw_read): Ditto. Add local p pointer to simplify | ||||
| 	pointer arithmetic. | ||||
| 	(fhandler_dev_raw::raw_write): Always set devbufend to 0 when starting | ||||
| 	with writing. Accomodate the fact that no devbuf exists under | ||||
| 	variable block size condition. | ||||
| 	* fhandler_tape.cc: Various formatting changes. | ||||
| 	(TAPE_FUNC): New macro. Use throughout as tape function loop. | ||||
| 	(get_ll): Convert into macro. | ||||
| 	(IS_EOM): New macro. | ||||
| 	(IS_EOF): New macro. | ||||
| 	(fhandler_dev_tape::is_eom): Use IS_EOM macro. | ||||
| 	(fhandler_dev_tape::is_eof): Use IS_EOF macro. | ||||
| 	(fhandler_dev_tape::write_file): New method. | ||||
| 	(fhandler_dev_tape::read_file): New method. | ||||
| 	(fhandler_dev_tape::open): Get drive information block here once. | ||||
| 	(fhandler_dev_tape::lseek): Remove unneeded duplicate code. | ||||
| 	(fhandler_dev_tape::dup): Duplicate drive information block. | ||||
| 	(fhandler_dev_tape::ioctl): Remove drvbuf in variable block size mode. | ||||
| 	Return ERROR_INVALID_BLOCK_LENGTH instead of ERROR_MORE_DATA if | ||||
| 	buffer contains data which would get lost on buffer size changing. | ||||
| 	Use absolute tape positioning also if drive only supports logical | ||||
| 	block positioning. | ||||
| 	(fhandler_dev_tape::tape_error): New method, created from former | ||||
| 	static function. | ||||
| 	(fhandler_dev_tape::tape_get_pos): Allow logical block reporting. | ||||
| 	Workaround tape driver bug. | ||||
| 	(fhandler_dev_tape::_tape_set_pos): Reset device buffer and flags | ||||
| 	after successful repositioning. | ||||
| 	(fhandler_dev_tape::tape_set_pos): Allow logical block positioning. | ||||
| 	Workaround tape driver bug. | ||||
| 	(fhandler_dev_tape::tape_erase): Use dp instead of calling | ||||
| 	GetTapeParameters. | ||||
| 	(fhandler_dev_tape::tape_prepare): Ditto. | ||||
| 	(fhandler_dev_tape::tape_get_blocksize): Remove. | ||||
| 	(fhandler_dev_tape::tape_set_blocksize): Don't call tape_get_blocksize. | ||||
| 	Error handling already done in fhandler_dev_tape::ioctl. | ||||
| 	(fhandler_dev_tape::tape_status): Remove local `dp' variable. | ||||
| 	Accomodate logical tape reporting.  Call tape_get_feature instead | ||||
| 	of accessing feature words directly. | ||||
| 	(fhandler_dev_tape::tape_compression): Use dp instead of calling | ||||
| 	GetTapeParameters.  Fix resetting datcompression. | ||||
|  | ||||
| 2004-03-12  Christopher Faylor  <cgf@redhat.com> | ||||
|  | ||||
| 	* wait.cc (wait4): Initialize pointer on entry.  Avoid calling | ||||
|   | ||||
| @@ -114,6 +114,7 @@ static NO_COPY struct | ||||
|   X (FILE_INVALID,		ENXIO), | ||||
|   X (INVALID_ADDRESS,		EOVERFLOW), | ||||
|   X (INVALID_BLOCK_LENGTH,	EIO), | ||||
|   X (BUS_RESET,			EIO), | ||||
|   { 0, NULL, 0} | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -514,6 +514,9 @@ class fhandler_dev_raw: public fhandler_base | ||||
|   int varblkop	      : 1; | ||||
|  | ||||
|   virtual void clear (void); | ||||
|   virtual BOOL write_file (const void *buf, DWORD to_write, | ||||
| 			   DWORD *written, int *err); | ||||
|   virtual BOOL read_file (void *buf, DWORD to_read, DWORD *read, int *err); | ||||
|   virtual int writebuf (void); | ||||
|  | ||||
|   /* returns not null, if `win_error' determines an end of media condition */ | ||||
| @@ -523,6 +526,13 @@ class fhandler_dev_raw: public fhandler_base | ||||
|  | ||||
|   fhandler_dev_raw (); | ||||
|  | ||||
|   inline void reset_devbuf (void) | ||||
|     { | ||||
|       devbufstart = devbufend = 0; | ||||
|       eom_detected = eof_detected = 0; | ||||
|       lastblk_to_read = is_writing = has_written = 0; | ||||
|     } | ||||
|  | ||||
|  public: | ||||
|   ~fhandler_dev_raw (void); | ||||
|  | ||||
| @@ -562,14 +572,17 @@ class fhandler_dev_floppy: public fhandler_dev_raw | ||||
| class fhandler_dev_tape: public fhandler_dev_raw | ||||
| { | ||||
|   int lasterr; | ||||
|   TAPE_GET_DRIVE_PARAMETERS dp; | ||||
|  | ||||
|   bool is_rewind_device () { return get_unit () < 128; } | ||||
|  | ||||
|  protected: | ||||
|   virtual void clear (void); | ||||
|  | ||||
|   virtual int is_eom (int win_error); | ||||
|   virtual int is_eof (int win_error); | ||||
|   virtual BOOL write_file (const void *buf, DWORD to_write, | ||||
| 			   DWORD *written, int *err); | ||||
|   virtual BOOL read_file (void *buf, DWORD to_read, DWORD *read, int *err); | ||||
|  | ||||
|  public: | ||||
|   fhandler_dev_tape (); | ||||
| @@ -586,13 +599,19 @@ class fhandler_dev_tape: public fhandler_dev_raw | ||||
|   virtual int ioctl (unsigned int cmd, void *buf); | ||||
|  | ||||
|  private: | ||||
|   inline bool tape_get_feature (DWORD parm) | ||||
|     { | ||||
|       return ((parm & TAPE_DRIVE_HIGH_FEATURES) | ||||
| 	      ? ((dp.FeaturesHigh & parm) != 0) | ||||
| 	      : ((dp.FeaturesLow & parm) != 0)); | ||||
|     } | ||||
|   int tape_error (const char *txt); | ||||
|   int tape_write_marks (int marktype, DWORD len); | ||||
|   int tape_get_pos (unsigned long *ret); | ||||
|   int tape_set_pos (int mode, long count, bool sfm_func = false); | ||||
|   int _tape_set_pos (int mode, long count); | ||||
|   int tape_erase (int mode); | ||||
|   int tape_prepare (int action); | ||||
|   bool tape_get_feature (DWORD parm); | ||||
|   int tape_get_blocksize (long *min, long *def, long *max, long *cur); | ||||
|   int tape_set_blocksize (long count); | ||||
|   int tape_status (struct mtget *get); | ||||
|   int tape_compression (long count); | ||||
|   | ||||
| @@ -24,52 +24,6 @@ | ||||
| #include "cygheap.h" | ||||
| #include "ntdll.h" | ||||
|  | ||||
| /* static wrapper functions to hide the effect of media changes and | ||||
|    bus resets which occurs after a new media is inserted. This is | ||||
|    also related to the used tape device.  */ | ||||
|  | ||||
| static BOOL write_file (HANDLE fh, const void *buf, DWORD to_write, | ||||
| 			DWORD *written, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   *err = 0; | ||||
|   if (!(ret = WriteFile (fh, buf, to_write, written, 0))) | ||||
|     { | ||||
|       if ((*err = GetLastError ()) == ERROR_MEDIA_CHANGED | ||||
| 	  || *err == ERROR_BUS_RESET) | ||||
| 	{ | ||||
| 	  *err = 0; | ||||
| 	  if (!(ret = WriteFile (fh, buf, to_write, written, 0))) | ||||
| 	    *err = GetLastError (); | ||||
| 	} | ||||
|     } | ||||
|   syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)", | ||||
| 		  ret, *err, fh, buf, to_write, *written); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| static BOOL read_file (HANDLE fh, void *buf, DWORD to_read, | ||||
| 		       DWORD *read, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   *err = 0; | ||||
|   if (!(ret = ReadFile (fh, buf, to_read, read, 0))) | ||||
|     { | ||||
|       if ((*err = GetLastError ()) == ERROR_MEDIA_CHANGED | ||||
| 	  || *err == ERROR_BUS_RESET) | ||||
| 	{ | ||||
| 	  *err = 0; | ||||
| 	  if (!(ret = ReadFile (fh, buf, to_read, read, 0))) | ||||
| 	    *err = GetLastError (); | ||||
| 	} | ||||
|     } | ||||
|   syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)", | ||||
| 		  ret, *err, fh, buf, to_read, *read); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /* fhandler_dev_raw */ | ||||
|  | ||||
| @@ -86,13 +40,43 @@ fhandler_dev_raw::clear (void) | ||||
|   varblkop = 0; | ||||
| } | ||||
|  | ||||
| /* Wrapper functions to allow fhandler_dev_tape to detect and care for | ||||
|    media changes and bus resets. */ | ||||
|  | ||||
| BOOL | ||||
| fhandler_dev_raw::write_file (const void *buf, DWORD to_write, | ||||
| 			      DWORD *written, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   *err = 0; | ||||
|   if (!(ret = WriteFile (get_handle (), buf, to_write, written, 0))) | ||||
|     *err = GetLastError (); | ||||
|   syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)", | ||||
| 		  ret, *err, get_handle (), buf, to_write, *written); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| BOOL | ||||
| fhandler_dev_raw::read_file (void *buf, DWORD to_read, DWORD *read, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   *err = 0; | ||||
|   if (!(ret = ReadFile (get_handle (), buf, to_read, read, 0))) | ||||
|     *err = GetLastError (); | ||||
|   syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)", | ||||
| 		  ret, *err, get_handle (), buf, to_read, *read); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_raw::writebuf (void) | ||||
| { | ||||
|   DWORD written; | ||||
|   int ret = 0; | ||||
|  | ||||
|   if (is_writing && devbuf && devbufend) | ||||
|   if (!varblkop && is_writing && devbuf && devbufend) | ||||
|     { | ||||
|       DWORD to_write; | ||||
|       int ret = 0; | ||||
| @@ -100,11 +84,9 @@ fhandler_dev_raw::writebuf (void) | ||||
|       memset (devbuf + devbufend, 0, devbufsiz - devbufend); | ||||
|       if (get_major () != DEV_TAPE_MAJOR) | ||||
| 	to_write = ((devbufend - 1) / 512 + 1) * 512; | ||||
|       else if (varblkop) | ||||
| 	to_write = devbufend; | ||||
|       else | ||||
| 	to_write = devbufsiz; | ||||
|       if (!write_file (get_handle (), devbuf, to_write, &written, &ret) | ||||
|       if (!write_file (devbuf, to_write, &written, &ret) | ||||
| 	  && is_eom (ret)) | ||||
| 	eom_detected = 1; | ||||
|       if (written) | ||||
| @@ -216,6 +198,7 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen) | ||||
|   int ret; | ||||
|   size_t len = ulen; | ||||
|   char *tgt; | ||||
|   char *p = (char *) ptr; | ||||
|  | ||||
|   /* In mode O_RDWR the buffer has to be written to device first */ | ||||
|   ret = writebuf (); | ||||
| @@ -251,10 +234,10 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen) | ||||
| 	    { | ||||
| 	      bytes_to_read = min (len, devbufend - devbufstart); | ||||
| 	      debug_printf ("read %d bytes from buffer (rest %d)", | ||||
| 			    bytes_to_read, devbufstart - devbufend); | ||||
| 	      memcpy (ptr, devbuf + devbufstart, bytes_to_read); | ||||
| 			    bytes_to_read, devbufend - devbufend); | ||||
| 	      memcpy (p, devbuf + devbufstart, bytes_to_read); | ||||
| 	      len -= bytes_to_read; | ||||
| 	      ptr = (void *) ((char *) ptr + bytes_to_read); | ||||
| 	      p += bytes_to_read; | ||||
| 	      bytes_read += bytes_to_read; | ||||
| 	      devbufstart += bytes_to_read; | ||||
|  | ||||
| @@ -266,21 +249,15 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen) | ||||
| 	    } | ||||
| 	  if (len > 0) | ||||
| 	    { | ||||
| 	      if (!varblkop && len >= devbufsiz) | ||||
| 	      if (len >= devbufsiz) | ||||
| 		{ | ||||
| 		  if (get_major () == DEV_TAPE_MAJOR) | ||||
| 		    bytes_to_read = (len / devbufsiz) * devbufsiz; | ||||
| 		  else | ||||
| 		    bytes_to_read = (len / 512) * 512; | ||||
| 		  tgt = (char *) ptr; | ||||
| 		  tgt = p; | ||||
| 		  debug_printf ("read %d bytes direct from file",bytes_to_read); | ||||
| 		} | ||||
| 	      else if (varblkop) | ||||
| 		{ | ||||
| 		  tgt = (char *) ptr; | ||||
| 		  bytes_to_read = len; | ||||
| 		  debug_printf ("read variable bytes direct from file"); | ||||
| 		} | ||||
| 	      else | ||||
| 		{ | ||||
| 		  tgt = devbuf; | ||||
| @@ -288,15 +265,10 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen) | ||||
| 		  debug_printf ("read %d bytes from file into buffer", | ||||
| 				bytes_to_read); | ||||
| 		} | ||||
| 	      if (!read_file (get_handle (), tgt, bytes_to_read, &read2, &ret)) | ||||
| 	      if (!read_file (tgt, bytes_to_read, &read2, &ret)) | ||||
| 		{ | ||||
| 		  if (!is_eof (ret) && !is_eom (ret)) | ||||
| 		    { | ||||
| 		      if (varblkop && ret == ERROR_MORE_DATA) | ||||
| 		        /* *ulen < blocksize.  Linux returns ENOMEM here | ||||
| 			   when reading with variable blocksize . */ | ||||
| 		        set_errno (ENOMEM); | ||||
| 		      else | ||||
| 		      __seterrno (); | ||||
| 		      goto err; | ||||
| 		    } | ||||
| @@ -325,26 +297,24 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen) | ||||
| 		  devbufstart = 0; | ||||
| 		  devbufend = read2; | ||||
| 		} | ||||
| 	      else if (varblkop) | ||||
| 		{ | ||||
| 		  /* When reading tapes with variable block size, we | ||||
| 		     leave right after reading one block. */ | ||||
| 		  bytes_read = read2; | ||||
| 		  break; | ||||
| 		} | ||||
| 	      else | ||||
| 		{ | ||||
| 		  len -= read2; | ||||
| 		  ptr = (void *) ((char *) ptr + read2); | ||||
| 		  p += read2; | ||||
| 		  bytes_read += read2; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   else if (!read_file (get_handle (), ptr, len, &bytes_read, &ret)) | ||||
|   else if (!read_file (p, len, &bytes_read, &ret)) | ||||
|     { | ||||
|       if (!is_eof (ret) && !is_eom (ret)) | ||||
| 	{ | ||||
| 	  if (varblkop && ret == ERROR_MORE_DATA) | ||||
| 	    /* *ulen < blocksize.  Linux returns ENOMEM here | ||||
| 	       when reading with variable blocksize . */ | ||||
| 	    set_errno (ENOMEM); | ||||
| 	  else | ||||
| 	  __seterrno (); | ||||
| 	  goto err; | ||||
| 	} | ||||
| @@ -389,18 +359,14 @@ fhandler_dev_raw::raw_write (const void *ptr, size_t len) | ||||
|     } | ||||
|  | ||||
|   if (!is_writing) | ||||
|     { | ||||
|       devbufend = devbufstart; | ||||
|       devbufstart = 0; | ||||
|     } | ||||
|     devbufstart = devbufend = 0; | ||||
|   is_writing = 1; | ||||
|  | ||||
|   if (devbuf) | ||||
|     { | ||||
|       while (len > 0) | ||||
| 	{ | ||||
| 	  if (!varblkop && | ||||
| 	      (len < devbufsiz || devbufend > 0) && devbufend < devbufsiz) | ||||
| 	  if ((len < devbufsiz || devbufend > 0) && devbufend < devbufsiz) | ||||
| 	    { | ||||
| 	      bytes_to_write = min (len, devbufsiz - devbufend); | ||||
| 	      memcpy (devbuf + devbufend, p, bytes_to_write); | ||||
| @@ -411,12 +377,7 @@ fhandler_dev_raw::raw_write (const void *ptr, size_t len) | ||||
| 	    } | ||||
| 	  else | ||||
| 	    { | ||||
| 	      if (varblkop) | ||||
| 		{ | ||||
| 		  bytes_to_write = len; | ||||
| 		  tgt = p; | ||||
| 		} | ||||
| 	      else if (devbufend == devbufsiz) | ||||
| 	      if (devbufend == devbufsiz) | ||||
| 		{ | ||||
| 		  bytes_to_write = devbufsiz; | ||||
| 		  tgt = devbuf; | ||||
| @@ -428,7 +389,7 @@ fhandler_dev_raw::raw_write (const void *ptr, size_t len) | ||||
| 		} | ||||
|  | ||||
| 	      ret = 0; | ||||
| 	      write_file (get_handle (), tgt, bytes_to_write, &written, &ret); | ||||
| 	      write_file (tgt, bytes_to_write, &written, &ret); | ||||
| 	      if (written) | ||||
| 		has_written = 1; | ||||
|  | ||||
| @@ -471,7 +432,7 @@ fhandler_dev_raw::raw_write (const void *ptr, size_t len) | ||||
|     } | ||||
|   else if (len > 0) | ||||
|     { | ||||
|       if (!write_file (get_handle (), ptr, len, &bytes_written, &ret)) | ||||
|       if (!write_file (p, len, &bytes_written, &ret)) | ||||
| 	{ | ||||
| 	  if (bytes_written) | ||||
| 	    has_written = 1; | ||||
|   | ||||
| @@ -21,6 +21,24 @@ details. */ | ||||
| #include "dtable.h" | ||||
| #include "cygheap.h" | ||||
|  | ||||
| /* Media changes and bus resets are sometimes reported and the function | ||||
|    hasn't been executed.  We repeat all functions which return with one | ||||
|    of these error codes. */ | ||||
| #define TAPE_FUNC(func) do { \ | ||||
| 			  lasterr = (func); \ | ||||
| 			} while (lasterr == ERROR_MEDIA_CHANGED \ | ||||
| 				 || lasterr == ERROR_BUS_RESET) | ||||
|  | ||||
| /* Convert LARGE_INTEGER into long long */ | ||||
| #define get_ll(pl)  (((long long) (pl).HighPart << 32) | (pl).LowPart) | ||||
|  | ||||
| #define IS_EOM(err) ((err) == ERROR_END_OF_MEDIA \ | ||||
| 		     || (err) == ERROR_EOM_OVERFLOW \ | ||||
| 		     || (err) == ERROR_NO_DATA_DETECTED) | ||||
|  | ||||
| #define IS_EOF(err) ((err) == ERROR_FILEMARK_DETECTED \ | ||||
| 		     || (err) == ERROR_SETMARK_DETECTED) | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /* fhandler_dev_tape */ | ||||
|  | ||||
| @@ -34,9 +52,7 @@ fhandler_dev_tape::clear (void) | ||||
| int | ||||
| fhandler_dev_tape::is_eom (int win_error) | ||||
| { | ||||
|   int ret = ((win_error == ERROR_END_OF_MEDIA) | ||||
| 	  || (win_error == ERROR_EOM_OVERFLOW) | ||||
| 	  || (win_error == ERROR_NO_DATA_DETECTED)); | ||||
|   int ret = IS_EOM (win_error); | ||||
|   if (ret) | ||||
|     debug_printf ("end of medium"); | ||||
|   return ret; | ||||
| @@ -45,13 +61,47 @@ fhandler_dev_tape::is_eom (int win_error) | ||||
| int | ||||
| fhandler_dev_tape::is_eof (int win_error) | ||||
| { | ||||
|   int ret = ((win_error == ERROR_FILEMARK_DETECTED) | ||||
| 	  || (win_error == ERROR_SETMARK_DETECTED)); | ||||
|   int ret = IS_EOF (win_error); | ||||
|   if (ret) | ||||
|     debug_printf ("end of file"); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| BOOL | ||||
| fhandler_dev_tape::write_file (const void *buf, DWORD to_write, | ||||
| 			       DWORD *written, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   do | ||||
|     { | ||||
|       *err = 0; | ||||
|       if (!(ret = WriteFile (get_handle (), buf, to_write, written, 0))) | ||||
| 	*err = GetLastError (); | ||||
|     } | ||||
|   while (*err == ERROR_MEDIA_CHANGED || *err == ERROR_BUS_RESET); | ||||
|   syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)", | ||||
| 		  ret, *err, get_handle (), buf, to_write, *written); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| BOOL | ||||
| fhandler_dev_tape::read_file (void *buf, DWORD to_read, DWORD *read, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   do | ||||
|     { | ||||
|       *err = 0; | ||||
|       if (!(ret = ReadFile (get_handle (), buf, to_read, read, 0))) | ||||
| 	*err = GetLastError (); | ||||
|     } | ||||
|   while (*err == ERROR_MEDIA_CHANGED || *err == ERROR_BUS_RESET); | ||||
|   syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)", | ||||
| 		  ret, *err, get_handle (), buf, to_read, *read); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| fhandler_dev_tape::fhandler_dev_tape () | ||||
|   : fhandler_dev_raw () | ||||
| { | ||||
| @@ -71,6 +121,10 @@ fhandler_dev_tape::open (int flags, mode_t) | ||||
|       struct mtget get; | ||||
|       struct mtop op; | ||||
|       struct mtpos pos; | ||||
|       DWORD varlen; | ||||
|  | ||||
|       TAPE_FUNC (GetTapeParameters (get_handle (), GET_TAPE_DRIVE_INFORMATION, | ||||
| 				    (varlen = sizeof dp, &varlen), &dp)); | ||||
|  | ||||
|       if (!ioctl (MTIOCGET, &get)) | ||||
| 	/* Tape drive supports and is set to variable block size. */ | ||||
| @@ -116,7 +170,7 @@ fhandler_dev_tape::close (void) | ||||
|   if (is_writing) | ||||
|     { | ||||
|       ret = writebuf (); | ||||
|       if ((has_written) && (! eom_detected)) | ||||
|       if (has_written && !eom_detected) | ||||
| 	{ | ||||
| 	  /* if last operation was writing, write a filemark */ | ||||
| 	  debug_printf ("writing filemark"); | ||||
| @@ -170,9 +224,6 @@ fhandler_dev_tape::lseek (_off64_t offset, int whence) | ||||
|   debug_printf ("lseek (%s, %d, %d)", get_name (), offset, whence); | ||||
|  | ||||
|   writebuf (); | ||||
|   eom_detected = eof_detected = 0; | ||||
|   lastblk_to_read = 0; | ||||
|   devbufstart = devbufend = 0; | ||||
|  | ||||
|   if (ioctl (MTIOCPOS, &pos)) | ||||
|     { | ||||
| @@ -223,6 +274,7 @@ fhandler_dev_tape::dup (fhandler_base *child) | ||||
|   fhandler_dev_tape *fhc = (fhandler_dev_tape *) child; | ||||
|  | ||||
|   fhc->lasterr = lasterr; | ||||
|   fhc->dp = dp; | ||||
|   return fhandler_dev_raw::dup (child); | ||||
| } | ||||
|  | ||||
| @@ -299,53 +351,45 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf) | ||||
| 	    break; | ||||
| 	  case MTSETBLK: | ||||
| 	    { | ||||
| 	      long min, max; | ||||
|  | ||||
| 	      if (!tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE)) | ||||
| 		{ | ||||
| 		  ret = ERROR_INVALID_PARAMETER; | ||||
| 		  break; | ||||
| 		} | ||||
| 	      ret = tape_get_blocksize (&min, NULL, &max, NULL); | ||||
| 	      if (ret) | ||||
| 		  break; | ||||
| 	      if (devbuf && (size_t) op->mt_count == devbufsiz && !varblkop) | ||||
| 	      if ((devbuf && (size_t) op->mt_count == devbufsiz) | ||||
| 	          || (!devbuf && op->mt_count == 0)) | ||||
| 		{ | ||||
| 		  /* Nothing has changed. */ | ||||
| 		  ret = 0; | ||||
| 		  break; | ||||
| 		} | ||||
| 	      if ((op->mt_count == 0 | ||||
| 		   && !tape_get_feature (TAPE_DRIVE_VARIABLE_BLOCK)) | ||||
| 		  || (op->mt_count > 0 | ||||
| 		      && (op->mt_count < min || op->mt_count > max))) | ||||
| 		      && ((DWORD) op->mt_count < dp.MinimumBlockSize | ||||
| 			  || (DWORD) op->mt_count > dp.MaximumBlockSize))) | ||||
| 		{ | ||||
| 		  ret = ERROR_INVALID_PARAMETER; | ||||
| 		  break; | ||||
| 		} | ||||
| 	      if (devbuf && op->mt_count > 0 | ||||
| 		  && (size_t) op->mt_count < devbufend - devbufstart) | ||||
| 	      if (devbuf && devbufend - devbufstart > 0 | ||||
| 	          && (op->mt_count == 0 | ||||
| 		      || (op->mt_count > 0 | ||||
| 		          && (size_t) op->mt_count < devbufend - devbufstart))) | ||||
| 		{ | ||||
| 		  ret = ERROR_MORE_DATA; | ||||
| 		  /* Not allowed if still data in devbuf. */ | ||||
| 		  ret = ERROR_INVALID_BLOCK_LENGTH; /* EIO */ | ||||
| 		  break; | ||||
| 		} | ||||
| 	      if (!(ret = tape_set_blocksize (op->mt_count))) | ||||
| 		{ | ||||
| 		  size_t size = 0; | ||||
| 		  if (op->mt_count == 0) | ||||
| 		    { | ||||
| 		      struct mtget get; | ||||
| 		      if ((ret = tape_status (&get)) != NO_ERROR) | ||||
| 			break; | ||||
| 		      size = get.mt_maxblksize; | ||||
| 		      ret = NO_ERROR; | ||||
| 		    } | ||||
| 		  char *buf = NULL; | ||||
| 		  if (size > 1L && !(buf = new char [size])) | ||||
| 		  if (op->mt_count > 1L && !(buf = new char [op->mt_count])) | ||||
| 		    { | ||||
| 		      ret = ERROR_OUTOFMEMORY; | ||||
| 		      break; | ||||
| 		    } | ||||
| 		  if (devbufsiz > 1L && size > 1L) | ||||
| 		  if (devbufsiz > 1L && op->mt_count > 1L) | ||||
| 		    { | ||||
| 		      memcpy (buf, devbuf + devbufstart, | ||||
| 			      devbufend - devbufstart); | ||||
| @@ -353,11 +397,10 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf) | ||||
| 		    } | ||||
| 		  else | ||||
| 		    devbufend = 0; | ||||
| 		  if (devbufsiz > 1L) | ||||
| 		    delete [] devbuf; | ||||
| 		  devbufstart = 0; | ||||
| 		  delete [] devbuf; | ||||
| 		  devbuf = buf; | ||||
| 		  devbufsiz = size; | ||||
| 		  devbufsiz = op->mt_count; | ||||
| 		  varblkop = op->mt_count == 0; | ||||
| 		} | ||||
| 	    } | ||||
| @@ -366,16 +409,12 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf) | ||||
| 	    ret = ERROR_INVALID_PARAMETER; | ||||
| 	    break; | ||||
| 	  case MTSEEK: | ||||
| 	    if (tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK)) | ||||
| 	      { | ||||
| 	    if (tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK) | ||||
| 	        || tape_get_feature (TAPE_DRIVE_LOGICAL_BLK)) | ||||
| 	      ret = tape_set_pos (TAPE_ABSOLUTE_BLOCK, op->mt_count); | ||||
| 		break; | ||||
| 	      } | ||||
| 	    if (! (ret = tape_get_pos (&block))) | ||||
| 	      { | ||||
| 	    else if (!(ret = tape_get_pos (&block))) | ||||
| 	      ret = tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, | ||||
| 				  op->mt_count - block); | ||||
| 	      } | ||||
| 	    break; | ||||
| 	  case MTTELL: | ||||
| 	    if (!(ret = tape_get_pos (&block))) | ||||
| @@ -440,12 +479,11 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf) | ||||
| /*                  Private functions used by `ioctl'                 */ | ||||
| /* ------------------------------------------------------------------ */ | ||||
|  | ||||
| static int | ||||
| tape_error (DWORD lasterr, const char *txt) | ||||
| int | ||||
| fhandler_dev_tape::tape_error (const char *txt) | ||||
| { | ||||
|   if (lasterr) | ||||
|     debug_printf ("%s: error: %d", txt, lasterr); | ||||
|  | ||||
|   return lasterr; | ||||
| } | ||||
|  | ||||
| @@ -453,14 +491,8 @@ int | ||||
| fhandler_dev_tape::tape_write_marks (int marktype, DWORD len) | ||||
| { | ||||
|   syscall_printf ("write_tapemark"); | ||||
|   while (((lasterr = WriteTapemark (get_handle (), | ||||
| 				    marktype, | ||||
| 				    len, | ||||
| 				    FALSE)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (lasterr == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|  | ||||
|   return tape_error (lasterr, "tape_write_marks"); | ||||
|   TAPE_FUNC (WriteTapemark (get_handle (), marktype, len, FALSE)); | ||||
|   return tape_error ("tape_write_marks"); | ||||
| } | ||||
|  | ||||
| int | ||||
| @@ -468,33 +500,42 @@ fhandler_dev_tape::tape_get_pos (unsigned long *ret) | ||||
| { | ||||
|   DWORD part, low, high; | ||||
|  | ||||
|   while (((lasterr = GetTapePosition (get_handle (), | ||||
| 				      TAPE_ABSOLUTE_POSITION, | ||||
| 				      &part, | ||||
| 				      &low, | ||||
| 				      &high)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (lasterr == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|   if (! tape_error (lasterr, "tape_get_pos") && ret) | ||||
|   lasterr = ERROR_INVALID_PARAMETER; | ||||
|   if (tape_get_feature (TAPE_DRIVE_GET_ABSOLUTE_BLK)) | ||||
|     { | ||||
|       TAPE_FUNC (GetTapePosition (get_handle (), TAPE_ABSOLUTE_POSITION, | ||||
| 				  &part, &low, &high)); | ||||
|       /* Workaround bug in Tandberg SLR device driver, which pretends | ||||
|          to support reporting of absolute blocks but instead returns | ||||
| 	 ERROR_INVALID_FUNCTION. */ | ||||
|       if (lasterr != ERROR_INVALID_FUNCTION) | ||||
| 	goto out; | ||||
|       dp.FeaturesLow &= ~TAPE_DRIVE_GET_ABSOLUTE_BLK; | ||||
|     } | ||||
|   if (tape_get_feature (TAPE_DRIVE_GET_LOGICAL_BLK)) | ||||
|     TAPE_FUNC (GetTapePosition (get_handle (), TAPE_LOGICAL_POSITION, | ||||
| 				&part, &low, &high)); | ||||
|  | ||||
| out: | ||||
|   if (!tape_error ("tape_get_pos") && ret) | ||||
|     *ret = low; | ||||
|  | ||||
|   return lasterr; | ||||
| } | ||||
|  | ||||
| static int _tape_set_pos (HANDLE hTape, int mode, long count) | ||||
| int | ||||
| fhandler_dev_tape::_tape_set_pos (int mode, long count) | ||||
| { | ||||
|   int err; | ||||
|  | ||||
|   while (((err = SetTapePosition (hTape, | ||||
| 				  mode, | ||||
| 				  1, | ||||
| 				  count, | ||||
| 				  count < 0 ? -1 : 0, | ||||
| 				  FALSE)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (err == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|  | ||||
|   return err; | ||||
|   TAPE_FUNC (SetTapePosition (get_handle (), mode, 0, count, | ||||
| 			      count < 0 ? -1 : 0, FALSE)); | ||||
|   /* Reset buffer after successful repositioning. */ | ||||
|   if (!lasterr || IS_EOF (lasterr) || IS_EOM (lasterr)) | ||||
|     { | ||||
|       reset_devbuf (); | ||||
|       eof_detected = IS_EOF (lasterr); | ||||
|       eom_detected = IS_EOM (lasterr); | ||||
|     } | ||||
|   return lasterr; | ||||
| } | ||||
|  | ||||
| int | ||||
| @@ -505,20 +546,14 @@ fhandler_dev_tape::tape_set_pos (int mode, long count, bool sfm_func) | ||||
|   switch (mode) | ||||
|     { | ||||
|       case TAPE_SPACE_RELATIVE_BLOCKS: | ||||
| 	lasterr = tape_get_pos (&pos); | ||||
|  | ||||
| 	if (lasterr) | ||||
| 	if (tape_get_pos (&pos)) | ||||
| 	  return lasterr; | ||||
|  | ||||
| 	tgtpos = pos + count; | ||||
|  | ||||
| 	while (((lasterr = _tape_set_pos (get_handle (), | ||||
| 					  mode, | ||||
| 					  count)) == ERROR_FILEMARK_DETECTED) | ||||
| 	       || (lasterr == ERROR_SETMARK_DETECTED)) | ||||
| 	while (count && (_tape_set_pos (mode, count), IS_EOF (lasterr))) | ||||
| 	  { | ||||
| 	    lasterr = tape_get_pos (&pos); | ||||
| 	    if (lasterr) | ||||
| 	    if (tape_get_pos (&pos)) | ||||
| 	      return lasterr; | ||||
| 	    count = tgtpos - pos; | ||||
| 	  } | ||||
| @@ -532,16 +567,13 @@ fhandler_dev_tape::tape_set_pos (int mode, long count, bool sfm_func) | ||||
| 	  { | ||||
| 	    if (pos > 0) | ||||
| 	      { | ||||
| 		if ((! _tape_set_pos (get_handle (), | ||||
| 				  TAPE_SPACE_RELATIVE_BLOCKS, | ||||
| 				  -1)) | ||||
| 		if (!_tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, -1) | ||||
| 		    || (sfm_func)) | ||||
| 		  ++count; | ||||
| 		_tape_set_pos (get_handle (), TAPE_SPACE_RELATIVE_BLOCKS, 1); | ||||
| 		_tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, 1); | ||||
| 	      } | ||||
|  | ||||
| 	    while (! (lasterr = _tape_set_pos (get_handle (), mode, -1)) | ||||
| 		   && count++ < 0) | ||||
| 	    while (!_tape_set_pos (mode, -1) && count++ < 0) | ||||
| 	      ; | ||||
|  | ||||
| 	    if (lasterr == ERROR_BEGINNING_OF_MEDIA) | ||||
| @@ -550,205 +582,117 @@ fhandler_dev_tape::tape_set_pos (int mode, long count, bool sfm_func) | ||||
| 		  lasterr = NO_ERROR; | ||||
| 	      } | ||||
| 	    else if (!sfm_func) | ||||
| 	      lasterr = _tape_set_pos (get_handle (), mode, 1); | ||||
| 	      _tape_set_pos (mode, 1); | ||||
| 	  } | ||||
| 	else | ||||
| 	  { | ||||
| 	    if (sfm_func) | ||||
| 	      { | ||||
| 		if (_tape_set_pos (get_handle (), | ||||
| 				   TAPE_SPACE_RELATIVE_BLOCKS, | ||||
| 				   1) == ERROR_FILEMARK_DETECTED) | ||||
| 		if (_tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, 1) | ||||
| 		    == ERROR_FILEMARK_DETECTED) | ||||
| 		  ++count; | ||||
| 		_tape_set_pos (get_handle (), TAPE_SPACE_RELATIVE_BLOCKS, -1); | ||||
| 		_tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, -1); | ||||
| 	      } | ||||
|  | ||||
| 	    if (! (lasterr = _tape_set_pos (get_handle (), mode, count)) | ||||
| 		&& sfm_func) | ||||
| 	      lasterr = _tape_set_pos (get_handle (), mode, -1); | ||||
| 	    if (!_tape_set_pos (mode, count) && sfm_func) | ||||
| 	      _tape_set_pos (mode, -1); | ||||
| 	  } | ||||
| 	break; | ||||
|       case TAPE_ABSOLUTE_BLOCK: | ||||
| 	if (!tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK)) | ||||
| 	  mode = TAPE_LOGICAL_BLOCK; | ||||
| 	_tape_set_pos (mode, count); | ||||
| 	/* Workaround bug in Tandberg SLR device driver, which pretends | ||||
| 	   to support absolute block positioning but instead returns | ||||
| 	   ERROR_INVALID_FUNCTION. */ | ||||
| 	if (lasterr == ERROR_INVALID_FUNCTION && mode == TAPE_ABSOLUTE_BLOCK) | ||||
| 	  { | ||||
| 	    dp.FeaturesHigh &= TAPE_DRIVE_HIGH_FEATURES | ||||
| 			       | ~TAPE_DRIVE_ABSOLUTE_BLK; | ||||
| 	    _tape_set_pos (TAPE_LOGICAL_BLOCK, count); | ||||
| 	  } | ||||
| 	  break; | ||||
|       case TAPE_SPACE_SETMARKS: | ||||
|       case TAPE_ABSOLUTE_BLOCK: | ||||
|       case TAPE_SPACE_END_OF_DATA: | ||||
|       case TAPE_REWIND: | ||||
| 	lasterr = _tape_set_pos (get_handle (), mode, count); | ||||
| 	_tape_set_pos (mode, count); | ||||
| 	break; | ||||
|     } | ||||
|  | ||||
|   return tape_error (lasterr, "tape_set_pos"); | ||||
|   return tape_error ("tape_set_pos"); | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_tape::tape_erase (int mode) | ||||
| { | ||||
|   DWORD varlen; | ||||
|   TAPE_GET_DRIVE_PARAMETERS dp; | ||||
|  | ||||
|   while (((lasterr = GetTapeParameters (get_handle (), | ||||
| 					GET_TAPE_DRIVE_INFORMATION, | ||||
| 					(varlen = sizeof dp, &varlen), | ||||
| 					&dp)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (lasterr == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|  | ||||
|   switch (mode) | ||||
|     { | ||||
|       case TAPE_ERASE_SHORT: | ||||
| 	if (! lasterr && ! (dp.FeaturesLow & TAPE_DRIVE_ERASE_SHORT)) | ||||
| 	if (!tape_get_feature (TAPE_DRIVE_ERASE_SHORT)) | ||||
| 	  mode = TAPE_ERASE_LONG; | ||||
| 	break; | ||||
|       case TAPE_ERASE_LONG: | ||||
| 	if (! lasterr && ! (dp.FeaturesLow & TAPE_DRIVE_ERASE_LONG)) | ||||
| 	if (!tape_get_feature (TAPE_DRIVE_ERASE_LONG)) | ||||
| 	  mode = TAPE_ERASE_SHORT; | ||||
| 	break; | ||||
|     } | ||||
|  | ||||
|   return tape_error (EraseTape (get_handle (), mode, false), "tape_erase"); | ||||
|   TAPE_FUNC (EraseTape (get_handle (), mode, false)); | ||||
|   /* Reset buffer after successful tape erasing. */ | ||||
|   if (!lasterr) | ||||
|     reset_devbuf (); | ||||
|   return tape_error ("tape_erase"); | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_tape::tape_prepare (int action) | ||||
| { | ||||
|   while (((lasterr = PrepareTape (get_handle (), | ||||
| 				  action, | ||||
| 				  FALSE)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (lasterr == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|   return tape_error (lasterr, "tape_prepare"); | ||||
| } | ||||
|  | ||||
| bool | ||||
| fhandler_dev_tape::tape_get_feature (DWORD parm) | ||||
| { | ||||
|   DWORD varlen; | ||||
|   TAPE_GET_DRIVE_PARAMETERS dp; | ||||
|  | ||||
|   while (((lasterr = GetTapeParameters (get_handle (), | ||||
| 					GET_TAPE_DRIVE_INFORMATION, | ||||
| 					(varlen = sizeof dp, &varlen), | ||||
| 					&dp)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (lasterr == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|  | ||||
|   if (lasterr) | ||||
|     return false; | ||||
|  | ||||
|   return ((parm & TAPE_DRIVE_HIGH_FEATURES) | ||||
| 	  ? ((dp.FeaturesHigh & parm) != 0) | ||||
| 	  : ((dp.FeaturesLow & parm) != 0)); | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_tape::tape_get_blocksize (long *min, long *def, long *max, long *cur) | ||||
| { | ||||
|   DWORD varlen; | ||||
|   TAPE_GET_DRIVE_PARAMETERS dp; | ||||
|   TAPE_GET_MEDIA_PARAMETERS mp; | ||||
|  | ||||
|   while (((lasterr = GetTapeParameters (get_handle (), | ||||
| 					GET_TAPE_DRIVE_INFORMATION, | ||||
| 					(varlen = sizeof dp, &varlen), | ||||
| 					&dp)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (lasterr == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|  | ||||
|   if (lasterr) | ||||
|     return tape_error (lasterr, "tape_get_blocksize"); | ||||
|  | ||||
|   while (((lasterr = GetTapeParameters (get_handle (), | ||||
| 					GET_TAPE_MEDIA_INFORMATION, | ||||
| 					(varlen = sizeof dp, &varlen), | ||||
| 					&mp)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (lasterr == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|  | ||||
|   if (lasterr) | ||||
|     return tape_error (lasterr, "tape_get_blocksize"); | ||||
|  | ||||
|   if (min) | ||||
|     *min = (long) dp.MinimumBlockSize; | ||||
|   if (def) | ||||
|     *def = (long) dp.DefaultBlockSize; | ||||
|   if (max) | ||||
|     *max = (long) dp.MaximumBlockSize; | ||||
|   if (cur) | ||||
|     *cur = (long) mp.BlockSize; | ||||
|  | ||||
|   return tape_error (lasterr, "tape_get_blocksize"); | ||||
|   TAPE_FUNC (PrepareTape (get_handle (), action, FALSE)); | ||||
|   /* Reset buffer after all successful preparations but lock and unlock. */ | ||||
|   if (!lasterr && action != TAPE_LOCK && action != TAPE_UNLOCK) | ||||
|     reset_devbuf (); | ||||
|   return tape_error ("tape_prepare"); | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_tape::tape_set_blocksize (long count) | ||||
| { | ||||
|   long min, max; | ||||
|   TAPE_SET_MEDIA_PARAMETERS mp; | ||||
|  | ||||
|   lasterr = tape_get_blocksize (&min, NULL, &max, NULL); | ||||
|  | ||||
|   if (lasterr) | ||||
|     return lasterr; | ||||
|  | ||||
|   if (count != 0 && (count < min || count > max)) | ||||
|     return tape_error (ERROR_INVALID_PARAMETER, "tape_set_blocksize"); | ||||
|  | ||||
|   mp.BlockSize = count; | ||||
|  | ||||
|   return tape_error (SetTapeParameters (get_handle (), | ||||
| 					SET_TAPE_MEDIA_INFORMATION, | ||||
| 					&mp), | ||||
| 		     "tape_set_blocksize"); | ||||
| } | ||||
|  | ||||
| static long long | ||||
| get_ll (PLARGE_INTEGER i) | ||||
| { | ||||
|   long long l = 0; | ||||
|  | ||||
|   l = i->HighPart; | ||||
|   l <<= 32; | ||||
|   l |= i->LowPart; | ||||
|   return l; | ||||
|   TAPE_FUNC (SetTapeParameters (get_handle (), SET_TAPE_MEDIA_INFORMATION, | ||||
|   				&mp)); | ||||
|   return tape_error ("tape_set_blocksize"); | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_tape::tape_status (struct mtget *get) | ||||
| { | ||||
|   DWORD varlen; | ||||
|   TAPE_GET_DRIVE_PARAMETERS dp; | ||||
|   TAPE_GET_MEDIA_PARAMETERS mp; | ||||
|   int notape = 0; | ||||
|  | ||||
|   if (!get) | ||||
|     return ERROR_INVALID_PARAMETER; | ||||
|  | ||||
|   while (((lasterr = GetTapeParameters (get_handle (), | ||||
| 					GET_TAPE_DRIVE_INFORMATION, | ||||
| 					(varlen = sizeof dp, &varlen), | ||||
| 					&dp)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (lasterr == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|  | ||||
|   /* Setting varlen to sizeof DP is by intention, actually!  Never set | ||||
|      it to sizeof MP which seems to be more correct but results in a | ||||
|      ERROR_MORE_DATA error at least on W2K. */ | ||||
|   if ((lasterr) || (lasterr = GetTapeParameters (get_handle (), | ||||
| 						 GET_TAPE_MEDIA_INFORMATION, | ||||
| 						 (varlen = sizeof dp, &varlen), | ||||
| 						 &mp))) | ||||
|   TAPE_FUNC (GetTapeParameters (get_handle (), GET_TAPE_MEDIA_INFORMATION, | ||||
| 				(varlen = sizeof dp, &varlen), &mp)); | ||||
|   if (lasterr) | ||||
|     notape = 1; | ||||
|  | ||||
|   memset (get, 0, sizeof *get); | ||||
|  | ||||
|   get->mt_type = MT_ISUNKNOWN; | ||||
|  | ||||
|   if (! notape && (dp.FeaturesLow & TAPE_DRIVE_TAPE_REMAINING)) | ||||
|   if (!notape && tape_get_feature (TAPE_DRIVE_TAPE_REMAINING)) | ||||
|     { | ||||
|       get->mt_remaining = get_ll (&mp.Remaining); | ||||
|       get->mt_remaining = get_ll (mp.Remaining); | ||||
|       get->mt_resid = get->mt_remaining >> 10; | ||||
|     } | ||||
|  | ||||
|   if ((dp.FeaturesHigh & TAPE_DRIVE_SET_BLOCK_SIZE) && ! notape) | ||||
|   if (tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE) && !notape) | ||||
|     get->mt_dsreg = mp.BlockSize; | ||||
|   else | ||||
|     get->mt_dsreg = dp.DefaultBlockSize; | ||||
| @@ -758,7 +702,8 @@ fhandler_dev_tape::tape_status (struct mtget *get) | ||||
|  | ||||
|   if (!notape) | ||||
|     { | ||||
|       if (dp.FeaturesLow & TAPE_DRIVE_GET_ABSOLUTE_BLK) | ||||
|       if (tape_get_feature (TAPE_DRIVE_GET_ABSOLUTE_BLK) | ||||
| 	  || tape_get_feature (TAPE_DRIVE_GET_LOGICAL_BLK)) | ||||
| 	tape_get_pos ((unsigned long *) &get->mt_blkno); | ||||
|  | ||||
|       if (!get->mt_blkno) | ||||
| @@ -766,23 +711,23 @@ fhandler_dev_tape::tape_status (struct mtget *get) | ||||
|  | ||||
|       get->mt_gstat |= GMT_ONLINE (-1); | ||||
|  | ||||
|       if ((dp.FeaturesLow & TAPE_DRIVE_WRITE_PROTECT) && mp.WriteProtected) | ||||
|       if (tape_get_feature (TAPE_DRIVE_WRITE_PROTECT) && mp.WriteProtected) | ||||
| 	get->mt_gstat |= GMT_WR_PROT (-1); | ||||
|  | ||||
|       if (dp.FeaturesLow & TAPE_DRIVE_TAPE_CAPACITY) | ||||
| 	get->mt_capacity = get_ll (&mp.Capacity); | ||||
|       if (tape_get_feature (TAPE_DRIVE_TAPE_CAPACITY)) | ||||
| 	get->mt_capacity = get_ll (mp.Capacity); | ||||
|     } | ||||
|  | ||||
|   if ((dp.FeaturesLow & TAPE_DRIVE_COMPRESSION) && dp.Compression) | ||||
|   if (tape_get_feature (TAPE_DRIVE_COMPRESSION) && dp.Compression) | ||||
|     get->mt_gstat |= GMT_HW_COMP (-1); | ||||
|  | ||||
|   if ((dp.FeaturesLow & TAPE_DRIVE_ECC) && dp.ECC) | ||||
|   if (tape_get_feature (TAPE_DRIVE_ECC) && dp.ECC) | ||||
|     get->mt_gstat |= GMT_HW_ECC (-1); | ||||
|  | ||||
|   if ((dp.FeaturesLow & TAPE_DRIVE_PADDING) && dp.DataPadding) | ||||
|   if (tape_get_feature (TAPE_DRIVE_PADDING) && dp.DataPadding) | ||||
|     get->mt_gstat |= GMT_PADDING (-1); | ||||
|  | ||||
|   if ((dp.FeaturesLow & TAPE_DRIVE_REPORT_SMKS) && dp.ReportSetmarks) | ||||
|   if (tape_get_feature (TAPE_DRIVE_REPORT_SMKS) && dp.ReportSetmarks) | ||||
|     get->mt_gstat |= GMT_IM_REP_EN (-1); | ||||
|  | ||||
|   get->mt_erreg = lasterr; | ||||
| @@ -800,40 +745,20 @@ fhandler_dev_tape::tape_status (struct mtget *get) | ||||
| int | ||||
| fhandler_dev_tape::tape_compression (long count) | ||||
| { | ||||
|   DWORD varlen; | ||||
|   TAPE_GET_DRIVE_PARAMETERS dpg; | ||||
|   TAPE_SET_DRIVE_PARAMETERS dps; | ||||
|  | ||||
|   while (((lasterr = GetTapeParameters (get_handle (), | ||||
| 					GET_TAPE_DRIVE_INFORMATION, | ||||
| 					(varlen = sizeof dpg, &varlen), | ||||
| 					&dpg)) == ERROR_MEDIA_CHANGED) | ||||
| 	 || (lasterr == ERROR_BUS_RESET)) | ||||
|     ; | ||||
|  | ||||
|   if (lasterr) | ||||
|     return tape_error (lasterr, "tape_compression"); | ||||
|  | ||||
|   if (! (dpg.FeaturesLow & TAPE_DRIVE_COMPRESSION)) | ||||
|   if (!tape_get_feature (TAPE_DRIVE_COMPRESSION)) | ||||
|     return ERROR_INVALID_PARAMETER; | ||||
|  | ||||
|   if (count) | ||||
|     { | ||||
|       dps.ECC = dpg.ECC; | ||||
|   dps.ECC = dp.ECC; | ||||
|   dps.Compression = count ? TRUE : FALSE; | ||||
|       dps.DataPadding = dpg.DataPadding; | ||||
|       dps.ReportSetmarks = dpg.ReportSetmarks; | ||||
|       dps.EOTWarningZoneSize = dpg.EOTWarningZoneSize; | ||||
|       lasterr = SetTapeParameters (get_handle (), | ||||
| 				   SET_TAPE_DRIVE_INFORMATION, | ||||
| 				   &dps); | ||||
|  | ||||
|       if (lasterr) | ||||
| 	return tape_error (lasterr, "tape_compression"); | ||||
|  | ||||
|       dpg.Compression = dps.Compression; | ||||
|     } | ||||
|  | ||||
|   return 0; | ||||
|   dps.DataPadding = dp.DataPadding; | ||||
|   dps.ReportSetmarks = dp.ReportSetmarks; | ||||
|   dps.EOTWarningZoneSize = dp.EOTWarningZoneSize; | ||||
|   TAPE_FUNC (SetTapeParameters (get_handle (), SET_TAPE_DRIVE_INFORMATION, | ||||
| 				&dps)); | ||||
|   if (!lasterr) | ||||
|     dp.Compression = dps.Compression; | ||||
|   return tape_error ("tape_compression"); | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user