Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright (c) 1999 |
michael@0 | 3 | * Silicon Graphics Computer Systems, Inc. |
michael@0 | 4 | * |
michael@0 | 5 | * Copyright (c) 1999 |
michael@0 | 6 | * Boris Fomitchev |
michael@0 | 7 | * |
michael@0 | 8 | * This material is provided "as is", with absolutely no warranty expressed |
michael@0 | 9 | * or implied. Any use is at your own risk. |
michael@0 | 10 | * |
michael@0 | 11 | * Permission to use or copy this software for any purpose is hereby granted |
michael@0 | 12 | * without fee, provided the above notices are retained on all copies. |
michael@0 | 13 | * Permission to modify the code and to distribute modified code is granted, |
michael@0 | 14 | * provided the above notices are retained, and a notice that the code was |
michael@0 | 15 | * modified is included with the above copyright notice. |
michael@0 | 16 | * |
michael@0 | 17 | */ |
michael@0 | 18 | |
michael@0 | 19 | #include <fstream> |
michael@0 | 20 | |
michael@0 | 21 | #if !defined (_STLP_WCE) |
michael@0 | 22 | # ifdef __BORLANDC__ |
michael@0 | 23 | # include <cfcntl.h> // For _O_RDONLY, etc |
michael@0 | 24 | # else |
michael@0 | 25 | # include <io.h> // For _get_osfhandle |
michael@0 | 26 | # include <fcntl.h> // For _O_RDONLY, etc |
michael@0 | 27 | # endif |
michael@0 | 28 | # include <sys/stat.h> // For _fstat |
michael@0 | 29 | #endif |
michael@0 | 30 | |
michael@0 | 31 | #define _TEXTBUF_SIZE 0x1000 |
michael@0 | 32 | |
michael@0 | 33 | const _STLP_fd INVALID_STLP_FD = INVALID_HANDLE_VALUE; |
michael@0 | 34 | |
michael@0 | 35 | #if !defined (INVALID_SET_FILE_POINTER) |
michael@0 | 36 | # define INVALID_SET_FILE_POINTER 0xffffffff |
michael@0 | 37 | #endif |
michael@0 | 38 | |
michael@0 | 39 | #ifndef O_ACCMODE |
michael@0 | 40 | # define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) |
michael@0 | 41 | #endif |
michael@0 | 42 | |
michael@0 | 43 | _STLP_BEGIN_NAMESPACE |
michael@0 | 44 | |
michael@0 | 45 | #if !defined(__MSL__) && !defined(_STLP_WCE) |
michael@0 | 46 | static ios_base::openmode flag_to_openmode(int mode) { |
michael@0 | 47 | ios_base::openmode ret = ios_base::__default_mode; |
michael@0 | 48 | |
michael@0 | 49 | switch (mode & O_ACCMODE) { |
michael@0 | 50 | case O_RDONLY: |
michael@0 | 51 | ret = ios_base::in; break; |
michael@0 | 52 | case O_WRONLY: |
michael@0 | 53 | ret = ios_base::out; break; |
michael@0 | 54 | case O_RDWR: |
michael@0 | 55 | ret = ios_base::in | ios_base::out; break; |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | if (mode & O_APPEND) |
michael@0 | 59 | ret |= ios_base::app; |
michael@0 | 60 | |
michael@0 | 61 | if (mode & O_BINARY) |
michael@0 | 62 | ret |= ios_base::binary; |
michael@0 | 63 | |
michael@0 | 64 | return ret; |
michael@0 | 65 | } |
michael@0 | 66 | #endif |
michael@0 | 67 | |
michael@0 | 68 | _STLP_MOVE_TO_PRIV_NAMESPACE |
michael@0 | 69 | |
michael@0 | 70 | // Helper functions for _Filebuf_base. |
michael@0 | 71 | |
michael@0 | 72 | static bool __is_regular_file(_STLP_fd fd) { |
michael@0 | 73 | BY_HANDLE_FILE_INFORMATION info; |
michael@0 | 74 | |
michael@0 | 75 | // Return true if the file handle isn't a directory. |
michael@0 | 76 | return GetFileInformationByHandle(fd, &info) && |
michael@0 | 77 | ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0); |
michael@0 | 78 | } |
michael@0 | 79 | |
michael@0 | 80 | // Number of characters in the file. |
michael@0 | 81 | static streamoff __file_size(_STLP_fd fd) { |
michael@0 | 82 | streamoff ret = 0; |
michael@0 | 83 | |
michael@0 | 84 | LARGE_INTEGER li; |
michael@0 | 85 | li.LowPart = GetFileSize(fd, (unsigned long*) &li.HighPart); |
michael@0 | 86 | if (li.LowPart != INVALID_FILE_SIZE || GetLastError() == NO_ERROR) |
michael@0 | 87 | ret = li.QuadPart; |
michael@0 | 88 | |
michael@0 | 89 | return ret; |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | _STLP_MOVE_TO_STD_NAMESPACE |
michael@0 | 93 | |
michael@0 | 94 | // Visual C++ and Intel use this, but not Metrowerks |
michael@0 | 95 | // Also MinGW, msvcrt.dll (but not crtdll.dll) dependent version |
michael@0 | 96 | #if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \ |
michael@0 | 97 | (defined (__MINGW32__) && defined (__MSVCRT__)) |
michael@0 | 98 | |
michael@0 | 99 | // fcntl(fileno, F_GETFL) for Microsoft library |
michael@0 | 100 | // 'semi-documented' defines: |
michael@0 | 101 | # define IOINFO_L2E 5 |
michael@0 | 102 | # define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) |
michael@0 | 103 | # define _pioinfo(i) ( __pioinfo[(i) >> IOINFO_L2E] + \ |
michael@0 | 104 | ((i) & (IOINFO_ARRAY_ELTS - 1)) ) |
michael@0 | 105 | # define FAPPEND 0x20 // O_APPEND flag |
michael@0 | 106 | # define FTEXT 0x80 // O_TEXT flag |
michael@0 | 107 | // end of 'semi-documented' defines |
michael@0 | 108 | |
michael@0 | 109 | // 'semi-documented' internal structure |
michael@0 | 110 | extern "C" { |
michael@0 | 111 | struct ioinfo { |
michael@0 | 112 | long osfhnd; // the real os HANDLE |
michael@0 | 113 | char osfile; // file handle flags |
michael@0 | 114 | char pipech; // pipe buffer |
michael@0 | 115 | # if defined (_MT) |
michael@0 | 116 | // multi-threaded locking |
michael@0 | 117 | int lockinitflag; |
michael@0 | 118 | CRITICAL_SECTION lock; |
michael@0 | 119 | # endif |
michael@0 | 120 | }; |
michael@0 | 121 | # if defined (__MINGW32__) |
michael@0 | 122 | __MINGW_IMPORT ioinfo * __pioinfo[]; |
michael@0 | 123 | # else |
michael@0 | 124 | extern _CRTIMP ioinfo * __pioinfo[]; |
michael@0 | 125 | # endif |
michael@0 | 126 | } // extern "C" |
michael@0 | 127 | // end of 'semi-documented' declarations |
michael@0 | 128 | |
michael@0 | 129 | static ios_base::openmode _get_osfflags(int fd, HANDLE oshandle) { |
michael@0 | 130 | char dosflags = 0; |
michael@0 | 131 | if (fd >= 0) |
michael@0 | 132 | dosflags = _pioinfo(fd)->osfile; |
michael@0 | 133 | //else |
michael@0 | 134 | //the file will be considered as open in binary mode with no append attribute |
michael@0 | 135 | // end of 'semi-documented' stuff |
michael@0 | 136 | |
michael@0 | 137 | int mode = 0; |
michael@0 | 138 | if (dosflags & FAPPEND) |
michael@0 | 139 | mode |= O_APPEND; |
michael@0 | 140 | |
michael@0 | 141 | if (dosflags & FTEXT) |
michael@0 | 142 | mode |= O_TEXT; |
michael@0 | 143 | else |
michael@0 | 144 | mode |= O_BINARY; |
michael@0 | 145 | |
michael@0 | 146 | // For Read/Write access we have to guess |
michael@0 | 147 | DWORD dummy, dummy2; |
michael@0 | 148 | BOOL writeOk = WriteFile(oshandle, &dummy2, 0, &dummy, 0); |
michael@0 | 149 | BOOL readOk = ReadFile(oshandle, &dummy2, 0, &dummy, NULL); |
michael@0 | 150 | if (writeOk && readOk) |
michael@0 | 151 | mode |= O_RDWR; |
michael@0 | 152 | else if (readOk) |
michael@0 | 153 | mode |= O_RDONLY; |
michael@0 | 154 | else |
michael@0 | 155 | mode |= O_WRONLY; |
michael@0 | 156 | |
michael@0 | 157 | return flag_to_openmode(mode); |
michael@0 | 158 | } |
michael@0 | 159 | |
michael@0 | 160 | #elif defined (__DMC__) |
michael@0 | 161 | |
michael@0 | 162 | # define FHND_APPEND 0x04 |
michael@0 | 163 | # define FHND_DEVICE 0x08 |
michael@0 | 164 | # define FHND_TEXT 0x10 |
michael@0 | 165 | |
michael@0 | 166 | extern "C" unsigned char __fhnd_info[_NFILE]; |
michael@0 | 167 | |
michael@0 | 168 | static ios_base::openmode _get_osfflags(int fd, HANDLE oshandle) { |
michael@0 | 169 | int mode = 0; |
michael@0 | 170 | |
michael@0 | 171 | if (__fhnd_info[fd] & FHND_APPEND) |
michael@0 | 172 | mode |= O_APPEND; |
michael@0 | 173 | |
michael@0 | 174 | if (__fhnd_info[fd] & FHND_TEXT == 0) |
michael@0 | 175 | mode |= O_BINARY; |
michael@0 | 176 | |
michael@0 | 177 | for (FILE *fp = &_iob[0]; fp < &_iob[_NFILE]; fp++) { |
michael@0 | 178 | if ((fileno(fp) == fd) && (fp->_flag & (_IOREAD | _IOWRT | _IORW))) { |
michael@0 | 179 | const int osflags = fp->_flag; |
michael@0 | 180 | |
michael@0 | 181 | if ((osflags & _IOREAD) && !(osflags & _IOWRT) && !(osflags & _IORW)) |
michael@0 | 182 | mode |= O_RDONLY; |
michael@0 | 183 | else if ((osflags & _IOWRT) && !(osflags & _IOREAD) && !(osflags & _IORW)) |
michael@0 | 184 | mode |= O_WRONLY; |
michael@0 | 185 | else |
michael@0 | 186 | mode |= O_RDWR; |
michael@0 | 187 | break; |
michael@0 | 188 | } |
michael@0 | 189 | } |
michael@0 | 190 | |
michael@0 | 191 | return flag_to_openmode(mode); |
michael@0 | 192 | } |
michael@0 | 193 | #endif |
michael@0 | 194 | |
michael@0 | 195 | size_t _Filebuf_base::_M_page_size = 4096; |
michael@0 | 196 | |
michael@0 | 197 | _Filebuf_base::_Filebuf_base() |
michael@0 | 198 | : _M_file_id(INVALID_STLP_FD), |
michael@0 | 199 | _M_openmode(0), |
michael@0 | 200 | _M_is_open(false), |
michael@0 | 201 | _M_should_close(false), |
michael@0 | 202 | _M_view_id(0) |
michael@0 | 203 | {} |
michael@0 | 204 | |
michael@0 | 205 | void _Filebuf_base::_S_initialize() { |
michael@0 | 206 | SYSTEM_INFO SystemInfo; |
michael@0 | 207 | GetSystemInfo(&SystemInfo); |
michael@0 | 208 | _M_page_size = SystemInfo.dwPageSize; |
michael@0 | 209 | // might be .dwAllocationGranularity |
michael@0 | 210 | } |
michael@0 | 211 | |
michael@0 | 212 | // Return the size of the file. This is a wrapper for stat. |
michael@0 | 213 | // Returns zero if the size cannot be determined or is ill-defined. |
michael@0 | 214 | streamoff _Filebuf_base::_M_file_size() { |
michael@0 | 215 | return _STLP_PRIV __file_size(_M_file_id); |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode, |
michael@0 | 219 | long permission) { |
michael@0 | 220 | _STLP_fd file_no; |
michael@0 | 221 | |
michael@0 | 222 | if (_M_is_open) |
michael@0 | 223 | return false; |
michael@0 | 224 | |
michael@0 | 225 | DWORD dwDesiredAccess, dwCreationDisposition; |
michael@0 | 226 | bool doTruncate = false; |
michael@0 | 227 | |
michael@0 | 228 | switch (openmode & (~ios_base::ate & ~ios_base::binary)) { |
michael@0 | 229 | case ios_base::out: |
michael@0 | 230 | case ios_base::out | ios_base::trunc: |
michael@0 | 231 | dwDesiredAccess = GENERIC_WRITE; |
michael@0 | 232 | dwCreationDisposition = OPEN_ALWAYS; |
michael@0 | 233 | // boris : even though it is very non-intuitive, standard |
michael@0 | 234 | // requires them both to behave same. |
michael@0 | 235 | doTruncate = true; |
michael@0 | 236 | break; |
michael@0 | 237 | case ios_base::out | ios_base::app: |
michael@0 | 238 | dwDesiredAccess = GENERIC_WRITE; |
michael@0 | 239 | dwCreationDisposition = OPEN_ALWAYS; |
michael@0 | 240 | break; |
michael@0 | 241 | case ios_base::in: |
michael@0 | 242 | dwDesiredAccess = GENERIC_READ; |
michael@0 | 243 | dwCreationDisposition = OPEN_EXISTING; |
michael@0 | 244 | permission = 0; // Irrelevant unless we're writing. |
michael@0 | 245 | break; |
michael@0 | 246 | case ios_base::in | ios_base::out: |
michael@0 | 247 | dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; |
michael@0 | 248 | dwCreationDisposition = OPEN_EXISTING; |
michael@0 | 249 | break; |
michael@0 | 250 | case ios_base::in | ios_base::out | ios_base::trunc: |
michael@0 | 251 | dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; |
michael@0 | 252 | dwCreationDisposition = OPEN_ALWAYS; |
michael@0 | 253 | doTruncate = true; |
michael@0 | 254 | break; |
michael@0 | 255 | default: // The above are the only combinations of |
michael@0 | 256 | return false; // flags allowed by the C++ standard. |
michael@0 | 257 | } |
michael@0 | 258 | |
michael@0 | 259 | DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; |
michael@0 | 260 | |
michael@0 | 261 | #if defined(_STLP_USE_WIDE_INTERFACE) |
michael@0 | 262 | file_no = CreateFile (_STLP_PRIV __ASCIIToWide(name).c_str(), |
michael@0 | 263 | #else |
michael@0 | 264 | file_no = CreateFileA(name, |
michael@0 | 265 | #endif |
michael@0 | 266 | dwDesiredAccess, dwShareMode, 0, |
michael@0 | 267 | dwCreationDisposition, permission, 0); |
michael@0 | 268 | |
michael@0 | 269 | if (file_no == INVALID_STLP_FD) |
michael@0 | 270 | return false; |
michael@0 | 271 | |
michael@0 | 272 | if ( |
michael@0 | 273 | #if !defined (_STLP_WCE) |
michael@0 | 274 | GetFileType(file_no) == FILE_TYPE_DISK && |
michael@0 | 275 | #endif |
michael@0 | 276 | ((doTruncate && SetEndOfFile(file_no) == 0) || |
michael@0 | 277 | (((openmode & ios_base::ate) != 0) && |
michael@0 | 278 | (SetFilePointer(file_no, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)))) { |
michael@0 | 279 | CloseHandle(file_no); |
michael@0 | 280 | return false; |
michael@0 | 281 | } |
michael@0 | 282 | |
michael@0 | 283 | _M_is_open = true; |
michael@0 | 284 | _M_file_id = file_no; |
michael@0 | 285 | _M_should_close = _M_is_open; |
michael@0 | 286 | _M_openmode = openmode; |
michael@0 | 287 | |
michael@0 | 288 | if (_M_is_open) |
michael@0 | 289 | _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); |
michael@0 | 290 | |
michael@0 | 291 | return (_M_is_open != 0); |
michael@0 | 292 | } |
michael@0 | 293 | |
michael@0 | 294 | bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode) { |
michael@0 | 295 | // This doesn't really grant everyone in the world read/write |
michael@0 | 296 | // access. On Unix, file-creation system calls always clear |
michael@0 | 297 | // bits that are set in the umask from the permissions flag. |
michael@0 | 298 | return this->_M_open(name, openmode, FILE_ATTRIBUTE_NORMAL); |
michael@0 | 299 | } |
michael@0 | 300 | |
michael@0 | 301 | bool _Filebuf_base::_M_open(_STLP_fd __id, ios_base::openmode init_mode) { |
michael@0 | 302 | #if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \ |
michael@0 | 303 | (defined (__MINGW32__) && defined (__MSVCRT__)) || defined (__DMC__) |
michael@0 | 304 | |
michael@0 | 305 | if (_M_is_open || __id == INVALID_STLP_FD) |
michael@0 | 306 | return false; |
michael@0 | 307 | |
michael@0 | 308 | if (init_mode != ios_base::__default_mode) |
michael@0 | 309 | _M_openmode = init_mode; |
michael@0 | 310 | else |
michael@0 | 311 | _M_openmode = _get_osfflags(-1, __id); |
michael@0 | 312 | |
michael@0 | 313 | _M_is_open = true; |
michael@0 | 314 | _M_file_id = __id; |
michael@0 | 315 | _M_should_close = false; |
michael@0 | 316 | _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); |
michael@0 | 317 | |
michael@0 | 318 | return true; |
michael@0 | 319 | #else |
michael@0 | 320 | (void)__id; |
michael@0 | 321 | (void)init_mode; // dwa 4/27/00 - suppress unused parameter warning |
michael@0 | 322 | |
michael@0 | 323 | // not available for the API |
michael@0 | 324 | return false; |
michael@0 | 325 | |
michael@0 | 326 | #endif |
michael@0 | 327 | } |
michael@0 | 328 | |
michael@0 | 329 | // Associated the filebuf with a file descriptor pointing to an already- |
michael@0 | 330 | // open file. Mode is set to be consistent with the way that the file |
michael@0 | 331 | // was opened. |
michael@0 | 332 | bool _Filebuf_base::_M_open(int file_no, ios_base::openmode init_mode) { |
michael@0 | 333 | if (_M_is_open || file_no < 0) |
michael@0 | 334 | return false; |
michael@0 | 335 | |
michael@0 | 336 | #if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \ |
michael@0 | 337 | (defined (__MINGW32__) && defined (__MSVCRT__)) || defined (__DMC__) |
michael@0 | 338 | |
michael@0 | 339 | HANDLE oshandle = (HANDLE)_get_osfhandle(file_no); |
michael@0 | 340 | if (oshandle == INVALID_STLP_FD) |
michael@0 | 341 | return false; |
michael@0 | 342 | |
michael@0 | 343 | if (init_mode != ios_base::__default_mode) |
michael@0 | 344 | _M_openmode = init_mode; |
michael@0 | 345 | else |
michael@0 | 346 | _M_openmode = _get_osfflags(file_no, oshandle); |
michael@0 | 347 | |
michael@0 | 348 | _M_file_id = oshandle; |
michael@0 | 349 | _M_is_open = true; |
michael@0 | 350 | _M_should_close = false; |
michael@0 | 351 | _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); |
michael@0 | 352 | return true; |
michael@0 | 353 | #else |
michael@0 | 354 | _STLP_MARK_PARAMETER_AS_UNUSED(&init_mode) |
michael@0 | 355 | // not available for the API |
michael@0 | 356 | return false; |
michael@0 | 357 | #endif |
michael@0 | 358 | } |
michael@0 | 359 | |
michael@0 | 360 | bool _Filebuf_base::_M_close() { |
michael@0 | 361 | if (!_M_is_open) |
michael@0 | 362 | return false; |
michael@0 | 363 | |
michael@0 | 364 | bool ok; |
michael@0 | 365 | |
michael@0 | 366 | if (!_M_should_close) |
michael@0 | 367 | ok = true; |
michael@0 | 368 | else { |
michael@0 | 369 | if (_M_file_id != INVALID_STLP_FD) { |
michael@0 | 370 | ok = (CloseHandle(_M_file_id) != 0); |
michael@0 | 371 | } |
michael@0 | 372 | else { |
michael@0 | 373 | ok = false; |
michael@0 | 374 | } |
michael@0 | 375 | } |
michael@0 | 376 | |
michael@0 | 377 | _M_is_open = _M_should_close = false; |
michael@0 | 378 | _M_openmode = 0; |
michael@0 | 379 | return ok; |
michael@0 | 380 | } |
michael@0 | 381 | |
michael@0 | 382 | |
michael@0 | 383 | #define _STLP_LF 10 |
michael@0 | 384 | #define _STLP_CR 13 |
michael@0 | 385 | #define _STLP_CTRLZ 26 |
michael@0 | 386 | |
michael@0 | 387 | // Read up to n characters into a buffer. Return value is number of |
michael@0 | 388 | // characters read. |
michael@0 | 389 | ptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n) { |
michael@0 | 390 | ptrdiff_t readen = 0; |
michael@0 | 391 | //Here cast to size_t is safe as n cannot be negative. |
michael@0 | 392 | size_t chunkSize = (min)(size_t(0xffffffff), __STATIC_CAST(size_t, n)); |
michael@0 | 393 | // The following, while validating that we are still able to extract chunkSize |
michael@0 | 394 | // charaters to the buffer, avoids extraction of too small chunk of datas |
michael@0 | 395 | // which would be counter performant. |
michael@0 | 396 | while (__STATIC_CAST(size_t, (n - readen)) >= chunkSize) { |
michael@0 | 397 | DWORD numberOfBytesRead; |
michael@0 | 398 | ReadFile(_M_file_id, buf + readen, __STATIC_CAST(DWORD, chunkSize), &numberOfBytesRead, 0); |
michael@0 | 399 | |
michael@0 | 400 | if (numberOfBytesRead == 0) |
michael@0 | 401 | break; |
michael@0 | 402 | |
michael@0 | 403 | if (!(_M_openmode & ios_base::binary)) { |
michael@0 | 404 | // translate CR-LFs to LFs in the buffer |
michael@0 | 405 | char *to = buf + readen; |
michael@0 | 406 | char *from = to; |
michael@0 | 407 | char *last = from + numberOfBytesRead - 1; |
michael@0 | 408 | for (; from <= last && *from != _STLP_CTRLZ; ++from) { |
michael@0 | 409 | if (*from != _STLP_CR) |
michael@0 | 410 | *to++ = *from; |
michael@0 | 411 | else { // found CR |
michael@0 | 412 | if (from < last) { // not at buffer end |
michael@0 | 413 | if (*(from + 1) != _STLP_LF) |
michael@0 | 414 | *to++ = _STLP_CR; |
michael@0 | 415 | } |
michael@0 | 416 | else { // last char is CR, peek for LF |
michael@0 | 417 | char peek = ' '; |
michael@0 | 418 | DWORD NumberOfBytesPeeked; |
michael@0 | 419 | ReadFile(_M_file_id, (LPVOID)&peek, 1, &NumberOfBytesPeeked, 0); |
michael@0 | 420 | if (NumberOfBytesPeeked != 0) { |
michael@0 | 421 | if (peek != _STLP_LF) { //not a <CR><LF> combination |
michael@0 | 422 | *to++ = _STLP_CR; |
michael@0 | 423 | if ((to < buf + n) && (peek != _STLP_CR)) |
michael@0 | 424 | //We have enough place to store peek and it is no a special |
michael@0 | 425 | //_STLP_CR character, we can store it. |
michael@0 | 426 | *to++ = peek; |
michael@0 | 427 | else |
michael@0 | 428 | SetFilePointer(_M_file_id, (LONG)-1, 0, FILE_CURRENT); |
michael@0 | 429 | } |
michael@0 | 430 | else { |
michael@0 | 431 | // A <CR><LF> combination, we keep the <LF>: |
michael@0 | 432 | *to++ = _STLP_LF; |
michael@0 | 433 | } |
michael@0 | 434 | } |
michael@0 | 435 | else { |
michael@0 | 436 | /* This case is tedious, we could |
michael@0 | 437 | * - put peek back in the file but this would then generate an infinite loop |
michael@0 | 438 | * - report an error as we don't know if in a future call to ReadFile we won't then |
michael@0 | 439 | * get a <LF>. Doing so would make all files with a <CR> last an invalid file |
michael@0 | 440 | * for STLport, a hard solution for STLport clients. |
michael@0 | 441 | * - store the <CR> in the returned buffer, the chosen solution, even if in this |
michael@0 | 442 | * case we could miss a <CR><LF> combination. |
michael@0 | 443 | */ |
michael@0 | 444 | *to++ = _STLP_CR; |
michael@0 | 445 | } |
michael@0 | 446 | } |
michael@0 | 447 | } // found CR |
michael@0 | 448 | } // for |
michael@0 | 449 | readen = to - buf; |
michael@0 | 450 | // seek back to TEXT end of file if hit CTRL-Z |
michael@0 | 451 | if (from <= last) { // terminated due to CTRLZ |
michael@0 | 452 | SetFilePointer(_M_file_id, -(LONG)((last + 1) - from), 0, FILE_CURRENT); |
michael@0 | 453 | break; |
michael@0 | 454 | } |
michael@0 | 455 | } |
michael@0 | 456 | else |
michael@0 | 457 | readen += numberOfBytesRead; |
michael@0 | 458 | } |
michael@0 | 459 | return readen; |
michael@0 | 460 | } |
michael@0 | 461 | |
michael@0 | 462 | // Write n characters from a buffer. Return value: true if we managed |
michael@0 | 463 | // to write the entire buffer, false if we didn't. |
michael@0 | 464 | bool _Filebuf_base::_M_write(char* buf, ptrdiff_t n) { |
michael@0 | 465 | for (;;) { |
michael@0 | 466 | ptrdiff_t written; |
michael@0 | 467 | |
michael@0 | 468 | //In the following implementation we are going to cast most of the ptrdiff_t |
michael@0 | 469 | //values in size_t to work with coherent unsigned values. Doing so make code |
michael@0 | 470 | //more simple especially in the min function call. |
michael@0 | 471 | |
michael@0 | 472 | // In append mode, every write does an implicit seek to the end |
michael@0 | 473 | // of the file. |
michael@0 | 474 | if (_M_openmode & ios_base::app) |
michael@0 | 475 | _M_seek(0, ios_base::end); |
michael@0 | 476 | |
michael@0 | 477 | if (_M_openmode & ios_base::binary) { |
michael@0 | 478 | // binary mode |
michael@0 | 479 | size_t bytes_to_write = (size_t)n; |
michael@0 | 480 | DWORD NumberOfBytesWritten; |
michael@0 | 481 | written = 0; |
michael@0 | 482 | for (; bytes_to_write != 0;) { |
michael@0 | 483 | WriteFile(_M_file_id, buf + written, |
michael@0 | 484 | __STATIC_CAST(DWORD, (min)(size_t(0xffffffff), bytes_to_write)), |
michael@0 | 485 | &NumberOfBytesWritten, 0); |
michael@0 | 486 | if (NumberOfBytesWritten == 0) |
michael@0 | 487 | return false; |
michael@0 | 488 | bytes_to_write -= NumberOfBytesWritten; |
michael@0 | 489 | written += NumberOfBytesWritten; |
michael@0 | 490 | } |
michael@0 | 491 | } |
michael@0 | 492 | else { |
michael@0 | 493 | char textbuf[_TEXTBUF_SIZE + 1]; // extra 1 in case LF at end |
michael@0 | 494 | char * nextblock = buf, * ptrtextbuf = textbuf; |
michael@0 | 495 | char * endtextbuf = textbuf + _TEXTBUF_SIZE; |
michael@0 | 496 | char * endblock = buf + n; |
michael@0 | 497 | ptrdiff_t nextblocksize = (min) (n, (ptrdiff_t)_TEXTBUF_SIZE); |
michael@0 | 498 | char * nextlf; |
michael@0 | 499 | |
michael@0 | 500 | while ( (nextblocksize > 0) && |
michael@0 | 501 | (nextlf = (char *)memchr(nextblock, _STLP_LF, nextblocksize)) != 0) { |
michael@0 | 502 | ptrdiff_t linelength = nextlf - nextblock; |
michael@0 | 503 | memcpy(ptrtextbuf, nextblock, linelength); |
michael@0 | 504 | ptrtextbuf += linelength; |
michael@0 | 505 | nextblock += (linelength + 1); |
michael@0 | 506 | * ptrtextbuf ++ = _STLP_CR; |
michael@0 | 507 | * ptrtextbuf ++ = _STLP_LF; |
michael@0 | 508 | nextblocksize = (min) (ptrdiff_t(endblock - nextblock), |
michael@0 | 509 | (max) (ptrdiff_t(0), ptrdiff_t(endtextbuf - ptrtextbuf))); |
michael@0 | 510 | } |
michael@0 | 511 | // write out what's left, > condition is here since for LF at the end , |
michael@0 | 512 | // endtextbuf may get < ptrtextbuf ... |
michael@0 | 513 | if (nextblocksize > 0) { |
michael@0 | 514 | memcpy(ptrtextbuf, nextblock, nextblocksize); |
michael@0 | 515 | ptrtextbuf += nextblocksize; |
michael@0 | 516 | nextblock += nextblocksize; |
michael@0 | 517 | } |
michael@0 | 518 | // now write out the translated buffer |
michael@0 | 519 | char * writetextbuf = textbuf; |
michael@0 | 520 | for (size_t NumberOfBytesToWrite = (size_t)(ptrtextbuf - textbuf); |
michael@0 | 521 | NumberOfBytesToWrite;) { |
michael@0 | 522 | DWORD NumberOfBytesWritten; |
michael@0 | 523 | WriteFile((HANDLE)_M_file_id, writetextbuf, |
michael@0 | 524 | __STATIC_CAST(DWORD, (min)(size_t(0xffffffff), NumberOfBytesToWrite)), |
michael@0 | 525 | &NumberOfBytesWritten, 0); |
michael@0 | 526 | if (!NumberOfBytesWritten) // write shortfall |
michael@0 | 527 | return false; |
michael@0 | 528 | writetextbuf += NumberOfBytesWritten; |
michael@0 | 529 | NumberOfBytesToWrite -= NumberOfBytesWritten; |
michael@0 | 530 | } |
michael@0 | 531 | // count non-translated characters |
michael@0 | 532 | written = (nextblock - buf); |
michael@0 | 533 | } |
michael@0 | 534 | |
michael@0 | 535 | if (n == written) |
michael@0 | 536 | return true; |
michael@0 | 537 | else if (written > 0 && written < n) { |
michael@0 | 538 | n -= written; |
michael@0 | 539 | buf += written; |
michael@0 | 540 | } |
michael@0 | 541 | else |
michael@0 | 542 | return false; |
michael@0 | 543 | } |
michael@0 | 544 | } |
michael@0 | 545 | |
michael@0 | 546 | // Wrapper for lseek or the like. |
michael@0 | 547 | streamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir) { |
michael@0 | 548 | streamoff result = -1; |
michael@0 | 549 | int whence; |
michael@0 | 550 | |
michael@0 | 551 | switch(dir) { |
michael@0 | 552 | case ios_base::beg: |
michael@0 | 553 | if (offset < 0 /* || offset > _M_file_size() */ ) |
michael@0 | 554 | return streamoff(-1); |
michael@0 | 555 | whence = FILE_BEGIN; |
michael@0 | 556 | break; |
michael@0 | 557 | case ios_base::cur: |
michael@0 | 558 | whence = FILE_CURRENT; |
michael@0 | 559 | break; |
michael@0 | 560 | case ios_base::end: |
michael@0 | 561 | if (/* offset > 0 || */ -offset > _M_file_size() ) |
michael@0 | 562 | return streamoff(-1); |
michael@0 | 563 | whence = FILE_END; |
michael@0 | 564 | break; |
michael@0 | 565 | default: |
michael@0 | 566 | return streamoff(-1); |
michael@0 | 567 | } |
michael@0 | 568 | |
michael@0 | 569 | LARGE_INTEGER li; |
michael@0 | 570 | li.QuadPart = offset; |
michael@0 | 571 | li.LowPart = SetFilePointer(_M_file_id, li.LowPart, &li.HighPart, whence); |
michael@0 | 572 | if (li.LowPart != INVALID_SET_FILE_POINTER || GetLastError() == NO_ERROR) |
michael@0 | 573 | result = li.QuadPart; |
michael@0 | 574 | |
michael@0 | 575 | return result; |
michael@0 | 576 | } |
michael@0 | 577 | |
michael@0 | 578 | |
michael@0 | 579 | // Attempts to memory-map len bytes of the current file, starting |
michael@0 | 580 | // at position offset. Precondition: offset is a multiple of the |
michael@0 | 581 | // page size. Postcondition: return value is a null pointer if the |
michael@0 | 582 | // memory mapping failed. Otherwise the return value is a pointer to |
michael@0 | 583 | // the memory-mapped file and the file position is set to offset. |
michael@0 | 584 | void* _Filebuf_base::_M_mmap(streamoff offset, streamoff len) { |
michael@0 | 585 | void* base; |
michael@0 | 586 | _M_view_id = CreateFileMapping(_M_file_id, (PSECURITY_ATTRIBUTES)0 , |
michael@0 | 587 | PAGE_READONLY, 0 /* len >> 32 */ , |
michael@0 | 588 | 0 /* len & 0xFFFFFFFF */ , // low-order DWORD of size |
michael@0 | 589 | 0); |
michael@0 | 590 | |
michael@0 | 591 | if (_M_view_id) { |
michael@0 | 592 | #if 0 |
michael@0 | 593 | /* |
michael@0 | 594 | printf("view %x created from file %x, error = %d, size = %d, map_offset = %d map_len = %d\n", |
michael@0 | 595 | _M_view_id, _M_file_id, GetLastError(), |
michael@0 | 596 | (int)cur_filesize, ULL(offset) & 0xffffffff, len); |
michael@0 | 597 | */ |
michael@0 | 598 | #endif |
michael@0 | 599 | LARGE_INTEGER li; |
michael@0 | 600 | li.QuadPart = offset; |
michael@0 | 601 | base = MapViewOfFile(_M_view_id, FILE_MAP_READ, li.HighPart, li.LowPart, |
michael@0 | 602 | #if !defined (__DMC__) |
michael@0 | 603 | __STATIC_CAST(SIZE_T, len)); |
michael@0 | 604 | #else |
michael@0 | 605 | __STATIC_CAST(DWORD, len)); |
michael@0 | 606 | #endif |
michael@0 | 607 | // check if mapping succeded and is usable |
michael@0 | 608 | if (base == 0 || _M_seek(offset + len, ios_base::beg) < 0) { |
michael@0 | 609 | this->_M_unmap(base, len); |
michael@0 | 610 | base = 0; |
michael@0 | 611 | } |
michael@0 | 612 | } else |
michael@0 | 613 | base = 0; |
michael@0 | 614 | |
michael@0 | 615 | return base; |
michael@0 | 616 | } |
michael@0 | 617 | |
michael@0 | 618 | void _Filebuf_base::_M_unmap(void* base, streamoff len) { |
michael@0 | 619 | // precondition : there is a valid mapping at the moment |
michael@0 | 620 | if (base != NULL) |
michael@0 | 621 | UnmapViewOfFile(base); |
michael@0 | 622 | // destroy view handle as well |
michael@0 | 623 | if (_M_view_id != NULL) |
michael@0 | 624 | CloseHandle(_M_view_id); |
michael@0 | 625 | _M_view_id = NULL; |
michael@0 | 626 | (void)len; //unused variable |
michael@0 | 627 | } |
michael@0 | 628 | |
michael@0 | 629 | _STLP_END_NAMESPACE |