OSDN Git Service

Fix MinGW-Bug #2026.
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Tue, 10 Sep 2013 10:00:20 +0000 (11:00 +0100)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Tue, 10 Sep 2013 10:00:20 +0000 (11:00 +0100)
ChangeLog
src/dmhguix.cpp
src/tarproc.cpp

index f010bbd..ba9730f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2013-09-10  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
+       Fix MinGW-Bug #2026.
+
+       * src/dmhguix.cpp (DMH_PTY_GUARDBYTES): New manifest constant.
+       (dmhTypePTY::printf) [buffer full]: Use it; it defines a reserved byte
+       count, at end of buffer, where expansion or scroll out is triggered;
+       use memcpy() for scroll out, but avoid overlapping regions.
+       (dmhTypePTY::printf) [output == '\r']: Handle it.
+
+       * src/tarproc.cpp (create_output_stream): Improve diagnostic messages;
+       discriminate between file collision and other privilege violations.
+       (pkgArchiveProcessor::ExtractFile): Don't return a zero status code,
+       when the output stream could not be successfully opened, so that...
+       (pkgTarArchiveInstaller::ProcessDataStream): ...we may avoid writing a
+       spurious manifest entry here.
+
 2013-09-06  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
        Update version, pre-empting subsequent release.
index e163376..70a5e2f 100644 (file)
@@ -40,6 +40,7 @@
  */
 #define DMH_PTY_MIN_BUFSIZ   4096
 #define DMH_PTY_MAX_BUFSIZ  32768
+#define DMH_PTY_GUARDBYTES      1
 
 class dmhTypePTY
 {
@@ -142,10 +143,14 @@ int dmhTypePTY::printf( const char *fmt, va_list argv )
     {
       /* An explicit '\r' in the data stream should return the
        * caret to the start of the current PHYSICAL line in the
-       * EDITTEXT display
-       *
-       * FIXME: must implement this; ignore, (and discount), it
-       * for now.
+       * EDITTEXT display.
+       */
+      char *mark = caret;
+      while( (mark > console_buffer) && (*--mark != '\n') )
+       caret = mark;
+
+      /* The '\r' character isn't actually written to the
+       * output buffer; discount it.
        */
       --retval;
     }
@@ -187,10 +192,12 @@ int dmhTypePTY::putchar( int charval )
 {
   /* Helper method for appending a single character to the PTY "device"
    * buffer; this will allocate an expanding buffer, (up to the maximum
-   * specified size limit), as may be required.
+   * specified size limit, with reservation of sufficient guard bytes to
+   * ensure that output may be safely terminated), as may be required.
    */
   size_t offset;
-  if( (offset = caret - console_buffer) >= max )
+  const size_t guarded_max = max - DMH_PTY_GUARDBYTES;
+  if( (offset = caret - console_buffer) >= guarded_max )
   {
     /* The current "device" buffer is full; compute a new size, for
      * possible buffer expansion.
@@ -215,7 +222,7 @@ int dmhTypePTY::putchar( int charval )
        caret = (console_buffer = newbuf) + offset;
       }
     }
-    if( offset >= max )
+    if( offset >= guarded_max )
     {
       /* The buffer has reached its maximum permitted size, (or there
        * was insufficient free memory to expand it), and there still
@@ -228,9 +235,34 @@ int dmhTypePTY::putchar( int charval )
       /* ...then copy it, and all following lines, to the start of the
        * buffer, so deleting the FIRST logical line, and thus free up
        * an equivalent amount of space at the end.
+       *
+       * Note: we might get away with a single memcpy() of the entire
+       * portion of the buffer, from the SECOND line onward, backwards
+       * to overwrite the FIRST line, but that would entail copying of
+       * overlapping memory regions, which is technically described as
+       * causing undefined behaviour; to avoid any possible problems,
+       * we identify a block size equal to the space occupied by the
+       * first line...
        */
-      for( caret = console_buffer; mark < endptr; )
-       *caret++ = *mark++;
+      size_t residual = caret - mark;
+      size_t block_size = mark - (caret = console_buffer);
+      while( residual >= block_size )
+      {
+       /* ...then copy the residual, in chunks of that size, (so that
+        * there is never any overlap), until we reduce the residual to
+        * less than the block size...
+        */
+       memcpy( caret, mark, block_size );
+       residual -= block_size; caret = mark; mark += block_size;
+      }
+      if( residual > 0 )
+      {
+       /* ...finishing up by copying any lesser sized final residual,
+        * and leaving the caret at the start of the space so freed.
+        */
+       memcpy( caret, mark, residual );
+       caret += residual;
+      }
     }
   }
   /* Finally, store the current character into the "device" buffer, and
index a31a117..dd40d3a 100644 (file)
@@ -96,7 +96,24 @@ static int create_output_stream( const char *name, int mode )
     /* Overwrite prevention was triggered; diagnose.
      */
     dmh_notify_extraction_failed( name );
-    dmh_notify( DMH_ERROR, "cannot replace existing file\n" );
+    if( errno == EEXIST )
+    {
+      /* The exception was triggered by an already existing file;
+       * this likely indicates a conflict between two packages.
+       */
+      dmh_notify( DMH_ERROR,
+         "%s: probable package conflict; existing file not overwritten\n",
+         name
+               );
+    }
+    else
+    { /* Otherwise, the user isn't allowed to write the extracted
+       * file, in the location designated for installation.
+       */
+      dmh_notify( DMH_ERROR,
+         "%s: permission denied; cannot store file\n", name
+       );
+    }
   }
   return fd;
 }
@@ -146,9 +163,11 @@ int pkgArchiveProcessor::ExtractFile( int fd, const char *pathname, int status )
       }
     }
   }
-  /* Finally, we pass the original status value back to the caller.
+  /* Finally, we pass either the original status value, or the
+   * failing file descriptor as an effective status, if no file
+   * could be extracted, back to the caller.
    */
-  return status;
+  return (fd == -1) ? fd : status;
 }
 
 /*******************