The MinGW.org Installation Manager Tool
Revision | 20b1d629e6b23539de8e55151f30e10b2238b803 (tree) |
---|---|
Zeit | 2013-09-10 19:00:20 |
Autor | Keith Marshall <keithmarshall@user...> |
Commiter | Keith Marshall |
Fix MinGW-Bug #2026.
@@ -1,3 +1,20 @@ | ||
1 | +2013-09-10 Keith Marshall <keithmarshall@users.sourceforge.net> | |
2 | + | |
3 | + Fix MinGW-Bug #2026. | |
4 | + | |
5 | + * src/dmhguix.cpp (DMH_PTY_GUARDBYTES): New manifest constant. | |
6 | + (dmhTypePTY::printf) [buffer full]: Use it; it defines a reserved byte | |
7 | + count, at end of buffer, where expansion or scroll out is triggered; | |
8 | + use memcpy() for scroll out, but avoid overlapping regions. | |
9 | + (dmhTypePTY::printf) [output == '\r']: Handle it. | |
10 | + | |
11 | + * src/tarproc.cpp (create_output_stream): Improve diagnostic messages; | |
12 | + discriminate between file collision and other privilege violations. | |
13 | + (pkgArchiveProcessor::ExtractFile): Don't return a zero status code, | |
14 | + when the output stream could not be successfully opened, so that... | |
15 | + (pkgTarArchiveInstaller::ProcessDataStream): ...we may avoid writing a | |
16 | + spurious manifest entry here. | |
17 | + | |
1 | 18 | 2013-09-06 Keith Marshall <keithmarshall@users.sourceforge.net> |
2 | 19 | |
3 | 20 | Update version, pre-empting subsequent release. |
@@ -40,6 +40,7 @@ | ||
40 | 40 | */ |
41 | 41 | #define DMH_PTY_MIN_BUFSIZ 4096 |
42 | 42 | #define DMH_PTY_MAX_BUFSIZ 32768 |
43 | +#define DMH_PTY_GUARDBYTES 1 | |
43 | 44 | |
44 | 45 | class dmhTypePTY |
45 | 46 | { |
@@ -142,10 +143,14 @@ int dmhTypePTY::printf( const char *fmt, va_list argv ) | ||
142 | 143 | { |
143 | 144 | /* An explicit '\r' in the data stream should return the |
144 | 145 | * caret to the start of the current PHYSICAL line in the |
145 | - * EDITTEXT display | |
146 | - * | |
147 | - * FIXME: must implement this; ignore, (and discount), it | |
148 | - * for now. | |
146 | + * EDITTEXT display. | |
147 | + */ | |
148 | + char *mark = caret; | |
149 | + while( (mark > console_buffer) && (*--mark != '\n') ) | |
150 | + caret = mark; | |
151 | + | |
152 | + /* The '\r' character isn't actually written to the | |
153 | + * output buffer; discount it. | |
149 | 154 | */ |
150 | 155 | --retval; |
151 | 156 | } |
@@ -187,10 +192,12 @@ int dmhTypePTY::putchar( int charval ) | ||
187 | 192 | { |
188 | 193 | /* Helper method for appending a single character to the PTY "device" |
189 | 194 | * buffer; this will allocate an expanding buffer, (up to the maximum |
190 | - * specified size limit), as may be required. | |
195 | + * specified size limit, with reservation of sufficient guard bytes to | |
196 | + * ensure that output may be safely terminated), as may be required. | |
191 | 197 | */ |
192 | 198 | size_t offset; |
193 | - if( (offset = caret - console_buffer) >= max ) | |
199 | + const size_t guarded_max = max - DMH_PTY_GUARDBYTES; | |
200 | + if( (offset = caret - console_buffer) >= guarded_max ) | |
194 | 201 | { |
195 | 202 | /* The current "device" buffer is full; compute a new size, for |
196 | 203 | * possible buffer expansion. |
@@ -215,7 +222,7 @@ int dmhTypePTY::putchar( int charval ) | ||
215 | 222 | caret = (console_buffer = newbuf) + offset; |
216 | 223 | } |
217 | 224 | } |
218 | - if( offset >= max ) | |
225 | + if( offset >= guarded_max ) | |
219 | 226 | { |
220 | 227 | /* The buffer has reached its maximum permitted size, (or there |
221 | 228 | * was insufficient free memory to expand it), and there still |
@@ -228,9 +235,34 @@ int dmhTypePTY::putchar( int charval ) | ||
228 | 235 | /* ...then copy it, and all following lines, to the start of the |
229 | 236 | * buffer, so deleting the FIRST logical line, and thus free up |
230 | 237 | * an equivalent amount of space at the end. |
238 | + * | |
239 | + * Note: we might get away with a single memcpy() of the entire | |
240 | + * portion of the buffer, from the SECOND line onward, backwards | |
241 | + * to overwrite the FIRST line, but that would entail copying of | |
242 | + * overlapping memory regions, which is technically described as | |
243 | + * causing undefined behaviour; to avoid any possible problems, | |
244 | + * we identify a block size equal to the space occupied by the | |
245 | + * first line... | |
231 | 246 | */ |
232 | - for( caret = console_buffer; mark < endptr; ) | |
233 | - *caret++ = *mark++; | |
247 | + size_t residual = caret - mark; | |
248 | + size_t block_size = mark - (caret = console_buffer); | |
249 | + while( residual >= block_size ) | |
250 | + { | |
251 | + /* ...then copy the residual, in chunks of that size, (so that | |
252 | + * there is never any overlap), until we reduce the residual to | |
253 | + * less than the block size... | |
254 | + */ | |
255 | + memcpy( caret, mark, block_size ); | |
256 | + residual -= block_size; caret = mark; mark += block_size; | |
257 | + } | |
258 | + if( residual > 0 ) | |
259 | + { | |
260 | + /* ...finishing up by copying any lesser sized final residual, | |
261 | + * and leaving the caret at the start of the space so freed. | |
262 | + */ | |
263 | + memcpy( caret, mark, residual ); | |
264 | + caret += residual; | |
265 | + } | |
234 | 266 | } |
235 | 267 | } |
236 | 268 | /* Finally, store the current character into the "device" buffer, and |
@@ -96,7 +96,24 @@ static int create_output_stream( const char *name, int mode ) | ||
96 | 96 | /* Overwrite prevention was triggered; diagnose. |
97 | 97 | */ |
98 | 98 | dmh_notify_extraction_failed( name ); |
99 | - dmh_notify( DMH_ERROR, "cannot replace existing file\n" ); | |
99 | + if( errno == EEXIST ) | |
100 | + { | |
101 | + /* The exception was triggered by an already existing file; | |
102 | + * this likely indicates a conflict between two packages. | |
103 | + */ | |
104 | + dmh_notify( DMH_ERROR, | |
105 | + "%s: probable package conflict; existing file not overwritten\n", | |
106 | + name | |
107 | + ); | |
108 | + } | |
109 | + else | |
110 | + { /* Otherwise, the user isn't allowed to write the extracted | |
111 | + * file, in the location designated for installation. | |
112 | + */ | |
113 | + dmh_notify( DMH_ERROR, | |
114 | + "%s: permission denied; cannot store file\n", name | |
115 | + ); | |
116 | + } | |
100 | 117 | } |
101 | 118 | return fd; |
102 | 119 | } |
@@ -146,9 +163,11 @@ int pkgArchiveProcessor::ExtractFile( int fd, const char *pathname, int status ) | ||
146 | 163 | } |
147 | 164 | } |
148 | 165 | } |
149 | - /* Finally, we pass the original status value back to the caller. | |
166 | + /* Finally, we pass either the original status value, or the | |
167 | + * failing file descriptor as an effective status, if no file | |
168 | + * could be extracted, back to the caller. | |
150 | 169 | */ |
151 | - return status; | |
170 | + return (fd == -1) ? fd : status; | |
152 | 171 | } |
153 | 172 | |
154 | 173 | /******************* |