Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Changes to support non-ASCII characters in win95 filenames. Ticket #2047. (CVS 3495) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9fa3ae584ae4936696fd2f23a64697f0 |
User & Date: | drh 2006-10-30 13:37:22.000 |
Context
2006-10-31
| ||
18:08 | Make the command-line shell ".dump" command more resilient in the face of database corruption. (CVS 3496) (check-in: ebd44f0b5e user: drh tags: trunk) | |
2006-10-30
| ||
13:37 | Changes to support non-ASCII characters in win95 filenames. Ticket #2047. (CVS 3495) (check-in: 9fa3ae584a user: drh tags: trunk) | |
2006-10-28
| ||
00:28 | Enhance the optimizer so that IS NULL can use an available index. (CVS 3494) (check-in: 64762a9d58 user: drh tags: trunk) | |
Changes
Changes to src/os_win.c.
︙ | ︙ | |||
127 128 129 130 131 132 133 | ** Convert a UTF-8 string to UTF-32. Space to hold the returned string ** is obtained from sqliteMalloc. */ static WCHAR *utf8ToUnicode(const char *zFilename){ int nChar; WCHAR *zWideFilename; | < < < | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | ** Convert a UTF-8 string to UTF-32. Space to hold the returned string ** is obtained from sqliteMalloc. */ static WCHAR *utf8ToUnicode(const char *zFilename){ int nChar; WCHAR *zWideFilename; nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); zWideFilename = sqliteMalloc( nChar*sizeof(zWideFilename[0]) ); if( zWideFilename==0 ){ return 0; } nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); if( nChar==0 ){ |
︙ | ︙ | |||
164 165 166 167 168 169 170 171 172 173 174 175 176 177 | 0, 0); if( nByte == 0 ){ sqliteFree(zFilename); zFilename = 0; } return zFilename; } #if OS_WINCE /************************************************************************* ** This section contains code for WinCE only. */ /* ** WindowsCE does not have a localtime() function. So create a | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | 0, 0); if( nByte == 0 ){ sqliteFree(zFilename); zFilename = 0; } return zFilename; } /* ** Convert a multibyte character string to UTF-32, based on the current ** Ansi codepage (CP_ACP). Space to hold the returned string is obtained ** from sqliteMalloc. */ static WCHAR *mbcsToUnicode(const char *zFilename){ int nByte; WCHAR *zMbcsFilename; nByte = MultiByteToWideChar(CP_ACP, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR); zMbcsFilename = sqliteMalloc( nByte*sizeof(zMbcsFilename[0]) ); if( zMbcsFilename==0 ){ return 0; } nByte = MultiByteToWideChar(CP_ACP, 0, zFilename, -1, zMbcsFilename, nByte); if( nByte==0 ){ sqliteFree(zMbcsFilename); zMbcsFilename = 0; } return zMbcsFilename; } /* ** Convert UTF-32 to multibyte character string, based on the user's Ansi ** codepage (CP_ACP). Space to hold the returned string is obtained from ** sqliteMalloc(). */ static char *unicodeToMbcs(const WCHAR *zWideFilename){ int nByte; char *zFilename; nByte = WideCharToMultiByte(CP_ACP, 0, zWideFilename, -1, 0, 0, 0, 0); zFilename = sqliteMalloc( nByte ); if( zFilename==0 ){ return 0; } nByte = WideCharToMultiByte(CP_ACP, 0, zWideFilename, -1, zFilename, nByte, 0, 0); if( nByte == 0 ){ sqliteFree(zFilename); zFilename = 0; } return zFilename; } /* ** Convert multibyte character string to UTF-8. Space to hold the ** returned string is obtained from sqliteMalloc(). */ static char *mbcsToUtf8(const char *zFilename){ char *zFilenameUtf8; WCHAR *zTmpWide; zTmpWide = mbcsToUnicode(zFilename); if( zTmpWide==0 ){ return 0; } zFilenameUtf8 = unicodeToUtf8(zTmpWide); sqliteFree(zTmpWide); return zFilenameUtf8; } /* ** Convert UTF-8 to multibyte character string. Space to hold the ** returned string is obtained from sqliteMalloc(). */ static char *utf8ToMbcs(const char *zFilename){ char *zFilenameMbcs; WCHAR *zTmpWide; zTmpWide = utf8ToUnicode(zFilename); if( zTmpWide==0 ){ return 0; } zFilenameMbcs = unicodeToMbcs(zTmpWide); sqliteFree(zTmpWide); return zFilenameMbcs; } #if OS_WINCE /************************************************************************* ** This section contains code for WinCE only. */ /* ** WindowsCE does not have a localtime() function. So create a |
︙ | ︙ | |||
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 | } return FALSE; } /* ** End of the special code for wince *****************************************************************************/ #endif /* OS_WINCE */ /* ** Delete the named file. ** ** Note that windows does not allow a file to be deleted if some other ** process has it open. Sometimes a virus scanner or indexing program ** will open a journal file shortly after it is created in order to do ** whatever it is it does. While this other process is holding the ** file open, we will be unable to delete it. To work around this ** problem, we delay 100 milliseconds and try to delete again. Up ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving ** up and returning an error. */ #define MX_DELETION_ATTEMPTS 3 int sqlite3WinDelete(const char *zFilename){ | > > > > > > > > > > > > > > > > > < > > > > | | | < | | > | > > > | | < | > | 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 | } return FALSE; } /* ** End of the special code for wince *****************************************************************************/ #endif /* OS_WINCE */ /* ** Convert a UTF-8 filename into whatever form the underlying ** operating system wants filenames in. Space to hold the result ** is obtained from sqliteMalloc and must be freed by the calling ** function. */ static void *convertUtf8Filename(const char *zFilename){ void *zConverted = 0; if( isNT() ){ zConverted = utf8ToUnicode(zFilename); }else{ zConverted = utf8ToMbcs(zFilename); } /* caller will handle out of memory */ return zConverted; } /* ** Delete the named file. ** ** Note that windows does not allow a file to be deleted if some other ** process has it open. Sometimes a virus scanner or indexing program ** will open a journal file shortly after it is created in order to do ** whatever it is it does. While this other process is holding the ** file open, we will be unable to delete it. To work around this ** problem, we delay 100 milliseconds and try to delete again. Up ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving ** up and returning an error. */ #define MX_DELETION_ATTEMPTS 3 int sqlite3WinDelete(const char *zFilename){ int cnt = 0; int rc; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } if( isNT() ){ do{ rc = DeleteFileW(zConverted); }while( rc==0 && GetFileAttributesW(zConverted)!=0xffffffff && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); }else{ #if OS_WINCE return SQLITE_NOMEM; #else do{ rc = DeleteFileA(zConverted); }while( rc==0 && GetFileAttributesA(zConverted)!=0xffffffff && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); #endif } sqliteFree(zConverted); TRACE2("DELETE \"%s\"\n", zFilename); return rc!=0 ? SQLITE_OK : SQLITE_IOERR; } /* ** Return TRUE if the named file exists. */ int sqlite3WinFileExists(const char *zFilename){ int exists = 0; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } if( isNT() ){ exists = GetFileAttributesW((WCHAR*)zConverted) != 0xffffffff; }else{ #if OS_WINCE return SQLITE_NOMEM; #else exists = GetFileAttributesA((char*)zConverted) != 0xffffffff; #endif } sqliteFree(zConverted); return exists; } /* Forward declaration */ static int allocateWinFile(winFile *pInit, OsFile **pId); /* |
︙ | ︙ | |||
550 551 552 553 554 555 556 | int sqlite3WinOpenReadWrite( const char *zFilename, OsFile **pId, int *pReadonly ){ winFile f; HANDLE h; | | > > > | > | | | | < | | > > > > | 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 | int sqlite3WinOpenReadWrite( const char *zFilename, OsFile **pId, int *pReadonly ){ winFile f; HANDLE h; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } assert( *pId==0 ); if( isNT() ){ h = CreateFileW((WCHAR*)zConverted, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ h = CreateFileW((WCHAR*)zConverted, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ sqliteFree(zConverted); return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } #if OS_WINCE if (!winceCreateLock(zFilename, &f)){ CloseHandle(h); sqliteFree(zConverted); return SQLITE_CANTOPEN; } #endif }else{ #if OS_WINCE return SQLITE_NOMEM; #else h = CreateFileA((char*)zConverted, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ h = CreateFileA((char*)zConverted, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ sqliteFree(zConverted); return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } #endif /* OS_WINCE */ } sqliteFree(zConverted); f.h = h; #if OS_WINCE f.zDeleteOnClose = 0; #endif TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); return allocateWinFile(&f, pId); } |
︙ | ︙ | |||
649 650 651 652 653 654 655 | ** a second open after the first one fails. The whole operation only ** fails if both open attempts are unsuccessful. */ int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ winFile f; HANDLE h; int fileflags; | | > > > | | < | > | 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 | ** a second open after the first one fails. The whole operation only ** fails if both open attempts are unsuccessful. */ int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ winFile f; HANDLE h; int fileflags; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } assert( *pId == 0 ); fileflags = FILE_FLAG_RANDOM_ACCESS; #if !OS_WINCE if( delFlag ){ fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE; } #endif if( isNT() ){ int cnt = 0; do{ h = CreateFileW((WCHAR*)zConverted, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) ); }else{ #if OS_WINCE return SQLITE_NOMEM; #else int cnt = 0; do{ h = CreateFileA((char*)zConverted, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) ); #endif /* OS_WINCE */ } sqliteFree(zConverted); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } f.h = h; #if OS_WINCE f.zDeleteOnClose = delFlag ? utf8ToUnicode(zFilename) : 0; f.hMutex = NULL; |
︙ | ︙ | |||
709 710 711 712 713 714 715 | ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){ winFile f; HANDLE h; | | > > > | | < | > | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 | ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){ winFile f; HANDLE h; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } assert( *pId==0 ); if( isNT() ){ h = CreateFileW((WCHAR*)zConverted, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); }else{ #if OS_WINCE return SQLITE_NOMEM; #else h = CreateFileA((char*)zConverted, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); #endif } sqliteFree(zConverted); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } f.h = h; #if OS_WINCE f.zDeleteOnClose = 0; f.hMutex = NULL; |
︙ | ︙ | |||
800 801 802 803 804 805 806 807 808 | WCHAR zWidePath[SQLITE_TEMPNAME_SIZE]; GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath); zMulti = unicodeToUtf8(zWidePath); if( zMulti ){ strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30); zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; sqliteFree(zMulti); } }else{ | > > > > | > > > > > > > > | 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 | WCHAR zWidePath[SQLITE_TEMPNAME_SIZE]; GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath); zMulti = unicodeToUtf8(zWidePath); if( zMulti ){ strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30); zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; sqliteFree(zMulti); }else{ return SQLITE_NOMEM; } }else{ char *zUtf8; char zMbcsPath[SQLITE_TEMPNAME_SIZE]; GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zMbcsPath); zUtf8 = mbcsToUtf8(zMbcsPath); if( zUtf8 ){ strncpy(zTempPath, zUtf8, SQLITE_TEMPNAME_SIZE-30); zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; sqliteFree(zUtf8); }else{ return SQLITE_NOMEM; } } for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} zTempPath[i] = 0; for(;;){ sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath); j = strlen(zBuf); sqlite3Randomness(15, &zBuf[j]); |
︙ | ︙ | |||
1020 1021 1022 1023 1024 1025 1026 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS /* ** Check that a given pathname is a directory and is writable ** */ int sqlite3WinIsDirWritable(char *zDirname){ int fileAttr; | | | > > > > | | < | > | 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS /* ** Check that a given pathname is a directory and is writable ** */ int sqlite3WinIsDirWritable(char *zDirname){ int fileAttr; void *zConverted; if( zDirname==0 ) return 0; if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0; zConverted = convertUtf8Filename(zDirname); if( zConverted==0 ){ return SQLITE_NOMEM; } if( isNT() ){ fileAttr = GetFileAttributesW((WCHAR*)zConverted); }else{ #if OS_WINCE return 0; #else fileAttr = GetFileAttributesA((char*)zConverted); #endif } sqliteFree(zConverted); if( fileAttr == 0xffffffff ) return 0; if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){ return 0; } return 1; } #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ |
︙ | ︙ | |||
1256 1257 1258 1259 1260 1261 1262 | zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; #elif OS_WINCE /* WinCE has no concept of a relative pathname, or so I am told. */ zFull = sqliteStrDup(zRelative); #else | < < > | | | | > > > | | > | | > > | > | > > > | 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 | zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; #elif OS_WINCE /* WinCE has no concept of a relative pathname, or so I am told. */ zFull = sqliteStrDup(zRelative); #else int nByte; void *zConverted; zConverted = convertUtf8Filename(zRelative); if( isNT() ){ WCHAR *zTemp, *zNotUsedW; nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, &zNotUsedW) + 1; zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ sqliteFree(zConverted); return 0; } GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, &zNotUsedW); sqliteFree(zConverted); zFull = unicodeToUtf8(zTemp); sqliteFree(zTemp); }else{ char *zTemp, *zNotUsed; nByte = GetFullPathNameA((char*)zConverted, 0, 0, &zNotUsed) + 1; zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ sqliteFree(zConverted); return 0; } GetFullPathNameA((char*)zConverted, nByte, zTemp, &zNotUsed); sqliteFree(zConverted); zFull = mbcsToUtf8(zTemp); sqliteFree(zTemp); } #endif return zFull; } /* ** The fullSync option is meaningless on windows. This is a no-op. |
︙ | ︙ |