Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch ttmrichter-skins Excluding Merge-Ins
This is equivalent to a diff from 861a885c74 to 1a6876db8d
2010-11-07
| ||
10:23 | Merge from trunk. Leaf check-in: 1a6876db8d user: michael tags: ttmrichter-skins | |
2010-11-06
| ||
23:59 | Add an undocumented --noverify option to the rebuild command to skip the verify_before_commit() sanity check. check-in: 6a11af1782 user: drh tags: trunk | |
2010-10-08
| ||
17:08 | EDITED www/server.wiki fixed formating and created ticket (I don't see the ticket in commit) check-in: 3f49a84995 user: navratil tags: ttmrichter-skins | |
2010-09-16
| ||
14:00 | Committing a merge. check-in: be5fd10aaf user: michael tags: ttmrichter-skins | |
2010-08-13
| ||
07:07 | Trying to figure out how to get merge conflicts to actually show up. check-in: d8f8932ff2 user: michael tags: ttmrichter-skins | |
03:49 | Merged with trunk. Leaf check-in: 861a885c74 user: michael tags: ttmrichter | |
03:30 | Added build for FreeBSD using clang. check-in: b775af5045 user: michael tags: ttmrichter | |
2010-08-12
| ||
19:39 | Reimplement the reconstruct command that was removed in the GPL to BSD license change. This resolves ticket [dfe1fc608a]. check-in: 3332895df8 user: bcsmith tags: trunk | |
Changes to Makefile.
14 14 # intended to direct the compilation below. 15 15 # 16 16 -include config.mk # Configure if present. 17 17 ifndef CONFIG_MK_COMPLETE 18 18 include $(MAKEDIR)/linux-gcc-config.mk # Default to linux-gcc. 19 19 endif 20 20 21 -#### The Tcl shell to run for test suites. 21 +#### C Compile and options for use in building executables that 22 +# will run on the target platform. This is usually the same 23 +# as BCC, unless you are cross-compiling. This C compiler builds 24 +# the finished binary for fossil. The BCC compiler above is used 25 +# for building intermediate code-generator tools. 26 +# 27 +#TCC = gcc -O6 28 +#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage 29 +TCC = gcc -g -Os -Wall 30 + 31 +# To add support for HTTPS 32 +TCC += -DFOSSIL_ENABLE_SSL 33 + 34 +#### Extra arguments for linking the finished binary. Fossil needs 35 +# to link against the Z-Lib compression library. There are no 36 +# other dependencies. We sometimes add the -static option here 37 +# so that we can build a static executable that will run in a 38 +# chroot jail. 39 +# 40 +LIB = -lz $(LDFLAGS) 41 + 42 +# If using HTTPS: 43 +LIB += -lcrypto -lssl 44 + 45 +#### Tcl shell for use in running the fossil testsuite. 22 46 # 23 47 TCLSH = tclsh 24 48 25 49 # You should not need to change anything below this line 26 50 ############################################################################### 51 +# 52 +# Automatic platform-specific options. 53 +HOST_OS!= uname -s 54 + 55 +LIB.SunOS= -lsocket -lnsl 56 +LIB += $(LIB.$(HOST_OS)) 57 + 58 +TCC.DragonFly += -DUSE_PREAD 59 +TCC.FreeBSD += -DUSE_PREAD 60 +TCC.NetBSD += -DUSE_PREAD 61 +TCC.OpenBSD += -DUSE_PREAD 62 +TCC += $(TCC.$(HOST_OS)) 63 + 27 64 include $(SRCDIR)/main.mk 28 65
Added skins/default1/footer.html.
1 +<div class="footer"> 2 +Fossil version $manifest_version $manifest_date 3 +</div> 4 +</body></html>
Added skins/default1/header.html.
1 +<html> 2 +<head> 3 +<title>$<project_name>: $<title></title> 4 +<link rel="alternate" type="application/rss+xml" title="RSS Feed" 5 + href="$baseurl/timeline.rss"> 6 +<link rel="stylesheet" href="$baseurl/style.css?blackwhite" type="text/css" 7 + media="screen"> 8 +</head> 9 +<body> 10 +<div class="header"> 11 + <div class="logo"> 12 + <img src="$baseurl/logo" alt="logo"> 13 + </div> 14 + <div class="title"><small>$<project_name></small><br>$<title></div> 15 + <div class="status"><nobr><th1> 16 + if {[info exists login]} { 17 + puts "Logged in as $login" 18 + } else { 19 + puts "Not logged in" 20 + } 21 + </th1></nobr></div> 22 +</div> 23 +<div class="mainmenu"><th1> 24 +html "<a href=''$baseurl$index_page''>Home</a> " 25 +if {[anycap jor]} { 26 + html "<a href=''$baseurl/timeline''>Timeline</a> " 27 +} 28 +if {[hascap oh]} { 29 + html "<a href=''$baseurl/dir?ci=tip''>Files</a> " 30 +} 31 +if {[hascap o]} { 32 + html "<a href=''$baseurl/leaves''>Leaves</a> " 33 + html "<a href=''$baseurl/brlist''>Branches</a> " 34 + html "<a href=''$baseurl/taglist''>Tags</a> " 35 +} 36 +if {[hascap r]} { 37 + html "<a href=''$baseurl/reportlist''>Tickets</a> " 38 +} 39 +if {[hascap j]} { 40 + html "<a href=''$baseurl/wiki''>Wiki</a> " 41 +} 42 +if {[hascap s]} { 43 + html "<a href=''$baseurl/setup''>Admin</a> " 44 +} elseif {[hascap a]} { 45 + html "<a href=''$baseurl/setup_ulist''>Users</a> " 46 +} 47 +if {[info exists login]} { 48 + html "<a href=''$baseurl/login''>Logout</a> " 49 +} else { 50 + html "<a href=''$baseurl/login''>Login</a> " 51 +} 52 +</th1></div>
Added skins/default1/info.txt.
1 +Title: Plain Gray 2 +Description: A black-and-white theme with the project title in a bar across the 3 + top and no logo image. 4 +Author: Unknown. 5 +
Added skins/default1/style.css.
1 +/* General settings for the entire page */ 2 +body { 3 + margin: 0ex 1ex; 4 + padding: 0px; 5 + background-color: white; 6 + font-family: sans-serif; 7 +} 8 + 9 +/* The project logo in the upper left-hand corner of each page */ 10 +div.logo { 11 + display: table-row; 12 + text-align: center; 13 + /* vertical-align: bottom;*/ 14 + font-size: 2em; 15 + font-weight: bold; 16 + background-color: #707070; 17 + color: #ffffff; 18 + min-width: 200px; 19 +} 20 + 21 +/* The page title centered at the top of each page */ 22 +div.title { 23 + display: table-cell; 24 + font-size: 1.5em; 25 + font-weight: bold; 26 + text-align: center; 27 + padding: 0 0 0 10px; 28 + color: #404040; 29 + vertical-align: bottom; 30 + width: 100%; 31 +} 32 + 33 +/* The login status message in the top right-hand corner */ 34 +div.status { 35 + display: table-cell; 36 + text-align: right; 37 + vertical-align: bottom; 38 + color: #404040; 39 + font-size: 0.8em; 40 + font-weight: bold; 41 + min-width: 200px; 42 +} 43 + 44 +/* The header across the top of the page */ 45 +div.header { 46 + display: table; 47 + width: 100%; 48 +} 49 + 50 +/* The main menu bar that appears at the top of the page beneath the header */ 51 +div.mainmenu { 52 + padding: 5px 10px 5px 10px; 53 + font-size: 0.9em; 54 + font-weight: bold; 55 + text-align: center; 56 + letter-spacing: 1px; 57 + background-color: #404040; 58 + color: white; 59 +} 60 + 61 +/* The submenu bar that *sometimes* appears below the main menu */ 62 +div.submenu { 63 + padding: 3px 10px 3px 0px; 64 + font-size: 0.9em; 65 + text-align: center; 66 + background-color: #606060; 67 + color: white; 68 +} 69 +div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited { 70 + padding: 3px 10px 3px 10px; 71 + color: white; 72 + text-decoration: none; 73 +} 74 +div.mainmenu a:hover, div.submenu a:hover { 75 + color: #404040; 76 + background-color: white; 77 +} 78 + 79 +/* All page content from the bottom of the menu or submenu down to the footer */ 80 +div.content { 81 + padding: 0ex 0ex 0ex 0ex; 82 +} 83 +/* Hyperlink colors */ 84 +div.content a { color: #604000; } 85 +div.content a:link { color: #604000;} 86 +div.content a:visited { color: #600000; } 87 + 88 +/* Some pages have section dividers */ 89 +div.section { 90 + margin-bottom: 0px; 91 + margin-top: 1em; 92 + padding: 1px 1px 1px 1px; 93 + font-size: 1.2em; 94 + font-weight: bold; 95 + background-color: #404040; 96 + color: white; 97 +} 98 + 99 +/* The "Date" that occurs on the left hand side of timelines */ 100 +div.divider { 101 + background: #a0a0a0; 102 + border: 2px #505050 solid; 103 + font-size: 1em; font-weight: normal; 104 + padding: .25em; 105 + margin: .2em 0 .2em 0; 106 + float: left; 107 + clear: left; 108 +} 109 + 110 +/* The footer at the very bottom of the page */ 111 +div.footer { 112 + font-size: 0.8em; 113 + margin-top: 12px; 114 + padding: 5px 10px 5px 10px; 115 + text-align: right; 116 + background-color: #404040; 117 + color: white; 118 +} 119 + 120 +/* The label/value pairs on (for example) the vinfo page */ 121 +table.label-value th { 122 + vertical-align: top; 123 + text-align: right; 124 + padding: 0.2ex 2ex; 125 +}
Added skins/default2/footer.html.
1 +<div class="footer"> 2 +Fossil version $manifest_version $manifest_date 3 +</div> 4 +</body></html>
Added skins/default2/header.html.
1 +<html> 2 +<head> 3 +<title>$<project_name>: $<title></title> 4 +<link rel="alternate" type="application/rss+xml" title="RSS Feed" 5 + href="$baseurl/timeline.rss"> 6 +<link rel="stylesheet" href="$baseurl/style.css?tan" type="text/css" 7 + media="screen"> 8 +</head> 9 +<body> 10 +<div class="header"> 11 + <div class="title">$<title></div> 12 + <div class="status"> 13 + <div class="logo"><nobr>$<project_name></nobr></div><br/> 14 + <nobr><th1> 15 + if {[info exists login]} { 16 + puts "Logged in as $login" 17 + } else { 18 + puts "Not logged in" 19 + } 20 + </th1></nobr></div> 21 +</div> 22 +<div class="mainmenu"><th1> 23 +html "<a href=''$baseurl$index_page''>Home</a> " 24 +if {[anycap jor]} { 25 + html "<a href=''$baseurl/timeline''>Timeline</a> " 26 +} 27 +if {[hascap oh]} { 28 + html "<a href=''$baseurl/dir?ci=tip''>Files</a> " 29 +} 30 +if {[hascap o]} { 31 + html "<a href=''$baseurl/leaves''>Leaves</a> " 32 + html "<a href=''$baseurl/brlist''>Branches</a> " 33 + html "<a href=''$baseurl/taglist''>Tags</a> " 34 +} 35 +if {[hascap r]} { 36 + html "<a href=''$baseurl/reportlist''>Tickets</a> " 37 +} 38 +if {[hascap j]} { 39 + html "<a href=''$baseurl/wiki''>Wiki</a> " 40 +} 41 +if {[hascap s]} { 42 + html "<a href=''$baseurl/setup''>Admin</a> " 43 +} elseif {[hascap a]} { 44 + html "<a href=''$baseurl/setup_ulist''>Users</a> " 45 +} 46 +if {[info exists login]} { 47 + html "<a href=''$baseurl/login''>Logout</a> " 48 +} else { 49 + html "<a href=''$baseurl/login''>Login</a> " 50 +} 51 +</th1></div>
Added skins/default2/info.txt.
1 +Title: Khaki, No Logo 2 +Description: A tan theme with the project title above the user identification 3 + and no logo image. 4 +Author: Unknown
Added skins/default2/style.css.
1 +/* General settings for the entire page */ 2 +body { 3 + margin: 0ex 0ex; 4 + padding: 0px; 5 + background-color: #fef3bc; 6 + font-family: sans-serif; 7 +} 8 + 9 +/* The project logo in the upper left-hand corner of each page */ 10 +div.logo { 11 + display: inline; 12 + text-align: center; 13 + vertical-align: bottom; 14 + font-weight: bold; 15 + font-size: 2.5em; 16 + color: #a09048; 17 +} 18 + 19 +/* The page title centered at the top of each page */ 20 +div.title { 21 + display: table-cell; 22 + font-size: 2em; 23 + font-weight: bold; 24 + text-align: left; 25 + padding: 0 0 0 5px; 26 + color: #a09048; 27 + vertical-align: bottom; 28 + width: 100%; 29 +} 30 + 31 +/* The login status message in the top right-hand corner */ 32 +div.status { 33 + display: table-cell; 34 + text-align: right; 35 + vertical-align: bottom; 36 + color: #a09048; 37 + padding: 5px 5px 0 0; 38 + font-size: 0.8em; 39 + font-weight: bold; 40 +} 41 + 42 +/* The header across the top of the page */ 43 +div.header { 44 + display: table; 45 + width: 100%; 46 +} 47 + 48 +/* The main menu bar that appears at the top of the page beneath 49 +** the header */ 50 +div.mainmenu { 51 + padding: 5px 10px 5px 10px; 52 + font-size: 0.9em; 53 + font-weight: bold; 54 + text-align: center; 55 + letter-spacing: 1px; 56 + background-color: #a09048; 57 + color: black; 58 +} 59 + 60 +/* The submenu bar that *sometimes* appears below the main menu */ 61 +div.submenu { 62 + padding: 3px 10px 3px 0px; 63 + font-size: 0.9em; 64 + text-align: center; 65 + background-color: #c0af58; 66 + color: white; 67 +} 68 +div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited { 69 + padding: 3px 10px 3px 10px; 70 + color: white; 71 + text-decoration: none; 72 +} 73 +div.mainmenu a:hover, div.submenu a:hover { 74 + color: #a09048; 75 + background-color: white; 76 +} 77 + 78 +/* All page content from the bottom of the menu or submenu down to 79 +** the footer */ 80 +div.content { 81 + padding: 1ex 5px; 82 +} 83 +div.content a { color: #706532; } 84 +div.content a:link { color: #706532; } 85 +div.content a:visited { color: #704032; } 86 +div.content a:hover { background-color: white; color: #706532; } 87 + 88 +/* Some pages have section dividers */ 89 +div.section { 90 + margin-bottom: 0px; 91 + margin-top: 1em; 92 + padding: 3px 3px 0 3px; 93 + font-size: 1.2em; 94 + font-weight: bold; 95 + background-color: #a09048; 96 + color: white; 97 +} 98 + 99 +/* The "Date" that occurs on the left hand side of timelines */ 100 +div.divider { 101 + background: #e1d498; 102 + border: 2px #a09048 solid; 103 + font-size: 1em; font-weight: normal; 104 + padding: .25em; 105 + margin: .2em 0 .2em 0; 106 + float: left; 107 + clear: left; 108 +} 109 + 110 +/* The footer at the very bottom of the page */ 111 +div.footer { 112 + font-size: 0.8em; 113 + margin-top: 12px; 114 + padding: 5px 10px 5px 10px; 115 + text-align: right; 116 + background-color: #a09048; 117 + color: white; 118 +} 119 + 120 +/* Hyperlink colors */ 121 +div.footer a { color: white; } 122 +div.footer a:link { color: white; } 123 +div.footer a:visited { color: white; } 124 +div.footer a:hover { background-color: white; color: #558195; } 125 + 126 +/* <verbatim> blocks */ 127 +pre.verbatim { 128 + background-color: #f5f5f5; 129 + padding: 0.5em; 130 +} 131 + 132 +/* The label/value pairs on (for example) the ci page */ 133 +table.label-value th { 134 + vertical-align: top; 135 + text-align: right; 136 + padding: 0.2ex 2ex; 137 +}
Added skins/default3/footer.html.
1 +</div> 2 +<div class="footer"> 3 +Fossil version $manifest_version $manifest_date 4 +</div> 5 +</body></html>
Added skins/default3/header.html.
1 +<html> 2 +<head> 3 +<title>$<project_name>: $<title></title> 4 +<link rel="alternate" type="application/rss+xml" title="RSS Feed" 5 + href="$baseurl/timeline.rss"> 6 +<link rel="stylesheet" href="$baseurl/style.css?black2" type="text/css" 7 + media="screen"> 8 +</head> 9 +<body> 10 +<div class="header"> 11 + <div class="logo"> 12 + <!-- <img src="$baseurl/logo" alt="logo"> --> 13 + <br><nobr>$<project_name></nobr> 14 + </div> 15 + <div class="title">$<title></div> 16 + <div class="status"><nobr><th1> 17 + if {[info exists login]} { 18 + puts "Logged in as $login" 19 + } else { 20 + puts "Not logged in" 21 + } 22 + </th1></nobr></div> 23 +</div> 24 +<div class="mainmenu"><ul><th1> 25 +html "<li><a href=''$baseurl$index_page''>Home</a></li>" 26 +if {[anycap jor]} { 27 + html "<li><a href=''$baseurl/timeline''>Timeline</a></li>" 28 +} 29 +if {[hascap oh]} { 30 + html "<li><a href=''$baseurl/dir?ci=tip''>Files</a></li>" 31 +} 32 +if {[hascap o]} { 33 + html "<li><a href=''$baseurl/leaves''>Leaves</a></li>" 34 + html "<li><a href=''$baseurl/brlist''>Branches</a></li>" 35 + html "<li><a href=''$baseurl/taglist''>Tags</a></li>" 36 +} 37 +if {[hascap r]} { 38 + html "<li><a href=''$baseurl/reportlist''>Tickets</a></li>" 39 +} 40 +if {[hascap j]} { 41 + html "<li><a href=''$baseurl/wiki''>Wiki</a></li>" 42 +} 43 +if {[hascap s]} { 44 + html "<li><a href=''$baseurl/setup''>Admin</a></li>" 45 +} elseif {[hascap a]} { 46 + html "<li><a href=''$baseurl/setup_ulist''>Users</a></li>" 47 +} 48 +if {[info exists login]} { 49 + html "<li><a href=''$baseurl/login''>Logout</a></li>" 50 +} else { 51 + html "<li><a href=''$baseurl/login''>Login</a></li>" 52 +} 53 +</th1></ul></div> 54 +<div id="container">
Added skins/default3/info.txt.
1 +Title: Black & White, Menu on Left, No Logo 2 +Description: Black letters on a white or cream background with the main menu 3 + stuck on the left-hand side. 4 +Author: Unknown 5 +
Added skins/default3/style.css.
1 +/* General settings for the entire page */ 2 +body { 3 + margin:0px 0px 0px 0px; 4 + padding:0px; 5 + font-family:verdana, arial, helvetica, "sans serif"; 6 + color:#333; 7 + background-color:white; 8 +} 9 + 10 +/* consistent colours */ 11 +h2 { 12 + color: #333; 13 +} 14 +h3 { 15 + color: #333; 16 +} 17 + 18 +/* The project logo in the upper left-hand corner of each page */ 19 +div.logo { 20 + display: table-cell; 21 + text-align: left; 22 + vertical-align: bottom; 23 + font-weight: bold; 24 + color: #333; 25 +} 26 + 27 +/* The page title centered at the top of each page */ 28 +div.title { 29 + display: table-cell; 30 + font-size: 2em; 31 + font-weight: bold; 32 + text-align: center; 33 + color: #333; 34 + vertical-align: bottom; 35 + width: 100%; 36 +} 37 + 38 +/* The login status message in the top right-hand corner */ 39 +div.status { 40 + display: table-cell; 41 + padding-right: 10px; 42 + text-align: right; 43 + vertical-align: bottom; 44 + padding-bottom: 5px; 45 + color: #333; 46 + font-size: 0.8em; 47 + font-weight: bold; 48 +} 49 + 50 +/* The header across the top of the page */ 51 +div.header { 52 + margin:10px 0px 10px 0px; 53 + padding:1px 0px 0px 20px; 54 + border-style:solid; 55 + border-color:black; 56 + border-width:1px 0px; 57 + background-color:#eee; 58 +} 59 + 60 +/* The main menu bar that appears at the top left of the page beneath 61 +** the header. Width must be co-ordinated with the container below */ 62 +div.mainmenu { 63 + float: left; 64 + margin-left: 10px; 65 + margin-right: 10px; 66 + font-size: 0.9em; 67 + font-weight: bold; 68 + padding:5px; 69 + background-color:#eee; 70 + border:1px solid #999; 71 + width:8em; 72 +} 73 + 74 +/* Main menu is now a list */ 75 +div.mainmenu ul { 76 + padding: 0; 77 + list-style:none; 78 +} 79 +div.mainmenu a, div.mainmenu a:visited{ 80 + padding: 1px 10px 1px 10px; 81 + color: #333; 82 + text-decoration: none; 83 +} 84 +div.mainmenu a:hover { 85 + color: #eee; 86 + background-color: #333; 87 +} 88 + 89 +/* Container for the sub-menu and content so they don''t spread 90 +** out underneath the main menu */ 91 +#container { 92 + padding-left: 9em; 93 +} 94 + 95 +/* The submenu bar that *sometimes* appears below the main menu */ 96 +div.submenu { 97 + padding: 3px 10px 3px 10px; 98 + font-size: 0.9em; 99 + text-align: center; 100 + border:1px solid #999; 101 + border-width:1px 0px; 102 + background-color: #eee; 103 + color: #333; 104 +} 105 +div.submenu a, div.submenu a:visited { 106 + padding: 3px 10px 3px 10px; 107 + color: #333; 108 + text-decoration: none; 109 +} 110 +div.submenu a:hover { 111 + color: #eee; 112 + background-color: #333; 113 +} 114 + 115 +/* All page content from the bottom of the menu or submenu down to 116 +** the footer */ 117 +div.content { 118 + float: right; 119 + padding: 2ex 1ex 0ex 2ex; 120 +} 121 + 122 +/* Some pages have section dividers */ 123 +div.section { 124 + margin-bottom: 0px; 125 + margin-top: 1em; 126 + padding: 1px 1px 1px 1px; 127 + font-size: 1.2em; 128 + font-weight: bold; 129 + border-style:solid; 130 + border-color:#999; 131 + border-width:1px 0px; 132 + background-color: #eee; 133 + color: #333; 134 +} 135 + 136 +/* The "Date" that occurs on the left hand side of timelines */ 137 +div.divider { 138 + background: #eee; 139 + border: 2px #999 solid; 140 + font-size: 1em; font-weight: normal; 141 + padding: .25em; 142 + margin: .2em 0 .2em 0; 143 + float: left; 144 + clear: left; 145 + color: #333 146 +} 147 + 148 +/* The footer at the very bottom of the page */ 149 +div.footer { 150 + font-size: 0.8em; 151 + margin-top: 12px; 152 + padding: 5px 10px 5px 10px; 153 + text-align: right; 154 + background-color: #eee; 155 + color: #555; 156 +} 157 + 158 +/* <verbatim> blocks */ 159 +pre.verbatim { 160 + background-color: #f5f5f5; 161 + padding: 0.5em; 162 +} 163 + 164 +/* The label/value pairs on (for example) the ci page */ 165 +table.label-value th { 166 + vertical-align: top; 167 + text-align: right; 168 + padding: 0.2ex 2ex; 169 +} 170 +
Changes to src/add.c.
34 34 */ 35 35 static void add_one_file(const char *zName, int vid, Blob *pOmit){ 36 36 Blob pathname; 37 37 const char *zPath; 38 38 39 39 file_tree_name(zName, &pathname, 1); 40 40 zPath = blob_str(&pathname); 41 - if( strcmp(zPath, "manifest")==0 42 - || strcmp(zPath, "_FOSSIL_")==0 41 + if( strcmp(zPath, "_FOSSIL_")==0 43 42 || strcmp(zPath, "_FOSSIL_-journal")==0 44 43 || strcmp(zPath, "_FOSSIL_-wal")==0 45 44 || strcmp(zPath, "_FOSSIL_-shm")==0 46 45 || strcmp(zPath, ".fos")==0 47 46 || strcmp(zPath, ".fos-journal")==0 48 47 || strcmp(zPath, ".fos-wal")==0 49 48 || strcmp(zPath, ".fos-shm")==0 50 - || strcmp(zPath, "manifest.uuid")==0 51 49 || blob_compare(&pathname, pOmit)==0 52 50 ){ 53 51 fossil_warning("cannot add %s", zPath); 54 52 }else{ 55 53 if( !file_is_simple_pathname(zPath) ){ 56 54 fossil_fatal("filename contains illegal characters: %s", zPath); 57 55 } 58 -#ifdef __MINGW32__ 56 +#if defined(_WIN32) 59 57 if( db_exists("SELECT 1 FROM vfile" 60 58 " WHERE pathname=%Q COLLATE nocase", zPath) ){ 61 59 db_multi_exec("UPDATE vfile SET deleted=0" 62 60 " WHERE pathname=%Q COLLATE nocase", zPath); 63 61 } 64 62 #else 65 63 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){ ................................................................................ 150 148 fossil_panic("no checkout to add to"); 151 149 } 152 150 db_begin_transaction(); 153 151 if( !file_tree_name(g.zRepositoryName, &repo, 0) ){ 154 152 blob_zero(&repo); 155 153 } 156 154 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)"); 157 -#ifdef __MINGW32__ 155 +#if defined(_WIN32) 158 156 db_multi_exec( 159 157 "CREATE INDEX IF NOT EXISTS vfile_pathname " 160 158 " ON vfile(pathname COLLATE nocase)" 161 159 ); 162 160 #endif 163 161 for(i=2; i<g.argc; i++){ 164 162 char *zName;
Changes to src/allrepo.c.
32 32 ** string is returned even if no quoting is needed. 33 33 */ 34 34 static char *quoteFilename(const char *zFilename){ 35 35 int i, c; 36 36 int needQuote = 0; 37 37 for(i=0; (c = zFilename[i])!=0; i++){ 38 38 if( c=='"' ) return 0; 39 - if( isspace(c) ) needQuote = 1; 39 + if( fossil_isspace(c) ) needQuote = 1; 40 40 if( c=='\\' && zFilename[i+1]==0 ) return 0; 41 41 if( c=='$' ) return 0; 42 42 } 43 43 if( needQuote ){ 44 44 return mprintf("\"%s\"", zFilename); 45 45 }else{ 46 46 return mprintf("%s", zFilename); ................................................................................ 51 51 /* 52 52 ** COMMAND: all 53 53 ** 54 54 ** Usage: %fossil all (list|ls|pull|push|rebuild|sync) 55 55 ** 56 56 ** The ~/.fossil file records the location of all repositories for a 57 57 ** user. This command performs certain operations on all repositories 58 -** that can be useful before or after a period of disconnection operation. 58 +** that can be useful before or after a period of disconnected operation. 59 59 ** 60 -** On Win32 systems, this file is located in %LOCALAPPDATA%, %APDDATA% 61 -** or %HOMEPATH% and is named _fossil. 60 +** On Win32 systems, the file is named "_fossil" and is located in 61 +** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%. 62 62 ** 63 63 ** Available operations are: 64 64 ** 65 +** ignore Arguments are repositories that should be ignored 66 +** by subsequent list, pull, push, rebuild, and sync. 67 +** 65 68 ** list | ls Display the location of all repositories 66 69 ** 67 70 ** pull Run a "pull" operation on all repositories 68 71 ** 69 72 ** push Run a "push" on all repositories 70 73 ** 71 74 ** rebuild Rebuild on all repositories 72 75 ** 73 76 ** sync Run a "sync" on all repositories 74 77 ** 75 78 ** Respositories are automatically added to the set of known repositories 76 79 ** when one of the following commands against the repository: clone, info, 77 -** pull, push, or sync 80 +** pull, push, or sync. Even previously ignored repositories are added back 81 +** to the list of repositories by these commands. 78 82 */ 79 83 void all_cmd(void){ 80 84 int n; 81 85 Stmt q; 82 86 const char *zCmd; 83 87 char *zSyscmd; 84 88 char *zFossil; ................................................................................ 97 101 zCmd = "push -autourl -R"; 98 102 }else if( strncmp(zCmd, "pull", n)==0 ){ 99 103 zCmd = "pull -autourl -R"; 100 104 }else if( strncmp(zCmd, "rebuild", n)==0 ){ 101 105 zCmd = "rebuild"; 102 106 }else if( strncmp(zCmd, "sync", n)==0 ){ 103 107 zCmd = "sync -autourl -R"; 108 + }else if( strncmp(zCmd, "ignore", n)==0 ){ 109 + int j; 110 + db_begin_transaction(); 111 + for(j=3; j<g.argc; j++){ 112 + db_multi_exec("DELETE FROM global_config WHERE name GLOB 'repo:%q'", 113 + g.argv[j]); 114 + } 115 + db_end_transaction(0); 116 + return; 104 117 }else{ 105 118 fossil_fatal("\"all\" subcommand should be one of: " 106 - "list ls push pull rebuild sync"); 119 + "ignore list ls push pull rebuild sync"); 107 120 } 108 121 zFossil = quoteFilename(g.argv[0]); 109 122 nMissing = 0; 110 123 db_prepare(&q, 111 124 "SELECT DISTINCT substr(name, 6) COLLATE nocase" 112 125 " FROM global_config" 113 126 " WHERE substr(name, 1, 5)=='repo:' ORDER BY 1" ................................................................................ 123 136 printf("%s\n", zFilename); 124 137 continue; 125 138 } 126 139 zQFilename = quoteFilename(zFilename); 127 140 zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename); 128 141 printf("%s\n", zSyscmd); 129 142 fflush(stdout); 130 - portable_system(zSyscmd); 143 + fossil_system(zSyscmd); 131 144 free(zSyscmd); 132 145 free(zQFilename); 133 146 } 134 147 135 148 /* If any repositories whose names appear in the ~/.fossil file could not 136 149 ** be found, remove those names from the ~/.fossil file. 137 150 */
Changes to src/attach.c.
73 73 for(i=0; zFilename[i]; i++){ 74 74 if( zFilename[i]=='/' && zFilename[i+1]!=0 ){ 75 75 zFilename = &zFilename[i+1]; 76 76 i = -1; 77 77 } 78 78 } 79 79 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ 80 - zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename); 80 + zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename); 81 81 }else{ 82 - zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename); 82 + zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename); 83 83 } 84 84 @ 85 85 @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a> 86 - @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br> 87 - if( zComment ) while( isspace(zComment[0]) ) zComment++; 86 + @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br /> 87 + if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++; 88 88 if( zComment && zComment[0] ){ 89 - @ %w(zComment)<br> 89 + @ %w(zComment)<br /> 90 90 } 91 91 if( zPage==0 && zTkt==0 ){ 92 92 if( zSrc==0 || zSrc[0]==0 ){ 93 93 zSrc = "Deleted from"; 94 94 }else { 95 95 zSrc = "Added to"; 96 96 } ................................................................................ 249 249 for(i=n=0; zName[i]; i++){ 250 250 if( zName[i]=='/' || zName[i]=='\\' ) n = i; 251 251 } 252 252 zName += n; 253 253 if( zName[0]==0 ) zName = "unknown"; 254 254 blob_appendf(&manifest, "A %F %F %s\n", zName, zTarget, zUUID); 255 255 zComment = PD("comment", ""); 256 - while( isspace(zComment[0]) ) zComment++; 256 + while( fossil_isspace(zComment[0]) ) zComment++; 257 257 n = strlen(zComment); 258 - while( n>0 && isspace(zComment[n-1]) ){ n--; } 258 + while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; } 259 259 if( n>0 ){ 260 260 blob_appendf(&manifest, "C %F\n", zComment); 261 261 } 262 262 zDate = db_text(0, "SELECT datetime('now')"); 263 263 zDate[10] = 'T'; 264 264 blob_appendf(&manifest, "D %s\n", zDate); 265 265 blob_appendf(&manifest, "U %F\n", g.zLogin ? g.zLogin : "nobody"); ................................................................................ 268 268 rid = content_put(&manifest, 0, 0); 269 269 manifest_crosslink(rid, &manifest); 270 270 db_end_transaction(0); 271 271 cgi_redirect(zFrom); 272 272 } 273 273 style_header("Add Attachment"); 274 274 @ <h2>Add Attachment To %s(zTargetType)</h2> 275 - @ <form action="%s(g.zBaseURL)/attachadd" method="POST" 276 - @ enctype="multipart/form-data"> 275 + @ <form action="%s(g.zBaseURL)/attachadd" method="post" 276 + @ enctype="multipart/form-data"><div> 277 277 @ File to Attach: 278 - @ <input type="file" name="f" size="60"><br> 279 - @ Description:<br> 280 - @ <textarea name="comment" cols=80 rows=5 wrap="virtual"></textarea><br> 278 + @ <input type="file" name="f" size="60" /><br /> 279 + @ Description:<br /> 280 + @ <textarea name="comment" cols="80" rows="5" wrap="virtual"></textarea><br /> 281 281 if( zTkt ){ 282 - @ <input type="hidden" name="tkt" value="%h(zTkt)"> 282 + @ <input type="hidden" name="tkt" value="%h(zTkt)" /> 283 283 }else{ 284 - @ <input type="hidden" name="page" value="%h(zPage)"> 284 + @ <input type="hidden" name="page" value="%h(zPage)" /> 285 285 } 286 - @ <input type="hidden" name="from" value="%h(zFrom)"> 287 - @ <input type="submit" name="ok" value="Add Attachment"> 288 - @ <input type="submit" name="cancel" value="Cancel"> 289 - @ </form> 286 + @ <input type="hidden" name="from" value="%h(zFrom)" /> 287 + @ <input type="submit" name="ok" value="Add Attachment" /> 288 + @ <input type="submit" name="cancel" value="Cancel" /> 289 + @ </div></form> 290 290 style_footer(); 291 291 } 292 292 293 293 294 294 /* 295 295 ** WEBPAGE: attachdelete 296 296 ** ................................................................................ 347 347 blob_appendf(&manifest, "Z %b\n", &cksum); 348 348 rid = content_put(&manifest, 0, 0); 349 349 manifest_crosslink(rid, &manifest); 350 350 db_end_transaction(0); 351 351 cgi_redirect(zFrom); 352 352 } 353 353 style_header("Delete Attachment"); 354 - @ <form action="%s(g.zBaseURL)/attachdelete" method="POST"> 354 + @ <form action="%s(g.zBaseURL)/attachdelete" method="post"><div> 355 355 @ <p>Confirm that you want to delete the attachment named 356 - @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br> 356 + @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br /></p> 357 357 if( zTkt ){ 358 - @ <input type="hidden" name="tkt" value="%h(zTkt)"> 358 + @ <input type="hidden" name="tkt" value="%h(zTkt)" /> 359 359 }else{ 360 - @ <input type="hidden" name="page" value="%h(zPage)"> 360 + @ <input type="hidden" name="page" value="%h(zPage)" /> 361 361 } 362 - @ <input type="hidden" name="file" value="%h(zFile)"> 363 - @ <input type="hidden" name="from" value="%h(zFrom)"> 364 - @ <input type="submit" name="confirm" value="Delete"> 365 - @ <input type="submit" name="cancel" value="Cancel"> 366 - @ </form> 362 + @ <input type="hidden" name="file" value="%h(zFile)" /> 363 + @ <input type="hidden" name="from" value="%h(zFrom)" /> 364 + @ <input type="submit" name="confirm" value="Delete" /> 365 + @ <input type="submit" name="cancel" value="Cancel" /> 366 + @ </div></form> 367 367 style_footer(); 368 368 369 369 }
Changes to src/bag.c.
84 84 int i; 85 85 Bag old; 86 86 int nDel = 0; /* Number of deleted entries */ 87 87 int nLive = 0; /* Number of live entries */ 88 88 89 89 old = *p; 90 90 assert( newSize>old.cnt ); 91 - p->a = malloc( sizeof(p->a[0])*newSize ); 91 + p->a = fossil_malloc( sizeof(p->a[0])*newSize ); 92 92 p->sz = newSize; 93 93 memset(p->a, 0, sizeof(p->a[0])*newSize ); 94 94 for(i=0; i<old.sz; i++){ 95 95 int e = old.a[i]; 96 96 if( e>0 ){ 97 97 unsigned h = bag_hash(e)%newSize; 98 98 while( p->a[h] ){
Changes to src/blob.c.
70 70 #define blob_is_reset(x) 71 71 #endif 72 72 73 73 /* 74 74 ** We find that the built-in isspace() function does not work for 75 75 ** some international character sets. So here is a substitute. 76 76 */ 77 -static int blob_isspace(char c){ 77 +int fossil_isspace(char c){ 78 78 return c==' ' || (c<='\r' && c>='\t'); 79 79 } 80 + 81 +/* 82 +** Other replacements for ctype.h functions. 83 +*/ 84 +int fossil_islower(char c){ return c>='a' && c<='z'; } 85 +int fossil_isupper(char c){ return c>='A' && c<='Z'; } 86 +int fossil_isdigit(char c){ return c>='0' && c<='9'; } 87 +int fossil_tolower(char c){ 88 + return fossil_isupper(c) ? c - 'A' + 'a' : c; 89 +} 90 +int fossil_isalpha(char c){ 91 + return (c>='a' && c<='z') || (c>='A' && c<='Z'); 92 +} 93 +int fossil_isalnum(char c){ 94 + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'); 95 +} 96 + 80 97 81 98 /* 82 99 ** COMMAND: test-isspace 83 100 */ 84 101 void isspace_cmd(void){ 85 102 int i; 86 103 for(i=0; i<=255; i++){ 87 104 if( i==' ' || i=='\n' || i=='\t' || i=='\v' 88 105 || i=='\f' || i=='\r' ){ 89 - assert( blob_isspace((char)i) ); 106 + assert( fossil_isspace((char)i) ); 90 107 }else{ 91 - assert( !blob_isspace((char)i) ); 108 + assert( !fossil_isspace((char)i) ); 92 109 } 93 110 } 94 111 printf("All 256 characters OK\n"); 95 112 } 96 113 97 114 /* 98 115 ** This routine is called if a blob operation fails because we ................................................................................ 117 134 if( newSize==0 ){ 118 135 free(pBlob->aData); 119 136 pBlob->aData = 0; 120 137 pBlob->nAlloc = 0; 121 138 pBlob->nUsed = 0; 122 139 pBlob->iCursor = 0; 123 140 }else if( newSize>pBlob->nAlloc || newSize<pBlob->nAlloc-4000 ){ 124 - char *pNew = realloc(pBlob->aData, newSize); 125 - if( pNew==0 ) blob_panic(); 141 + char *pNew = fossil_realloc(pBlob->aData, newSize); 126 142 pBlob->aData = pNew; 127 143 pBlob->nAlloc = newSize; 128 144 if( pBlob->nUsed>pBlob->nAlloc ){ 129 145 pBlob->nUsed = pBlob->nAlloc; 130 146 } 131 147 } 132 148 } ................................................................................ 143 159 ** A reallocation function for when the initial string is in unmanaged 144 160 ** space. Copy the string to memory obtained from malloc(). 145 161 */ 146 162 static void blobReallocStatic(Blob *pBlob, unsigned int newSize){ 147 163 if( newSize==0 ){ 148 164 *pBlob = empty_blob; 149 165 }else{ 150 - char *pNew = malloc( newSize ); 151 - if( pNew==0 ) blob_panic(); 166 + char *pNew = fossil_malloc( newSize ); 152 167 if( pBlob->nUsed>newSize ) pBlob->nUsed = newSize; 153 168 memcpy(pNew, pBlob->aData, pBlob->nUsed); 154 169 pBlob->aData = pNew; 155 170 pBlob->xRealloc = blobReallocMalloc; 156 171 pBlob->nAlloc = newSize; 157 172 } 158 173 } ................................................................................ 427 442 ** 428 443 ** All this does is reduce the length counter. This routine does 429 444 ** not insert a new zero terminator. 430 445 */ 431 446 int blob_trim(Blob *p){ 432 447 char *z = p->aData; 433 448 int n = p->nUsed; 434 - while( n>0 && blob_isspace(z[n-1]) ){ n--; } 449 + while( n>0 && fossil_isspace(z[n-1]) ){ n--; } 435 450 p->nUsed = n; 436 451 return n; 437 452 } 438 453 439 454 /* 440 455 ** Extract a single token from pFrom and use it to initialize pTo. 441 456 ** Return the number of bytes in the token. If no token is found, ................................................................................ 450 465 ** pTo will be an ephermeral blob. If pFrom changes, it might alter 451 466 ** pTo as well. 452 467 */ 453 468 int blob_token(Blob *pFrom, Blob *pTo){ 454 469 char *aData = pFrom->aData; 455 470 int n = pFrom->nUsed; 456 471 int i = pFrom->iCursor; 457 - while( i<n && blob_isspace(aData[i]) ){ i++; } 472 + while( i<n && fossil_isspace(aData[i]) ){ i++; } 458 473 pFrom->iCursor = i; 459 - while( i<n && !blob_isspace(aData[i]) ){ i++; } 474 + while( i<n && !fossil_isspace(aData[i]) ){ i++; } 460 475 blob_extract(pFrom, i-pFrom->iCursor, pTo); 461 - while( i<n && blob_isspace(aData[i]) ){ i++; } 476 + while( i<n && fossil_isspace(aData[i]) ){ i++; } 462 477 pFrom->iCursor = i; 463 478 return pTo->nUsed; 464 479 } 465 480 466 481 /* 467 482 ** Extract everything from the current cursor to the end of the blob 468 483 ** into a new blob. The new blob is an ephemerial reference to the ................................................................................ 521 536 ** the integer value in *pValue. 522 537 */ 523 538 int blob_is_int(Blob *pBlob, int *pValue){ 524 539 const char *z = blob_buffer(pBlob); 525 540 int i, n, c, v; 526 541 n = blob_size(pBlob); 527 542 v = 0; 528 - for(i=0; i<n && (c = z[i])!=0 && isdigit(c); i++){ 543 + for(i=0; i<n && (c = z[i])!=0 && c>='0' && c<='9'; i++){ 529 544 v = v*10 + c - '0'; 530 545 } 531 546 if( i==n ){ 532 547 *pValue = v; 533 548 return 1; 534 549 }else{ 535 550 return 0; ................................................................................ 610 625 if( zFilename==0 || zFilename[0]==0 611 626 || (zFilename[0]=='-' && zFilename[1]==0) ){ 612 627 return blob_read_from_channel(pBlob, stdin, -1); 613 628 } 614 629 size = file_size(zFilename); 615 630 blob_zero(pBlob); 616 631 if( size<0 ){ 617 - fossil_panic("no such file: %s", zFilename); 632 + fossil_fatal("no such file: %s", zFilename); 618 633 } 619 634 if( size==0 ){ 620 635 return 0; 621 636 } 622 637 blob_resize(pBlob, size); 623 638 in = fopen(zFilename, "rb"); 624 639 if( in==0 ){ ................................................................................ 658 673 zName = zBuf; 659 674 strcpy(zName, zFilename); 660 675 } 661 676 nName = file_simplify_name(zName, nName); 662 677 for(i=1; i<nName; i++){ 663 678 if( zName[i]=='/' ){ 664 679 zName[i] = 0; 665 -#ifdef __MINGW32__ 680 +#if defined(_WIN32) 666 681 /* 667 682 ** On Windows, local path looks like: C:/develop/project/file.txt 668 683 ** The if stops us from trying to create a directory of a drive letter 669 684 ** C: in this example. 670 685 */ 671 686 if( !(i==2 && zName[1]==':') ){ 672 687 #endif 673 688 if( file_mkdir(zName, 1) ){ 674 689 fossil_fatal_recursive("unable to create directory %s", zName); 675 690 return 0; 676 691 } 677 -#ifdef __MINGW32__ 692 +#if defined(_WIN32) 678 693 } 679 694 #endif 680 695 zName[i] = '/'; 681 696 } 682 697 } 683 698 out = fopen(zName, "wb"); 684 699 if( out==0 ){ ................................................................................ 854 869 blob_reset(&b1); 855 870 blob_reset(&b2); 856 871 blob_reset(&b3); 857 872 } 858 873 printf("ok\n"); 859 874 } 860 875 861 -#ifdef __MINGW32__ 876 +#if defined(_WIN32) 862 877 /* 863 878 ** Convert every \n character in the given blob into \r\n. 864 879 */ 865 880 void blob_add_cr(Blob *p){ 866 881 char *z = p->aData; 867 882 int j = p->nUsed; 868 883 int i, n; ................................................................................ 894 909 z = p->aData; 895 910 for(i=j=0; z[i]; i++){ 896 911 if( z[i]!='\r' ) z[j++] = z[i]; 897 912 } 898 913 z[j] = 0; 899 914 p->nUsed = j; 900 915 } 916 + 917 +/* 918 +** Shell-escape the given string. Append the result to a blob. 919 +*/ 920 +void shell_escape(Blob *pBlob, const char *zIn){ 921 + int n = blob_size(pBlob); 922 + int k = strlen(zIn); 923 + int i, c; 924 + char *z; 925 + for(i=0; (c = zIn[i])!=0; i++){ 926 + if( fossil_isspace(c) || c=='"' || (c=='\\' && zIn[i+1]!=0) ){ 927 + blob_appendf(pBlob, "\"%s\"", zIn); 928 + z = blob_buffer(pBlob); 929 + for(i=n+1; i<=n+k; i++){ 930 + if( z[i]=='"' ) z[i] = '_'; 931 + } 932 + return; 933 + } 934 + } 935 + blob_append(pBlob, zIn, -1); 936 +}
Changes to src/branch.c.
33 33 char *zUuid; /* Artifact ID of origin */ 34 34 Stmt q; /* Generic query */ 35 35 const char *zBranch; /* Name of the new branch */ 36 36 char *zDate; /* Date that branch was created */ 37 37 char *zComment; /* Check-in comment for the new branch */ 38 38 const char *zColor; /* Color of the new branch */ 39 39 Blob branch; /* manifest for the new branch */ 40 - Blob parent; /* root check-in manifest */ 41 - Manifest mParent; /* Parsed parent manifest */ 40 + Manifest *pParent; /* Parsed parent manifest */ 42 41 Blob mcksum; /* Self-checksum on the manifest */ 42 + const char *zDateOvrd; /* Override date string */ 43 + const char *zUserOvrd; /* Override user name */ 43 44 44 45 noSign = find_option("nosign","",0)!=0; 45 46 zColor = find_option("bgcolor","c",1); 47 + zDateOvrd = find_option("date-override",0,1); 48 + zUserOvrd = find_option("user-override",0,1); 46 49 verify_all_options(); 47 50 if( g.argc<5 ){ 48 51 usage("new BRANCH-NAME CHECK-IN ?-bgcolor COLOR?"); 49 52 } 50 53 db_find_and_open_repository(1); 51 54 noSign = db_get_int("omitsign", 0)|noSign; 52 55 ................................................................................ 65 68 66 69 user_select(); 67 70 db_begin_transaction(); 68 71 rootid = name_to_rid(g.argv[4]); 69 72 if( rootid==0 ){ 70 73 fossil_fatal("unable to locate check-in off of which to branch"); 71 74 } 75 + 76 + pParent = manifest_get(rootid, CFTYPE_MANIFEST); 77 + if( pParent==0 ){ 78 + fossil_fatal("%s is not a valid check-in", g.argv[4]); 79 + } 72 80 73 81 /* Create a manifest for the new branch */ 74 82 blob_zero(&branch); 83 + if( pParent->zBaseline ){ 84 + blob_appendf(&branch, "B %s\n", pParent->zBaseline); 85 + } 75 86 zComment = mprintf("Create new branch named \"%h\"", zBranch); 76 87 blob_appendf(&branch, "C %F\n", zComment); 77 - zDate = db_text(0, "SELECT datetime('now')"); 88 + zDate = date_in_standard_format(zDateOvrd ? zDateOvrd : "now"); 78 89 zDate[10] = 'T'; 79 90 blob_appendf(&branch, "D %s\n", zDate); 80 91 81 92 /* Copy all of the content from the parent into the branch */ 82 - content_get(rootid, &parent); 83 - manifest_parse(&mParent, &parent); 84 - if( mParent.type!=CFTYPE_MANIFEST ){ 85 - fossil_fatal("%s is not a valid check-in", g.argv[4]); 86 - } 87 - for(i=0; i<mParent.nFile; ++i){ 88 - if( mParent.aFile[i].zPerm[0] ){ 89 - blob_appendf(&branch, "F %F %s %s\n", 90 - mParent.aFile[i].zName, 91 - mParent.aFile[i].zUuid, 92 - mParent.aFile[i].zPerm); 93 - }else{ 94 - blob_appendf(&branch, "F %F %s\n", 95 - mParent.aFile[i].zName, 96 - mParent.aFile[i].zUuid); 93 + for(i=0; i<pParent->nFile; ++i){ 94 + blob_appendf(&branch, "F %F", pParent->aFile[i].zName); 95 + if( pParent->aFile[i].zUuid ){ 96 + blob_appendf(&branch, " %s", pParent->aFile[i].zUuid); 97 + if( pParent->aFile[i].zPerm && pParent->aFile[i].zPerm[0] ){ 98 + blob_appendf(&branch, " %s", pParent->aFile[i].zPerm); 99 + } 97 100 } 101 + blob_append(&branch, "\n", 1); 98 102 } 99 103 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rootid); 100 104 blob_appendf(&branch, "P %s\n", zUuid); 101 - blob_appendf(&branch, "R %s\n", mParent.zRepoCksum); 102 - manifest_clear(&mParent); 105 + blob_appendf(&branch, "R %s\n", pParent->zRepoCksum); 106 + manifest_destroy(pParent); 103 107 104 108 /* Add the symbolic branch name and the "branch" tag to identify 105 109 ** this as a new branch */ 106 110 if( zColor!=0 ){ 107 111 blob_appendf(&branch, "T *bgcolor * %F\n", zColor); 108 112 } 109 113 blob_appendf(&branch, "T *branch * %F\n", zBranch); ................................................................................ 118 122 rootid); 119 123 while( db_step(&q)==SQLITE_ROW ){ 120 124 const char *zTag = db_column_text(&q, 0); 121 125 blob_appendf(&branch, "T -%F *\n", zTag); 122 126 } 123 127 db_finalize(&q); 124 128 125 - blob_appendf(&branch, "U %F\n", g.zLogin); 129 + blob_appendf(&branch, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); 126 130 md5sum_blob(&branch, &mcksum); 127 131 blob_appendf(&branch, "Z %b\n", &mcksum); 128 132 if( !noSign && clearsign(&branch, &branch) ){ 129 133 Blob ans; 130 134 blob_zero(&ans); 131 135 prompt_user("unable to sign manifest. continue (y/N)? ", &ans); 132 136 if( blob_str(&ans)[0]!='y' ){ ................................................................................ 213 217 ** WEBPAGE: brlist 214 218 ** 215 219 ** Show a timeline of all branches 216 220 */ 217 221 void brlist_page(void){ 218 222 Stmt q; 219 223 int cnt; 224 + int showClosed = P("closed")!=0; 220 225 221 226 login_check_credentials(); 222 227 if( !g.okRead ){ login_needed(); return; } 223 228 224 - style_header("Branches"); 229 + style_header(showClosed ? "Closed Branches" : "Open Branches"); 225 230 style_submenu_element("Timeline", "Timeline", "brtimeline"); 231 + if( showClosed ){ 232 + style_submenu_element("Open","Open","brlist"); 233 + }else{ 234 + style_submenu_element("Closed","Closed","brlist?closed"); 235 + } 226 236 login_anonymous_available(); 227 237 compute_leaves(0, 1); 228 238 style_sidebox_begin("Nomenclature:", "33%"); 229 239 @ <ol> 230 - @ <li> An <b>open branch</b> is a branch that has one or 240 + @ <li> An <div class="sideboxDescribed"><a href="brlist"> 241 + @ open branch</a></div> is a branch that has one or 231 242 @ more <a href="leaves">open leaves.</a> 232 243 @ The presence of open leaves presumably means 233 244 @ that the branch is still being extended with new check-ins.</li> 234 - @ <li> A <b>closed branch</b> is a branch with only 235 - @ <a href="leaves?closed">closed leaves</a>. 245 + @ <li> A <div class="sideboxDescribed"><a href="brlist?closed"> 246 + @ closed branch</a></div> is a branch with only 247 + @ <div class="sideboxDescribed"><a href="leaves?closed"> 248 + @ closed leaves</a></div>. 236 249 @ Closed branches are fixed and do not change (unless they are first 237 250 @ reopened)</li> 238 251 @ </ol> 239 252 style_sidebox_end(); 240 253 241 - db_prepare(&q, 242 - "SELECT DISTINCT value FROM tagxref" 243 - " WHERE tagid=%d AND value NOT NULL" 244 - " AND rid IN leaves" 245 - " ORDER BY value /*sort*/", 246 - TAG_BRANCH 247 - ); 248 254 cnt = 0; 255 + if( !showClosed ){ 256 + db_prepare(&q, 257 + "SELECT DISTINCT value FROM tagxref" 258 + " WHERE tagid=%d AND value NOT NULL" 259 + " AND rid IN leaves" 260 + " ORDER BY value /*sort*/", 261 + TAG_BRANCH 262 + ); 263 + }else{ 264 + db_prepare(&q, 265 + "SELECT value FROM tagxref" 266 + " WHERE tagid=%d AND value NOT NULL" 267 + " EXCEPT " 268 + "SELECT value FROM tagxref" 269 + " WHERE tagid=%d AND value NOT NULL" 270 + " AND rid IN leaves" 271 + " ORDER BY value /*sort*/", 272 + TAG_BRANCH, TAG_BRANCH 273 + ); 274 + } 249 275 while( db_step(&q)==SQLITE_ROW ){ 250 276 const char *zBr = db_column_text(&q, 0); 251 277 if( cnt==0 ){ 252 - @ <h2>Open Branches:</h2> 278 + if( showClosed ){ 279 + @ <h2>Closed Branches:</h2> 280 + }else{ 281 + @ <h2>Open Branches:</h2> 282 + } 253 283 @ <ul> 254 284 cnt++; 255 285 } 256 - if( g.okHistory ){ 257 - @ <li><a href="%s(g.zBaseURL)/timeline?r=%T(zBr)">%h(zBr)</a></li> 258 - }else{ 259 - @ <li><b>%h(zBr)</b></li> 260 - } 261 - } 262 - db_finalize(&q); 263 - if( cnt ){ 264 - @ </ul> 265 - } 266 - cnt = 0; 267 - db_prepare(&q, 268 - "SELECT value FROM tagxref" 269 - " WHERE tagid=%d AND value NOT NULL" 270 - " EXCEPT " 271 - "SELECT value FROM tagxref" 272 - " WHERE tagid=%d AND value NOT NULL" 273 - " AND rid IN leaves" 274 - " ORDER BY value /*sort*/", 275 - TAG_BRANCH, TAG_BRANCH 276 - ); 277 - while( db_step(&q)==SQLITE_ROW ){ 278 - const char *zBr = db_column_text(&q, 0); 279 - if( cnt==0 ){ 280 - @ <h2>Closed Branches:</h2> 281 - @ <ul> 282 - cnt++; 283 - } 284 286 if( g.okHistory ){ 285 287 @ <li><a href="%s(g.zBaseURL)/timeline?r=%T(zBr)">%h(zBr)</a></li> 286 288 }else{ 287 289 @ <li><b>%h(zBr)</b></li> 288 290 } 289 291 } 290 292 if( cnt ){ 291 293 @ </ul> 292 294 } 293 295 db_finalize(&q); 294 - @ </ul> 295 - @ <br clear="both"> 296 - @ <script> 296 + @ <script type="text/JavaScript"> 297 297 @ function xin(id){ 298 298 @ } 299 299 @ function xout(id){ 300 300 @ } 301 301 @ </script> 302 302 style_footer(); 303 303 } ................................................................................ 344 344 "%s AND blob.rid IN (SELECT rid FROM tagxref" 345 345 " WHERE tagtype>0 AND tagid=%d AND srcid!=0)" 346 346 " ORDER BY event.mtime DESC", 347 347 timeline_query_for_www(), TAG_BRANCH 348 348 ); 349 349 www_print_timeline(&q, 0, brtimeline_extra); 350 350 db_finalize(&q); 351 - @ <br clear="both"> 352 - @ <script> 351 + @ <script type="text/JavaScript"> 353 352 @ function xin(id){ 354 353 @ } 355 354 @ function xout(id){ 356 355 @ } 357 356 @ </script> 358 357 style_footer(); 359 358 }
Changes to src/browse.c.
69 69 ** to the "dir" page for the directory. 70 70 ** 71 71 ** There is no hyperlink on the file element of the path. 72 72 ** 73 73 ** The computed string is appended to the pOut blob. pOut should 74 74 ** have already been initialized. 75 75 */ 76 -void hyperlinked_path(const char *zPath, Blob *pOut){ 76 +void hyperlinked_path(const char *zPath, Blob *pOut, const char *zCI){ 77 77 int i, j; 78 78 char *zSep = ""; 79 79 80 80 for(i=0; zPath[i]; i=j){ 81 81 for(j=i; zPath[j] && zPath[j]!='/'; j++){} 82 82 if( zPath[j] && g.okHistory ){ 83 - blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>", 84 - zSep, g.zBaseURL, j, zPath, j-i, &zPath[i]); 83 + if( zCI ){ 84 + blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&name=%#T\">%#h</a>", 85 + zSep, g.zBaseURL, zCI, j, zPath, j-i, &zPath[i]); 86 + }else{ 87 + blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>", 88 + zSep, g.zBaseURL, j, zPath, j-i, &zPath[i]); 89 + } 85 90 }else{ 86 91 blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]); 87 92 } 88 93 zSep = "/"; 89 94 while( zPath[j]=='/' ){ j++; } 90 95 } 91 96 } ................................................................................ 97 102 ** Query parameters: 98 103 ** 99 104 ** name=PATH Directory to display. Required. 100 105 ** ci=LABEL Show only files in this check-in. Optional. 101 106 */ 102 107 void page_dir(void){ 103 108 const char *zD = P("name"); 109 + int nD = zD ? strlen(zD)+1 : 0; 104 110 int mxLen; 105 111 int nCol, nRow; 106 112 int cnt, i; 107 113 char *zPrefix; 108 114 Stmt q; 109 115 const char *zCI = P("ci"); 110 116 int rid = 0; 111 - Blob content; 117 + char *zUuid = 0; 112 118 Blob dirname; 113 - Manifest m; 119 + Manifest *pM = 0; 114 120 const char *zSubdirLink; 115 121 116 122 login_check_credentials(); 117 123 if( !g.okHistory ){ login_needed(); return; } 118 124 style_header("File List"); 119 125 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0, 120 126 pathelementFunc, 0, 0); 121 127 122 128 /* If the name= parameter is an empty string, make it a NULL pointer */ 123 129 if( zD && strlen(zD)==0 ){ zD = 0; } 124 130 125 - /* If a specific check-in is requested, fetch and parse it. */ 126 - if( zCI && (rid = name_to_rid(zCI))!=0 && content_get(rid, &content) ){ 127 - if( !manifest_parse(&m, &content) || m.type!=CFTYPE_MANIFEST ){ 131 + /* If a specific check-in is requested, fetch and parse it. If the 132 + ** specific check-in does not exist, clear zCI. zCI==0 will cause all 133 + ** files from all check-ins to be displayed. 134 + */ 135 + if( zCI ){ 136 + pM = manifest_get_by_name(zCI, &rid); 137 + if( pM ){ 138 + zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); 139 + }else{ 128 140 zCI = 0; 129 141 } 130 142 } 143 + 131 144 132 145 /* Compute the title of the page */ 133 146 blob_zero(&dirname); 134 147 if( zD ){ 135 148 blob_append(&dirname, "in directory ", -1); 136 - hyperlinked_path(zD, &dirname); 149 + hyperlinked_path(zD, &dirname, zCI); 137 150 zPrefix = mprintf("%h/", zD); 138 151 }else{ 139 152 blob_append(&dirname, "in the top-level directory", -1); 140 153 zPrefix = ""; 141 154 } 142 155 if( zCI ){ 143 - char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); 144 156 char zShort[20]; 145 157 memcpy(zShort, zUuid, 10); 146 158 zShort[10] = 0; 147 159 @ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>] 148 160 @ %s(blob_str(&dirname))</h2> 149 - zSubdirLink = mprintf("%s/dir?ci=%S&name=%T", g.zTop, zUuid, zPrefix); 161 + zSubdirLink = mprintf("%s/dir?ci=%S&name=%T", g.zTop, zUuid, zPrefix); 150 162 if( zD ){ 151 163 style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid); 152 164 style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD); 153 165 }else{ 154 166 style_submenu_element("All", "All", "%s/dir", g.zBaseURL); 155 167 } 156 168 }else{ 169 + int hasTrunk; 157 170 @ <h2>The union of all files from all check-ins 158 171 @ %s(blob_str(&dirname))</h2> 172 + hasTrunk = db_exists( 173 + "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'", 174 + TAG_BRANCH); 159 175 zSubdirLink = mprintf("%s/dir?name=%T", g.zBaseURL, zPrefix); 160 176 if( zD ){ 161 177 style_submenu_element("Top", "Top", "%s/dir", g.zBaseURL); 162 - style_submenu_element("Tip", "Tip", "%s/dir?name=%t&ci=tip", 178 + style_submenu_element("Tip", "Tip", "%s/dir?name=%t&ci=tip", 163 179 g.zBaseURL, zD); 164 - style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&ci=trunk", 165 - g.zBaseURL,zD); 180 + if( hasTrunk ){ 181 + style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&ci=trunk", 182 + g.zBaseURL,zD); 183 + } 166 184 }else{ 167 185 style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zBaseURL); 168 - style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zBaseURL); 186 + if( hasTrunk ){ 187 + style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zBaseURL); 188 + } 169 189 } 170 190 } 171 191 172 192 /* Compute the temporary table "localfiles" containing the names 173 193 ** of all files and subdirectories in the zD[] directory. 174 194 ** 175 195 ** Subdirectory names begin with "/". This causes them to sort 176 196 ** first and it also gives us an easy way to distinguish files 177 197 ** from directories in the loop that follows. 178 198 */ 179 199 db_multi_exec( 180 200 "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL, u);" 181 - "CREATE TEMP TABLE allfiles(x UNIQUE NOT NULL, u);" 182 201 ); 183 202 if( zCI ){ 184 203 Stmt ins; 185 - int i; 186 - db_prepare(&ins, "INSERT INTO allfiles VALUES(:x, :u)"); 187 - for(i=0; i<m.nFile; i++){ 188 - db_bind_text(&ins, ":x", m.aFile[i].zName); 189 - db_bind_text(&ins, ":u", m.aFile[i].zUuid); 204 + ManifestFile *pFile; 205 + ManifestFile *pPrev = 0; 206 + int nPrev = 0; 207 + int c; 208 + 209 + db_prepare(&ins, 210 + "INSERT OR IGNORE INTO localfiles VALUES(pathelement(:x,0), :u)" 211 + ); 212 + manifest_file_rewind(pM); 213 + while( (pFile = manifest_file_next(pM,0))!=0 ){ 214 + if( nD>0 && memcmp(pFile->zName, zD, nD-1)!=0 ) continue; 215 + if( pPrev && memcmp(&pFile->zName[nD],&pPrev->zName[nD],nPrev)==0 ){ 216 + continue; 217 + } 218 + db_bind_text(&ins, ":x", &pFile->zName[nD]); 219 + db_bind_text(&ins, ":u", pFile->zUuid); 190 220 db_step(&ins); 191 221 db_reset(&ins); 222 + pPrev = pFile; 223 + for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){} 224 + if( c=='/' ) nPrev++; 192 225 } 193 226 db_finalize(&ins); 194 - }else{ 227 + }else if( zD ){ 195 228 db_multi_exec( 196 - "INSERT INTO allfiles SELECT name, NULL FROM filename" 197 - ); 198 - } 199 - if( zD ){ 200 - db_multi_exec( 201 - "INSERT OR IGNORE INTO localfiles " 202 - " SELECT pathelement(x,%d), u FROM allfiles" 203 - " WHERE x GLOB '%q/*'", 204 - strlen(zD)+1, zD 229 + "INSERT OR IGNORE INTO localfiles" 230 + " SELECT pathelement(name,%d), NULL FROM filename" 231 + " WHERE name GLOB '%q/*'", 232 + nD, zD 205 233 ); 206 234 }else{ 207 235 db_multi_exec( 208 - "INSERT OR IGNORE INTO localfiles " 209 - " SELECT pathelement(x,0), u FROM allfiles" 236 + "INSERT OR IGNORE INTO localfiles" 237 + " SELECT pathelement(name,0), NULL FROM filename" 210 238 ); 211 239 } 212 240 213 241 /* Generate a multi-column table listing the contents of zD[] 214 242 ** directory. 215 243 */ 216 244 mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/"); 217 245 cnt = db_int(0, "SELECT count(*) FROM localfiles /*scan*/"); 218 246 nCol = 4; 219 247 nRow = (cnt+nCol-1)/nCol; 220 248 db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x /*scan*/"); 221 - @ <table border="0" width="100%%"><tr><td valign="top" width="25%%"> 249 + @ <table class="browser"><tr><td class="browser"><ul class="browser"> 222 250 i = 0; 223 251 while( db_step(&q)==SQLITE_ROW ){ 224 252 const char *zFN; 225 253 if( i==nRow ){ 226 - @ </td><td valign="top" width="25%%"> 254 + @ </ul></td><td class="browser"><ul class="browser"> 227 255 i = 0; 228 256 } 229 257 i++; 230 258 zFN = db_column_text(&q, 0); 231 259 if( zFN[0]=='/' ){ 232 260 zFN++; 233 261 @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li> 234 262 }else if( zCI ){ 235 263 const char *zUuid = db_column_text(&q, 1); 236 - @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFN)</a> 264 + @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFN)</a></li> 237 265 }else{ 238 - @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)</a> 266 + @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN) 267 + @ </a></li> 239 268 } 240 269 } 241 270 db_finalize(&q); 242 - @ </td></tr></table> 271 + manifest_destroy(pM); 272 + @ </ul></td></tr></table> 243 273 style_footer(); 244 274 }
Changes to src/captcha.c.
67 67 68 68 /* 69 69 ** Render an 8-character hexadecimal string as ascii art. 70 70 ** Space to hold the result is obtained from malloc() and should be freed 71 71 ** by the caller. 72 72 */ 73 73 char *captcha_render(const char *zPw){ 74 - char *z = malloc( 500 ); 74 + char *z = fossil_malloc( 500 ); 75 75 int i, j, k, m; 76 76 77 77 k = 0; 78 78 for(i=0; i<6; i++){ 79 79 for(j=0; j<8; j++){ 80 80 unsigned char v = hexValue(zPw[j]); 81 81 v = (aFont1[v] >> ((5-i)*4)) & 0xf; ................................................................................ 200 200 201 201 /* 202 202 ** Render an 8-digit hexadecimal string as ascii arg. 203 203 ** Space to hold the result is obtained from malloc() and should be freed 204 204 ** by the caller. 205 205 */ 206 206 char *captcha_render(const char *zPw){ 207 - char *z = malloc( 300 ); 207 + char *z = fossil_malloc( 300 ); 208 208 int i, j, k, m; 209 209 const char *zChar; 210 210 211 211 k = 0; 212 212 for(i=0; i<4; i++){ 213 213 for(j=0; j<8; j++){ 214 214 unsigned char v = hexValue(zPw[j]); ................................................................................ 357 357 358 358 /* 359 359 ** Render an 8-digit hexadecimal string as ascii arg. 360 360 ** Space to hold the result is obtained from malloc() and should be freed 361 361 ** by the caller. 362 362 */ 363 363 char *captcha_render(const char *zPw){ 364 - char *z = malloc( 600 ); 364 + char *z = fossil_malloc( 600 ); 365 365 int i, j, k, m; 366 366 const char *zChar; 367 367 368 368 k = 0; 369 369 for(i=0; i<6; i++){ 370 370 for(j=0; j<8; j++){ 371 371 unsigned char v = hexValue(zPw[j]); ................................................................................ 397 397 printf("%s:\n%s", zHex, z); 398 398 free(z); 399 399 } 400 400 } 401 401 402 402 /* 403 403 ** Compute a seed value for a captcha. The seed is public and is sent 404 -** has a hidden parameter with the page that contains the captcha. Knowledge 404 +** as a hidden parameter with the page that contains the captcha. Knowledge 405 405 ** of the seed is insufficient for determining the captcha without additional 406 406 ** information held only on the server and never revealed. 407 407 */ 408 408 unsigned int captcha_seed(void){ 409 409 unsigned int x; 410 410 sqlite3_randomness(sizeof(x), &x); 411 411 x &= 0x7fffffff;
Changes to src/cgi.c.
18 18 ** This file contains C functions and procedures that provide useful 19 19 ** services to CGI programs. There are procedures for parsing and 20 20 ** dispensing QUERY_STRING parameters and cookies, the "mprintf()" 21 21 ** formatting function and its cousins, and routines to encode and 22 22 ** decode strings in HTML or HTTP. 23 23 */ 24 24 #include "config.h" 25 -#ifdef __MINGW32__ 25 +#ifdef _WIN32 26 26 # include <windows.h> /* for Sleep once server works again */ 27 -# include <winsock2.h> /* socket operations */ 28 -# define sleep Sleep /* windows does not have sleep, but Sleep */ 29 -# include <ws2tcpip.h> 27 +# if defined(__MINGW32__) 28 +# define sleep Sleep /* windows does not have sleep, but Sleep */ 29 +# include <ws2tcpip.h> 30 +# endif 30 31 #else 31 32 # include <sys/socket.h> 32 33 # include <netinet/in.h> 33 34 # include <arpa/inet.h> 34 35 # include <sys/times.h> 35 36 # include <sys/time.h> 36 37 # include <sys/wait.h> ................................................................................ 39 40 #ifdef __EMX__ 40 41 typedef int socklen_t; 41 42 #endif 42 43 #include <time.h> 43 44 #include <stdio.h> 44 45 #include <stdlib.h> 45 46 #include <unistd.h> 47 +#if defined (__POCC__) 48 +# undef INTERFACE 49 +#endif 46 50 #include "cgi.h" 47 51 48 52 #if INTERFACE 49 53 /* 50 54 ** Shortcuts for cgi_parameter. P("x") returns the value of query parameter 51 55 ** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y") 52 56 ** does the same except "y" is returned in place of NULL if there is not match. ................................................................................ 381 385 ** 382 386 ** zName and zValue are not copied and must not change or be 383 387 ** deallocated after this routine returns. 384 388 */ 385 389 void cgi_set_parameter_nocopy(const char *zName, const char *zValue){ 386 390 if( nAllocQP<=nUsedQP ){ 387 391 nAllocQP = nAllocQP*2 + 10; 388 - aParamQP = realloc( aParamQP, nAllocQP*sizeof(aParamQP[0]) ); 389 - if( aParamQP==0 ) fossil_exit(1); 392 + aParamQP = fossil_realloc( aParamQP, nAllocQP*sizeof(aParamQP[0]) ); 390 393 } 391 394 aParamQP[nUsedQP].zName = zName; 392 395 aParamQP[nUsedQP].zValue = zValue; 393 396 if( g.fHttpTrace ){ 394 397 fprintf(stderr, "# cgi: %s = [%s]\n", zName, zValue); 395 398 } 396 399 aParamQP[nUsedQP].seq = seqQP++; ................................................................................ 457 460 ** should not be deallocated or changed again after this routine 458 461 ** returns or it will corrupt the parameter table. 459 462 */ 460 463 static void add_param_list(char *z, int terminator){ 461 464 while( *z ){ 462 465 char *zName; 463 466 char *zValue; 464 - while( isspace(*z) ){ z++; } 467 + while( fossil_isspace(*z) ){ z++; } 465 468 zName = z; 466 469 while( *z && *z!='=' && *z!=terminator ){ z++; } 467 470 if( *z=='=' ){ 468 471 *z = 0; 469 472 z++; 470 473 zValue = z; 471 474 while( *z && *z!=terminator ){ z++; } ................................................................................ 474 477 z++; 475 478 } 476 479 dehttpize(zValue); 477 480 }else{ 478 481 if( *z ){ *z++ = 0; } 479 482 zValue = ""; 480 483 } 481 - if( islower(zName[0]) ){ 484 + if( fossil_islower(zName[0]) ){ 482 485 cgi_set_parameter_nocopy(zName, zValue); 483 486 } 484 487 } 485 488 } 486 489 487 490 /* 488 491 ** *pz is a string that consists of multiple lines of text. This ................................................................................ 569 572 ** '\000' characters are inserted in z[] at the end of each token. 570 573 ** This routine returns the total number of tokens on the line, 6 571 574 ** in the example above. 572 575 */ 573 576 static int tokenize_line(char *z, int mxArg, char **azArg){ 574 577 int i = 0; 575 578 while( *z ){ 576 - while( isspace(*z) || *z==';' ){ z++; } 579 + while( fossil_isspace(*z) || *z==';' ){ z++; } 577 580 if( *z=='"' && z[1] ){ 578 581 *z = 0; 579 582 z++; 580 583 if( i<mxArg-1 ){ azArg[i++] = z; } 581 584 while( *z && *z!='"' ){ z++; } 582 585 if( *z==0 ) break; 583 586 *z = 0; 584 587 z++; 585 588 }else{ 586 589 if( i<mxArg-1 ){ azArg[i++] = z; } 587 - while( *z && !isspace(*z) && *z!=';' && *z!='"' ){ z++; } 590 + while( *z && !fossil_isspace(*z) && *z!=';' && *z!='"' ){ z++; } 588 591 if( *z && *z!='"' ){ 589 592 *z = 0; 590 593 z++; 591 594 } 592 595 } 593 596 } 594 597 azArg[i] = 0; ................................................................................ 615 618 616 619 zBoundry = get_line_from_string(&z, &len); 617 620 if( zBoundry==0 ) return; 618 621 while( (zLine = get_line_from_string(&z, &len))!=0 ){ 619 622 if( zLine[0]==0 ){ 620 623 int nContent = 0; 621 624 zValue = get_bounded_content(&z, &len, zBoundry, &nContent); 622 - if( zName && zValue && islower(zName[0]) ){ 625 + if( zName && zValue && fossil_islower(zName[0]) ){ 623 626 cgi_set_parameter_nocopy(zName, zValue); 624 627 if( showBytes ){ 625 628 cgi_set_parameter_nocopy(mprintf("%s:bytes", zName), 626 629 mprintf("%d",nContent)); 627 630 } 628 631 } 629 632 zName = 0; 630 633 showBytes = 0; 631 634 }else{ 632 635 nArg = tokenize_line(zLine, sizeof(azArg)/sizeof(azArg[0]), azArg); 633 636 for(i=0; i<nArg; i++){ 634 - int c = tolower(azArg[i][0]); 637 + int c = fossil_tolower(azArg[i][0]); 635 638 int n = strlen(azArg[i]); 636 639 if( c=='c' && sqlite3_strnicmp(azArg[i],"content-disposition:",n)==0 ){ 637 640 i++; 638 641 }else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){ 639 642 zName = azArg[++i]; 640 643 }else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){ 641 644 char *z = azArg[++i]; 642 - if( zName && z && islower(zName[0]) ){ 645 + if( zName && z && fossil_islower(zName[0]) ){ 643 646 cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z); 644 647 } 645 648 showBytes = 1; 646 649 }else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){ 647 650 char *z = azArg[++i]; 648 - if( zName && z && islower(zName[0]) ){ 651 + if( zName && z && fossil_islower(zName[0]) ){ 649 652 cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z); 650 653 } 651 654 } 652 655 } 653 656 } 654 657 } 655 658 } ................................................................................ 675 678 676 679 len = atoi(PD("CONTENT_LENGTH", "0")); 677 680 g.zContentType = zType = P("CONTENT_TYPE"); 678 681 if( len>0 && zType ){ 679 682 blob_zero(&g.cgiIn); 680 683 if( strcmp(zType,"application/x-www-form-urlencoded")==0 681 684 || strncmp(zType,"multipart/form-data",19)==0 ){ 682 - z = malloc( len+1 ); 683 - if( z==0 ) fossil_exit(1); 685 + z = fossil_malloc( len+1 ); 684 686 len = fread(z, 1, len, g.httpIn); 685 687 z[len] = 0; 686 688 if( zType[0]=='a' ){ 687 689 add_param_list(z, '&'); 688 690 }else{ 689 691 process_multipart_form_data(z, len); 690 692 } ................................................................................ 767 769 } 768 770 } 769 771 770 772 /* If no match is found and the name begins with an upper-case 771 773 ** letter, then check to see if there is an environment variable 772 774 ** with the given name. 773 775 */ 774 - if( isupper(zName[0]) ){ 776 + if( fossil_isupper(zName[0]) ){ 775 777 const char *zValue = getenv(zName); 776 778 if( zValue ){ 777 779 cgi_set_parameter_nocopy(zName, zValue); 778 780 CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue)); 779 781 return zValue; 780 782 } 781 783 } ................................................................................ 849 851 cgi_parameter("",""); /* Force the parameters into sorted order */ 850 852 for(i=0; i<nUsedQP; i++){ 851 853 cgi_printf("%s = %s <br />\n", 852 854 htmlize(aParamQP[i].zName, -1), htmlize(aParamQP[i].zValue, -1)); 853 855 } 854 856 } 855 857 856 -/* 857 -** Write HTML text for an option menu to standard output. zParam 858 -** is the query parameter that the option menu sets. zDflt is the 859 -** initial value of the option menu. Addition arguments are name/value 860 -** pairs that define values on the menu. The list is terminated with 861 -** a single NULL argument. 862 -*/ 863 -void cgi_optionmenu(int in, const char *zP, const char *zD, ...){ 864 - va_list ap; 865 - char *zName, *zVal; 866 - int dfltSeen = 0; 867 - cgi_printf("%*s<select size=1 name=\"%s\">\n", in, "", zP); 868 - va_start(ap, zD); 869 - while( (zName = va_arg(ap, char*))!=0 && (zVal = va_arg(ap, char*))!=0 ){ 870 - if( strcmp(zVal,zD)==0 ){ dfltSeen = 1; break; } 871 - } 872 - va_end(ap); 873 - if( !dfltSeen ){ 874 - if( zD[0] ){ 875 - cgi_printf("%*s<option value=\"%h\" selected>%h</option>\n", 876 - in+2, "", zD, zD); 877 - }else{ 878 - cgi_printf("%*s<option value=\"\" selected> </option>\n", in+2, ""); 879 - } 880 - } 881 - va_start(ap, zD); 882 - while( (zName = va_arg(ap, char*))!=0 && (zVal = va_arg(ap, char*))!=0 ){ 883 - if( zName[0] ){ 884 - cgi_printf("%*s<option value=\"%h\"%s>%h</option>\n", 885 - in+2, "", 886 - zVal, 887 - strcmp(zVal, zD) ? "" : " selected", 888 - zName 889 - ); 890 - }else{ 891 - cgi_printf("%*s<option value=\"\"%s> </option>\n", 892 - in+2, "", 893 - strcmp(zVal, zD) ? "" : " selected" 894 - ); 895 - } 896 - } 897 - va_end(ap); 898 - cgi_printf("%*s</select>\n", in, ""); 899 -} 900 - 901 -/* 902 -** This routine works a lot like cgi_optionmenu() except that the list of 903 -** values is contained in an array. Also, the values are just values, not 904 -** name/value pairs as in cgi_optionmenu. 905 -*/ 906 -void cgi_v_optionmenu( 907 - int in, /* Indent by this amount */ 908 - const char *zP, /* The query parameter name */ 909 - const char *zD, /* Default value */ 910 - const char **az /* NULL-terminated list of allowed values */ 911 -){ 912 - const char *zVal; 913 - int i; 914 - cgi_printf("%*s<select size=1 name=\"%s\">\n", in, "", zP); 915 - for(i=0; az[i]; i++){ 916 - if( strcmp(az[i],zD)==0 ) break; 917 - } 918 - if( az[i]==0 ){ 919 - if( zD[0]==0 ){ 920 - cgi_printf("%*s<option value=\"\" selected> </option>\n", 921 - in+2, ""); 922 - }else{ 923 - cgi_printf("%*s<option value=\"%h\" selected>%h</option>\n", 924 - in+2, "", zD, zD); 925 - } 926 - } 927 - while( (zVal = *(az++))!=0 ){ 928 - if( zVal[0] ){ 929 - cgi_printf("%*s<option value=\"%h\"%s>%h</option>\n", 930 - in+2, "", 931 - zVal, 932 - strcmp(zVal, zD) ? "" : " selected", 933 - zVal 934 - ); 935 - }else{ 936 - cgi_printf("%*s<option value=\"\"%s> </option>\n", 937 - in+2, "", 938 - strcmp(zVal, zD) ? "" : " selected" 939 - ); 940 - } 941 - } 942 - cgi_printf("%*s</select>\n", in, ""); 943 -} 944 - 945 -/* 946 -** This routine works a lot like cgi_v_optionmenu() except that the list 947 -** is a list of pairs. The first element of each pair is the value used 948 -** internally and the second element is the value displayed to the user. 949 -*/ 950 -void cgi_v_optionmenu2( 951 - int in, /* Indent by this amount */ 952 - const char *zP, /* The query parameter name */ 953 - const char *zD, /* Default value */ 954 - const char **az /* NULL-terminated list of allowed values */ 955 -){ 956 - const char *zVal; 957 - int i; 958 - cgi_printf("%*s<select size=1 name=\"%s\">\n", in, "", zP); 959 - for(i=0; az[i]; i+=2){ 960 - if( strcmp(az[i],zD)==0 ) break; 961 - } 962 - if( az[i]==0 ){ 963 - if( zD[0]==0 ){ 964 - cgi_printf("%*s<option value=\"\" selected> </option>\n", 965 - in+2, ""); 966 - }else{ 967 - cgi_printf("%*s<option value=\"%h\" selected>%h</option>\n", 968 - in+2, "", zD, zD); 969 - } 970 - } 971 - while( (zVal = *(az++))!=0 ){ 972 - const char *zName = *(az++); 973 - if( zName[0] ){ 974 - cgi_printf("%*s<option value=\"%h\"%s>%h</option>\n", 975 - in+2, "", 976 - zVal, 977 - strcmp(zVal, zD) ? "" : " selected", 978 - zName 979 - ); 980 - }else{ 981 - cgi_printf("%*s<option value=\"%h\"%s> </option>\n", 982 - in+2, "", 983 - zVal, 984 - strcmp(zVal, zD) ? "" : " selected" 985 - ); 986 - } 987 - } 988 - cgi_printf("%*s</select>\n", in, ""); 989 -} 990 - 991 858 /* 992 859 ** This routine works like "printf" except that it has the 993 860 ** extra formatting capabilities such as %h and %t. 994 861 */ 995 862 void cgi_printf(const char *zFormat, ...){ 996 863 va_list ap; 997 864 va_start(ap,zFormat); ................................................................................ 1045 912 */ 1046 913 static char *extract_token(char *zInput, char **zLeftOver){ 1047 914 char *zResult = 0; 1048 915 if( zInput==0 ){ 1049 916 if( zLeftOver ) *zLeftOver = 0; 1050 917 return 0; 1051 918 } 1052 - while( isspace(*zInput) ){ zInput++; } 919 + while( fossil_isspace(*zInput) ){ zInput++; } 1053 920 zResult = zInput; 1054 - while( *zInput && !isspace(*zInput) ){ zInput++; } 921 + while( *zInput && !fossil_isspace(*zInput) ){ zInput++; } 1055 922 if( *zInput ){ 1056 923 *zInput = 0; 1057 924 zInput++; 1058 - while( isspace(*zInput) ){ zInput++; } 925 + while( fossil_isspace(*zInput) ){ zInput++; } 1059 926 } 1060 927 if( zLeftOver ){ *zLeftOver = zInput; } 1061 928 return zResult; 1062 929 } 1063 930 1064 931 /* 1065 932 ** This routine handles a single HTTP request which is coming in on ................................................................................ 1070 937 ** the setup. Once all the setup is finished, this procedure returns 1071 938 ** and subsequent code handles the actual generation of the webpage. 1072 939 */ 1073 940 void cgi_handle_http_request(const char *zIpAddr){ 1074 941 char *z, *zToken; 1075 942 int i; 1076 943 struct sockaddr_in remoteName; 1077 - size_t size = sizeof(struct sockaddr_in); 944 + socklen_t size = sizeof(struct sockaddr_in); 1078 945 char zLine[2000]; /* A single line of input. */ 1079 946 1080 947 g.fullHttpReply = 1; 1081 948 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ 1082 949 malformed_request(); 1083 950 } 1084 951 zToken = extract_token(zLine, &z); ................................................................................ 1098 965 cgi_setenv("REQUEST_URI", zToken); 1099 966 for(i=0; zToken[i] && zToken[i]!='?'; i++){} 1100 967 if( zToken[i] ) zToken[i++] = 0; 1101 968 cgi_setenv("PATH_INFO", zToken); 1102 969 cgi_setenv("QUERY_STRING", &zToken[i]); 1103 970 if( zIpAddr==0 && 1104 971 getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName, 1105 - (socklen_t*)&size)>=0 972 + &size)>=0 1106 973 ){ 1107 974 zIpAddr = inet_ntoa(remoteName.sin_addr); 1108 975 } 1109 976 if( zIpAddr ){ 1110 977 cgi_setenv("REMOTE_ADDR", zIpAddr); 1111 978 g.zIpAddr = mprintf("%s", zIpAddr); 1112 979 } ................................................................................ 1115 982 */ 1116 983 while( fgets(zLine,sizeof(zLine),g.httpIn) ){ 1117 984 char *zFieldName; 1118 985 char *zVal; 1119 986 1120 987 zFieldName = extract_token(zLine,&zVal); 1121 988 if( zFieldName==0 || *zFieldName==0 ) break; 1122 - while( isspace(*zVal) ){ zVal++; } 989 + while( fossil_isspace(*zVal) ){ zVal++; } 1123 990 i = strlen(zVal); 1124 - while( i>0 && isspace(zVal[i-1]) ){ i--; } 991 + while( i>0 && fossil_isspace(zVal[i-1]) ){ i--; } 1125 992 zVal[i] = 0; 1126 - for(i=0; zFieldName[i]; i++){ zFieldName[i] = tolower(zFieldName[i]); } 1127 - if( strcmp(zFieldName,"user-agent:")==0 ){ 1128 - cgi_setenv("HTTP_USER_AGENT", zVal); 1129 - }else if( strcmp(zFieldName,"content-length:")==0 ){ 993 + for(i=0; zFieldName[i]; i++){ 994 + zFieldName[i] = fossil_tolower(zFieldName[i]); 995 + } 996 + if( strcmp(zFieldName,"content-length:")==0 ){ 1130 997 cgi_setenv("CONTENT_LENGTH", zVal); 1131 - }else if( strcmp(zFieldName,"referer:")==0 ){ 1132 - cgi_setenv("HTTP_REFERER", zVal); 1133 - }else if( strcmp(zFieldName,"host:")==0 ){ 1134 - cgi_setenv("HTTP_HOST", zVal); 1135 998 }else if( strcmp(zFieldName,"content-type:")==0 ){ 1136 999 cgi_setenv("CONTENT_TYPE", zVal); 1137 1000 }else if( strcmp(zFieldName,"cookie:")==0 ){ 1138 1001 cgi_setenv("HTTP_COOKIE", zVal); 1002 + }else if( strcmp(zFieldName,"https:")==0 ){ 1003 + cgi_setenv("HTTPS", zVal); 1004 + }else if( strcmp(zFieldName,"host:")==0 ){ 1005 + cgi_setenv("HTTP_HOST", zVal); 1139 1006 }else if( strcmp(zFieldName,"if-none-match:")==0 ){ 1140 1007 cgi_setenv("HTTP_IF_NONE_MATCH", zVal); 1141 1008 }else if( strcmp(zFieldName,"if-modified-since:")==0 ){ 1142 1009 cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal); 1143 1010 } 1011 +#if 0 1012 + else if( strcmp(zFieldName,"referer:")==0 ){ 1013 + cgi_setenv("HTTP_REFERER", zVal); 1014 + }else if( strcmp(zFieldName,"user-agent:")==0 ){ 1015 + cgi_setenv("HTTP_USER_AGENT", zVal); 1016 + } 1017 +#endif 1144 1018 } 1145 1019 1146 1020 cgi_init(); 1147 1021 } 1148 1022 1023 +#if INTERFACE 1024 +/* 1025 +** Bitmap values for the flags parameter to cgi_http_server(). 1026 +*/ 1027 +#define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */ 1028 + 1029 +#endif /* INTERFACE */ 1030 + 1149 1031 /* 1150 1032 ** Maximum number of child processes that we can have running 1151 1033 ** at one time before we start slowing things down. 1152 1034 */ 1153 1035 #define MAX_PARALLEL 2 1154 1036 1155 1037 /* ................................................................................ 1158 1040 ** As new connections arrive, fork a child and let child return 1159 1041 ** out of this procedure call. The child will handle the request. 1160 1042 ** The parent never returns from this procedure. 1161 1043 ** 1162 1044 ** Return 0 to each child as it runs. If unable to establish a 1163 1045 ** listening socket, return non-zero. 1164 1046 */ 1165 -int cgi_http_server(int mnPort, int mxPort, char *zBrowser){ 1166 -#ifdef __MINGW32__ 1047 +int cgi_http_server(int mnPort, int mxPort, char *zBrowser, int flags){ 1048 +#if defined(_WIN32) 1167 1049 /* Use win32_http_server() instead */ 1168 1050 fossil_exit(1); 1169 1051 #else 1170 1052 int listener = -1; /* The server socket */ 1171 1053 int connection; /* A socket for each individual connection */ 1172 1054 fd_set readfds; /* Set of file descriptors for select() */ 1173 - size_t lenaddr; /* Length of the inaddr structure */ 1055 + socklen_t lenaddr; /* Length of the inaddr structure */ 1174 1056 int child; /* PID of the child process */ 1175 1057 int nchildren = 0; /* Number of child processes */ 1176 1058 struct timeval delay; /* How long to wait inside select() */ 1177 1059 struct sockaddr_in inaddr; /* The socket address */ 1178 1060 int opt = 1; /* setsockopt flag */ 1179 1061 int iPort = mnPort; 1180 1062 1181 1063 while( iPort<=mxPort ){ 1182 1064 memset(&inaddr, 0, sizeof(inaddr)); 1183 1065 inaddr.sin_family = AF_INET; 1184 - inaddr.sin_addr.s_addr = INADDR_ANY; 1066 + if( flags & HTTP_SERVER_LOCALHOST ){ 1067 + inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1068 + }else{ 1069 + inaddr.sin_addr.s_addr = htonl(INADDR_ANY); 1070 + } 1185 1071 inaddr.sin_port = htons(iPort); 1186 1072 listener = socket(AF_INET, SOCK_STREAM, 0); 1187 1073 if( listener<0 ){ 1188 1074 iPort++; 1189 1075 continue; 1190 1076 } 1191 1077 ................................................................................ 1222 1108 /* Slow down if connections are arriving too fast */ 1223 1109 sleep( nchildren-MAX_PARALLEL ); 1224 1110 } 1225 1111 delay.tv_sec = 60; 1226 1112 delay.tv_usec = 0; 1227 1113 FD_ZERO(&readfds); 1228 1114 FD_SET( listener, &readfds); 1229 - if( select( listener+1, &readfds, 0, 0, &delay) ){ 1115 + select( listener+1, &readfds, 0, 0, &delay); 1116 + if( FD_ISSET(listener, &readfds) ){ 1230 1117 lenaddr = sizeof(inaddr); 1231 - connection = accept(listener, (struct sockaddr*)&inaddr, 1232 - (socklen_t*) &lenaddr); 1118 + connection = accept(listener, (struct sockaddr*)&inaddr, &lenaddr); 1233 1119 if( connection>=0 ){ 1234 1120 child = fork(); 1235 1121 if( child!=0 ){ 1236 1122 if( child>0 ) nchildren++; 1237 1123 close(connection); 1238 1124 }else{ 1239 1125 close(0);
Changes to src/checkin.c.
213 213 int nTerm = 0; 214 214 int i; 215 215 int cTerm; 216 216 217 217 if( zGlobList==0 || zGlobList[0]==0 ) return "0"; 218 218 blob_zero(&expr); 219 219 while( zGlobList[0] ){ 220 - while( isspace(zGlobList[0]) || zGlobList[0]==',' ) zGlobList++; 220 + while( fossil_isspace(zGlobList[0]) || zGlobList[0]==',' ) zGlobList++; 221 221 if( zGlobList[0]==0 ) break; 222 222 if( zGlobList[0]=='\'' || zGlobList[0]=='"' ){ 223 223 cTerm = zGlobList[0]; 224 224 zGlobList++; 225 225 }else{ 226 226 cTerm = ','; 227 227 } 228 228 for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){} 229 229 if( cTerm==',' ){ 230 - while( i>0 && isspace(zGlobList[i-1]) ){ i--; } 230 + while( i>0 && fossil_isspace(zGlobList[i-1]) ){ i--; } 231 231 } 232 232 blob_appendf(&expr, "%s%s GLOB '%.*q'", zSep, zVal, i, zGlobList); 233 233 zSep = " OR "; 234 234 if( cTerm!=',' && zGlobList[i] ) i++; 235 235 zGlobList += i; 236 236 if( zGlobList[0] ) zGlobList++; 237 237 nTerm++; ................................................................................ 257 257 void extra_cmd(void){ 258 258 Blob path; 259 259 Blob repo; 260 260 Stmt q; 261 261 int n; 262 262 const char *zIgnoreFlag = find_option("ignore",0,1); 263 263 int allFlag = find_option("dotfiles",0,0)!=0; 264 + int outputManifest = db_get_boolean("manifest",0); 264 265 265 266 db_must_be_within_tree(); 266 267 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)"); 267 268 n = strlen(g.zLocalRoot); 268 269 blob_init(&path, g.zLocalRoot, n-1); 269 270 if( zIgnoreFlag==0 ){ 270 271 zIgnoreFlag = db_get("ignore-glob", 0); 271 272 } 272 273 vfile_scan(0, &path, blob_size(&path), allFlag); 273 274 db_prepare(&q, 274 275 "SELECT x FROM sfile" 275 - " WHERE x NOT IN ('manifest','manifest.uuid','_FOSSIL_'," 276 + " WHERE x NOT IN ('%s','%s','_FOSSIL_'," 276 277 "'_FOSSIL_-journal','.fos','.fos-journal'," 277 278 "'_FOSSIL_-wal','_FOSSIL_-shm','.fos-wal'," 278 279 "'.fos-shm')" 279 280 " AND NOT %s" 280 281 " ORDER BY 1", 282 + outputManifest ? "manifest" : "_FOSSIL_", 283 + outputManifest ? "manifest.uuid" : "_FOSSIL_", 281 284 glob_expr("x", zIgnoreFlag) 282 285 ); 283 286 if( file_tree_name(g.zRepositoryName, &repo, 0) ){ 284 287 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); 285 288 } 286 289 while( db_step(&q)==SQLITE_ROW ){ 287 290 printf("%s\n", db_column_text(&q, 0)); ................................................................................ 399 402 if( zEditor==0 ){ 400 403 zEditor = getenv("VISUAL"); 401 404 } 402 405 if( zEditor==0 ){ 403 406 zEditor = getenv("EDITOR"); 404 407 } 405 408 if( zEditor==0 ){ 406 -#ifdef __MINGW32__ 409 +#if defined(_WIN32) 407 410 zEditor = "notepad"; 408 411 #else 409 412 zEditor = "ed"; 410 413 #endif 411 414 } 412 415 zFile = db_text(0, "SELECT '%qci-comment-' || hex(randomblob(6)) || '.txt'", 413 416 g.zLocalRoot); 414 -#ifdef __MINGW32__ 417 +#if defined(_WIN32) 415 418 blob_add_cr(&text); 416 419 #endif 417 420 blob_write_to_file(&text, zFile); 418 421 zCmd = mprintf("%s \"%s\"", zEditor, zFile); 419 422 printf("%s\n", zCmd); 420 - if( portable_system(zCmd) ){ 423 + if( fossil_system(zCmd) ){ 421 424 fossil_panic("editor aborted"); 422 425 } 423 426 blob_reset(&text); 424 427 blob_read_from_file(&text, zFile); 425 428 blob_remove_cr(&text); 426 429 unlink(zFile); 427 430 free(zFile); 428 431 blob_zero(pComment); 429 432 while( blob_line(&text, &line) ){ 430 433 int i, n; 431 434 char *z; 432 435 n = blob_size(&line); 433 436 z = blob_buffer(&line); 434 - for(i=0; i<n && isspace(z[i]); i++){} 437 + for(i=0; i<n && fossil_isspace(z[i]); i++){} 435 438 if( i<n && z[i]=='#' ) continue; 436 439 if( i<n || blob_size(pComment)>0 ){ 437 440 blob_appendf(pComment, "%b", &line); 438 441 } 439 442 } 440 443 blob_reset(&text); 441 444 zComment = blob_str(pComment); 442 445 i = strlen(zComment); 443 - while( i>0 && isspace(zComment[i-1]) ){ i--; } 446 + while( i>0 && fossil_isspace(zComment[i-1]) ){ i--; } 444 447 blob_resize(pComment, i); 445 448 } 446 449 447 450 /* 448 451 ** Populate the Global.aCommitFile[] based on the command line arguments 449 452 ** to a [commit] command. Global.aCommitFile is an array of integers 450 453 ** sized at (N+1), where N is the number of arguments passed to [commit]. ................................................................................ 459 462 ** to mean "all files". 460 463 */ 461 464 void select_commit_files(void){ 462 465 if( g.argc>2 ){ 463 466 int ii; 464 467 Blob b; 465 468 blob_zero(&b); 466 - g.aCommitFile = malloc(sizeof(int)*(g.argc-1)); 469 + g.aCommitFile = fossil_malloc(sizeof(int)*(g.argc-1)); 467 470 468 471 for(ii=2; ii<g.argc; ii++){ 469 472 int iId; 470 473 file_tree_name(g.argv[ii], &b, 1); 471 474 iId = db_int(-1, "SELECT id FROM vfile WHERE pathname=%Q", blob_str(&b)); 472 475 if( iId<0 ){ 473 476 fossil_fatal("fossil knows nothing about: %s", g.argv[ii]); ................................................................................ 511 514 b = db_exists( 512 515 "SELECT 1 FROM event" 513 516 " WHERE datetime(mtime)>=%Q" 514 517 " AND type='ci' AND objid=%d", 515 518 zDate, rid 516 519 ); 517 520 if( b ){ 518 - fossil_fatal("ancestor check-in [%.10s] (%s) is younger (clock skew?)", 519 - zUuid, zDate); 521 + fossil_fatal("ancestor check-in [%.10s] (%s) is not older (clock skew?)" 522 + " Use -f to override.", zUuid, zDate); 520 523 } 521 524 #endif 525 +} 526 + 527 +/* 528 +** zDate should be a valid date string. Convert this string into the 529 +** format YYYY-MM-DDTHH:MM:SS. If the string is not a valid date, 530 +** print a fatal error and quit. 531 +*/ 532 +char *date_in_standard_format(const char *zInputDate){ 533 + char *zDate = db_text(0, "SELECT datetime(%Q)", zInputDate); 534 + if( zDate[0]==0 ){ 535 + fossil_fatal("unrecognized date format (%s): use \"YYYY-MM-DD HH:MM:SS\"", 536 + zInputDate); 537 + } 538 + assert( strlen(zDate)==19 ); 539 + assert( zDate[10]==' ' ); 540 + zDate[10] = 'T'; 541 + return zDate; 542 +} 543 + 544 +/* 545 +** Create a manifest. 546 +*/ 547 +static void create_manifest( 548 + Blob *pOut, /* Write the manifest here */ 549 + const char *zBaselineUuid, /* UUID of baseline, or zero */ 550 + Manifest *pBaseline, /* Make it a delta manifest if not zero */ 551 + Blob *pComment, /* Check-in comment text */ 552 + int vid, /* blob-id of the parent manifest */ 553 + int verifyDate, /* Verify that child is younger */ 554 + Blob *pCksum, /* Repository checksum. May be 0 */ 555 + const char *zDateOvrd, /* Date override. If 0 then use 'now' */ 556 + const char *zUserOvrd, /* User override. If 0 then use g.zLogin */ 557 + const char *zBranch, /* Branch name. May be 0 */ 558 + const char *zBgColor, /* Background color. May be 0 */ 559 + int *pnFBcard /* Number of generated B- and F-cards */ 560 +){ 561 + char *zDate; /* Date of the check-in */ 562 + char *zParentUuid; /* UUID of parent check-in */ 563 + Blob filename; /* A single filename */ 564 + int nBasename; /* Size of base filename */ 565 + Stmt q; /* Query of files changed */ 566 + Stmt q2; /* Query of merge parents */ 567 + Blob mcksum; /* Manifest checksum */ 568 + ManifestFile *pFile; /* File from the baseline */ 569 + int nFBcard = 0; /* Number of B-cards and F-cards */ 570 + 571 + assert( pBaseline==0 || pBaseline->zBaseline==0 ); 572 + assert( pBaseline==0 || zBaselineUuid!=0 ); 573 + blob_zero(pOut); 574 + zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); 575 + if( pBaseline ){ 576 + blob_appendf(pOut, "B %s\n", zBaselineUuid); 577 + manifest_file_rewind(pBaseline); 578 + pFile = manifest_file_next(pBaseline, 0); 579 + nFBcard++; 580 + }else{ 581 + pFile = 0; 582 + } 583 + blob_appendf(pOut, "C %F\n", blob_str(pComment)); 584 + zDate = date_in_standard_format(zDateOvrd ? zDateOvrd : "now"); 585 + blob_appendf(pOut, "D %s\n", zDate); 586 + zDate[10] = ' '; 587 + db_prepare(&q, 588 + "SELECT pathname, uuid, origname, blob.rid, isexe" 589 + " FROM vfile JOIN blob ON vfile.mrid=blob.rid" 590 + " WHERE NOT deleted AND vfile.vid=%d" 591 + " ORDER BY 1", vid); 592 + blob_zero(&filename); 593 + blob_appendf(&filename, "%s", g.zLocalRoot); 594 + nBasename = blob_size(&filename); 595 + while( db_step(&q)==SQLITE_ROW ){ 596 + const char *zName = db_column_text(&q, 0); 597 + const char *zUuid = db_column_text(&q, 1); 598 + const char *zOrig = db_column_text(&q, 2); 599 + int frid = db_column_int(&q, 3); 600 + int isexe = db_column_int(&q, 4); 601 + const char *zPerm; 602 + int cmp; 603 + blob_append(&filename, zName, -1); 604 +#if !defined(_WIN32) 605 + /* For unix, extract the "executable" permission bit directly from 606 + ** the filesystem. On windows, the "executable" bit is retained 607 + ** unchanged from the original. */ 608 + isexe = file_isexe(blob_str(&filename)); 609 +#endif ................................................................................ 610 + if( isexe ){ 611 + zPerm = " x"; 612 + }else{ 613 + zPerm = ""; 614 + } 615 + if( !g.markPrivate ) content_make_public(frid); 616 + while( pFile && strcmp(pFile->zName,zName)<0 ){ 617 + blob_appendf(pOut, "F %F\n", pFile->zName); 618 + pFile = manifest_file_next(pBaseline, 0); 619 + nFBcard++; 620 + } 621 + cmp = 1; 622 + if( pFile==0 623 + || (cmp = strcmp(pFile->zName,zName))!=0 624 + || strcmp(pFile->zUuid, zUuid)!=0 625 + ){ 626 + blob_resize(&filename, nBasename); 627 + if( zOrig==0 || strcmp(zOrig,zName)==0 ){ 628 + blob_appendf(pOut, "F %F %s%s\n", zName, zUuid, zPerm); 629 + }else{ 630 + if( zPerm[0]==0 ){ zPerm = " w"; } 631 + blob_appendf(pOut, "F %F %s%s %F\n", zName, zUuid, zPerm, zOrig); 632 + } 633 + nFBcard++; 634 + } 635 + if( cmp==0 ) pFile = manifest_file_next(pBaseline,0); 636 + } 637 + blob_reset(&filename); 638 + db_finalize(&q); 639 + while( pFile ){ 640 + blob_appendf(pOut, "F %F\n", pFile->zName); 641 + pFile = manifest_file_next(pBaseline, 0); 642 + nFBcard++; 643 + } 644 + blob_appendf(pOut, "P %s", zParentUuid); 645 + if( verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate); 646 + free(zParentUuid); 647 + db_prepare(&q2, "SELECT merge FROM vmerge WHERE id=:id"); 648 + db_bind_int(&q2, ":id", 0); 649 + while( db_step(&q2)==SQLITE_ROW ){ 650 + char *zMergeUuid; 651 + int mid = db_column_int(&q2, 0); 652 + if( !g.markPrivate && content_is_private(mid) ) continue; 653 + zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid); 654 + if( zMergeUuid ){ 655 + blob_appendf(pOut, " %s", zMergeUuid); 656 + if( verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate); 657 + free(zMergeUuid); 658 + } 659 + } 660 + db_finalize(&q2); 661 + free(zDate); 662 + 663 + blob_appendf(pOut, "\n"); 664 + if( pCksum ) blob_appendf(pOut, "R %b\n", pCksum); 665 + if( zBranch && zBranch[0] ){ 666 + Stmt q; 667 + if( zBgColor && zBgColor[0] ){ 668 + blob_appendf(pOut, "T *bgcolor * %F\n", zBgColor); 669 + } 670 + blob_appendf(pOut, "T *branch * %F\n", zBranch); 671 + blob_appendf(pOut, "T *sym-%F *\n", zBranch); 672 + 673 + /* Cancel all other symbolic tags */ 674 + db_prepare(&q, 675 + "SELECT tagname FROM tagxref, tag" 676 + " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid" 677 + " AND tagtype>0 AND tagname GLOB 'sym-*'" 678 + " AND tagname!='sym-'||%Q" 679 + " ORDER BY tagname", 680 + vid, zBranch); 681 + while( db_step(&q)==SQLITE_ROW ){ 682 + const char *zTag = db_column_text(&q, 0); 683 + blob_appendf(pOut, "T -%F *\n", zTag); 684 + } 685 + db_finalize(&q); 686 + } 687 + blob_appendf(pOut, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); 688 + md5sum_blob(pOut, &mcksum); 689 + blob_appendf(pOut, "Z %b\n", &mcksum); 690 + if( pnFBcard ) *pnFBcard = nFBcard; 522 691 } 692 + 523 693 524 694 /* 525 695 ** COMMAND: ci 526 696 ** COMMAND: commit 527 697 ** 528 698 ** Usage: %fossil commit ?OPTIONS? ?FILE...? 529 699 ** 530 700 ** Create a new version containing all of the changes in the current 531 701 ** checkout. You will be prompted to enter a check-in comment unless 532 -** the comment has been specified on the command-line using "-m". 533 -** The editor defined in the "editor" fossil option (see %fossil help set) 534 -** will be used, or from the "VISUAL" or "EDITOR" environment variables 535 -** (in that order) if no editor is set. 702 +** the comment has been specified on the command-line using "-m" or a 703 +** file containing the comment using -M. The editor defined in the 704 +** "editor" fossil option (see %fossil help set) will be used, or from 705 +** the "VISUAL" or "EDITOR" environment variables (in that order) if 706 +** no editor is set. 707 +** 708 +** All files that have changed will be committed unless some subset of 709 +** files is specified on the command line. 536 710 ** 537 -** You will be prompted for your GPG passphrase in order to sign the 538 -** new manifest unless the "--nosign" option is used. All files that 539 -** have changed will be committed unless some subset of files is 540 -** specified on the command line. 541 -** 542 -** The --branch option followed by a branch name cases the new check-in 711 +** The --branch option followed by a branch name causes the new check-in 543 712 ** to be placed in the named branch. The --bgcolor option can be followed 544 713 ** by a color name (ex: '#ffc0c0') to specify the background color of 545 714 ** entries in the new branch when shown in the web timeline interface. 546 715 ** 547 716 ** A check-in is not permitted to fork unless the --force or -f 548 717 ** option appears. A check-in is not allowed against a closed check-in. 549 718 ** 550 719 ** The --private option creates a private check-in that is never synced. 551 720 ** Children of private check-ins are automatically private. 552 721 ** 553 722 ** Options: 554 723 ** 555 724 ** --comment|-m COMMENT-TEXT 725 +** --message-file|-M COMMENT-FILE 556 726 ** --branch NEW-BRANCH-NAME 557 727 ** --bgcolor COLOR 558 728 ** --nosign 559 729 ** --force|-f 560 730 ** --private 731 +** --baseline 732 +** --delta 561 733 ** 562 734 */ 563 735 void commit_cmd(void){ 564 - int rc; 565 - int vid, nrid, nvid; 566 - Blob comment; 567 - const char *zComment; 568 - Stmt q; 569 - Stmt q2; 570 - char *zUuid, *zDate; 736 + int hasChanges; /* True if unsaved changes exist */ 737 + int vid; /* blob-id of parent version */ 738 + int nrid; /* blob-id of a modified file */ 739 + int nvid; /* Blob-id of the new check-in */ 740 + Blob comment; /* Check-in comment */ 741 + const char *zComment; /* Check-in comment */ 742 + Stmt q; /* Query to find files that have been modified */ 743 + char *zUuid; /* UUID of the new check-in */ 571 744 int noSign = 0; /* True to omit signing the manifest using GPG */ 572 745 int isAMerge = 0; /* True if checking in a merge */ 573 746 int forceFlag = 0; /* Force a fork */ 747 + int forceDelta = 0; /* Force a delta-manifest */ 748 + int forceBaseline = 0; /* Force a baseline-manifest */ 574 749 char *zManifestFile; /* Name of the manifest file */ 575 - int nBasename; /* Length of "g.zLocalRoot/" */ 750 + int useCksum; /* True if checksums should be computed and verified */ 751 + int outputManifest; /* True to output "manifest" and "manifest.uuid" */ 752 + int testRun; /* True for a test run. Debugging only */ 576 753 const char *zBranch; /* Create a new branch with this name */ 577 754 const char *zBgColor; /* Set background color when branching */ 578 755 const char *zDateOvrd; /* Override date string */ 579 756 const char *zUserOvrd; /* Override user name */ 580 757 const char *zComFile; /* Read commit message from this file */ 581 - Blob filename; /* complete filename */ 582 - Blob manifest; 758 + Blob manifest; /* Manifest in baseline form */ 583 759 Blob muuid; /* Manifest uuid */ 584 - Blob mcksum; /* Self-checksum on the manifest */ 585 760 Blob cksum1, cksum2; /* Before and after commit checksums */ 586 761 Blob cksum1b; /* Checksum recorded in the manifest */ 762 + int szD; /* Size of the delta manifest */ 763 + int szB; /* Size of the baseline manifest */ 587 764 588 765 url_proxy_options(); 589 766 noSign = find_option("nosign",0,0)!=0; 767 + forceDelta = find_option("delta",0,0)!=0; 768 + forceBaseline = find_option("baseline",0,0)!=0; 769 + if( forceDelta && forceBaseline ){ 770 + fossil_fatal("cannot use --delta and --baseline together"); 771 + } 772 + testRun = find_option("test",0,0)!=0; 590 773 zComment = find_option("comment","m",1); 591 774 forceFlag = find_option("force", "f", 0)!=0; 592 775 zBranch = find_option("branch","b",1); 593 776 zBgColor = find_option("bgcolor",0,1); 594 777 zComFile = find_option("message-file", "M", 1); 595 778 if( find_option("private",0,0) ){ 596 779 g.markPrivate = 1; ................................................................................ 598 781 if( zBgColor==0 ) zBgColor = "#fec084"; /* Orange */ 599 782 } 600 783 zDateOvrd = find_option("date-override",0,1); 601 784 zUserOvrd = find_option("user-override",0,1); 602 785 db_must_be_within_tree(); 603 786 noSign = db_get_boolean("omitsign", 0)|noSign; 604 787 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; } 788 + useCksum = db_get_boolean("repo-cksum", 1); 789 + outputManifest = db_get_boolean("manifest", 0); 605 790 verify_all_options(); 791 + 792 + /* So that older versions of Fossil (that do not understand delta- 793 + ** manifest) can continue to use this repository, do not create a new 794 + ** delta-manifest unless this repository already contains one or more 795 + ** delta-manifets, or unless the delta-manifest is explicitly requested 796 + ** by the --delta option. 797 + */ 798 + if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){ 799 + forceBaseline = 1; 800 + } 606 801 607 802 /* Get the ID of the parent manifest artifact */ 608 803 vid = db_lget_int("checkout", 0); 609 804 if( content_is_private(vid) ){ 610 805 g.markPrivate = 1; 611 806 } 612 807 613 808 /* 614 809 ** Autosync if autosync is enabled and this is not a private check-in. 615 810 */ 616 811 if( !g.markPrivate ){ 617 812 autosync(AUTOSYNC_PULL); 618 813 } 814 + 815 + /* Require confirmation to continue with the check-in if there is 816 + ** clock skew 817 + */ 818 + if( g.clockSkewSeen ){ 819 + Blob ans; 820 + blob_zero(&ans); 821 + prompt_user("continue in spite of time skew (y/N)? ", &ans); 822 + if( blob_str(&ans)[0]!='y' ){ 823 + fossil_exit(1); 824 + } 825 + } 619 826 620 827 /* There are two ways this command may be executed. If there are 621 828 ** no arguments following the word "commit", then all modified files 622 829 ** in the checked out directory are committed. If one or more arguments 623 830 ** follows "commit", then only those files are committed. 624 831 ** 625 832 ** After the following function call has returned, the Global.aCommitFile[] ................................................................................ 637 844 /* 638 845 ** Check that the user exists. 639 846 */ 640 847 if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ 641 848 fossil_fatal("no such user: %s", g.zLogin); 642 849 } 643 850 851 + hasChanges = unsaved_changes(); 644 852 db_begin_transaction(); 645 853 db_record_repository_filename(0); 646 - rc = unsaved_changes(); 647 - if( rc==0 && !isAMerge && !forceFlag ){ 648 - fossil_panic("nothing has changed"); 854 + if( hasChanges==0 && !isAMerge && !forceFlag ){ 855 + fossil_fatal("nothing has changed"); 649 856 } 650 857 651 858 /* If one or more files that were named on the command line have not 652 859 ** been modified, bail out now. 653 860 */ 654 861 if( g.aCommitFile ){ 655 862 Blob unmodified; ................................................................................ 676 883 */ 677 884 if( db_exists("SELECT 1 FROM tagxref" 678 885 " WHERE tagid=%d AND rid=%d AND tagtype>0", 679 886 TAG_CLOSED, vid) ){ 680 887 fossil_fatal("cannot commit against a closed leaf"); 681 888 } 682 889 683 - vfile_aggregate_checksum_disk(vid, &cksum1); 890 + if( useCksum ) vfile_aggregate_checksum_disk(vid, &cksum1); 684 891 if( zComment ){ 685 892 blob_zero(&comment); 686 893 blob_append(&comment, zComment, -1); 687 894 }else if( zComFile ){ 688 895 blob_zero(&comment); 689 896 blob_read_from_file(&comment, zComFile); 690 897 }else{ ................................................................................ 731 938 content_deltify(rid, nrid, 0); 732 939 } 733 940 db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id); 734 941 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); 735 942 } 736 943 db_finalize(&q); 737 944 738 - /* Create the manifest */ 739 - blob_zero(&manifest); 945 + /* Create the new manifest */ 740 946 if( blob_size(&comment)==0 ){ 741 947 blob_append(&comment, "(no comment)", -1); 742 948 } 743 - blob_appendf(&manifest, "C %F\n", blob_str(&comment)); 744 - zDate = db_text(0, "SELECT datetime('%q')", zDateOvrd ? zDateOvrd : "now"); 745 - zDate[10] = 'T'; 746 - blob_appendf(&manifest, "D %s\n", zDate); 747 - zDate[10] = ' '; 748 - db_prepare(&q, 749 - "SELECT pathname, uuid, origname, blob.rid, isexe" 750 - " FROM vfile JOIN blob ON vfile.mrid=blob.rid" 751 - " WHERE NOT deleted AND vfile.vid=%d" 752 - " ORDER BY 1", vid); 753 - blob_zero(&filename); 754 - blob_appendf(&filename, "%s", g.zLocalRoot); 755 - nBasename = blob_size(&filename); 756 - while( db_step(&q)==SQLITE_ROW ){ 757 - const char *zName = db_column_text(&q, 0); 758 - const char *zUuid = db_column_text(&q, 1); 759 - const char *zOrig = db_column_text(&q, 2); 760 - int frid = db_column_int(&q, 3); 761 - int isexe = db_column_int(&q, 4); 762 - const char *zPerm; 763 - blob_append(&filename, zName, -1); 764 -#ifndef __MINGW32__ 765 - /* For unix, extract the "executable" permission bit directly from 766 - ** the filesystem. On windows, the "executable" bit is retained 767 - ** unchanged from the original. */ 768 - isexe = file_isexe(blob_str(&filename)); 769 -#endif 770 - if( isexe ){ 771 - zPerm = " x"; 949 + if( forceDelta ){ 950 + blob_zero(&manifest); 951 + }else{ 952 + create_manifest(&manifest, 0, 0, &comment, vid, 953 + !forceFlag, useCksum ? &cksum1 : 0, 954 + zDateOvrd, zUserOvrd, zBranch, zBgColor, &szB); 955 + } 956 + 957 + /* See if a delta-manifest would be more appropriate */ 958 + if( !forceBaseline ){ 959 + const char *zBaselineUuid; 960 + Manifest *pParent; 961 + Manifest *pBaseline; 962 + pParent = manifest_get(vid, CFTYPE_MANIFEST); 963 + if( pParent && pParent->zBaseline ){ 964 + zBaselineUuid = pParent->zBaseline; 965 + pBaseline = manifest_get_by_name(zBaselineUuid, 0); 772 966 }else{ 773 - zPerm = ""; 774 - } 775 - blob_resize(&filename, nBasename); 776 - if( zOrig==0 || strcmp(zOrig,zName)==0 ){ 777 - blob_appendf(&manifest, "F %F %s%s\n", zName, zUuid, zPerm); 778 - }else{ 779 - if( zPerm[0]==0 ){ zPerm = " w"; } 780 - blob_appendf(&manifest, "F %F %s%s %F\n", zName, zUuid, zPerm, zOrig); 967 + zBaselineUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); 968 + pBaseline = pParent; 781 969 } 782 - if( !g.markPrivate ) content_make_public(frid); 783 - } 784 - blob_reset(&filename); 785 - db_finalize(&q); 786 - zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); 787 - blob_appendf(&manifest, "P %s", zUuid); 788 - checkin_verify_younger(vid, zUuid, zDate); 789 - 790 - db_prepare(&q2, "SELECT merge FROM vmerge WHERE id=:id"); 791 - db_bind_int(&q2, ":id", 0); 792 - while( db_step(&q2)==SQLITE_ROW ){ 793 - int mid = db_column_int(&q2, 0); 794 - if( !g.markPrivate && content_is_private(mid) ) continue; 795 - zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid); 796 - if( zUuid ){ 797 - blob_appendf(&manifest, " %s", zUuid); 798 - checkin_verify_younger(mid, zUuid, zDate); 799 - free(zUuid); 970 + if( pBaseline ){ 971 + Blob delta; 972 + create_manifest(&delta, zBaselineUuid, pBaseline, &comment, vid, 973 + !forceFlag, useCksum ? &cksum1 : 0, 974 + zDateOvrd, zUserOvrd, zBranch, zBgColor, &szD); 975 + /* 976 + ** At this point, two manifests have been constructed, either of 977 + ** which would work for this checkin. The first manifest (held 978 + ** in the "manifest" variable) is a baseline manifest and the second 979 + ** (held in variable named "delta") is a delta manifest. The 980 + ** question now is: which manifest should we use? 981 + ** 982 + ** Let B be the number of F-cards in the baseline manifest and 983 + ** let D be the number of F-cards in the delta manifest, plus one for 984 + ** the B-card. (B is held in the szB variable and D is held in the 985 + ** szD variable.) Assume that all delta manifests adds X new F-cards. 986 + ** Then to minimize the total number of F- and B-cards in the repository, 987 + ** we should use the delta manifest if and only if: 988 + ** 989 + ** D*D < B*X - X*X 990 + ** 991 + ** X is an unknown here, but for most repositories, we will not be 992 + ** far wrong if we assume X=3. 993 + */ 994 + if( forceDelta || (szD*szD)<(szB*3-9) ){ 995 + blob_reset(&manifest); 996 + manifest = delta; 997 + }else{ 998 + blob_reset(&delta); 999 + } 1000 + }else if( forceDelta ){ 1001 + fossil_panic("unable to find a baseline-manifest for the delta"); 800 1002 } 801 1003 } 802 - db_reset(&q2); 803 - 804 - blob_appendf(&manifest, "\n"); 805 - blob_appendf(&manifest, "R %b\n", &cksum1); 806 - if( zBranch && zBranch[0] ){ 807 - Stmt q; 808 - if( zBgColor && zBgColor[0] ){ 809 - blob_appendf(&manifest, "T *bgcolor * %F\n", zBgColor); 810 - } 811 - blob_appendf(&manifest, "T *branch * %F\n", zBranch); 812 - blob_appendf(&manifest, "T *sym-%F *\n", zBranch); 813 - 814 - /* Cancel all other symbolic tags */ 815 - db_prepare(&q, 816 - "SELECT tagname FROM tagxref, tag" 817 - " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid" 818 - " AND tagtype>0 AND tagname GLOB 'sym-*'" 819 - " AND tagname!='sym-'||%Q" 820 - " ORDER BY tagname", 821 - vid, zBranch); 822 - while( db_step(&q)==SQLITE_ROW ){ 823 - const char *zTag = db_column_text(&q, 0); 824 - blob_appendf(&manifest, "T -%F *\n", zTag); 825 - } 826 - db_finalize(&q); 827 - } 828 - blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); 829 - md5sum_blob(&manifest, &mcksum); 830 - blob_appendf(&manifest, "Z %b\n", &mcksum); 831 - zManifestFile = mprintf("%smanifest", g.zLocalRoot); 832 1004 if( !noSign && !g.markPrivate && clearsign(&manifest, &manifest) ){ 833 1005 Blob ans; 834 1006 blob_zero(&ans); 835 1007 prompt_user("unable to sign manifest. continue (y/N)? ", &ans); 836 1008 if( blob_str(&ans)[0]!='y' ){ 837 1009 fossil_exit(1); 838 1010 } 839 1011 } 840 - blob_write_to_file(&manifest, zManifestFile); 841 - blob_reset(&manifest); 842 - blob_read_from_file(&manifest, zManifestFile); 843 - free(zManifestFile); 1012 + 1013 + /* If the --test option is specified, output the manifest file 1014 + ** and rollback the transaction. 1015 + */ 1016 + if( testRun ){ 1017 + blob_write_to_file(&manifest, ""); 1018 + } 1019 + 1020 + if( outputManifest ){ 1021 + zManifestFile = mprintf("%smanifest", g.zLocalRoot); 1022 + blob_write_to_file(&manifest, zManifestFile); 1023 + blob_reset(&manifest); 1024 + blob_read_from_file(&manifest, zManifestFile); 1025 + free(zManifestFile); 1026 + } 844 1027 nvid = content_put(&manifest, 0, 0); 845 1028 if( nvid==0 ){ 846 1029 fossil_panic("trouble committing manifest: %s", g.zErrMsg); 847 1030 } 848 1031 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); 849 1032 manifest_crosslink(nvid, &manifest); 850 1033 content_deltify(vid, nvid, 0); 851 1034 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); 852 1035 printf("New_Version: %s\n", zUuid); 853 - zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot); 854 - blob_zero(&muuid); 855 - blob_appendf(&muuid, "%s\n", zUuid); 856 - blob_write_to_file(&muuid, zManifestFile); 857 - free(zManifestFile); 858 - blob_reset(&muuid); 1036 + if( outputManifest ){ 1037 + zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot); 1038 + blob_zero(&muuid); 1039 + blob_appendf(&muuid, "%s\n", zUuid); 1040 + blob_write_to_file(&muuid, zManifestFile); 1041 + free(zManifestFile); 1042 + blob_reset(&muuid); 1043 + } 859 1044 860 1045 861 1046 /* Update the vfile and vmerge tables */ 862 1047 db_multi_exec( 863 1048 "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND file_is_selected(id);" 864 1049 "DELETE FROM vmerge WHERE file_is_selected(id) OR id=0;" 865 1050 "UPDATE vfile SET vid=%d;" 866 1051 "UPDATE vfile SET rid=mrid, chnged=0, deleted=0, origname=NULL" 867 1052 " WHERE file_is_selected(id);" 868 1053 , vid, nvid 869 1054 ); 870 1055 db_lset_int("checkout", nvid); 871 1056 872 - /* Verify that the repository checksum matches the expected checksum 873 - ** calculated before the checkin started (and stored as the R record 874 - ** of the manifest file). 875 - */ 876 - vfile_aggregate_checksum_repository(nvid, &cksum2); 877 - if( blob_compare(&cksum1, &cksum2) ){ 878 - fossil_panic("tree checksum does not match repository after commit"); 879 - } 880 - 881 - /* Verify that the manifest checksum matches the expected checksum */ 882 - vfile_aggregate_checksum_manifest(nvid, &cksum2, &cksum1b); 883 - if( blob_compare(&cksum1, &cksum1b) ){ 884 - fossil_panic("manifest checksum does not agree with manifest: " 885 - "%b versus %b", &cksum1, &cksum1b); 886 - } 887 - if( blob_compare(&cksum1, &cksum2) ){ 888 - fossil_panic("tree checksum does not match manifest after commit: " 889 - "%b versus %b", &cksum1, &cksum2); 890 - } 891 - 892 - /* Verify that the commit did not modify any disk images. */ 893 - vfile_aggregate_checksum_disk(nvid, &cksum2); 894 - if( blob_compare(&cksum1, &cksum2) ){ 895 - fossil_panic("tree checksums before and after commit do not match"); 1057 + if( useCksum ){ 1058 + /* Verify that the repository checksum matches the expected checksum 1059 + ** calculated before the checkin started (and stored as the R record 1060 + ** of the manifest file). 1061 + */ 1062 + vfile_aggregate_checksum_repository(nvid, &cksum2); 1063 + if( blob_compare(&cksum1, &cksum2) ){ 1064 + fossil_panic("tree checksum does not match repository after commit"); 1065 + } 1066 + 1067 + /* Verify that the manifest checksum matches the expected checksum */ 1068 + vfile_aggregate_checksum_manifest(nvid, &cksum2, &cksum1b); 1069 + if( blob_compare(&cksum1, &cksum1b) ){ 1070 + fossil_panic("manifest checksum does not agree with manifest: " 1071 + "%b versus %b", &cksum1, &cksum1b); 1072 + } 1073 + if( blob_compare(&cksum1, &cksum2) ){ 1074 + fossil_panic("tree checksum does not match manifest after commit: " 1075 + "%b versus %b", &cksum1, &cksum2); 1076 + } 1077 + 1078 + /* Verify that the commit did not modify any disk images. */ 1079 + vfile_aggregate_checksum_disk(nvid, &cksum2); 1080 + if( blob_compare(&cksum1, &cksum2) ){ 1081 + fossil_panic("tree checksums before and after commit do not match"); 1082 + } 896 1083 } 897 1084 898 1085 /* Clear the undo/redo stack */ 899 1086 undo_reset(); 900 1087 901 1088 /* Commit */ 902 1089 db_multi_exec("DELETE FROM vvar WHERE name='ci-comment'"); 1090 + if( testRun ){ 1091 + db_end_transaction(1); 1092 + exit(1); 1093 + } 903 1094 db_end_transaction(0); 904 1095 905 1096 if( !g.markPrivate ){ 906 1097 autosync(AUTOSYNC_PUSH); 907 1098 } 908 1099 if( count_nonbranch_children(vid)>1 ){ 909 1100 printf("**** warning: a fork has occurred *****\n"); 910 1101 } 911 1102 }
Changes to src/checkout.c.
76 76 return vid; 77 77 } 78 78 79 79 /* 80 80 ** Load a vfile from a record ID. 81 81 */ 82 82 void load_vfile_from_rid(int vid){ 83 - Blob manifest; 84 - 85 83 if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){ 86 84 return; 87 85 } 88 - content_get(vid, &manifest); 89 - vfile_build(vid, &manifest); 90 - blob_reset(&manifest); 86 + vfile_build(vid); 91 87 } 92 88 93 89 /* 94 90 ** Set or clear the vfile.isexe flag for a file. 95 91 */ 96 92 static void set_or_clear_isexe(const char *zFilename, int vid, int onoff){ 97 - db_multi_exec("UPDATE vfile SET isexe=%d WHERE vid=%d and pathname=%Q", 98 - onoff, vid, zFilename); 93 + static Stmt s; 94 + db_static_prepare(&s, 95 + "UPDATE vfile SET isexe=:isexe" 96 + " WHERE vid=:vid AND pathname=:path AND isexe!=:isexe" 97 + ); 98 + db_bind_int(&s, ":isexe", onoff); 99 + db_bind_int(&s, ":vid", vid); 100 + db_bind_text(&s, ":path", zFilename); 101 + db_step(&s); 102 + db_reset(&s); 103 +} 104 + 105 +/* 106 +** Set or clear the execute permission bit (as appropriate) for all 107 +** files in the current check-out. 108 +*/ 109 +void checkout_set_all_exe(int vid){ 110 + Blob filename; 111 + int baseLen; 112 + Manifest *pManifest; 113 + ManifestFile *pFile; 114 + 115 + /* Check the EXE permission status of all files 116 + */ 117 + pManifest = manifest_get(vid, CFTYPE_MANIFEST); 118 + if( pManifest==0 ) return; 119 + blob_zero(&filename); 120 + blob_appendf(&filename, "%s/", g.zLocalRoot); 121 + baseLen = blob_size(&filename); 122 + manifest_file_rewind(pManifest); 123 + while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ 124 + int isExe; 125 + blob_append(&filename, pFile->zName, -1); 126 + isExe = pFile->zPerm && strstr(pFile->zPerm, "x"); 127 + file_setexe(blob_str(&filename), isExe); 128 + set_or_clear_isexe(pFile->zName, vid, isExe); 129 + blob_resize(&filename, baseLen); 130 + } 131 + blob_reset(&filename); 132 + manifest_destroy(pManifest); 99 133 } 134 + 100 135 101 136 /* 102 -** Read the manifest file given by vid out of the repository 103 -** and store it in the root of the local check-out. 137 +** If the "manifest" setting is true, then automatically generate 138 +** files named "manifest" and "manifest.uuid" containing, respectively, 139 +** the text of the manifest and the artifact ID of the manifest. 104 140 */ 105 141 void manifest_to_disk(int vid){ 106 142 char *zManFile; 107 143 Blob manifest; 108 144 Blob hash; 109 - Blob filename; 110 - int baseLen; 111 - int i; 112 - Manifest m; 113 145 114 - blob_zero(&manifest); 115 - zManFile = mprintf("%smanifest", g.zLocalRoot); 116 - content_get(vid, &manifest); 117 - blob_write_to_file(&manifest, zManFile); 118 - free(zManFile); 119 - blob_zero(&hash); 120 - sha1sum_blob(&manifest, &hash); 121 - zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); 122 - blob_append(&hash, "\n", 1); 123 - blob_write_to_file(&hash, zManFile); 124 - free(zManFile); 125 - blob_reset(&hash); 126 - manifest_parse(&m, &manifest); 127 - blob_zero(&filename); 128 - blob_appendf(&filename, "%s/", g.zLocalRoot); 129 - baseLen = blob_size(&filename); 130 - for(i=0; i<m.nFile; i++){ 131 - int isExe; 132 - blob_append(&filename, m.aFile[i].zName, -1); 133 - isExe = m.aFile[i].zPerm && strstr(m.aFile[i].zPerm, "x"); 134 - file_setexe(blob_str(&filename), isExe); 135 - set_or_clear_isexe(m.aFile[i].zName, vid, isExe); 136 - blob_resize(&filename, baseLen); 146 + if( db_get_boolean("manifest",0) ){ 147 + blob_zero(&manifest); 148 + content_get(vid, &manifest); 149 + zManFile = mprintf("%smanifest", g.zLocalRoot); 150 + blob_write_to_file(&manifest, zManFile); 151 + free(zManFile); 152 + blob_zero(&hash); 153 + sha1sum_blob(&manifest, &hash); 154 + zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); 155 + blob_append(&hash, "\n", 1); 156 + blob_write_to_file(&hash, zManFile); 157 + free(zManFile); 158 + blob_reset(&hash); 159 + }else{ 160 + if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){ 161 + zManFile = mprintf("%smanifest", g.zLocalRoot); 162 + unlink(zManFile); 163 + free(zManFile); 164 + } 165 + if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){ 166 + zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); 167 + unlink(zManFile); 168 + free(zManFile); 169 + } 137 170 } 138 - blob_reset(&filename); 139 - manifest_clear(&m); 171 + 140 172 } 141 173 142 174 /* 143 175 ** COMMAND: checkout 144 176 ** COMMAND: co 145 177 ** 146 178 ** Usage: %fossil checkout VERSION ?-f|--force? ?--keep? ................................................................................ 206 238 if( !keepFlag ){ 207 239 uncheckout(prior); 208 240 } 209 241 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid); 210 242 if( !keepFlag ){ 211 243 vfile_to_disk(vid, 0, 1, promptFlag); 212 244 } 245 + checkout_set_all_exe(vid); 213 246 manifest_to_disk(vid); 214 247 db_lset_int("checkout", vid); 215 248 undo_reset(); 216 249 db_multi_exec("DELETE FROM vmerge"); 217 250 if( !keepFlag ){ 218 251 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b); 219 252 vfile_aggregate_checksum_disk(vid, &cksum2); 220 253 if( blob_compare(&cksum1, &cksum2) ){ 221 254 printf("WARNING: manifest checksum does not agree with disk\n"); 222 255 } 223 - if( blob_compare(&cksum1, &cksum1b) ){ 256 + if( blob_size(&cksum1b) && blob_compare(&cksum1, &cksum1b) ){ 224 257 printf("WARNING: manifest checksum does not agree with manifest\n"); 225 258 } 226 259 } 227 260 db_end_transaction(0); 228 261 } 229 262 230 263 /*
Changes to src/clearsign.c.
37 37 return 0; 38 38 } 39 39 zRand = db_text(0, "SELECT hex(randomblob(10))"); 40 40 zOut = mprintf("out-%s", zRand); 41 41 zIn = mprintf("in-%z", zRand); 42 42 blob_write_to_file(pIn, zOut); 43 43 zCmd = mprintf("%s %s %s", zBase, zIn, zOut); 44 - rc = portable_system(zCmd); 44 + rc = fossil_system(zCmd); 45 45 free(zCmd); 46 46 if( rc==0 ){ 47 47 if( pOut==pIn ){ 48 48 blob_reset(pIn); 49 49 } 50 50 blob_zero(pOut); 51 51 blob_read_from_file(pOut, zIn);
Changes to src/comformat.c.
36 36 int tlen = lineLength - indent; 37 37 int si, sk, i, k; 38 38 int doIndent = 0; 39 39 char zBuf[400]; 40 40 int lineCnt = 0; 41 41 42 42 for(;;){ 43 - while( isspace(zText[0]) ){ zText++; } 43 + while( fossil_isspace(zText[0]) ){ zText++; } 44 44 if( zText[0]==0 ){ 45 45 if( doIndent==0 ){ 46 46 printf("\n"); 47 47 lineCnt = 1; 48 48 } 49 49 return lineCnt; 50 50 } 51 51 for(sk=si=i=k=0; zText[i] && k<tlen; i++){ 52 52 char c = zText[i]; 53 - if( isspace(c) ){ 53 + if( fossil_isspace(c) ){ 54 54 si = i; 55 55 sk = k; 56 56 if( k==0 || zBuf[k-1]!=' ' ){ 57 57 zBuf[k++] = ' '; 58 58 } 59 59 }else{ 60 60 zBuf[k] = c; 61 - if( c=='-' && k>0 && isalpha(zBuf[k-1]) ){ 61 + if( c=='-' && k>0 && fossil_isalpha(zBuf[k-1]) ){ 62 62 si = i+1; 63 63 sk = k+1; 64 64 } 65 65 k++; 66 66 } 67 67 } 68 68 if( doIndent ){
Changes to src/config.h.
14 14 ** http://www.hwaci.com/drh/ 15 15 ** 16 16 ******************************************************************************* 17 17 ** 18 18 ** A common header file used by all modules. 19 19 */ 20 20 21 +/* The following macros are necessary for large-file support under 22 +** some linux distributions, and possibly other unixes as well. 23 +*/ 24 +#define _LARGE_FILE 1 25 +#ifndef _FILE_OFFSET_BITS 26 +# define _FILE_OFFSET_BITS 64 27 +#endif 28 +#define _LARGEFILE_SOURCE 1 29 + 30 +#ifndef _RC_COMPILE_ 31 + 21 32 /* 22 33 ** System header files used by all modules 23 34 */ 24 35 #include <unistd.h> 25 36 #include <stdio.h> 26 37 #include <stdlib.h> 27 -#include <ctype.h> 38 +/* #include <ctype.h> // do not use - causes problems */ 28 39 #include <string.h> 29 40 #include <stdarg.h> 30 41 #include <assert.h> 31 -#ifdef __MINGW32__ 32 -# include <windows.h> 42 + 43 +#endif 44 + 45 +#if defined( __MINGW32__) || defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__) 46 +# if defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__) 47 + typedef int socklen_t; 48 +# endif 49 +# ifndef _WIN32 50 +# define _WIN32 51 +# endif 33 52 #else 53 +# include <sys/types.h> 54 +# include <signal.h> 34 55 # include <pwd.h> 35 56 #endif 36 57 58 +/* 59 +** Define the compiler variant, used to compile the project 60 +*/ 61 +#if !defined(COMPILER_NAME) 62 +# if defined(__DMC__) 63 +# define COMPILER_NAME "dmc" 64 +# elif defined(__POCC__) 65 +# if defined(_M_X64) 66 +# define COMPILER_NAME "pellesc64" 67 +# else 68 +# define COMPILER_NAME "pellesc32" 69 +# endif 70 +# elif defined(_MSC_VER) 71 +# define COMPILER_NAME "msc" 72 +# elif defined(__MINGW32__) 73 +# define COMPILER_NAME "mingw32" 74 +# elif defined(_WIN32) 75 +# define COMPILER_NAME "win32" 76 +# elif defined(__GNUC__) 77 +# define COMPILER_NAME "gcc-" __VERSION__ 78 +# else 79 +# define COMPILER_NAME "unknown" 80 +# endif 81 +#endif 82 + 83 +#ifndef _RC_COMPILE_ 84 + 37 85 #include "sqlite3.h" 38 86 39 87 /* 40 88 ** Typedef for a 64-bit integer 41 89 */ 42 -typedef sqlite_int64 i64; 43 -typedef sqlite_uint64 u64; 90 +typedef sqlite3_int64 i64; 91 +typedef sqlite3_uint64 u64; 44 92 45 93 /* 46 94 ** Unsigned character type 47 95 */ 48 96 typedef unsigned char u8; 49 97 50 -/* 51 -** Standard colors. These colors can also be changed using a stylesheet. 52 -*/ 53 - 54 -/* A blue border and background. Used for the title bar and for dates 55 -** in a timeline. 56 -*/ 57 -#define BORDER1 "#a0b5f4" /* Stylesheet class: border1 */ 58 -#define BG1 "#d0d9f4" /* Stylesheet class: bkgnd1 */ 59 - 60 -/* A red border and background. Use for releases in the timeline. 61 -*/ 62 -#define BORDER2 "#ec9898" /* Stylesheet class: border2 */ 63 -#define BG2 "#f7c0c0" /* Stylesheet class: bkgnd2 */ 64 - 65 -/* A gray background. Used for column headers in the Wiki Table of Contents 66 -** and to highlight ticket properties. 67 -*/ 68 -#define BG3 "#d0d0d0" /* Stylesheet class: bkgnd3 */ 69 - 70 -/* A light-gray background. Used for title bar, menus, and rlog alternation 71 -*/ 72 -#define BG4 "#f0f0f0" /* Stylesheet class: bkgnd4 */ 73 - 74 -/* A deeper gray background. Used for branches 75 -*/ 76 -#define BG5 "#dddddd" /* Stylesheet class: bkgnd5 */ 77 - 78 -/* Default HTML page header */ 79 -#define HEADER "<html>\n" \ 80 - "<head>\n" \ 81 - "<link rel=\"alternate\" type=\"application/rss+xml\"\n" \ 82 - " title=\"%N Timeline Feed\" href=\"%B/timeline.rss\">\n" \ 83 - "<title>%N: %T</title>\n</head>\n" \ 84 - "<body bgcolor=\"white\">" 85 - 86 -/* Default HTML page footer */ 87 -#define FOOTER "<div id=\"footer\"><small><small>\n" \ 88 - "<a href=\"about\">Fossil version %V</a>\n" \ 89 - "</small></small></div>\n" \ 90 - "</body></html>\n" 91 - 92 98 /* In the timeline, check-in messages are truncated at the first space 93 99 ** that is more than MX_CKIN_MSG from the beginning, or at the first 94 100 ** paragraph break that is more than MN_CKIN_MSG from the beginning. 95 101 */ 96 102 #define MN_CKIN_MSG 100 97 103 #define MX_CKIN_MSG 300 104 + 105 +/* 106 +** The following macros are used to cast pointers to integers and 107 +** integers to pointers. The way you do this varies from one compiler 108 +** to the next, so we have developed the following set of #if statements 109 +** to generate appropriate macros for a wide range of compilers. 110 +** 111 +** The correct "ANSI" way to do this is to use the intptr_t type. 112 +** Unfortunately, that typedef is not available on all compilers, or 113 +** if it is available, it requires an #include of specific headers 114 +** that vary from one machine to the next. 115 +*/ 116 +#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ 117 +# define FOSSIL_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) 118 +# define FOSSIL_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) 119 +#elif !defined(__GNUC__) /* Works for compilers other than LLVM */ 120 +# define FOSSIL_INT_TO_PTR(X) ((void*)&((char*)0)[X]) 121 +# define FOSSIL_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) 122 +#else /* Generates a warning - but it always works */ 123 +# define FOSSIL_INT_TO_PTR(X) ((void*)(X)) 124 +# define FOSSIL_PTR_TO_INT(X) ((int)(X)) 125 +#endif 126 + 98 127 99 128 /* Unset the following to disable internationalization code. */ 100 129 #ifndef FOSSIL_I18N 101 130 # define FOSSIL_I18N 1 102 131 #endif 103 132 104 133 #if FOSSIL_I18N ................................................................................ 105 134 # include <locale.h> 106 135 # include <langinfo.h> 107 136 #endif 108 137 #ifndef CODESET 109 138 # undef FOSSIL_I18N 110 139 # define FOSSIL_I18N 0 111 140 #endif 141 + 142 +#endif /* _RC_COMPILE_ */
Changes to src/configure.c.
72 72 { "css", CONFIGSET_SKIN }, 73 73 { "header", CONFIGSET_SKIN }, 74 74 { "footer", CONFIGSET_SKIN }, 75 75 { "logo-mimetype", CONFIGSET_SKIN }, 76 76 { "logo-image", CONFIGSET_SKIN }, 77 77 { "project-name", CONFIGSET_PROJ }, 78 78 { "project-description", CONFIGSET_PROJ }, 79 + { "manifest", CONFIGSET_PROJ }, 79 80 { "index-page", CONFIGSET_SKIN }, 80 81 { "timeline-block-markup", CONFIGSET_SKIN }, 81 82 { "timeline-max-comment", CONFIGSET_SKIN }, 82 83 { "ticket-table", CONFIGSET_TKT }, 83 84 { "ticket-common", CONFIGSET_TKT }, 84 85 { "ticket-newpage", CONFIGSET_TKT }, 85 86 { "ticket-viewpage", CONFIGSET_TKT }, ................................................................................ 452 453 zPw = 0; 453 454 g.dontKeepUrl = 1; 454 455 }else{ 455 456 zServer = db_get("last-sync-url", 0); 456 457 if( zServer==0 ){ 457 458 fossil_fatal("no server specified"); 458 459 } 459 - zPw = db_get("last-sync-pw", 0); 460 + zPw = unobscure(db_get("last-sync-pw", 0)); 460 461 } 461 462 url_parse(zServer); 462 463 if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw); 463 464 user_select(); 465 + url_enable_proxy("via proxy: "); 464 466 if( strncmp(zMethod, "push", n)==0 ){ 465 467 client_sync(0,0,0,0,mask); 466 468 }else{ 467 469 client_sync(0,0,0,mask,0); 468 470 } 469 471 }else 470 472 if( strncmp(zMethod, "reset", n)==0 ){
Changes to src/content.c.
17 17 ** 18 18 ** Procedures store and retrieve records from the repository 19 19 */ 20 20 #include "config.h" 21 21 #include "content.h" 22 22 #include <assert.h> 23 23 24 -/* 25 -** Macros for debugging 26 -*/ 27 -#if 0 28 -# define CONTENT_TRACE(X) printf X; 29 -#else 30 -# define CONTENT_TRACE(X) 31 -#endif 32 - 33 24 /* 34 25 ** The artifact retrival cache 35 26 */ 36 -#define MX_CACHE_CNT 50 /* Maximum number of positive cache entries */ 37 -#define EXPELL_INTERVAL 5 /* How often to expell from a full cache */ 38 27 static struct { 39 - int n; /* Current number of positive cache entries */ 28 + i64 szTotal; /* Total size of all entries in the cache */ 29 + int n; /* Current number of eache entries */ 30 + int nAlloc; /* Number of slots allocated in a[] */ 40 31 int nextAge; /* Age counter for implementing LRU */ 41 32 int skipCnt; /* Used to limit entries expelled from cache */ 42 - struct { /* One instance of this for each cache entry */ 33 + struct cacheLine { /* One instance of this for each cache entry */ 43 34 int rid; /* Artifact id */ 44 35 int age; /* Age. Newer is larger */ 45 36 Blob content; /* Content of the artifact */ 46 - } a[MX_CACHE_CNT]; /* The positive cache */ 37 + } *a; /* The positive cache */ 38 + Bag inCache; /* Set of artifacts currently in cache */ 47 39 48 40 /* 49 41 ** The missing artifact cache. 50 42 ** 51 43 ** Artifacts whose record ID are in missingCache cannot be retrieved 52 44 ** either because they are phantoms or because they are a delta that 53 45 ** depends on a phantom. Artifacts whose content we are certain is ................................................................................ 54 46 ** available are in availableCache. If an artifact is in neither cache 55 47 ** then its current availablity is unknown. 56 48 */ 57 49 Bag missing; /* Cache of artifacts that are incomplete */ 58 50 Bag available; /* Cache of artifacts that are complete */ 59 51 } contentCache; 60 52 53 +/* 54 +** Remove the oldest element from the content cache 55 +*/ 56 +static void content_cache_expire_oldest(void){ 57 + int i; 58 + int mnAge = contentCache.nextAge; 59 + int mn = -1; 60 + for(i=0; i<contentCache.n; i++){ 61 + if( contentCache.a[i].age<mnAge ){ 62 + mnAge = contentCache.a[i].age; 63 + mn = i; 64 + } 65 + } 66 + if( mn>=0 ){ 67 + bag_remove(&contentCache.inCache, contentCache.a[mn].rid); 68 + contentCache.szTotal -= blob_size(&contentCache.a[mn].content); 69 + blob_reset(&contentCache.a[mn].content); 70 + contentCache.n--; 71 + contentCache.a[mn] = contentCache.a[contentCache.n]; 72 + } 73 +} 74 + 75 +/* 76 +** Add an entry to the content cache 77 +*/ 78 +void content_cache_insert(int rid, Blob *pBlob){ 79 + struct cacheLine *p; 80 + if( contentCache.n>500 || contentCache.szTotal>50000000 ){ 81 + content_cache_expire_oldest(); 82 + } 83 + if( contentCache.n>=contentCache.nAlloc ){ 84 + contentCache.nAlloc = contentCache.nAlloc*2 + 10; 85 + contentCache.a = fossil_realloc(contentCache.a, 86 + contentCache.nAlloc*sizeof(contentCache.a[0])); 87 + } 88 + p = &contentCache.a[contentCache.n++]; 89 + p->rid = rid; 90 + p->age = contentCache.nextAge++; 91 + contentCache.szTotal += blob_size(pBlob); 92 + p->content = *pBlob; 93 + blob_zero(pBlob); 94 + bag_insert(&contentCache.inCache, rid); 95 +} 61 96 62 97 /* 63 98 ** Clear the content cache. 64 99 */ 65 100 void content_clear_cache(void){ 66 101 int i; 67 102 for(i=0; i<contentCache.n; i++){ 68 103 blob_reset(&contentCache.a[i].content); 69 104 } 70 105 bag_clear(&contentCache.missing); 71 106 bag_clear(&contentCache.available); 107 + bag_clear(&contentCache.inCache); 72 108 contentCache.n = 0; 109 + contentCache.szTotal = 0; 73 110 } 74 111 75 112 /* 76 113 ** Return the srcid associated with rid. Or return 0 if rid is 77 114 ** original content and not a delta. 78 115 */ 79 116 static int findSrcid(int rid){ ................................................................................ 93 130 /* 94 131 ** Check to see if content is available for artifact "rid". Return 95 132 ** true if it is. Return false if rid is a phantom or depends on 96 133 ** a phantom. 97 134 */ 98 135 int content_is_available(int rid){ 99 136 int srcid; 100 - if( bag_find(&contentCache.missing, rid) ){ 101 - return 0; 102 - } 103 - if( bag_find(&contentCache.available, rid) ){ 104 - return 1; 105 - } 106 - if( db_int(-1, "SELECT size FROM blob WHERE rid=%d", rid)<0 ){ 107 - bag_insert(&contentCache.missing, rid); 108 - return 0; 109 - } 110 - srcid = findSrcid(rid); 111 - if( srcid==0 ){ 112 - bag_insert(&contentCache.available, rid); 113 - return 1; 114 - } 115 - if( content_is_available(srcid) ){ 116 - bag_insert(&contentCache.available, rid); 117 - return 1; 118 - }else{ 119 - bag_insert(&contentCache.missing, rid); 120 - return 0; 121 - } 137 + int depth = 0; /* Limit to recursion depth */ 138 + while( depth++ < 10000000 ){ 139 + if( bag_find(&contentCache.missing, rid) ){ 140 + return 0; 141 + } 142 + if( bag_find(&contentCache.available, rid) ){ 143 + return 1; 144 + } 145 + if( db_int(-1, "SELECT size FROM blob WHERE rid=%d", rid)<0 ){ 146 + bag_insert(&contentCache.missing, rid); 147 + return 0; 148 + } 149 + srcid = findSrcid(rid); 150 + if( srcid==0 ){ 151 + bag_insert(&contentCache.available, rid); 152 + return 1; 153 + } 154 + rid = srcid; 155 + } 156 + fossil_panic("delta-loop in repository"); 157 + return 0; 122 158 } 123 159 124 160 /* 125 161 ** Mark artifact rid as being available now. Update the cache to 126 162 ** show that everything that was formerly unavailable because rid 127 163 ** was missing is now available. 128 164 */ ................................................................................ 161 197 blob_uncompress(pBlob, pBlob); 162 198 rc = 1; 163 199 } 164 200 db_reset(&q); 165 201 return rc; 166 202 } 167 203 168 - 169 204 /* 170 205 ** Extract the content for ID rid and put it into the 171 206 ** uninitialized blob. Return 1 on success. If the record 172 207 ** is a phantom, zero pBlob and return 0. 173 208 */ 174 209 int content_get(int rid, Blob *pBlob){ 175 - Blob src; 176 - int srcid; 177 - int rc = 0; 210 + int rc; 178 211 int i; 179 - static Bag inProcess; 212 + int nextRid; 180 213 181 214 assert( g.repositoryOpen ); 182 215 blob_zero(pBlob); 183 216 if( rid==0 ) return 0; 184 217 185 218 /* Early out if we know the content is not available */ 186 219 if( bag_find(&contentCache.missing, rid) ){ 187 - CONTENT_TRACE(("%*smiss from cache: %d\n", 188 - bag_count(&inProcess), "", rid)) 189 220 return 0; 190 221 } 191 222 192 223 /* Look for the artifact in the cache first */ 193 - for(i=0; i<contentCache.n; i++){ 194 - if( contentCache.a[i].rid==rid ){ 195 - *pBlob = contentCache.a[i].content; 196 - blob_zero(&contentCache.a[i].content); 197 - contentCache.n--; 198 - if( i<contentCache.n ){ 199 - contentCache.a[i] = contentCache.a[contentCache.n]; 224 + if( bag_find(&contentCache.inCache, rid) ){ 225 + for(i=0; i<contentCache.n; i++){ 226 + if( contentCache.a[i].rid==rid ){ 227 + blob_copy(pBlob, &contentCache.a[i].content); 228 + contentCache.a[i].age = contentCache.nextAge++; 229 + return 1; 230 + } 231 + } 232 + } 233 + 234 + nextRid = findSrcid(rid); 235 + if( nextRid==0 ){ 236 + rc = content_of_blob(rid, pBlob); 237 + }else{ 238 + int n = 1; 239 + int nAlloc = 10; 240 + int *a = 0; 241 + int mx; 242 + Blob delta, next; 243 + 244 + a = fossil_malloc( sizeof(a[0])*nAlloc ); 245 + a[0] = rid; 246 + a[1] = nextRid; 247 + n = 1; 248 + while( !bag_find(&contentCache.inCache, nextRid) 249 + && (nextRid = findSrcid(nextRid))>0 ){ 250 + n++; 251 + if( n>=nAlloc ){ 252 + nAlloc = nAlloc*2 + 10; 253 + a = fossil_realloc(a, nAlloc*sizeof(a[0])); 200 254 } 201 - CONTENT_TRACE(("%*scache: %d\n", 202 - bag_count(&inProcess), "", rid)) 203 - return 1; 255 + a[n] = nextRid; 204 256 } 205 - } 206 - 207 - /* See if we need to apply a delta to find this artifact */ 208 - srcid = findSrcid(rid); 209 - CONTENT_TRACE(("%*ssearching for %d. Need %d.\n", 210 - bag_count(&inProcess), "", rid, srcid)) 211 - 212 - 213 - if( srcid ){ 214 - /* Yes, a delta is required */ 215 - if( bag_find(&inProcess, srcid) ){ 216 - db_multi_exec( 217 - "UPDATE blob SET content=NULL, size=-1 WHERE rid=%d;" 218 - "DELETE FROM delta WHERE rid=%d;" 219 - "INSERT OR IGNORE INTO phantom VALUES(%d);", 220 - srcid, srcid, srcid 221 - ); 222 - blob_zero(pBlob); 223 - return 0; 224 - } 225 - bag_insert(&inProcess, srcid); 226 - 227 - if( content_get(srcid, &src) ){ 228 - Blob delta; 229 - if( content_of_blob(rid, &delta) ){ 230 - blob_init(pBlob,0,0); 231 - blob_delta_apply(&src, &delta, pBlob); 257 + mx = n; 258 + rc = content_get(a[n], pBlob); 259 + n--; 260 + while( rc && n>=0 ){ 261 + rc = content_of_blob(a[n], &delta); 262 + if( rc ){ 263 + blob_delta_apply(pBlob, &delta, &next); 232 264 blob_reset(&delta); 233 - rc = 1; 234 - } 235 - 236 - /* Save the srcid artifact in the cache */ 237 - if( contentCache.n<MX_CACHE_CNT ){ 238 - i = contentCache.n++; 239 - }else if( ((contentCache.skipCnt++)%EXPELL_INTERVAL)!=0 ){ 240 - i = -1; 241 - }else{ 242 - int j, best; 243 - best = contentCache.nextAge+1; 244 - i = -1; 245 - for(j=0; j<contentCache.n; j++){ 246 - if( contentCache.a[j].age<best ){ 247 - i = j; 248 - best = contentCache.a[j].age; 249 - } 265 + if( (mx-n)%8==0 ){ 266 + content_cache_insert(a[n+1], pBlob); 267 + }else{ 268 + blob_reset(pBlob); 250 269 } 251 - CONTENT_TRACE(("%*sexpell %d from cache\n", 252 - bag_count(&inProcess), "", contentCache.a[i].rid)) 253 - blob_reset(&contentCache.a[i].content); 270 + *pBlob = next; 254 271 } 255 - if( i>=0 ){ 256 - contentCache.a[i].content = src; 257 - contentCache.a[i].age = contentCache.nextAge++; 258 - contentCache.a[i].rid = srcid; 259 - CONTENT_TRACE(("%*sadd %d to cache\n", 260 - bag_count(&inProcess), "", srcid)) 261 - }else{ 262 - blob_reset(&src); 263 - } 272 + n--; 264 273 } 265 - bag_remove(&inProcess, srcid); 266 - }else{ 267 - /* No delta required. Read content directly from the database */ 268 - if( content_of_blob(rid, pBlob) ){ 269 - rc = 1; 270 - } 274 + free(a); 275 + if( !rc ) blob_reset(pBlob); 271 276 } 272 277 if( rc==0 ){ 273 278 bag_insert(&contentCache.missing, rid); 274 279 }else{ 275 280 bag_insert(&contentCache.available, rid); 276 281 } 277 282 return rc; 278 283 } 279 284 280 285 /* 281 -** COMMAND: artifact 286 +** COMMAND: artifact 282 287 ** 283 -** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? 288 +** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS? 284 289 ** 285 290 ** Extract an artifact by its SHA1 hash and write the results on 286 291 ** standard output, or if the optional 4th argument is given, in 287 292 ** the named output file. 293 +** 294 +** Options: 295 +** 296 +** -R|--repository FILE Extract artifacts from repository FILE 288 297 */ 289 298 void artifact_cmd(void){ 290 299 int rid; 291 300 Blob content; 292 301 const char *zFile; 293 - if( g.argc!=4 && g.argc!=3 ) usage("RECORDID ?FILENAME?"); 302 + db_find_and_open_repository(1); 303 + if( g.argc!=4 && g.argc!=3 ) usage("ARTIFACT-ID ?FILENAME? ?OPTIONS?"); 294 304 zFile = g.argc==4 ? g.argv[3] : "-"; 295 - db_must_be_within_tree(); 296 305 rid = name_to_rid(g.argv[2]); 297 306 content_get(rid, &content); 298 307 blob_write_to_file(&content, zFile); 299 308 } 300 309 301 310 /* 302 311 ** COMMAND: test-content-rawget ................................................................................ 314 323 rid = name_to_rid(g.argv[2]); 315 324 blob_zero(&content); 316 325 db_blob(&content, "SELECT content FROM blob WHERE rid=%d", rid); 317 326 blob_uncompress(&content, &content); 318 327 blob_write_to_file(&content, zFile); 319 328 } 320 329 330 +/* 331 +** The following flag is set to disable the automatic calls to 332 +** manifest_crosslink() when a record is dephantomized. This 333 +** flag can be set (for example) when doing a clone when we know 334 +** that rebuild will be run over all records at the conclusion 335 +** of the operation. 336 +*/ 337 +static int ignoreDephantomizations = 0; 338 + 321 339 /* 322 340 ** When a record is converted from a phantom to a real record, 323 341 ** if that record has other records that are derived by delta, 324 342 ** then call manifest_crosslink() on those other records. 343 +** 344 +** If the formerly phantom record or any of the other records 345 +** derived by delta from the former phantom are a baseline manifest, 346 +** then also invoke manifest_crosslink() on the delta-manifests 347 +** associated with that baseline. 348 +** 349 +** Tail recursion is used to minimize stack depth. 325 350 */ 326 351 void after_dephantomize(int rid, int linkFlag){ 327 352 Stmt q; 328 - int prevTid = 0; 329 - 330 - /* The prevTid variable is used to delay invoking this routine 331 - ** recursively, if possible, until after the query has finalized, 332 - ** in order to avoid having an excessive number of prepared statements. 333 - ** This is most effective in the common case where the query returns 334 - ** just one row. 335 - */ 336 - db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid); 337 - while( db_step(&q)==SQLITE_ROW ){ 338 - int tid = db_column_int(&q, 0); 339 - if( prevTid ) after_dephantomize(prevTid, 1); 340 - prevTid = tid; 341 - } 342 - db_finalize(&q); 343 - if( prevTid ) after_dephantomize(prevTid, 1); 344 - if( linkFlag ){ 345 - Blob content; 346 - content_get(rid, &content); 347 - manifest_crosslink(rid, &content); 348 - blob_reset(&content); 349 - } 353 + int nChildAlloc = 0; 354 + int *aChild = 0; 355 + Blob content; 356 + 357 + if( ignoreDephantomizations ) return; 358 + while( rid ){ 359 + int nChildUsed = 0; 360 + int i; 361 + 362 + /* Parse the object rid itself */ 363 + if( linkFlag ){ 364 + content_get(rid, &content); 365 + manifest_crosslink(rid, &content); 366 + blob_reset(&content); 367 + } 368 + 369 + /* Parse all delta-manifests that depend on baseline-manifest rid */ 370 + db_prepare(&q, "SELECT rid FROM orphan WHERE baseline=%d", rid); 371 + while( db_step(&q)==SQLITE_ROW ){ 372 + int child = db_column_int(&q, 0); 373 + if( nChildUsed>=nChildAlloc ){ 374 + nChildAlloc = nChildAlloc*2 + 10; 375 + aChild = fossil_realloc(aChild, nChildAlloc*sizeof(aChild)); 376 + } 377 + aChild[nChildUsed++] = child; 378 + } 379 + db_finalize(&q); 380 + for(i=0; i<nChildUsed; i++){ 381 + content_get(aChild[i], &content); 382 + manifest_crosslink(aChild[i], &content); 383 + blob_reset(&content); 384 + } 385 + if( nChildUsed ){ 386 + db_multi_exec("DELETE FROM orphan WHERE baseline=%d", rid); 387 + } 388 + 389 + /* Recursively dephantomize all artifacts that are derived by 390 + ** delta from artifact rid */ 391 + nChildUsed = 0; 392 + db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid); 393 + while( db_step(&q)==SQLITE_ROW ){ 394 + int child = db_column_int(&q, 0); 395 + if( nChildUsed>=nChildAlloc ){ 396 + nChildAlloc = nChildAlloc*2 + 10; 397 + aChild = fossil_realloc(aChild, nChildAlloc*sizeof(aChild)); 398 + } 399 + aChild[nChildUsed++] = child; 400 + } 401 + db_finalize(&q); 402 + for(i=1; i<nChildUsed; i++){ 403 + after_dephantomize(aChild[i], 1); 404 + } 405 + 406 + /* Tail recursion for the common case where only a single artifact 407 + ** is derived by delta from rid... */ 408 + rid = nChildUsed>0 ? aChild[0] : 0; 409 + linkFlag = 1; 410 + } 411 + free(aChild); 412 +} 413 + 414 +/* 415 +** Turn dephantomization processing on or off. 416 +*/ 417 +void content_enable_dephantomize(int onoff){ 418 + ignoreDephantomizations = !onoff; 350 419 } 351 420 352 421 /* 353 422 ** Write content into the database. Return the record ID. If the 354 423 ** content is already in the database, just return the record ID. 355 424 ** 356 425 ** If srcId is specified, then pBlob is delta content from
Changes to src/db.c.
25 25 ** (2) The "repository" database 26 26 ** 27 27 ** (3) A local checkout database named "_FOSSIL_" or ".fos" 28 28 ** and located at the root of the local copy of the source tree. 29 29 ** 30 30 */ 31 31 #include "config.h" 32 +#if ! defined(_WIN32) 33 +# include <pwd.h> 34 +#endif 32 35 #include <sqlite3.h> 33 36 #include <sys/types.h> 34 37 #include <sys/stat.h> 35 38 #include <unistd.h> 36 39 #include "db.h" 37 40 38 41 #if INTERFACE ................................................................................ 132 135 void db_force_rollback(void){ 133 136 static int busy = 0; 134 137 if( busy || g.db==0 ) return; 135 138 busy = 1; 136 139 undo_rollback(); 137 140 if( nBegin ){ 138 141 sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0); 142 + nBegin = 0; 139 143 if( isNewRepo ){ 140 144 db_close(); 141 145 unlink(g.zRepositoryName); 142 146 } 143 147 } 144 - nBegin = 0; 145 148 busy = 0; 146 149 } 147 150 148 151 /* 149 152 ** Install a commit hook. Hooks are installed in sequence order. 150 153 ** It is an error to install the same commit hook more than once. 151 154 ** ................................................................................ 532 535 }else{ 533 536 z = 0; 534 537 } 535 538 db_finalize(&s); 536 539 return z; 537 540 } 538 541 539 -#ifdef __MINGW32__ 542 +#if defined(_WIN32) 540 543 extern char *sqlite3_win32_mbcs_to_utf8(const char*); 541 544 #endif 542 545 543 546 /* 544 547 ** Initialize a new database file with the given schema. If anything 545 548 ** goes wrong, call db_err() to exit. 546 549 */ ................................................................................ 550 553 ... /* Additional SQL to run. Terminate with NULL. */ 551 554 ){ 552 555 sqlite3 *db; 553 556 int rc; 554 557 const char *zSql; 555 558 va_list ap; 556 559 557 -#ifdef __MINGW32__ 560 +#if defined(_WIN32) 558 561 zFileName = sqlite3_win32_mbcs_to_utf8(zFileName); 559 562 #endif 560 563 rc = sqlite3_open(zFileName, &db); 561 564 if( rc!=SQLITE_OK ){ 562 565 db_err(sqlite3_errmsg(db)); 563 566 } 564 567 sqlite3_busy_timeout(db, 5000); ................................................................................ 585 588 */ 586 589 static sqlite3 *openDatabase(const char *zDbName){ 587 590 int rc; 588 591 const char *zVfs; 589 592 sqlite3 *db; 590 593 591 594 zVfs = getenv("FOSSIL_VFS"); 592 -#ifdef __MINGW32__ 595 +#if defined(_WIN32) 593 596 zDbName = sqlite3_win32_mbcs_to_utf8(zDbName); 594 597 #endif 595 598 rc = sqlite3_open_v2( 596 599 zDbName, &db, 597 600 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 598 601 zVfs 599 602 ); ................................................................................ 613 616 */ 614 617 void db_open_or_attach(const char *zDbName, const char *zLabel){ 615 618 if( !g.db ){ 616 619 g.db = openDatabase(zDbName); 617 620 g.zRepoDb = "main"; 618 621 db_connection_init(); 619 622 }else{ 620 -#ifdef __MINGW32__ 623 +#if defined(_WIN32) 621 624 zDbName = sqlite3_win32_mbcs_to_utf8(zDbName); 622 625 #endif 623 626 db_multi_exec("ATTACH DATABASE %Q AS %s", zDbName, zLabel); 624 627 g.zRepoDb = mprintf("%s", zLabel); 625 628 } 626 629 } 627 630 ................................................................................ 637 640 ** connection so that we can join between the various databases. In that 638 641 ** case, invoke this routine with useAttach as 1. 639 642 */ 640 643 void db_open_config(int useAttach){ 641 644 char *zDbName; 642 645 const char *zHome; 643 646 if( g.configOpen ) return; 644 -#ifdef __MINGW32__ 647 +#if defined(_WIN32) 645 648 zHome = getenv("LOCALAPPDATA"); 646 649 if( zHome==0 ){ 647 650 zHome = getenv("APPDATA"); 648 651 if( zHome==0 ){ 649 652 zHome = getenv("HOMEPATH"); 650 653 } 651 654 } ................................................................................ 659 662 fossil_fatal("cannot locate home directory - " 660 663 "please set the HOME environment variable"); 661 664 } 662 665 #endif 663 666 if( file_isdir(zHome)!=1 ){ 664 667 fossil_fatal("invalid home directory: %s", zHome); 665 668 } 666 -#ifndef __MINGW32__ 669 +#ifndef _WIN32 667 670 if( access(zHome, W_OK) ){ 668 671 fossil_fatal("home directory %s must be writeable", zHome); 669 672 } 670 673 #endif 671 674 g.zHome = mprintf("%/", zHome); 672 -#ifdef __MINGW32__ 675 +#if defined(_WIN32) 673 676 /* . filenames give some window systems problems and many apps problems */ 674 677 zDbName = mprintf("%//_fossil", zHome); 675 678 #else 676 679 zDbName = mprintf("%s/.fossil", zHome); 677 680 #endif 678 681 if( file_size(zDbName)<1024*3 ){ 679 682 db_init_database(zDbName, zConfigSchema, (char*)0); ................................................................................ 892 895 db_open_repository(0); 893 896 } 894 897 895 898 /* 896 899 ** Close the database connection. 897 900 */ 898 901 void db_close(void){ 902 + sqlite3_stmt *pStmt; 899 903 if( g.db==0 ) return; 900 904 while( pAllStmt ){ 901 905 db_finalize(pAllStmt); 902 906 } 903 907 db_end_transaction(1); 908 + pStmt = 0; 909 + while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){ 910 + fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt)); 911 + } 904 912 g.repositoryOpen = 0; 905 913 g.localOpen = 0; 906 914 g.configOpen = 0; 915 + sqlite3_wal_checkpoint(g.db, 0); 907 916 sqlite3_close(g.db); 908 917 g.db = 0; 918 + if( g.dbConfig ){ 919 + sqlite3_close(g.dbConfig); 920 + g.dbConfig = 0; 921 + } 909 922 } 910 923 911 924 912 925 /* 913 926 ** Create a new empty repository database with the given name. 914 927 ** 915 928 ** Only the schema is initialized. The required VAR tables entries ................................................................................ 932 945 void db_create_default_users(int setupUserOnly, const char *zDefaultUser){ 933 946 const char *zUser; 934 947 zUser = db_get("default-user", 0); 935 948 if( zUser==0 ){ 936 949 zUser = zDefaultUser; 937 950 } 938 951 if( zUser==0 ){ 939 -#ifdef __MINGW32__ 952 +#if defined(_WIN32) 940 953 zUser = getenv("USERNAME"); 941 954 #else 942 955 zUser = getenv("USER"); 943 956 #endif 944 957 } 945 958 if( zUser==0 ){ 946 959 zUser = "root"; ................................................................................ 998 1011 db_create_default_users(0, zDefaultUser); 999 1012 user_select(); 1000 1013 1001 1014 if( zInitialDate ){ 1002 1015 int rid; 1003 1016 blob_zero(&manifest); 1004 1017 blob_appendf(&manifest, "C initial\\sempty\\scheck-in\n"); 1005 - zDate = db_text(0, "SELECT datetime(%Q)", zInitialDate); 1006 - zDate[10]='T'; 1018 + zDate = date_in_standard_format(zInitialDate); 1007 1019 blob_appendf(&manifest, "D %s\n", zDate); 1008 1020 blob_appendf(&manifest, "P\n"); 1009 1021 md5sum_init(); 1010 1022 blob_appendf(&manifest, "R %s\n", md5sum_finish(0)); 1011 1023 blob_appendf(&manifest, "T *branch * trunk\n"); 1012 1024 blob_appendf(&manifest, "T *sym-trunk *\n"); 1013 1025 blob_appendf(&manifest, "U %F\n", g.zLogin); ................................................................................ 1251 1263 ** If g.useAttach that means the ~/.fossil database was opened with 1252 1264 ** the useAttach flag set to 1. In that case no connection swap is required 1253 1265 ** so this routine is a no-op. 1254 1266 */ 1255 1267 void db_swap_connections(void){ 1256 1268 if( !g.useAttach ){ 1257 1269 sqlite3 *dbTemp = g.db; 1258 - assert( g.dbConfig!=0 ); 1259 1270 g.db = g.dbConfig; 1260 1271 g.dbConfig = dbTemp; 1261 1272 } 1262 1273 } 1263 1274 1264 1275 /* 1265 1276 ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the ................................................................................ 1372 1383 } 1373 1384 void db_lset_int(const char *zName, int value){ 1374 1385 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); 1375 1386 } 1376 1387 1377 1388 /* 1378 1389 ** Record the name of a local repository in the global_config() database. 1379 -** The repostiroy filename %s is recorded as an entry with a "name" field 1390 +** The repository filename %s is recorded as an entry with a "name" field 1380 1391 ** of the following form: 1381 1392 ** 1382 1393 ** repo:%s 1383 1394 ** 1384 1395 ** The value field is set to 1. 1385 1396 */ 1386 1397 void db_record_repository_filename(const char *zName){ ................................................................................ 1479 1490 }else{ 1480 1491 printf("%-20s\n", zName); 1481 1492 } 1482 1493 db_finalize(&q); 1483 1494 } 1484 1495 1485 1496 1497 +/* 1498 +** define all settings, which can be controlled via the set/unset 1499 +** command. var is the name of the internal configuration name for db_(un)set. 1500 +** If var is 0, the settings name is used. 1501 +** width is the length for the edit field on the behavior page, 0 1502 +** is used for on/off checkboxes. 1503 +** The behaviour page doesn't use a special layout. It lists all 1504 +** set-commands and displays the 'set'-help as info. 1505 +*/ 1506 +#if INTERFACE 1507 +struct stControlSettings { 1508 + char const *name; /* Name of the setting */ 1509 + char const *var; /* Internal variable name used by db_set() */ 1510 + int width; /* Width of display. 0 for boolean values */ 1511 + char const *def; /* Default value */ 1512 +}; 1513 +#endif /* INTERFACE */ 1514 +struct stControlSettings const ctrlSettings[] = { 1515 + { "auto-captcha", "autocaptcha", 0, "on" }, 1516 + { "auto-shun", 0, 0, "on" }, 1517 + { "autosync", 0, 0, "on" }, 1518 + { "binary-glob", 0, 32, "" }, 1519 + { "clearsign", 0, 0, "off" }, 1520 + { "diff-command", 0, 16, "" }, 1521 + { "dont-push", 0, 0, "off" }, 1522 + { "editor", 0, 16, "" }, 1523 + { "gdiff-command", 0, 16, "gdiff" }, 1524 + { "ignore-glob", 0, 40, "" }, 1525 + { "http-port", 0, 16, "8080" }, 1526 + { "localauth", 0, 0, "off" }, 1527 + { "manifest", 0, 0, "off" }, 1528 + { "mtime-changes", 0, 0, "on" }, 1529 + { "pgp-command", 0, 32, "gpg --clearsign -o " }, 1530 + { "proxy", 0, 32, "off" }, 1531 + { "repo-cksum", 0, 0, "on" }, 1532 + { "ssh-command", 0, 32, "" }, 1533 + { "web-browser", 0, 32, "" }, 1534 + { 0,0,0,0 } 1535 +}; 1536 + 1486 1537 /* 1487 1538 ** COMMAND: settings 1488 1539 ** COMMAND: unset 1489 1540 ** %fossil settings ?PROPERTY? ?VALUE? ?-global? 1490 1541 ** %fossil unset PROPERTY ?-global? 1491 1542 ** 1492 1543 ** The "settings" command with no arguments lists all properties and their ................................................................................ 1497 1548 ** 1498 1549 ** 1499 1550 ** auto-captcha If enabled, the Login page provides a button to 1500 1551 ** fill in the captcha password. Default: on 1501 1552 ** 1502 1553 ** auto-shun If enabled, automatically pull the shunning list 1503 1554 ** from a server to which the client autosyncs. 1555 +** Default: on 1504 1556 ** 1505 1557 ** autosync If enabled, automatically pull prior to commit 1506 1558 ** or update and automatically push after commit or 1507 1559 ** tag or branch creation. If the value is "pullonly" 1508 1560 ** then only pull operations occur automatically. 1561 +** Default: on 1509 1562 ** 1510 1563 ** binary-glob The VALUE is a comma-separated list of GLOB patterns 1511 1564 ** that should be treated as binary files for merging 1512 1565 ** purposes. Example: *.xml 1513 1566 ** 1514 1567 ** clearsign When enabled, fossil will attempt to sign all commits 1515 1568 ** with gpg. When disabled (the default), commits will 1516 -** be unsigned. 1569 +** be unsigned. Default: off 1517 1570 ** 1518 1571 ** diff-command External command to run when performing a diff. 1519 1572 ** If undefined, the internal text diff will be used. 1520 1573 ** 1521 1574 ** dont-push Prevent this repository from pushing from client to 1522 1575 ** server. Useful when setting up a private branch. 1523 1576 ** ................................................................................ 1534 1587 ** Example: *.o,*.obj,*.exe 1535 1588 ** 1536 1589 ** localauth If enabled, require that HTTP connections from 1537 1590 ** 127.0.0.1 be authenticated by password. If 1538 1591 ** false, all HTTP requests from localhost have 1539 1592 ** unrestricted access to the repository. 1540 1593 ** 1594 +** manifest If enabled, automatically create files "manifest" and 1595 +** "manifest.uuid" in every checkout. The SQLite and 1596 +** Fossil repositories both require this. Default: off. 1597 +** 1541 1598 ** mtime-changes Use file modification times (mtimes) to detect when 1542 1599 ** files have been modified. (Default "on".) 1543 1600 ** 1544 1601 ** pgp-command Command used to clear-sign manifests at check-in. 1545 1602 ** The default is "gpg --clearsign -o ". 1546 1603 ** 1547 1604 ** proxy URL of the HTTP proxy. If undefined or "off" then 1548 1605 ** the "http_proxy" environment variable is consulted. 1549 1606 ** If the http_proxy environment variable is undefined 1550 1607 ** then a direct HTTP connection is used. 1608 +** 1609 +** repo-cksum Compute checksums over all files in each checkout 1610 +** as a double-check of correctness. Defaults to "on". 1611 +** Disable on large repositories for a performance 1612 +** improvement. 1613 +** 1614 +** ssh-command Command used to talk to a remote machine with 1615 +** the "ssh://" protocol. 1551 1616 ** 1552 1617 ** web-browser A shell command used to launch your preferred 1553 1618 ** web browser when given a URL as an argument. 1554 1619 ** Defaults to "start" on windows, "open" on Mac, 1555 1620 ** and "firefox" on Unix. 1556 1621 */ 1557 1622 void setting_cmd(void){ 1558 - static const char *azName[] = { 1559 - "auto-captcha", 1560 - "auto-shun", 1561 - "autosync", 1562 - "binary-glob", 1563 - "clearsign", 1564 - "diff-command", 1565 - "dont-push", 1566 - "editor", 1567 - "gdiff-command", 1568 - "ignore-glob", 1569 - "http-port", 1570 - "localauth", 1571 - "mtime-changes", 1572 - "pgp-command", 1573 - "proxy", 1574 - "web-browser", 1575 - }; 1576 1623 int i; 1577 1624 int globalFlag = find_option("global","g",0)!=0; 1578 1625 int unsetFlag = g.argv[1][0]=='u'; 1579 1626 db_open_config(1); 1580 1627 db_find_and_open_repository(0); 1581 1628 if( !g.repositoryOpen ){ 1582 1629 globalFlag = 1; 1583 1630 } 1584 1631 if( unsetFlag && g.argc!=3 ){ 1585 1632 usage("PROPERTY ?-global?"); 1586 1633 } 1587 1634 if( g.argc==2 ){ 1588 - for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ 1589 - print_setting(azName[i]); 1635 + for(i=0; ctrlSettings[i].name; i++){ 1636 + print_setting(ctrlSettings[i].name); 1590 1637 } 1591 1638 }else if( g.argc==3 || g.argc==4 ){ 1592 1639 const char *zName = g.argv[2]; 1640 + int isManifest; 1593 1641 int n = strlen(zName); 1594 - for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ 1595 - if( strncmp(azName[i], zName, n)==0 ) break; 1642 + for(i=0; ctrlSettings[i].name; i++){ 1643 + if( strncmp(ctrlSettings[i].name, zName, n)==0 ) break; 1596 1644 } 1597 - if( i>=sizeof(azName)/sizeof(azName[0]) ){ 1645 + if( !ctrlSettings[i].name ){ 1598 1646 fossil_fatal("no such setting: %s", zName); 1599 1647 } 1648 + isManifest = strcmp(ctrlSettings[i].name, "manifest")==0; 1649 + if( isManifest && globalFlag ){ 1650 + fossil_fatal("cannot set 'manifest' globally"); 1651 + } 1600 1652 if( unsetFlag ){ 1601 - db_unset(azName[i], globalFlag); 1653 + db_unset(ctrlSettings[i].name, globalFlag); 1602 1654 }else if( g.argc==4 ){ 1603 - db_set(azName[i], g.argv[3], globalFlag); 1655 + db_set(ctrlSettings[i].name, g.argv[3], globalFlag); 1604 1656 }else{ 1605 - print_setting(azName[i]); 1657 + isManifest = 0; 1658 + print_setting(ctrlSettings[i].name); 1659 + } 1660 + if( isManifest ){ 1661 + manifest_to_disk(db_lget_int("checkout", 0)); 1606 1662 } 1607 1663 }else{ 1608 1664 usage("?PROPERTY? ?VALUE?"); 1609 1665 } 1610 1666 } 1667 + 1668 +/* 1669 +** The input in a a timespan measured in days. Return a string which 1670 +** describes that timespan in units of seconds, minutes, hours, days, 1671 +** or years, depending on its duration. 1672 +*/ 1673 +char *db_timespan_name(double rSpan){ 1674 + if( rSpan<0 ) rSpan = -rSpan; 1675 + rSpan *= 24.0*3600.0; /* Convert units to seconds */ 1676 + if( rSpan<120.0 ){ 1677 + return sqlite3_mprintf("%.1f seconds", rSpan); 1678 + } 1679 + rSpan /= 60.0; /* Convert units to minutes */ 1680 + if( rSpan<90.0 ){ 1681 + return sqlite3_mprintf("%.1f minutes", rSpan); 1682 + } 1683 + rSpan /= 60.0; /* Convert units to hours */ 1684 + if( rSpan<=48.0 ){ 1685 + return sqlite3_mprintf("%.1f hours", rSpan); 1686 + } 1687 + rSpan /= 24.0; /* Convert units to days */ 1688 + if( rSpan<=365.0 ){ 1689 + return sqlite3_mprintf("%.1f days", rSpan); 1690 + } 1691 + rSpan /= 356.24; /* Convert units to years */ 1692 + return sqlite3_mprintf("%.1f years", rSpan); 1693 +} 1694 + 1695 +/* 1696 +** COMMAND: test-timespan 1697 +** %fossil test-timespan TIMESTAMP 1698 +** 1699 +** Print the approximate span of time from now to TIMESTAMP. 1700 +*/ 1701 +void test_timespan_cmd(void){ 1702 + double rDiff; 1703 + if( g.argc!=3 ) usage("TIMESTAMP"); 1704 + sqlite3_open(":memory:", &g.db); 1705 + rDiff = db_double(0.0, "SELECT julianday('now') - julianday(%Q)", g.argv[2]); 1706 + printf("Time differences: %s\n", db_timespan_name(rDiff)); 1707 + sqlite3_close(g.db); 1708 + g.db = 0; 1709 +}
Changes to src/delta.c.
193 193 } 194 194 195 195 /* 196 196 ** Compute a 32-bit checksum on the N-byte buffer. Return the result. 197 197 */ 198 198 static unsigned int checksum(const char *zIn, size_t N){ 199 199 const unsigned char *z = (const unsigned char *)zIn; 200 - unsigned sum = 0; 200 + unsigned sum0 = 0; 201 + unsigned sum1 = 0; 202 + unsigned sum2 = 0; 203 + unsigned sum3 = 0; 201 204 while(N >= 16){ 202 - sum += ((unsigned)z[0] + z[4] + z[8] + z[12]) << 24; 203 - sum += ((unsigned)z[1] + z[5] + z[9] + z[13]) << 16; 204 - sum += ((unsigned)z[2] + z[6] + z[10]+ z[14]) << 8; 205 - sum += ((unsigned)z[3] + z[7] + z[11]+ z[15]); 205 + sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]); 206 + sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]); 207 + sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]); 208 + sum3 += ((unsigned)z[3] + z[7] + z[11]+ z[15]); 206 209 z += 16; 207 210 N -= 16; 208 211 } 209 212 while(N >= 4){ 210 - sum += (z[0]<<24) | (z[1]<<16) | (z[2]<<8) | z[3]; 213 + sum0 += z[0]; 214 + sum1 += z[1]; 215 + sum2 += z[2]; 216 + sum3 += z[3]; 211 217 z += 4; 212 218 N -= 4; 213 219 } 220 + sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24); 214 221 switch(N){ 215 - case 3: sum += (z[2] << 8); 216 - case 2: sum += (z[1] << 16); 217 - case 1: sum += (z[0] << 24); 222 + case 3: sum3 += (z[2] << 8); 223 + case 2: sum3 += (z[1] << 16); 224 + case 1: sum3 += (z[0] << 24); 218 225 default: ; 219 226 } 220 - return sum; 227 + return sum3; 221 228 } 222 229 223 230 /* 224 231 ** Create a new delta. 225 232 ** 226 233 ** The delta is written into a preallocated buffer, zDelta, which 227 234 ** should be at least 60 bytes longer than the target file, zOut. ................................................................................ 315 322 return zDelta - zOrigDelta; 316 323 } 317 324 318 325 /* Compute the hash table used to locate matching sections in the 319 326 ** source file. 320 327 */ 321 328 nHash = lenSrc/NHASH; 322 - collide = malloc( nHash*2*sizeof(int) ); 323 - if( collide==0 ) return -1; 329 + collide = fossil_malloc( nHash*2*sizeof(int) ); 324 330 landmark = &collide[nHash]; 325 331 memset(landmark, -1, nHash*sizeof(int)); 326 332 memset(collide, -1, nHash*sizeof(int)); 327 333 for(i=0; i<lenSrc-NHASH; i+=NHASH){ 328 334 int hv; 329 335 hash_init(&h, &zSrc[i]); 330 336 hv = hash_32bit(&h) % nHash; ................................................................................ 511 517 int lenSrc, /* Length of the source file */ 512 518 const char *zDelta, /* Delta to apply to the pattern */ 513 519 int lenDelta, /* Length of the delta */ 514 520 char *zOut /* Write the output into this preallocated buffer */ 515 521 ){ 516 522 unsigned int limit; 517 523 unsigned int total = 0; 524 +#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST 518 525 char *zOrigOut = zOut; 526 +#endif 519 527 520 528 limit = getInt(&zDelta, &lenDelta); 521 529 if( *zDelta!='\n' ){ 522 530 /* ERROR: size integer not terminated by "\n" */ 523 531 return -1; 524 532 } 525 533 zDelta++; lenDelta--; ................................................................................ 566 574 zDelta += cnt; 567 575 lenDelta -= cnt; 568 576 break; 569 577 } 570 578 case ';': { 571 579 zDelta++; lenDelta--; 572 580 zOut[0] = 0; 581 +#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST 573 582 if( cnt!=checksum(zOrigOut, total) ){ 574 583 /* ERROR: bad checksum */ 575 584 return -1; 576 585 } 586 +#endif 577 587 if( total!=limit ){ 578 588 /* ERROR: generated size does not match predicted size */ 579 589 return -1; 580 590 } 581 591 return total; 582 592 } 583 593 default: {
Changes to src/descendants.c.
316 316 style_submenu_element("Open", "Open", "leaves"); 317 317 } 318 318 style_header("Leaves"); 319 319 login_anonymous_available(); 320 320 compute_leaves(0, showAll ? 0 : showClosed ? 2 : 1); 321 321 style_sidebox_begin("Nomenclature:", "33%"); 322 322 @ <ol> 323 - @ <li> A <b>leaf</b> is a check-in with no descendants.</li> 324 - @ <li> An <b>open leaf</b> is a leaf that does not have a "closed" tag 323 + @ <li> A <div class="sideboxDescribed">leaf</div> 324 + @ is a check-in with no descendants.</li> 325 + @ <li> An <div class="sideboxDescribed">open leaf</div> 326 + @ is a leaf that does not have a "closed" tag 325 327 @ and is thus assumed to still be in use.</li> 326 - @ <li> A <b>closed leaf</b> has a "closed" tag and is thus assumed to 328 + @ <li> A <div class="sideboxDescribed">closed leaf</div> 329 + @ has a "closed" tag and is thus assumed to 327 330 @ be historical and no longer in active use.</li> 328 331 @ </ol> 329 332 style_sidebox_end(); 330 333 331 334 if( showAll ){ 332 335 @ <h1>All leaves, both open and closed:</h1> 333 336 }else if( showClosed ){ ................................................................................ 339 342 "%s" 340 343 " AND blob.rid IN leaves" 341 344 " ORDER BY event.mtime DESC", 342 345 timeline_query_for_www() 343 346 ); 344 347 www_print_timeline(&q, TIMELINE_LEAFONLY, leaves_extra); 345 348 db_finalize(&q); 346 - @ <br clear="both"> 347 - @ <script> 349 + @ <br /> 350 + @ <script type="text/JavaScript"> 348 351 @ function xin(id){ 349 352 @ } 350 353 @ function xout(id){ 351 354 @ } 352 355 @ </script> 353 356 style_footer(); 354 357 }
Changes to src/diff.c.
63 63 }; 64 64 65 65 /* 66 66 ** Return an array of DLine objects containing a pointer to the 67 67 ** start of each line and a hash of that line. The lower 68 68 ** bits of the hash store the length of each line. 69 69 ** 70 -** Trailing whitespace is removed from each line. 70 +** Trailing whitespace is removed from each line. 2010-08-20: Not any 71 +** more. If trailing whitespace is ignored, the "patch" command gets 72 +** confused by the diff output. Ticket [a9f7b23c2e376af5b0e5b] 71 73 ** 72 74 ** Return 0 if the file is binary or contains a line that is 73 75 ** too long. 74 76 */ 75 -static DLine *break_into_lines(const char *z, int n, int *pnLine){ 77 +static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){ 76 78 int nLine, i, j, k, x; 77 79 unsigned int h, h2; 78 80 DLine *a; 79 81 80 82 /* Count the number of lines. Allocate space to hold 81 83 ** the returned array. 82 84 */ ................................................................................ 92 94 } 93 95 j = 0; 94 96 } 95 97 } 96 98 if( j>LENGTH_MASK ){ 97 99 return 0; 98 100 } 99 - a = malloc( nLine*sizeof(a[0]) ); 100 - if( a==0 ) fossil_panic("out of memory"); 101 + a = fossil_malloc( nLine*sizeof(a[0]) ); 101 102 memset(a, 0, nLine*sizeof(a[0]) ); 103 + if( n==0 ){ 104 + *pnLine = 0; 105 + return a; 106 + } 102 107 103 108 /* Fill in the array */ 104 109 for(i=0; i<nLine; i++){ 105 110 a[i].z = z; 106 111 for(j=0; z[j] && z[j]!='\n'; j++){} 107 - for(k=j; k>0 && isspace(z[k-1]); k--){} 112 + k = j; 113 + while( ignoreWS && k>0 && fossil_isspace(z[k-1]) ){ k--; } 108 114 for(h=0, x=0; x<k; x++){ 109 115 h = h ^ (h<<2) ^ z[x]; 110 116 } 111 117 a[i].h = h = (h<<LENGTH_MASK_SZ) | k;; 112 118 h2 = h % nLine; 113 119 a[i].iNext = a[h2].iHash; 114 120 a[h2].iHash = i+1; ................................................................................ 136 142 blob_append(pOut, "\n", 1); 137 143 } 138 144 139 145 /* 140 146 ** Expand the size of aEdit[] array to hold nEdit elements. 141 147 */ 142 148 static void expandEdit(DContext *p, int nEdit){ 143 - int *a; 144 - a = realloc(p->aEdit, nEdit*sizeof(int)); 145 - if( a==0 ){ 146 - free( p->aEdit ); 147 - p->nEdit = 0; 148 - nEdit = 0; 149 - } 150 - p->aEdit = a; 149 + p->aEdit = fossil_realloc(p->aEdit, nEdit*sizeof(int)); 151 150 p->nEditAlloc = nEdit; 152 151 } 153 152 154 153 /* 155 154 ** Append a new COPY/DELETE/INSERT triple. 156 155 */ 157 156 static void appendTriple(DContext *p, int nCopy, int nDel, int nIns){ ................................................................................ 277 276 m = R[r+nr*3]; 278 277 if( m>nContext ) m = nContext; 279 278 for(j=0; j<m; j++){ 280 279 appendDiffLine(pOut, " ", &B[b+j]); 281 280 } 282 281 } 283 282 } 283 + 284 +/* 285 +** Compute the optimal longest common subsequence (LCS) using an 286 +** exhaustive search. This version of the LCS is only used for 287 +** shorter input strings since runtime is O(N*N) where N is the 288 +** input string length. 289 +*/ 290 +static void optimalLCS( 291 + DContext *p, /* Two files being compared */ 292 + int iS1, int iE1, /* Range of lines in p->aFrom[] */ 293 + int iS2, int iE2, /* Range of lines in p->aTo[] */ 294 + int *piSX, int *piEX, /* Write p->aFrom[] common segment here */ 295 + int *piSY, int *piEY /* Write p->aTo[] common segment here */ 296 +){ 297 + int mxLength = 0; /* Length of longest common subsequence */ 298 + int i, j; /* Loop counters */ 299 + int k; /* Length of a candidate subsequence */ 300 + int iSXb = iS1; /* Best match so far */ 301 + int iSYb = iS2; /* Best match so far */ 302 + 303 + for(i=iS1; i<iE1-mxLength; i++){ 304 + for(j=iS2; j<iE2-mxLength; j++){ 305 + if( !same_dline(&p->aFrom[i], &p->aTo[j]) ) continue; 306 + if( mxLength && !same_dline(&p->aFrom[i+mxLength], &p->aTo[j+mxLength]) ){ 307 + continue; 308 + } 309 + k = 1; 310 + while( i+k<iE1 && j+k<iE2 && same_dline(&p->aFrom[i+k],&p->aTo[j+k]) ){ 311 + k++; 312 + } 313 + if( k>mxLength ){ 314 + iSXb = i; 315 + iSYb = j; 316 + mxLength = k; 317 + } 318 + } 319 + } 320 + *piSX = iSXb; 321 + *piEX = iSXb + mxLength; 322 + *piSY = iSYb; 323 + *piEY = iSYb + mxLength; 324 +} 284 325 285 326 /* 286 327 ** Compare two blocks of text on lines iS1 through iE1-1 of the aFrom[] 287 328 ** file and lines iS2 through iE2-1 of the aTo[] file. Locate a sequence 288 329 ** of lines in these two blocks that are exactly the same. Return 289 330 ** the bounds of the matching sequence. 331 +** 332 +** If there are two or more possible answers of the same length, the 333 +** returned sequence should be the one closest to the center of the 334 +** input range. 335 +** 336 +** Ideally, the common sequence should be the longest possible common 337 +** sequence. However, an exact computation of LCS is O(N*N) which is 338 +** way too slow for larger files. So this routine uses an O(N) 339 +** heuristic approximation based on hashing that usually works about 340 +** as well. But if the O(N) algorithm doesn't get a good solution 341 +** and N is not too large, we fall back to an exact solution by 342 +** calling optimalLCS(). 290 343 */ 291 344 static void longestCommonSequence( 292 345 DContext *p, /* Two files being compared */ 293 346 int iS1, int iE1, /* Range of lines in p->aFrom[] */ 294 347 int iS2, int iE2, /* Range of lines in p->aTo[] */ 295 348 int *piSX, int *piEX, /* Write p->aFrom[] common segment here */ 296 349 int *piSY, int *piEY /* Write p->aTo[] common segment here */ ................................................................................ 300 353 int iSX, iSY, iEX, iEY; /* Current match */ 301 354 double score; /* Current score */ 302 355 int skew; /* How lopsided is the match */ 303 356 int dist; /* Distance of match from center */ 304 357 int mid; /* Center of the span */ 305 358 int iSXb, iSYb, iEXb, iEYb; /* Best match so far */ 306 359 int iSXp, iSYp, iEXp, iEYp; /* Previous match */ 360 + 307 361 308 362 iSXb = iSXp = iS1; 309 363 iEXb = iEXp = iS1; 310 364 iSYb = iSYp = iS2; 311 365 iEYb = iEYp = iS2; 312 366 mid = (iE1 + iS1)/2; 313 367 for(i=iS1; i<iE1; i++){ ................................................................................ 352 406 }else{ 353 407 iSXp = iSX; 354 408 iSYp = iSY; 355 409 iEXp = iEX; 356 410 iEYp = iEY; 357 411 } 358 412 } 359 - *piSX = iSXb; 360 - *piSY = iSYb; 361 - *piEX = iEXb; 362 - *piEY = iEYb; 413 + if( iSXb==iEXb && (iE1-iS1)*(iE2-iS2)<400 ){ 414 + /* If no common sequence is found using the hashing heuristic and 415 + ** the input is not too big, use the expensive exact solution */ 416 + optimalLCS(p, iS1, iE1, iS2, iE2, piSX, piEX, piSY, piEY); 417 + }else{ 418 + *piSX = iSXb; 419 + *piSY = iSYb; 420 + *piEX = iEXb; 421 + *piEY = iEYb; 422 + } 363 423 /* printf("LCS(%d..%d/%d..%d) = %d..%d/%d..%d\n", 364 424 iS1, iE1, iS2, iE2, *piSX, *piEX, *piSY, *piEY); */ 365 425 } 366 426 367 427 /* 368 428 ** Do a single step in the difference. Compute a sequence of 369 429 ** copy/delete/insert steps that will convert lines iS1 through iE1-1 of ................................................................................ 470 530 ** file is encountered, 0 is returned and pOut is written with 471 531 ** text "cannot compute difference between binary files". 472 532 */ 473 533 int *text_diff( 474 534 Blob *pA_Blob, /* FROM file */ 475 535 Blob *pB_Blob, /* TO file */ 476 536 Blob *pOut, /* Write unified diff here if not NULL */ 477 - int nContext /* Amount of context to unified diff */ 537 + int nContext, /* Amount of context to unified diff */ 538 + int ignoreEolWs /* Ignore whitespace at the end of lines */ 478 539 ){ 479 540 DContext c; 480 541 481 542 /* Prepare the input files */ 482 543 memset(&c, 0, sizeof(c)); 483 - c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob), &c.nFrom); 484 - c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob), &c.nTo); 544 + c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob), 545 + &c.nFrom, ignoreEolWs); 546 + c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob), 547 + &c.nTo, ignoreEolWs); 485 548 if( c.aFrom==0 || c.aTo==0 ){ 486 549 free(c.aFrom); 487 550 free(c.aTo); 488 551 if( pOut ){ 489 552 blob_appendf(pOut, "cannot compute difference between binary files\n"); 490 553 } 491 554 return 0; ................................................................................ 520 583 int i; 521 584 int *R; 522 585 if( g.argc<4 ) usage("FILE1 FILE2 ..."); 523 586 blob_read_from_file(&a, g.argv[2]); 524 587 for(i=3; i<g.argc; i++){ 525 588 if( i>3 ) printf("-------------------------------\n"); 526 589 blob_read_from_file(&b, g.argv[i]); 527 - R = text_diff(&a, &b, 0, 0); 590 + R = text_diff(&a, &b, 0, 0, 0); 528 591 for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){ 529 592 printf(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]); 530 593 } 531 594 /* free(R); */ 532 595 blob_reset(&b); 533 596 } 534 597 } ................................................................................ 538 601 */ 539 602 void test_udiff_cmd(void){ 540 603 Blob a, b, out; 541 604 if( g.argc!=4 ) usage("FILE1 FILE2"); 542 605 blob_read_from_file(&a, g.argv[2]); 543 606 blob_read_from_file(&b, g.argv[3]); 544 607 blob_zero(&out); 545 - text_diff(&a, &b, &out, 3); 608 + text_diff(&a, &b, &out, 3, 0); 546 609 blob_write_to_file(&out, "-"); 547 610 } 548 611 549 612 /************************************************************************** 550 613 ** The basic difference engine is above. What follows is the annotation 551 614 ** engine. Both are in the same file since they share many components. 552 615 */ ................................................................................ 572 635 ** to be annotated. The annotator takes control of the input Blob and 573 636 ** will release it when it is finished with it. 574 637 */ 575 638 static int annotation_start(Annotator *p, Blob *pInput){ 576 639 int i; 577 640 578 641 memset(p, 0, sizeof(*p)); 579 - p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput), &p->c.nTo); 642 + p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,1); 580 643 if( p->c.aTo==0 ){ 581 644 return 1; 582 645 } 583 - p->aOrig = malloc( sizeof(p->aOrig[0])*p->c.nTo ); 584 - if( p->aOrig==0 ) fossil_panic("out of memory"); 646 + p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); 585 647 for(i=0; i<p->c.nTo; i++){ 586 648 p->aOrig[i].z = p->c.aTo[i].z; 587 649 p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK; 588 650 p->aOrig[i].zSrc = 0; 589 651 } 590 652 p->nOrig = p->c.nTo; 591 653 return 0; ................................................................................ 600 662 */ 601 663 static int annotation_step(Annotator *p, Blob *pParent, char *zPName){ 602 664 int i, j; 603 665 int lnTo; 604 666 605 667 /* Prepare the parent file to be diffed */ 606 668 p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), 607 - &p->c.nFrom); 669 + &p->c.nFrom, 1); 608 670 if( p->c.aFrom==0 ){ 609 671 return 1; 610 672 } 611 673 612 674 /* Compute the differences going from pParent to the file being 613 675 ** annotated. */ 614 676 diff_all(&p->c); ................................................................................ 755 817 756 818 /* 757 819 ** COMMAND: annotate 758 820 ** 759 821 ** %fossil annotate FILENAME 760 822 ** 761 823 ** Output the text of a file with markings to show when each line of 762 -** the file was introduced. 824 +** the file was last modified. 763 825 */ 764 826 void annotate_cmd(void){ 765 827 int fnid; /* Filename ID */ 766 828 int fid; /* File instance ID */ 767 829 int mid; /* Manifest where file was checked in */ 768 830 Blob treename; /* FILENAME translated to canonical form */ 769 831 char *zFilename; /* Cannonical filename */
Changes to src/diffcmd.c.
18 18 ** This file contains code used to implement the "diff" command 19 19 */ 20 20 #include "config.h" 21 21 #include "diffcmd.h" 22 22 #include <assert.h> 23 23 24 24 /* 25 -** Shell-escape the given string. Append the result to a blob. 25 +** Diff option flags 26 26 */ 27 -static void shell_escape(Blob *pBlob, const char *zIn){ 28 - int n = blob_size(pBlob); 29 - int k = strlen(zIn); 30 - int i, c; 31 - char *z; 32 - for(i=0; (c = zIn[i])!=0; i++){ 33 - if( isspace(c) || c=='"' || (c=='\\' && zIn[i+1]!=0) ){ 34 - blob_appendf(pBlob, "\"%s\"", zIn); 35 - z = blob_buffer(pBlob); 36 - for(i=n+1; i<=n+k; i++){ 37 - if( z[i]=='"' ) z[i] = '_'; 38 - } 39 - return; 40 - } 41 - } 42 - blob_append(pBlob, zIn, -1); 43 -} 44 - 45 -/* 46 -** This function implements a cross-platform "system()" interface. 47 -*/ 48 -int portable_system(const char *zOrigCmd){ 49 - int rc; 50 -#ifdef __MINGW32__ 51 - /* On windows, we have to put double-quotes around the entire command. 52 - ** Who knows why - this is just the way windows works. 53 - */ 54 - char *zNewCmd = mprintf("\"%s\"", zOrigCmd); 55 - rc = system(zNewCmd); 56 - free(zNewCmd); 57 -#else 58 - /* On unix, evaluate the command directly. 59 - */ 60 - rc = system(zOrigCmd); 61 -#endif 62 - return rc; 63 -} 27 +#define DIFF_NEWFILE 0x01 /* Treat non-existing fails as empty files */ 28 +#define DIFF_NOEOLWS 0x02 /* Ignore whitespace at the end of lines */ 64 29 65 30 /* 66 31 ** Show the difference between two files, one in memory and one on disk. 67 32 ** 68 33 ** The difference is the set of edits needed to transform pFile1 into 69 34 ** zFile2. The content of pFile1 is in memory. zFile2 exists on disk. 70 35 ** ................................................................................ 71 36 ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the 72 37 ** command zDiffCmd to do the diffing. 73 38 */ 74 39 static void diff_file( 75 40 Blob *pFile1, /* In memory content to compare from */ 76 41 const char *zFile2, /* On disk content to compare to */ 77 42 const char *zName, /* Display name of the file */ 78 - const char *zDiffCmd /* Command for comparison */ 43 + const char *zDiffCmd, /* Command for comparison */ 44 + int ignoreEolWs /* Ignore whitespace at end of line */ 79 45 ){ 80 46 if( zDiffCmd==0 ){ 81 - Blob out; /* Diff output text */ 82 - Blob file2; /* Content of zFile2 */ 47 + Blob out; /* Diff output text */ 48 + Blob file2; /* Content of zFile2 */ 49 + const char *zName2; /* Name of zFile2 for display */ 83 50 84 51 /* Read content of zFile2 into memory */ 85 52 blob_zero(&file2); 86 - blob_read_from_file(&file2, zFile2); 53 + if( file_size(zFile2)<0 ){ 54 + zName2 = "/dev/null"; 55 + }else{ 56 + blob_read_from_file(&file2, zFile2); 57 + zName2 = zName; 58 + } 87 59 88 60 /* Compute and output the differences */ 89 61 blob_zero(&out); 90 - text_diff(pFile1, &file2, &out, 5); 91 - printf("--- %s\n+++ %s\n", zName, zName); 62 + text_diff(pFile1, &file2, &out, 5, ignoreEolWs); 63 + printf("--- %s\n+++ %s\n", zName, zName2); 92 64 printf("%s\n", blob_str(&out)); 93 65 94 66 /* Release memory resources */ 95 67 blob_reset(&file2); 96 68 blob_reset(&out); 97 69 }else{ 98 70 int cnt = 0; ................................................................................ 112 84 blob_zero(&cmd); 113 85 blob_appendf(&cmd, "%s ", zDiffCmd); 114 86 shell_escape(&cmd, blob_str(&nameFile1)); 115 87 blob_append(&cmd, " ", 1); 116 88 shell_escape(&cmd, zFile2); 117 89 118 90 /* Run the external diff command */ 119 - portable_system(blob_str(&cmd)); 91 + fossil_system(blob_str(&cmd)); 120 92 121 93 /* Delete the temporary file and clean up memory used */ 122 94 unlink(blob_str(&nameFile1)); 123 95 blob_reset(&nameFile1); 124 96 blob_reset(&cmd); 125 97 } 126 98 } ................................................................................ 134 106 ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the 135 107 ** command zDiffCmd to do the diffing. 136 108 */ 137 109 static void diff_file_mem( 138 110 Blob *pFile1, /* In memory content to compare from */ 139 111 Blob *pFile2, /* In memory content to compare to */ 140 112 const char *zName, /* Display name of the file */ 141 - const char *zDiffCmd /* Command for comparison */ 113 + const char *zDiffCmd, /* Command for comparison */ 114 + int ignoreEolWs /* Ignore whitespace at end of lines */ 142 115 ){ 143 116 if( zDiffCmd==0 ){ 144 117 Blob out; /* Diff output text */ 145 118 146 119 blob_zero(&out); 147 - text_diff(pFile1, pFile2, &out, 5); 120 + text_diff(pFile1, pFile2, &out, 5, ignoreEolWs); 148 121 printf("--- %s\n+++ %s\n", zName, zName); 149 122 printf("%s\n", blob_str(&out)); 150 123 151 124 /* Release memory resources */ 152 125 blob_reset(&out); 153 126 }else{ 154 127 Blob cmd; ................................................................................ 165 138 blob_zero(&cmd); 166 139 blob_appendf(&cmd, "%s ", zDiffCmd); 167 140 shell_escape(&cmd, zTemp1); 168 141 blob_append(&cmd, " ", 1); 169 142 shell_escape(&cmd, zTemp2); 170 143 171 144 /* Run the external diff command */ 172 - portable_system(blob_str(&cmd)); 145 + fossil_system(blob_str(&cmd)); 173 146 174 147 /* Delete the temporary file and clean up memory used */ 175 148 unlink(zTemp1); 176 149 unlink(zTemp2); 177 150 blob_reset(&cmd); 178 151 } 179 152 } 180 153 181 154 /* 182 155 ** Do a diff against a single file named in g.argv[2] from version zFrom 183 156 ** against the same file on disk. 184 157 */ 185 -static void diff_one_against_disk(const char *zFrom, const char *zDiffCmd){ 158 +static void diff_one_against_disk( 159 + const char *zFrom, /* Name of file */ 160 + const char *zDiffCmd, /* Use this "diff" command */ 161 + int ignoreEolWs /* Ignore whitespace changes at end of lines */ 162 +){ 186 163 Blob fname; 187 164 Blob content; 188 165 file_tree_name(g.argv[2], &fname, 1); 189 166 historical_version_of_file(zFrom, blob_str(&fname), &content, 0); 190 - diff_file(&content, g.argv[2], g.argv[2], zDiffCmd); 167 + diff_file(&content, g.argv[2], g.argv[2], zDiffCmd, ignoreEolWs); 191 168 blob_reset(&content); 192 169 blob_reset(&fname); 193 170 } 194 171 195 172 /* 196 173 ** Run a diff between the version zFrom and files on disk. zFrom might 197 174 ** be NULL which means to simply show the difference between the edited 198 175 ** files on disk and the check-out on which they are based. 199 176 */ 200 -static void diff_all_against_disk(const char *zFrom, const char *zDiffCmd){ 177 +static void diff_all_against_disk( 178 + const char *zFrom, /* Version to difference from */ 179 + const char *zDiffCmd, /* Use this diff command. NULL for built-in */ 180 + int diffFlags /* Flags controlling diff output */ 181 +){ 201 182 int vid; 202 183 Blob sql; 203 184 Stmt q; 185 + int ignoreEolWs; /* Ignore end-of-line whitespace */ 186 + int asNewFile; /* Treat non-existant files as empty files */ 204 187 188 + ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0; 189 + asNewFile = (diffFlags & DIFF_NEWFILE)!=0; 205 190 vid = db_lget_int("checkout", 0); 206 191 vfile_check_signature(vid, 1); 207 192 blob_zero(&sql); 208 193 db_begin_transaction(); 209 194 if( zFrom ){ 210 195 int rid = name_to_rid(zFrom); 211 196 if( !is_a_version(rid) ){ ................................................................................ 244 229 } 245 230 db_prepare(&q, blob_str(&sql)); 246 231 while( db_step(&q)==SQLITE_ROW ){ 247 232 const char *zPathname = db_column_text(&q,0); 248 233 int isDeleted = db_column_int(&q, 1); 249 234 int isChnged = db_column_int(&q,2); 250 235 int isNew = db_column_int(&q,3); 236 + int srcid = db_column_int(&q, 4); 251 237 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); 238 + char *zToFree = zFullName; 239 + int showDiff = 1; 252 240 if( isDeleted ){ 253 241 printf("DELETED %s\n", zPathname); 242 + if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; } 254 243 }else if( access(zFullName, 0) ){ 255 244 printf("MISSING %s\n", zPathname); 245 + if( !asNewFile ){ showDiff = 0; } 256 246 }else if( isNew ){ 257 247 printf("ADDED %s\n", zPathname); 258 - }else if( isDeleted ){ 259 - printf("DELETED %s\n", zPathname); 248 + srcid = 0; 249 + if( !asNewFile ){ showDiff = 0; } 260 250 }else if( isChnged==3 ){ 261 251 printf("ADDED_BY_MERGE %s\n", zPathname); 262 - }else{ 263 - int srcid = db_column_int(&q, 4); 252 + srcid = 0; 253 + if( !asNewFile ){ showDiff = 0; } 254 + } 255 + if( showDiff ){ 264 256 Blob content; 265 - content_get(srcid, &content); 257 + if( srcid>0 ){ 258 + content_get(srcid, &content); 259 + }else{ 260 + blob_zero(&content); 261 + } 266 262 printf("Index: %s\n=======================================" 267 263 "============================\n", 268 264 zPathname 269 265 ); 270 - diff_file(&content, zFullName, zPathname, zDiffCmd); 266 + diff_file(&content, zFullName, zPathname, zDiffCmd, ignoreEolWs); 271 267 blob_reset(&content); 272 268 } 273 - free(zFullName); 269 + free(zToFree); 274 270 } 275 271 db_finalize(&q); 276 272 db_end_transaction(1); /* ROLLBACK */ 277 273 } 278 274 279 275 /* 280 276 ** Output the differences between two versions of a single file. 281 277 ** zFrom and zTo are the check-ins containing the two file versions. 282 278 ** The filename is contained in g.argv[2]. 283 279 */ 284 280 static void diff_one_two_versions( 285 281 const char *zFrom, 286 282 const char *zTo, 287 - const char *zDiffCmd 283 + const char *zDiffCmd, 284 + int ignoreEolWs 288 285 ){ 289 286 char *zName; 290 287 Blob fname; 291 288 Blob v1, v2; 292 289 file_tree_name(g.argv[2], &fname, 1); 293 290 zName = blob_str(&fname); 294 291 historical_version_of_file(zFrom, zName, &v1, 0); 295 292 historical_version_of_file(zTo, zName, &v2, 0); 296 - diff_file_mem(&v1, &v2, zName, zDiffCmd); 293 + diff_file_mem(&v1, &v2, zName, zDiffCmd, ignoreEolWs); 297 294 blob_reset(&v1); 298 295 blob_reset(&v2); 299 296 blob_reset(&fname); 300 297 } 298 + 299 +/* 300 +** Show the difference between two files identified by ManifestFile 301 +** entries. 302 +*/ 303 +static void diff_manifest_entry( 304 + struct ManifestFile *pFrom, 305 + struct ManifestFile *pTo, 306 + const char *zDiffCmd, 307 + int ignoreEolWs 308 +){ 309 + Blob f1, f2; 310 + int rid; 311 + const char *zName = pFrom ? pFrom->zName : pTo->zName; 312 + printf("Index: %s\n=======================================" 313 + "============================\n", zName); 314 + if( pFrom ){ 315 + rid = uuid_to_rid(pFrom->zUuid, 0); 316 + content_get(rid, &f1); 317 + }else{ 318 + blob_zero(&f1); 319 + } 320 + if( pTo ){ 321 + rid = uuid_to_rid(pTo->zUuid, 0); 322 + content_get(rid, &f2); 323 + }else{ 324 + blob_zero(&f2); 325 + } 326 + diff_file_mem(&f1, &f2, zName, zDiffCmd, ignoreEolWs); 327 + blob_reset(&f1); 328 + blob_reset(&f2); 329 +} 301 330 302 331 /* 303 332 ** Output the differences between two check-ins. 304 333 */ 305 334 static void diff_all_two_versions( 306 335 const char *zFrom, 307 336 const char *zTo, 308 - const char *zDiffCmd 337 + const char *zDiffCmd, 338 + int diffFlags 309 339 ){ 310 - Manifest mFrom, mTo; 311 - int iFrom, iTo; 340 + Manifest *pFrom, *pTo; 341 + ManifestFile *pFromFile, *pToFile; 342 + int ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0 ? 1 : 0; 343 + int asNewFlag = (diffFlags & DIFF_NEWFILE)!=0 ? 1 : 0; 344 + 345 + pFrom = manifest_get_by_name(zFrom, 0); 346 + manifest_file_rewind(pFrom); 347 + pFromFile = manifest_file_next(pFrom,0); 348 + pTo = manifest_get_by_name(zTo, 0); 349 + manifest_file_rewind(pTo); 350 + pToFile = manifest_file_next(pTo,0); 312 351 313 - manifest_from_name(zFrom, &mFrom); 314 - manifest_from_name(zTo, &mTo); 315 - iFrom = iTo = 0; 316 - while( iFrom<mFrom.nFile && iTo<mTo.nFile ){ 352 + while( pFromFile || pToFile ){ 317 353 int cmp; 318 - if( iFrom>=mFrom.nFile ){ 354 + if( pFromFile==0 ){ 319 355 cmp = +1; 320 - }else if( iTo>=mTo.nFile ){ 356 + }else if( pToFile==0 ){ 321 357 cmp = -1; 322 358 }else{ 323 - cmp = strcmp(mFrom.aFile[iFrom].zName, mTo.aFile[iTo].zName); 359 + cmp = strcmp(pFromFile->zName, pToFile->zName); 324 360 } 325 361 if( cmp<0 ){ 326 - printf("DELETED %s\n", mFrom.aFile[iFrom].zName); 327 - iFrom++; 362 + printf("DELETED %s\n", pFromFile->zName); 363 + if( asNewFlag ){ 364 + diff_manifest_entry(pFromFile, 0, zDiffCmd, ignoreEolWs); 365 + } 366 + pFromFile = manifest_file_next(pFrom,0); 328 367 }else if( cmp>0 ){ 329 - printf("ADDED %s\n", mTo.aFile[iTo].zName); 330 - iTo++; 331 - }else if( strcmp(mFrom.aFile[iFrom].zUuid, mTo.aFile[iTo].zUuid)==0 ){ 368 + printf("ADDED %s\n", pToFile->zName); 369 + if( asNewFlag ){ 370 + diff_manifest_entry(0, pToFile, zDiffCmd, ignoreEolWs); 371 + } 372 + pToFile = manifest_file_next(pTo,0); 373 + }else if( strcmp(pFromFile->zUuid, pToFile->zUuid)==0 ){ 332 374 /* No changes */ 333 - iFrom++; 334 - iTo++; 375 + pFromFile = manifest_file_next(pFrom,0); 376 + pToFile = manifest_file_next(pTo,0); 335 377 }else{ 336 - Blob f1, f2; 337 - int rid; 338 - printf("CHANGED %s\n", mFrom.aFile[iFrom].zName); 339 - rid = uuid_to_rid(mFrom.aFile[iFrom].zUuid, 0); 340 - content_get(rid, &f1); 341 - rid = uuid_to_rid(mTo.aFile[iTo].zUuid, 0); 342 - content_get(rid, &f2); 343 - diff_file_mem(&f1, &f2, mFrom.aFile[iFrom].zName, zDiffCmd); 344 - blob_reset(&f1); 345 - blob_reset(&f2); 346 - iFrom++; 347 - iTo++; 378 + printf("CHANGED %s\n", pFromFile->zName); 379 + diff_manifest_entry(pFromFile, pToFile, zDiffCmd, ignoreEolWs); 380 + pFromFile = manifest_file_next(pFrom,0); 381 + pToFile = manifest_file_next(pTo,0); 348 382 } 349 383 } 350 - manifest_clear(&mFrom); 351 - manifest_clear(&mTo); 384 + manifest_destroy(pFrom); 385 + manifest_destroy(pTo); 352 386 } 353 387 354 388 /* 355 389 ** COMMAND: diff 356 390 ** COMMAND: gdiff 357 391 ** 358 392 ** Usage: %fossil diff|gdiff ?options? ?FILE? ................................................................................ 371 405 ** no "--to" option then the (possibly edited) files in the current check-out 372 406 ** are used. 373 407 ** 374 408 ** The "-i" command-line option forces the use of the internal diff logic 375 409 ** rather than any external diff program that might be configured using 376 410 ** the "setting" command. If no external diff program is configured, then 377 411 ** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff". 412 +** 413 +** The "-N" or "--new-file" option causes the complete text of added or 414 +** deleted files to be displayed. 378 415 */ 379 416 void diff_cmd(void){ 380 417 int isGDiff; /* True for gdiff. False for normal diff */ 381 418 int isInternDiff; /* True for internal diff */ 419 + int hasNFlag; /* True if -N or --new-file flag is used */ 382 420 const char *zFrom; /* Source version number */ 383 421 const char *zTo; /* Target version number */ 384 422 const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */ 423 + int diffFlags = 0; /* Flags to control the DIFF */ 385 424 386 425 isGDiff = g.argv[1][0]=='g'; 387 426 isInternDiff = find_option("internal","i",0)!=0; 388 427 zFrom = find_option("from", "r", 1); 389 428 zTo = find_option("to", 0, 1); 429 + hasNFlag = find_option("new-file","N",0)!=0; 430 + 390 431 432 + if( hasNFlag ) diffFlags |= DIFF_NEWFILE; 391 433 if( zTo==0 ){ 392 434 db_must_be_within_tree(); 393 435 verify_all_options(); 394 - if( !isInternDiff && g.argc==3 ){ 436 + if( !isInternDiff ){ 395 437 zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0); 396 438 } 397 439 if( g.argc==3 ){ 398 - diff_one_against_disk(zFrom, zDiffCmd); 440 + diff_one_against_disk(zFrom, zDiffCmd, 0); 399 441 }else{ 400 - diff_all_against_disk(zFrom, zDiffCmd); 442 + diff_all_against_disk(zFrom, zDiffCmd, diffFlags); 401 443 } 402 444 }else if( zFrom==0 ){ 403 445 fossil_fatal("must use --from if --to is present"); 404 446 }else{ 405 447 db_find_and_open_repository(1); 406 448 verify_all_options(); 407 - if( !isInternDiff && g.argc==3 ){ 449 + if( !isInternDiff ){ 408 450 zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0); 409 451 } 410 452 if( g.argc==3 ){ 411 - diff_one_two_versions(zFrom, zTo, zDiffCmd); 453 + diff_one_two_versions(zFrom, zTo, zDiffCmd, 0); 412 454 }else{ 413 - diff_all_two_versions(zFrom, zTo, zDiffCmd); 455 + diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags); 414 456 } 415 457 } 416 458 }
Changes to src/doc.c.
288 288 z = zName; 289 289 for(i=0; zName[i]; i++){ 290 290 if( zName[i]=='.' ) z = &zName[i+1]; 291 291 } 292 292 len = strlen(z); 293 293 if( len<sizeof(zSuffix)-1 ){ 294 294 strcpy(zSuffix, z); 295 - for(i=0; zSuffix[i]; i++) zSuffix[i] = tolower(zSuffix[i]); 295 + for(i=0; zSuffix[i]; i++) zSuffix[i] = fossil_tolower(zSuffix[i]); 296 296 first = 0; 297 297 last = sizeof(aMime)/sizeof(aMime[0]); 298 298 while( first<=last ){ 299 299 int c; 300 300 i = (first+last)/2; 301 301 c = strcmp(zSuffix, aMime[i].zSuffix); 302 302 if( c==0 ) return aMime[i].zMimetype; ................................................................................ 386 386 " WHERE vid=%d AND fname=%Q", vid, zName); 387 387 if( rid==0 && db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){ 388 388 goto doc_not_found; 389 389 } 390 390 391 391 if( rid==0 ){ 392 392 Stmt s; 393 - Blob baseline; 394 - Manifest m; 393 + Manifest *pM; 394 + ManifestFile *pFile; 395 395 396 396 /* Add the vid baseline to the cache */ 397 397 if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){ 398 398 db_multi_exec("DELETE FROM vcache"); 399 399 } 400 - if( content_get(vid, &baseline)==0 ){ 401 - goto doc_not_found; 402 - } 403 - if( manifest_parse(&m, &baseline)==0 || m.type!=CFTYPE_MANIFEST ){ 400 + pM = manifest_get(vid, CFTYPE_MANIFEST); 401 + if( pM==0 ){ 404 402 goto doc_not_found; 405 403 } 406 404 db_prepare(&s, 407 405 "INSERT INTO vcache(vid,fname,rid)" 408 406 " SELECT %d, :fname, rid FROM blob" 409 407 " WHERE uuid=:uuid", 410 408 vid 411 409 ); 412 - for(i=0; i<m.nFile; i++){ 413 - db_bind_text(&s, ":fname", m.aFile[i].zName); 414 - db_bind_text(&s, ":uuid", m.aFile[i].zUuid); 410 + manifest_file_rewind(pM); 411 + while( (pFile = manifest_file_next(pM,0))!=0 ){ 412 + db_bind_text(&s, ":fname", pFile->zName); 413 + db_bind_text(&s, ":uuid", pFile->zUuid); 415 414 db_step(&s); 416 415 db_reset(&s); 417 416 } 418 417 db_finalize(&s); 419 - manifest_clear(&m); 418 + manifest_destroy(pM); 420 419 421 420 /* Try again to find the file */ 422 421 rid = db_int(0, "SELECT rid FROM vcache" 423 422 " WHERE vid=%d AND fname=%Q", vid, zName); 424 423 } 425 424 if( rid==0 ){ 426 425 goto doc_not_found;
Changes to src/encode.c.
42 42 case '&': count += 5; break; 43 43 case '"': count += 6; break; 44 44 default: count++; break; 45 45 } 46 46 i++; 47 47 } 48 48 i = 0; 49 - zOut = malloc( count+1 ); 50 - if( zOut==0 ) return 0; 49 + zOut = fossil_malloc( count+1 ); 51 50 while( n-->0 && (c = *zIn)!=0 ){ 52 51 switch( c ){ 53 52 case '<': 54 53 zOut[i++] = '&'; 55 54 zOut[i++] = 'l'; 56 55 zOut[i++] = 't'; 57 56 zOut[i++] = ';'; ................................................................................ 98 97 static char *EncodeHttp(const char *zIn, int n, int encodeSlash){ 99 98 int c; 100 99 int i = 0; 101 100 int count = 0; 102 101 char *zOut; 103 102 int other; 104 103 # define IsSafeChar(X) \ 105 - (isalnum(X) || (X)=='.' || (X)=='$' || (X)=='-' || (X)=='_' || (X)==other) 104 + (fossil_isalnum(X) || (X)=='.' || (X)=='$' \ 105 + || (X)=='~' || (X)=='-' || (X)=='_' || (X)==other) 106 106 107 107 if( zIn==0 ) return 0; 108 108 if( n<0 ) n = strlen(zIn); 109 109 other = encodeSlash ? 'a' : '/'; 110 110 while( i<n && (c = zIn[i])!=0 ){ 111 111 if( IsSafeChar(c) || c==' ' ){ 112 112 count++; 113 113 }else{ 114 114 count += 3; 115 115 } 116 116 i++; 117 117 } 118 118 i = 0; 119 - zOut = malloc( count+1 ); 120 - if( zOut==0 ) return 0; 119 + zOut = fossil_malloc( count+1 ); 121 120 while( n-->0 && (c = *zIn)!=0 ){ 122 121 if( IsSafeChar(c) ){ 123 122 zOut[i++] = c; 124 123 }else if( c==' ' ){ 125 124 zOut[i++] = '+'; 126 125 }else{ 127 126 zOut[i++] = '%'; ................................................................................ 231 230 if( nIn<0 ) nIn = strlen(zIn); 232 231 for(i=n=0; i<nIn; i++){ 233 232 c = zIn[i]; 234 233 if( c==0 || c==' ' || c=='\n' || c=='\t' || c=='\r' || c=='\f' || c=='\v' 235 234 || c=='\\' ) n++; 236 235 } 237 236 n += nIn; 238 - zOut = malloc( n+1 ); 237 + zOut = fossil_malloc( n+1 ); 239 238 if( zOut ){ 240 239 for(i=j=0; i<nIn; i++){ 241 240 int c = zIn[i]; 242 241 if( c==0 ){ 243 242 zOut[j++] = '\\'; 244 243 zOut[j++] = '0'; 245 244 }else if( c=='\\' ){ 246 245 zOut[j++] = '\\'; 247 246 zOut[j++] = '\\'; 248 - }else if( isspace(c) ){ 247 + }else if( fossil_isspace(c) ){ 249 248 zOut[j++] = '\\'; 250 249 switch( c ){ 251 250 case '\n': c = 'n'; break; 252 251 case ' ': c = 's'; break; 253 252 case '\t': c = 't'; break; 254 253 case '\r': c = 'r'; break; 255 254 case '\v': c = 'v'; break; ................................................................................ 266 265 } 267 266 268 267 /* 269 268 ** Decode a fossilized string in-place. 270 269 */ 271 270 void defossilize(char *z){ 272 271 int i, j, c; 273 - for(i=j=0; z[i]; i++){ 274 - c = z[i]; 272 + for(i=0; (c=z[i])!=0 && c!='\\'; i++){} 273 + if( c==0 ) return; 274 + for(j=i; (c=z[i])!=0; i++){ 275 275 if( c=='\\' && z[i+1] ){ 276 276 i++; 277 277 switch( z[i] ){ 278 278 case 'n': c = '\n'; break; 279 279 case 's': c = ' '; break; 280 280 case 't': c = '\t'; break; 281 281 case 'r': c = '\r'; break; ................................................................................ 307 307 char *encode64(const char *zData, int nData){ 308 308 char *z64; 309 309 int i, n; 310 310 311 311 if( nData<=0 ){ 312 312 nData = strlen(zData); 313 313 } 314 - z64 = malloc( (nData*4)/3 + 8 ); 314 + z64 = fossil_malloc( (nData*4)/3 + 8 ); 315 315 for(i=n=0; i+2<nData; i+=3){ 316 316 z64[n++] = zBase[ (zData[i]>>2) & 0x3f ]; 317 317 z64[n++] = zBase[ ((zData[i]<<4) & 0x30) | ((zData[i+1]>>4) & 0x0f) ]; 318 318 z64[n++] = zBase[ ((zData[i+1]<<2) & 0x3c) | ((zData[i+2]>>6) & 0x03) ]; 319 319 z64[n++] = zBase[ zData[i+2] & 0x3f ]; 320 320 } 321 321 if( i+1<nData ){ ................................................................................ 368 368 if( !isInit ){ 369 369 for(i=0; i<128; i++){ trans[i] = 0; } 370 370 for(i=0; zBase[i]; i++){ trans[zBase[i] & 0x7f] = i; } 371 371 isInit = 1; 372 372 } 373 373 n64 = strlen(z64); 374 374 while( n64>0 && z64[n64-1]=='=' ) n64--; 375 - zData = malloc( (n64*3)/4 + 4 ); 375 + zData = fossil_malloc( (n64*3)/4 + 4 ); 376 376 for(i=j=0; i+3<n64; i+=4){ 377 377 a = trans[z64[i] & 0x7f]; 378 378 b = trans[z64[i+1] & 0x7f]; 379 379 c = trans[z64[i+2] & 0x7f]; 380 380 d = trans[z64[i+3] & 0x7f]; 381 381 zData[j++] = ((a<<2) & 0xfc) | ((b>>4) & 0x03); 382 382 zData[j++] = ((b<<4) & 0xf0) | ((c>>2) & 0x0f); ................................................................................ 503 503 */ 504 504 void canonical16(char *z, int n){ 505 505 while( *z && n-- ){ 506 506 *z = zEncode[zDecode[(*z)&0x7f]&0x1f]; 507 507 z++; 508 508 } 509 509 } 510 + 511 +/* Randomness used for XOR-ing by the obscure() and unobscure() routines */ 512 +static const unsigned char aObscurer[16] = { 513 + 0xa7, 0x21, 0x31, 0xe3, 0x2a, 0x50, 0x2c, 0x86, 514 + 0x4c, 0xa4, 0x52, 0x25, 0xff, 0x49, 0x35, 0x85 515 +}; 516 + 517 + 518 +/* 519 +** Obscure plain text so that it is not easily readable. 520 +** 521 +** This is used for storing sensitive information (such as passwords) in a 522 +** way that prevents their exposure through idle browsing. This is not 523 +** encryption. Anybody who really wants the password can still get it. 524 +** 525 +** The text is XOR-ed with a repeating pattern then converted to hex. 526 +** Space to hold the returned string is obtained from malloc and should 527 +** be freed by the caller. 528 +*/ 529 +char *obscure(const char *zIn){ 530 + int n, i; 531 + unsigned char salt; 532 + char *zOut; 533 + 534 + if( zIn==0 ) return 0; 535 + n = strlen(zIn); 536 + zOut = fossil_malloc( n*2+3 ); 537 + sqlite3_randomness(1, &salt); 538 + zOut[n+1] = (char)salt; 539 + for(i=0; i<n; i++) zOut[i+n+2] = zIn[i]^aObscurer[i&0x0f]^salt; 540 + encode16((unsigned char*)&zOut[n+1], (unsigned char*)zOut, n+1); 541 + return zOut; 542 +} 543 + 544 +/* 545 +** Undo the obscuring of text performed by obscure(). Or, if the input is 546 +** not hexadecimal (meaning the input is not the output of obscure()) then 547 +** do the equivalent of strdup(). 548 +** 549 +** The result is memory obtained from malloc that should be freed by the caller. 550 +*/ 551 +char *unobscure(const char *zIn){ 552 + int n, i; 553 + unsigned char salt; 554 + char *zOut; 555 + 556 + if( zIn==0 ) return 0; 557 + n = strlen(zIn); 558 + zOut = fossil_malloc( n + 1 ); 559 + if( n<2 560 + || decode16((unsigned char*)zIn, &salt, 2) 561 + || decode16((unsigned char*)&zIn[2], (unsigned char*)zOut, n-2) 562 + ){ 563 + memcpy(zOut, zIn, n+1); 564 + }else{ 565 + n = n/2 - 1; 566 + for(i=0; i<n; i++) zOut[i] = zOut[i]^aObscurer[i&0x0f]^salt; 567 + zOut[n] = 0; 568 + } 569 + return zOut; 570 +} 571 + 572 +/* 573 +** Command to test obscure() and unobscure(). These commands are also useful 574 +** utilities for decoding passwords found in the database. 575 +** 576 +** COMMAND: test-obscure 577 +*/ 578 +void test_obscure_cmd(void){ 579 + int i; 580 + char *z, *z2; 581 + for(i=2; i<g.argc; i++){ 582 + z = obscure(g.argv[i]); 583 + z2 = unobscure(z); 584 + printf("OBSCURE: %s -> %s (%s)\n", g.argv[i], z, z2); 585 + free(z); 586 + free(z2); 587 + z = unobscure(g.argv[i]); 588 + printf("UNOBSCURE: %s -> %s\n", g.argv[i], z); 589 + free(z); 590 + } 591 +}
Added src/event.c.
1 +/* 2 +** Copyright (c) 2010 D. Richard Hipp 3 +** 4 +** This program is free software; you can redistribute it and/or 5 +** modify it under the terms of the Simplified BSD License (also 6 +** known as the "2-Clause License" or "FreeBSD License".) 7 + 8 +** This program is distributed in the hope that it will be useful, 9 +** but without any warranty; without even the implied warranty of 10 +** merchantability or fitness for a particular purpose. 11 +** 12 +** Author contact information: 13 +** drh@hwaci.com 14 +** http://www.hwaci.com/drh/ 15 +** 16 +******************************************************************************* 17 +** 18 +** This file contains code to do formatting of event messages: 19 +** 20 +** Milestones 21 +** Blog posts 22 +** New articles 23 +** Process checkpoints 24 +** Announcements 25 +*/ 26 +#include <assert.h> 27 +#include <ctype.h> 28 +#include "config.h" 29 +#include "event.h" 30 + 31 +/* 32 +** Output a hyperlink to an event given its tagid. 33 +*/ 34 +void hyperlink_to_event_tagid(int tagid){ 35 + char *zEventId; 36 + char zShort[12]; 37 + 38 + zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d", 39 + tagid); 40 + sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zEventId); 41 + if( g.okHistory ){ 42 + @ [<a href="%s(g.zTop)/event?name=%s(zEventId)">%s(zShort)</a>] 43 + }else{ 44 + @ [%s(zShort)] 45 + } 46 + free(zEventId); 47 +} 48 + 49 +/* 50 +** WEBPAGE: event 51 +** URL: /event 52 +** PARAMETERS: 53 +** 54 +** name=EVENTID // Identify the event to display EVENTID must be complete 55 +** detail=BOOLEAN // Show details if TRUE. Default is FALSE. Optional. 56 +** aid=ARTIFACTID // Which specific version of the event. Optional. 57 +** 58 +** Display an existing event identified by EVENTID 59 +*/ 60 +void event_page(void){ 61 + int rid = 0; /* rid of the event artifact */ 62 + char *zUuid; /* UUID corresponding to rid */ 63 + const char *zEventId; /* Event identifier */ 64 + char *zETime; /* Time of the event */ 65 + char *zATime; /* Time the artifact was created */ 66 + int specRid; /* rid specified by aid= parameter */ 67 + int prevRid, nextRid; /* Previous or next edits of this event */ 68 + Manifest *pEvent; /* Parsed event artifact */ 69 + Blob fullbody; /* Complete content of the event body */ 70 + Blob title; /* Title extracted from the event body */ 71 + Blob tail; /* Event body that comes after the title */ 72 + Stmt q1; /* Query to search for the event */ 73 + int showDetail; /* True to show details */ 74 + 75 + 76 + /* wiki-read privilege is needed in order to read events. 77 + */ 78 + login_check_credentials(); 79 + if( !g.okRdWiki ){ 80 + login_needed(); 81 + return; 82 + } 83 + 84 + zEventId = P("name"); 85 + if( zEventId==0 ){ fossil_redirect_home(); return; } 86 + zUuid = (char*)P("aid"); 87 + specRid = zUuid ? uuid_to_rid(zUuid, 0) : 0; 88 + rid = nextRid = prevRid = 0; 89 + db_prepare(&q1, 90 + "SELECT rid FROM tagxref" 91 + " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB 'event-%q*')" 92 + " ORDER BY mtime DESC", 93 + zEventId 94 + ); 95 + while( db_step(&q1)==SQLITE_ROW ){ 96 + nextRid = rid; 97 + rid = db_column_int(&q1, 0); 98 + if( specRid==0 || specRid==rid ){ 99 + if( db_step(&q1)==SQLITE_ROW ){ 100 + prevRid = db_column_int(&q1, 0); 101 + } 102 + break; 103 + } 104 + } 105 + db_finalize(&q1); 106 + if( rid==0 || (specRid!=0 && specRid!=rid) ){ 107 + style_header("No Such Event"); 108 + @ Cannot locate specified event 109 + style_footer(); 110 + return; 111 + } 112 + zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); 113 + showDetail = atoi(PD("detail","0")); 114 + 115 + /* Extract the event content. 116 + */ 117 + pEvent = manifest_get(rid, CFTYPE_EVENT); 118 + if( pEvent==0 ){ 119 + fossil_panic("Object #%d is not an event", rid); 120 + } 121 + blob_init(&fullbody, pEvent->zWiki, -1); 122 + if( wiki_find_title(&fullbody, &title, &tail) ){ 123 + style_header(blob_str(&title)); 124 + }else{ 125 + style_header("Event %S", zEventId); 126 + tail = fullbody; 127 + } 128 + if( g.okWrWiki && g.okWrite && nextRid==0 ){ 129 + style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s", 130 + g.zTop, zEventId); 131 + } 132 + zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate); 133 + style_submenu_element("Context", "Context", "%s/timeline?c=%T", 134 + g.zTop, zETime); 135 + if( g.okHistory ){ 136 + if( showDetail ){ 137 + style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s", 138 + g.zTop, zEventId, zUuid); 139 + if( nextRid ){ 140 + char *zNext; 141 + zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); 142 + style_submenu_element("Next", "Next", 143 + "%s/event?name=%s&aid=%s&detail=1", 144 + g.zTop, zEventId, zNext); 145 + free(zNext); 146 + } 147 + if( prevRid ){ 148 + char *zPrev; 149 + zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid); 150 + style_submenu_element("Prev", "Prev", 151 + "%s/event?name=%s&aid=%s&detail=1", 152 + g.zTop, zEventId, zPrev); 153 + free(zPrev); 154 + } 155 + }else{ 156 + style_submenu_element("Detail", "Detail", 157 + "%s/event?name=%s&aid=%s&detail=1", 158 + g.zTop, zEventId, zUuid); 159 + } 160 + } 161 + 162 + if( showDetail && g.okHistory ){ 163 + int i; 164 + const char *zClr = 0; 165 + Blob comment; 166 + 167 + zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate); 168 + @ <p>Event [<a href="%s(g.zTop)/artifact/%s(zUuid)">%S(zUuid)</a>] at 169 + @ [<a href="%s(g.zTop)/timeline?c=%T(zETime)">%s(zETime)</a>] 170 + @ entered by user <b>%h(pEvent->zUser)</b> on 171 + @ [<a href="%s(g.zTop)/timeline?c=%T(zATime)">%s(zATime)</a>]:</p> 172 + @ <blockquote> 173 + for(i=0; i<pEvent->nTag; i++){ 174 + if( strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){ 175 + zClr = pEvent->aTag[i].zValue; 176 + } 177 + } 178 + if( zClr && zClr[0]==0 ) zClr = 0; 179 + if( zClr ){ 180 + @ <div style="background-color: %h(zClr);"> 181 + }else{ 182 + @ <div> 183 + } 184 + blob_init(&comment, pEvent->zComment, -1); 185 + wiki_convert(&comment, 0, WIKI_INLINE); 186 + blob_reset(&comment); 187 + @ </div> 188 + @ </blockquote><hr /> 189 + } 190 + 191 + wiki_convert(&tail, 0, 0); 192 + style_footer(); 193 + manifest_destroy(pEvent); 194 +} 195 + 196 +/* 197 +** WEBPAGE: eventedit 198 +** URL: /eventedit?name=EVENTID 199 +** 200 +** Edit an event. If name is omitted, create a new event. 201 +*/ 202 +void eventedit_page(void){ 203 + char *zTag; 204 + int rid = 0; 205 + Blob event; 206 + const char *zEventId; 207 + char *zHtmlPageName; 208 + int n; 209 + const char *z; 210 + char *zBody = (char*)P("w"); 211 + char *zETime = (char*)P("t"); 212 + const char *zComment = P("c"); 213 + const char *zTags = P("g"); 214 + const char *zClr; 215 + 216 + if( zBody ){ 217 + zBody = mprintf("%s", zBody); 218 + } 219 + login_check_credentials(); 220 + zEventId = P("name"); 221 + if( zEventId==0 ){ 222 + zEventId = db_text(0, "SELECT lower(hex(randomblob(20)))"); 223 + }else{ 224 + int nEventId = strlen(zEventId); 225 + if( nEventId!=40 || !validate16(zEventId, 40) ){ 226 + fossil_redirect_home(); 227 + return; 228 + } 229 + } 230 + zTag = mprintf("event-%s", zEventId); 231 + rid = db_int(0, 232 + "SELECT rid FROM tagxref" 233 + " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" 234 + " ORDER BY mtime DESC", zTag 235 + ); 236 + free(zTag); 237 + 238 + /* Need both check-in and wiki-write or wiki-create privileges in order 239 + ** to edit/create an event. 240 + */ 241 + if( !g.okWrite || (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){ 242 + login_needed(); 243 + return; 244 + } 245 + 246 + /* Figure out the color */ 247 + if( rid ){ 248 + zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid); 249 + }else{ 250 + zClr = ""; 251 + } 252 + zClr = PD("clr",zClr); 253 + if( strcmp(zClr,"##")==0 ) zClr = PD("cclr",""); 254 + 255 + 256 + /* If editing an existing event, extract the key fields to use as 257 + ** a starting point for the edit. 258 + */ 259 + if( rid && (zBody==0 || zETime==0 || zComment==0 || zTags==0) ){ 260 + Manifest *pEvent; 261 + pEvent = manifest_get(rid, CFTYPE_EVENT); 262 + if( pEvent && pEvent->type==CFTYPE_EVENT ){ 263 + if( zBody==0 ) zBody = pEvent->zWiki; 264 + if( zETime==0 ){ 265 + zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate); 266 + } 267 + if( zComment==0 ) zComment = pEvent->zComment; 268 + } 269 + if( zTags==0 ){ 270 + zTags = db_text(0, 271 + "SELECT group_concat(substr(tagname,5),', ')" 272 + " FROM tagxref, tag" 273 + " WHERE tagxref.rid=%d" 274 + " AND tagxref.tagid=tag.tagid" 275 + " AND tag.tagname GLOB 'sym-*'", 276 + rid 277 + ); 278 + } 279 + } 280 + zETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))", zETime); 281 + if( P("submit")!=0 && (zBody!=0 && zComment!=0) ){ 282 + char *zDate; 283 + Blob cksum; 284 + int nrid; 285 + blob_zero(&event); 286 + db_begin_transaction(); 287 + login_verify_csrf_secret(); 288 + blob_appendf(&event, "C %F\n", zComment); 289 + zDate = db_text(0, "SELECT datetime('now')"); 290 + zDate[10] = 'T'; 291 + blob_appendf(&event, "D %s\n", zDate); 292 + free(zDate); 293 + zETime[10] = 'T'; 294 + blob_appendf(&event, "E %s %s\n", zETime, zEventId); 295 + zETime[10] = ' '; 296 + if( rid ){ 297 + char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); 298 + blob_appendf(&event, "P %s\n", zUuid); 299 + free(zUuid); 300 + } 301 + if( zClr && zClr[0] ){ 302 + blob_appendf(&event, "T +bgcolor * %F\n", zClr); 303 + } 304 + if( zTags && zTags[0] ){ 305 + Blob tags, one; 306 + int i, j; 307 + Stmt q; 308 + char *zBlob; 309 + 310 + /* Load the tags string into a blob */ 311 + blob_zero(&tags); 312 + blob_append(&tags, zTags, -1); 313 + 314 + /* Collapse all sequences of whitespace and "," characters into 315 + ** a single space character */ 316 + zBlob = blob_str(&tags); 317 + for(i=j=0; zBlob[i]; i++, j++){ 318 + if( fossil_isspace(zBlob[i]) || zBlob[i]==',' ){ 319 + while( fossil_isspace(zBlob[i+1]) ){ i++; } 320 + zBlob[j] = ' '; 321 + }else{ 322 + zBlob[j] = zBlob[i]; 323 + } 324 + } 325 + blob_resize(&tags, j); 326 + 327 + /* Parse out each tag and load it into a temporary table for sorting */ 328 + db_multi_exec("CREATE TEMP TABLE newtags(x);"); 329 + while( blob_token(&tags, &one) ){ 330 + db_multi_exec("INSERT INTO newtags VALUES(%B)", &one); 331 + } 332 + blob_reset(&tags); 333 + 334 + /* Extract the tags in sorted order and make an entry in the 335 + ** artifact for each. */ 336 + db_prepare(&q, "SELECT x FROM newtags ORDER BY x"); 337 + while( db_step(&q)==SQLITE_ROW ){ 338 + blob_appendf(&event, "T +sym-%F *\n", db_column_text(&q, 0)); 339 + } 340 + db_finalize(&q); 341 + } 342 + if( g.zLogin ){ 343 + blob_appendf(&event, "U %F\n", g.zLogin); 344 + } 345 + blob_appendf(&event, "W %d\n%s\n", strlen(zBody), zBody); 346 + md5sum_blob(&event, &cksum); 347 + blob_appendf(&event, "Z %b\n", &cksum); 348 + blob_reset(&cksum); 349 + nrid = content_put(&event, 0, 0); 350 + db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); 351 + manifest_crosslink(nrid, &event); 352 + blob_reset(&event); 353 + content_deltify(rid, nrid, 0); 354 + db_end_transaction(0); 355 + cgi_redirectf("event?name=%T", zEventId); 356 + } 357 + if( P("cancel")!=0 ){ 358 + cgi_redirectf("event?name=%T", zEventId); 359 + return; 360 + } 361 + if( zBody==0 ){ 362 + zBody = mprintf("<i>Event Text</i>"); 363 + } 364 + zHtmlPageName = mprintf("Edit Event %S", zEventId); 365 + style_header(zHtmlPageName); 366 + if( P("preview")!=0 ){ 367 + Blob title, tail, com; 368 + @ <p><b>Timeline comment preview:</b></p> 369 + @ <blockquote> 370 + @ <table border="0"> 371 + if( zClr && zClr[0] ){ 372 + @ <tr><td style="background-color: %h(zClr);"> 373 + }else{ 374 + @ <tr><td> 375 + } 376 + blob_zero(&com); 377 + blob_append(&com, zComment, -1); 378 + wiki_convert(&com, 0, WIKI_INLINE); 379 + @ </td></tr></table> 380 + @ </blockquote> 381 + @ <p><b>Page content preview:</b><p> 382 + @ <blockquote> 383 + blob_zero(&event); 384 + blob_append(&event, zBody, -1); 385 + if( wiki_find_title(&event, &title, &tail) ){ 386 + @ <h2 align="center">%h(blob_str(&title))</h2> 387 + wiki_convert(&tail, 0, 0); 388 + }else{ 389 + wiki_convert(&event, 0, 0); 390 + } 391 + @ </blockquote><hr /> 392 + blob_reset(&event); 393 + } 394 + for(n=2, z=zBody; z[0]; z++){ 395 + if( z[0]=='\n' ) n++; 396 + } 397 + if( n<20 ) n = 20; 398 + if( n>40 ) n = 40; 399 + @ <form method="post" action="%s(g.zBaseURL)/eventedit"><div> 400 + login_insert_csrf_secret(); 401 + @ <input type="hidden" name="name" value="%h(zEventId)" /> 402 + @ <table border="0" cellspacing="10"> 403 + 404 + @ <tr><td align="right" valign="top"><b>Event Time:</b></td> 405 + @ <td valign="top"> 406 + @ <input type="text" name="t" size="25" value="%h(zETime)" /> 407 + @ </td></tr> 408 + 409 + @ <tr><td align="right" valign="top"><b>Timeline Comment:</b></td> 410 + @ <td valign="top"> 411 + @ <textarea name="c" class="eventedit" cols="80" 412 + @ rows="3" wrap="virtual">%h(zComment)</textarea> 413 + @ </td></tr> 414 + 415 + @ <tr><td align="right" valign="top"><b>Background Color:</b></td> 416 + @ <td valign="top"> 417 + render_color_chooser(0, zClr, 0, "clr", "cclr"); 418 + @ </td></tr> 419 + 420 + @ <tr><td align="right" valign="top"><b>Tags:</b></td> 421 + @ <td valign="top"> 422 + @ <input type="text" name="g" size="40" value="%h(zTags)" /> 423 + @ </td></tr> 424 + 425 + @ <tr><td align="right" valign="top"><b>Page Content:</b></td> 426 + @ <td valign="top"> 427 + @ <textarea name="w" class="eventedit" cols="80" 428 + @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> 429 + @ </td></tr> 430 + 431 + @ <tr><td colspan="2"> 432 + @ <input type="submit" name="preview" value="Preview Your Changes" /> 433 + @ <input type="submit" name="submit" value="Apply These Changes" /> 434 + @ <input type="submit" name="cancel" value="Cancel" /> 435 + @ </td></tr></table> 436 + @ </div></form> 437 + style_footer(); 438 +}
Changes to src/file.c.
21 21 #include <sys/types.h> 22 22 #include <sys/stat.h> 23 23 #include <unistd.h> 24 24 #include "file.h" 25 25 26 26 /* 27 27 ** The file status information from the most recent stat() call. 28 +** 29 +** Use _stati64 rather than stat on windows, in order to handle files 30 +** larger than 2GB. 28 31 */ 29 -static struct stat fileStat; 32 +#if defined(_WIN32) && defined(__MSVCRT__) 33 + static struct _stati64 fileStat; 34 +# define stat _stati64 35 +#else 36 + static struct stat fileStat; 37 +#endif 30 38 static int fileStatValid = 0; 31 39 32 40 /* 33 41 ** Fill in the fileStat variable for the file named zFilename. 34 42 ** If zFilename==0, then use the previous value of fileStat if 35 43 ** there is a previous value. 36 44 ** ................................................................................ 81 89 82 90 /* 83 91 ** Return TRUE if the named file is an executable. Return false 84 92 ** for directories, devices, fifos, symlinks, etc. 85 93 */ 86 94 int file_isexe(const char *zFilename){ 87 95 if( getStat(zFilename) || !S_ISREG(fileStat.st_mode) ) return 0; 88 -#ifdef __MINGW32__ 96 +#if defined(_WIN32) 97 +# if defined(__DMC__) || defined(_MSC_VER) 98 +# define S_IXUSR _S_IEXEC 99 +# endif 89 100 return ((S_IXUSR)&fileStat.st_mode)!=0; 90 101 #else 91 102 return ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0; 92 103 #endif 93 104 } 94 105 95 106 ................................................................................ 143 154 fclose(out); 144 155 } 145 156 146 157 /* 147 158 ** Set or clear the execute bit on a file. 148 159 */ 149 160 void file_setexe(const char *zFilename, int onoff){ 150 -#ifndef __MINGW32__ 161 +#if !defined(_WIN32) 151 162 struct stat buf; 152 163 if( stat(zFilename, &buf)!=0 ) return; 153 164 if( onoff ){ 154 165 if( (buf.st_mode & 0111)!=0111 ){ 155 166 chmod(zFilename, buf.st_mode | 0111); 156 167 } 157 168 }else{ 158 169 if( (buf.st_mode & 0111)!=0 ){ 159 170 chmod(zFilename, buf.st_mode & ~0111); 160 171 } 161 172 } 162 -#endif /* __MINGW32__ */ 173 +#endif /* _WIN32 */ 163 174 } 164 175 165 176 /* 166 177 ** Create the directory named in the argument, if it does not already 167 178 ** exist. If forceFlag is 1, delete any prior non-directory object 168 179 ** with the same name. 169 180 ** ................................................................................ 172 183 int file_mkdir(const char *zName, int forceFlag){ 173 184 int rc = file_isdir(zName); 174 185 if( rc==2 ){ 175 186 if( !forceFlag ) return 1; 176 187 unlink(zName); 177 188 } 178 189 if( rc!=1 ){ 179 -#ifdef __MINGW32__ 190 +#if defined(_WIN32) 180 191 return mkdir(zName); 181 192 #else 182 193 return mkdir(zName, 0755); 183 194 #endif 184 195 } 185 196 return 0; 186 197 } ................................................................................ 229 240 ** * removing /A/../ 230 241 ** 231 242 ** Changes are made in-place. Return the new name length. 232 243 */ 233 244 int file_simplify_name(char *z, int n){ 234 245 int i, j; 235 246 if( n<0 ) n = strlen(z); 236 -#ifdef __MINGW32__ 247 +#if defined(_WIN32) 237 248 for(i=0; i<n; i++){ 238 249 if( z[i]=='\\' ) z[i] = '/'; 239 250 } 240 251 #endif 241 252 while( n>1 && z[n-1]=='/' ){ n--; } 242 253 for(i=j=0; i<n; i++){ 243 254 if( z[i]=='/' ){ ................................................................................ 264 275 ** Make the name absolute if it is relative. 265 276 ** Remove redundant / characters 266 277 ** Remove all /./ path elements. 267 278 ** Convert /A/../ to just / 268 279 */ 269 280 void file_canonical_name(const char *zOrigName, Blob *pOut){ 270 281 if( zOrigName[0]=='/' 271 -#ifdef __MINGW32__ 282 +#if defined(_WIN32) 272 283 || zOrigName[0]=='\\' 273 284 || (strlen(zOrigName)>3 && zOrigName[1]==':' 274 285 && (zOrigName[2]=='\\' || zOrigName[2]=='/')) 275 286 #endif 276 287 ){ 277 288 blob_set(pOut, zOrigName); 278 289 blob_materialize(pOut); ................................................................................ 286 297 blob_appendf(pOut, "%//%/", zPwd, zOrigName); 287 298 } 288 299 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut))); 289 300 } 290 301 291 302 /* 292 303 ** COMMAND: test-canonical-name 304 +** Usage: %fossil test-canonical-name FILENAME... 293 305 ** 294 306 ** Test the operation of the canonical name generator. 307 +** Also test Fossil's ability to measure attributes of a file. 295 308 */ 296 309 void cmd_test_canonical_name(void){ 297 310 int i; 298 311 Blob x; 299 312 blob_zero(&x); 300 313 for(i=2; i<g.argc; i++){ 301 - file_canonical_name(g.argv[i], &x); 314 + const char *zName = g.argv[i]; 315 + file_canonical_name(zName, &x); 302 316 printf("%s\n", blob_buffer(&x)); 303 317 blob_reset(&x); 318 + printf(" file_size = %lld\n", file_size(zName)); 319 + printf(" file_mtime = %lld\n", file_mtime(zName)); 320 + printf(" file_isfile = %d\n", file_isfile(zName)); 321 + printf(" file_isexe = %d\n", file_isexe(zName)); 322 + printf(" file_isdir = %d\n", file_isdir(zName)); 304 323 } 305 324 } 306 325 307 326 /* 308 327 ** Return TRUE if the given filename is canonical. 309 328 ** 310 329 ** Canonical names are full pathnames using "/" not "\" and which 311 330 ** contain no "/./" or "/../" terms. 312 331 */ 313 332 int file_is_canonical(const char *z){ 314 333 int i; 315 334 if( z[0]!='/' 316 -#ifdef __MINGW32__ 335 +#if defined(_WIN32) 317 336 && (z[0]==0 || z[1]!=':' || z[2]!='/') 318 337 #endif 319 338 ) return 0; 320 339 321 340 for(i=0; z[i]; i++){ 322 341 if( z[i]=='\\' ) return 0; 323 342 if( z[i]=='/' ){
Changes to src/finfo.c.
129 129 " AND event.objid=mlink.mid" 130 130 " ORDER BY event.mtime DESC /*sort*/", 131 131 TAG_BRANCH, 132 132 zFilename 133 133 ); 134 134 blob_zero(&title); 135 135 blob_appendf(&title, "History of "); 136 - hyperlinked_path(zFilename, &title); 136 + hyperlinked_path(zFilename, &title, 0); 137 137 @ <h2>%b(&title)</h2> 138 138 blob_reset(&title); 139 139 pGraph = graph_init(); 140 140 @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div> 141 - @ <table cellspacing=0 border=0 cellpadding=0> 141 + @ <table class="timelineTable"> 142 142 while( db_step(&q)==SQLITE_ROW ){ 143 143 const char *zDate = db_column_text(&q, 0); 144 144 const char *zCom = db_column_text(&q, 1); 145 145 const char *zUser = db_column_text(&q, 2); 146 146 int fpid = db_column_int(&q, 3); 147 147 int frid = db_column_int(&q, 4); 148 148 const char *zPUuid = db_column_text(&q, 5); ................................................................................ 155 155 char zShort[20]; 156 156 char zShortCkin[20]; 157 157 if( zBr==0 ) zBr = "trunk"; 158 158 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr); 159 159 if( memcmp(zDate, zPrevDate, 10) ){ 160 160 sprintf(zPrevDate, "%.10s", zDate); 161 161 @ <tr><td> 162 - @ <div class="divider"><nobr>%s(zPrevDate)</nobr></div> 162 + @ <div class="divider">%s(zPrevDate)</div> 163 163 @ </td></tr> 164 164 } 165 165 memcpy(zTime, &zDate[11], 5); 166 166 zTime[5] = 0; 167 - @ <tr><td valign="top" align="right"> 167 + @ <tr><td class="timelineTime"> 168 168 @ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td> 169 - @ <td width="20" align="left" valign="top"><div id="m%d(gidx)"></div></td> 169 + @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td> 170 170 if( zBgClr && zBgClr[0] ){ 171 - @ <td valign="top" align="left" bgcolor="%h(zBgClr)"> 171 + @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> 172 172 }else{ 173 - @ <td valign="top" align="left"> 173 + @ <td class="timelineTableCell"> 174 174 } 175 175 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); 176 176 sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); 177 177 if( zUuid ){ 178 178 if( g.okHistory ){ 179 179 @ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%S(zUuid)]</a> 180 180 }else{ ................................................................................ 185 185 @ <b>Deleted</b> by check-in 186 186 } 187 187 hyperlink_to_uuid(zShortCkin); 188 188 @ %h(zCom) (user: 189 189 hyperlink_to_user(zUser, zDate, ""); 190 190 @ branch: %h(zBr)) 191 191 if( g.okHistory && zUuid ){ 192 + const char *z = zFilename; 192 193 if( fpid ){ 193 194 @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&v2=%s(zUuid)">[diff]</a> 194 195 } 195 - @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&filename=%h(zFilename)"> 196 + @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&filename=%h(z)"> 196 197 @ [annotate]</a> 197 198 } 198 - @ </td> 199 + @ </td></tr> 199 200 } 200 201 db_finalize(&q); 201 202 if( pGraph ){ 202 203 graph_finish(pGraph, 1); 203 204 if( pGraph->nErr ){ 204 205 graph_free(pGraph); 205 206 pGraph = 0; 206 207 }else{ 207 - @ <tr><td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div> 208 + @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div> 209 + @ </td></tr> 208 210 } 209 211 } 210 212 @ </table> 211 213 timeline_output_graph_javascript(pGraph); 212 214 style_footer(); 213 215 }
Changes to src/graph.c.
19 19 */ 20 20 #include "config.h" 21 21 #include "graph.h" 22 22 #include <assert.h> 23 23 24 24 #if INTERFACE 25 25 26 -#define GR_MAX_PARENT 10 27 -#define GR_MAX_RAIL 32 26 +#define GR_MAX_PARENT 10 /* Most parents for any one node */ 27 +#define GR_MAX_RAIL 32 /* Max number of "rails" to display */ 28 28 29 29 /* The graph appears vertically beside a timeline. Each row in the 30 30 ** timeline corresponds to a row in the graph. 31 31 */ 32 32 struct GraphRow { 33 33 int rid; /* The rid for the check-in */ 34 34 int nParent; /* Number of parents */ ................................................................................ 36 36 char *zBranch; /* Branch name */ 37 37 char *zBgClr; /* Background Color */ 38 38 39 39 GraphRow *pNext; /* Next row down in the list of all rows */ 40 40 GraphRow *pPrev; /* Previous row */ 41 41 42 42 int idx; /* Row index. First is 1. 0 used for "none" */ 43 - u8 isLeaf; /* True if no direct child nodes */ 43 + int idxTop; /* Direct descendent highest up on the graph */ 44 + GraphRow *pChild; /* Child immediately above this node */ 44 45 u8 isDup; /* True if this is duplicate of a prior entry */ 45 46 int iRail; /* Which rail this check-in appears on. 0-based.*/ 46 47 int aiRaiser[GR_MAX_RAIL]; /* Raisers from this node to a higher row. */ 47 48 int bDescender; /* Raiser from bottom of graph to here. */ 48 49 u32 mergeIn; /* Merge in from other rails */ 49 50 int mergeOut; /* Merge out to this rail */ 50 51 int mergeUpto; /* Draw the merge rail up to this level */ ................................................................................ 51 52 52 53 u32 railInUse; /* Mask of occupied rails */ 53 54 }; 54 55 55 56 /* Context while building a graph 56 57 */ 57 58 struct GraphContext { 58 - int nErr; /* Number of errors encountered */ 59 - int mxRail; /* Number of rails required to render the graph */ 60 - GraphRow *pFirst; /* First row in the list */ 61 - GraphRow *pLast; /* Last row in the list */ 62 - int nBranch; /* Number of distinct branches */ 63 - char **azBranch; /* Names of the branches */ 59 + int nErr; /* Number of errors encountered */ 60 + int mxRail; /* Number of rails required to render the graph */ 61 + GraphRow *pFirst; /* First row in the list */ 62 + GraphRow *pLast; /* Last row in the list */ 63 + int nBranch; /* Number of distinct branches */ 64 + char **azBranch; /* Names of the branches */ 64 65 int nRow; /* Number of rows */ 65 - int railMap[GR_MAX_RAIL]; /* Rail order mapping */ 66 66 int nHash; /* Number of slots in apHash[] */ 67 - GraphRow **apHash; /* Hash table of rows */ 67 + GraphRow **apHash; /* Hash table of GraphRow objects. Key: rid */ 68 68 }; 69 69 70 70 #endif 71 71 72 72 /* 73 73 ** Malloc for zeroed space. Panic if unable to provide the 74 74 ** requested space. 75 75 */ 76 76 void *safeMalloc(int nByte){ 77 - void *p = malloc(nByte); 78 - if( p==0 ) fossil_panic("out of memory"); 77 + void *p = fossil_malloc(nByte); 79 78 memset(p, 0, nByte); 80 79 return p; 81 80 } 82 81 83 82 /* 84 83 ** Create and initialize a GraphContext 85 84 */ ................................................................................ 101 100 for(i=0; i<p->nBranch; i++) free(p->azBranch[i]); 102 101 free(p->azBranch); 103 102 free(p->apHash); 104 103 free(p); 105 104 } 106 105 107 106 /* 108 -** Insert a row into the hash table. If there is already another 109 -** row with the same rid, overwrite the prior entry if the overwrite 110 -** flag is set. 107 +** Insert a row into the hash table. pRow->rid is the key. Keys must 108 +** be unique. If there is already another row with the same rid, 109 +** overwrite the prior entry if and only if the overwrite flag is set. 111 110 */ 112 111 static void hashInsert(GraphContext *p, GraphRow *pRow, int overwrite){ 113 112 int h; 114 113 h = pRow->rid % p->nHash; 115 114 while( p->apHash[h] && p->apHash[h]->rid!=pRow->rid ){ 116 115 h++; 117 116 if( h>=p->nHash ) h = 0; ................................................................................ 133 132 return p->apHash[h]; 134 133 } 135 134 136 135 /* 137 136 ** Return the canonical pointer for a given branch name. 138 137 ** Multiple calls to this routine with equivalent strings 139 138 ** will return the same pointer. 139 +** 140 +** The returned value is a pointer to a (readonly) string that 141 +** has the useful property that strings can be checked for 142 +** equality by comparing pointers. 140 143 ** 141 144 ** Note: also used for background color names. 142 145 */ 143 146 static char *persistBranchName(GraphContext *p, const char *zBranch){ 144 147 int i; 145 148 for(i=0; i<p->nBranch; i++){ 146 149 if( strcmp(zBranch, p->azBranch[i])==0 ) return p->azBranch[i]; 147 150 } 148 151 p->nBranch++; 149 - p->azBranch = realloc(p->azBranch, sizeof(char*)*p->nBranch); 150 - if( p->azBranch==0 ) fossil_panic("out of memory"); 152 + p->azBranch = fossil_realloc(p->azBranch, sizeof(char*)*p->nBranch); 151 153 p->azBranch[p->nBranch-1] = mprintf("%s", zBranch); 152 154 return p->azBranch[p->nBranch-1]; 153 155 } 154 156 155 157 /* 156 -** Add a new row t the graph context. Rows are added from top to bottom. 158 +** Add a new row to the graph context. Rows are added from top to bottom. 157 159 */ 158 160 int graph_add_row( 159 161 GraphContext *p, /* The context to which the row is added */ 160 162 int rid, /* RID for the check-in */ 161 163 int nParent, /* Number of parents */ 162 164 int *aParent, /* Array of parents */ 163 165 const char *zBranch, /* Branch for this check-in */ ................................................................................ 177 179 if( p->pFirst==0 ){ 178 180 p->pFirst = pRow; 179 181 }else{ 180 182 p->pLast->pNext = pRow; 181 183 } 182 184 p->pLast = pRow; 183 185 p->nRow++; 184 - pRow->idx = p->nRow; 186 + pRow->idx = pRow->idxTop = p->nRow; 185 187 return pRow->idx; 186 188 } 187 189 188 190 /* 189 191 ** Return the index of a rail currently not in use for any row between 190 192 ** top and bottom, inclusive. 191 193 */ ................................................................................ 217 219 iBest = i; 218 220 } 219 221 } 220 222 } 221 223 if( iBestDist>1000 ) p->nErr++; 222 224 return iBest; 223 225 } 226 + 227 +/* 228 +** Assign all children of node pBottom to the same rail as pBottom. 229 +*/ 230 +static void assignChildrenToRail(GraphRow *pBottom){ 231 + int iRail = pBottom->iRail; 232 + GraphRow *pCurrent; 233 + GraphRow *pPrior; 234 + u32 mask = 1<<iRail; 235 + 236 + pBottom->iRail = iRail; 237 + pBottom->railInUse |= mask; 238 + pPrior = pBottom; 239 + for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ 240 + assert( pPrior->idx > pCurrent->idx ); 241 + assert( pCurrent->iRail<0 ); 242 + pCurrent->iRail = iRail; 243 + pCurrent->railInUse |= mask; 244 + pPrior->aiRaiser[iRail] = pCurrent->idx; 245 + while( pPrior->idx > pCurrent->idx ){ 246 + pPrior->railInUse |= mask; 247 + pPrior = pPrior->pPrev; 248 + assert( pPrior!=0 ); 249 + } 250 + if( pCurrent->pPrev ){ 251 + pCurrent->pPrev->railInUse |= mask; 252 + } 253 + } 254 +} 255 + 224 256 225 257 /* 226 258 ** Compute the complete graph 227 259 */ 228 260 void graph_finish(GraphContext *p, int omitDescenders){ 229 - GraphRow *pRow, *pDesc, *pDup, *pLoop; 261 + GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; 230 262 int i; 231 263 u32 mask; 232 264 u32 inUse; 233 265 int hasDup = 0; /* True if one or more isDup entries */ 234 266 const char *zTrunk; 235 267 236 268 if( p==0 || p->pFirst==0 || p->nErr ) return; ................................................................................ 246 278 hasDup = 1; 247 279 pDup->isDup = 1; 248 280 } 249 281 hashInsert(p, pRow, 1); 250 282 } 251 283 p->mxRail = -1; 252 284 253 - /* Purge merge-parents that are out-of-graph 285 + /* Purge merge-parents that are out-of-graph. 286 + ** 287 + ** Each node has one primary parent and zero or more "merge" parents. 288 + ** A merge parent is a prior checkin from which changes were merged into 289 + ** the current check-in. If a merge parent is not in the visible section 290 + ** of this graph, then no arrows will be drawn for it, so remove it from 291 + ** the aParent[] array. 254 292 */ 255 293 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ 256 294 for(i=1; i<pRow->nParent; i++){ 257 295 if( hashFind(p, pRow->aParent[i])==0 ){ 258 296 pRow->aParent[i] = pRow->aParent[--pRow->nParent]; 259 297 i--; 260 298 } 261 299 } 262 300 } 263 301 264 - /* Figure out which nodes have no direct children (children on 265 - ** the same rail). Mark such nodes as isLeaf. 302 + /* Find the pChild pointer for each node. 303 + ** 304 + ** The pChild points to node directly above on the same rail. 305 + ** The pChild must be in the same branch. Leaf nodes have a NULL 306 + ** pChild. 307 + ** 308 + ** In the case of a fork, choose the pChild that results in the 309 + ** longest rail. 266 310 */ 267 - memset(p->apHash, 0, sizeof(p->apHash[0])*p->nHash); 268 - for(pRow=p->pLast; pRow; pRow=pRow->pPrev) pRow->isLeaf = 1; 269 - for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ 270 - GraphRow *pParent; 271 - hashInsert(p, pRow, 0); 272 - if( !pRow->isDup 273 - && pRow->nParent>0 274 - && (pParent = hashFind(p, pRow->aParent[0]))!=0 275 - && pRow->zBranch==pParent->zBranch 276 - ){ 277 - pParent->isLeaf = 0; 311 + for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ 312 + if( pRow->isDup ) continue; 313 + if( pRow->nParent==0 ) continue; 314 + pParent = hashFind(p, pRow->aParent[0]); 315 + if( pParent==0 ) continue; 316 + if( pParent->zBranch!=pRow->zBranch ) continue; 317 + if( pParent->idx <= pRow->idx ) continue; 318 + if( pRow->idxTop < pParent->idxTop ){ 319 + pParent->pChild = pRow; 320 + pParent->idxTop = pRow->idxTop; 278 321 } 279 322 } 280 323 281 324 /* Identify rows where the primary parent is off screen. Assign 282 325 ** each to a rail and draw descenders to the bottom of the screen. 326 + ** 327 + ** Strive to put the "trunk" branch on far left. 283 328 */ 284 329 zTrunk = persistBranchName(p, "trunk"); 285 330 for(i=0; i<2; i++){ 286 - for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ 331 + for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ 287 332 if( i==0 ){ 288 333 if( pRow->zBranch!=zTrunk ) continue; 289 334 }else { 290 335 if( pRow->iRail>=0 ) continue; 291 336 } 292 337 if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){ 293 338 if( omitDescenders ){ 294 - pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, 0, 0); 339 + pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0, 0); 295 340 }else{ 296 341 pRow->iRail = ++p->mxRail; 297 342 } 298 343 mask = 1<<(pRow->iRail); 299 344 if( omitDescenders ){ 300 345 if( pRow->pNext ) pRow->pNext->railInUse |= mask; 301 - for(pDesc=pRow; pDesc; pDesc=pDesc->pPrev){ 302 - pDesc->railInUse |= mask; 303 - if( pDesc->zBranch==pRow->zBranch && pDesc->isLeaf ) break; 304 - } 305 346 }else{ 306 347 pRow->bDescender = pRow->nParent>0; 307 - for(pDesc=pRow; pDesc; pDesc=pDesc->pNext){ 308 - pDesc->railInUse |= mask; 348 + for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ 349 + pLoop->railInUse |= mask; 309 350 } 310 351 } 352 + assignChildrenToRail(pRow); 311 353 } 312 354 } 313 355 } 314 356 315 357 /* Assign rails to all rows that are still unassigned. 316 - ** The first primary child of a row goes on the same rail as 317 - ** that row. 318 358 */ 319 359 inUse = (1<<(p->mxRail+1))-1; 320 360 for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ 321 361 int parentRid; 322 - if( pRow->iRail>=0 ) continue; 362 + 363 + if( pRow->iRail>=0 ){ 364 + if( pRow->pChild==0 ) inUse &= ~(1<<pRow->iRail); 365 + continue; 366 + } 323 367 if( pRow->isDup ){ 324 368 pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0); 325 369 pDesc = pRow; 370 + pParent = 0; 326 371 }else{ 327 372 assert( pRow->nParent>0 ); 328 373 parentRid = pRow->aParent[0]; 329 - pDesc = hashFind(p, parentRid); 330 - if( pDesc==0 ){ 374 + pParent = hashFind(p, parentRid); 375 + if( pParent==0 ){ 331 376 /* Time skew */ 332 377 pRow->iRail = ++p->mxRail; 333 378 pRow->railInUse = 1<<pRow->iRail; 334 379 continue; 335 380 } 336 - if( pDesc->aiRaiser[pDesc->iRail]==0 && pDesc->zBranch==pRow->zBranch ){ 337 - pRow->iRail = pDesc->iRail; 338 - }else{ 339 - pRow->iRail = findFreeRail(p, 0, pDesc->idx, inUse, pDesc->iRail); 340 - } 341 - pDesc->aiRaiser[pRow->iRail] = pRow->idx; 381 + pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail); 382 + pParent->aiRaiser[pRow->iRail] = pRow->idx; 342 383 } 343 384 mask = 1<<pRow->iRail; 344 - if( pRow->isLeaf ){ 385 + if( pRow->pPrev ) pRow->pPrev->railInUse |= mask; 386 + if( pRow->pNext ) pRow->pNext->railInUse |= mask; 387 + if( pRow->pChild==0 ){ 345 388 inUse &= ~mask; 346 389 }else{ 347 390 inUse |= mask; 391 + assignChildrenToRail(pRow); 348 392 } 349 - for(pLoop=pRow; pLoop && pLoop!=pDesc; pLoop=pLoop->pNext){ 350 - pLoop->railInUse |= mask; 393 + if( pParent ){ 394 + for(pLoop=pParent; pLoop && pLoop!=pRow; pLoop=pLoop->pPrev){ 395 + pLoop->railInUse |= mask; 396 + } 351 397 } 352 - pDesc->railInUse |= mask; 353 398 } 354 399 355 400 /* 356 401 ** Insert merge rails and merge arrows 357 402 */ 358 403 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ 359 404 for(i=1; i<pRow->nParent; i++){ ................................................................................ 362 407 if( pDesc==0 ) continue; 363 408 if( pDesc->mergeOut<0 ){ 364 409 int iTarget = (pRow->iRail + pDesc->iRail)/2; 365 410 pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx, 0, iTarget); 366 411 pDesc->mergeUpto = pRow->idx; 367 412 mask = 1<<pDesc->mergeOut; 368 413 pDesc->railInUse |= mask; 369 - for(pDesc=pRow->pNext; pDesc && pDesc->rid!=parentRid; 370 - pDesc=pDesc->pNext){ 371 - pDesc->railInUse |= mask; 414 + for(pLoop=pRow->pNext; pLoop && pLoop->rid!=parentRid; 415 + pLoop=pLoop->pNext){ 416 + pLoop->railInUse |= mask; 372 417 } 373 418 } 374 419 pRow->mergeIn |= 1<<pDesc->mergeOut; 375 420 } 376 421 } 377 422 378 423 /* ................................................................................ 396 441 pRow->mergeIn |= 1<<pDesc->mergeOut; 397 442 } 398 443 } 399 444 400 445 /* 401 446 ** Find the maximum rail number. 402 447 */ 403 - for(i=0; i<GR_MAX_RAIL; i++) p->railMap[i] = i; 404 448 p->mxRail = 0; 405 449 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ 406 450 if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; 407 451 if( pRow->mergeOut>p->mxRail ) p->mxRail = pRow->mergeOut; 408 452 } 409 453 }
Changes to src/http.c.
40 40 Blob pw; /* The nonce with user password appended */ 41 41 Blob sig; /* The signature field */ 42 42 43 43 blob_zero(pLogin); 44 44 if( g.urlUser==0 || strcmp(g.urlUser, "anonymous")==0 ){ 45 45 return; /* If no login card for users "nobody" and "anonymous" */ 46 46 } 47 + if( g.urlIsSsh ){ 48 + return; /* If no login card for SSH: */ 49 + } 47 50 blob_zero(&nonce); 48 51 blob_zero(&pw); 49 52 sha1sum_blob(pPayload, &nonce); 50 53 blob_copy(&pw, &nonce); 51 54 zLogin = g.urlUser; 52 55 if( g.urlPasswd ){ 53 56 zPw = g.urlPasswd; ................................................................................ 55 58 /* Password failure while doing a sync from the web interface */ 56 59 cgi_printf("*** incorrect or missing password for user %h\n", zLogin); 57 60 zPw = 0; 58 61 }else{ 59 62 /* Password failure while doing a sync from the command-line interface */ 60 63 url_prompt_for_password(); 61 64 zPw = g.urlPasswd; 62 - if( !g.dontKeepUrl ) db_set("last-sync-pw", zPw, 0); 65 + if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0); 63 66 } 64 67 65 68 /* The login card wants the SHA1 hash of the password, so convert the 66 69 ** password to its SHA1 hash it it isn't already a SHA1 hash. 67 70 ** 68 71 ** Except, if the password begins with "*" then use the characters 69 72 ** after the "*" as a cleartext password. Put an "*" at the beginning ................................................................................ 98 101 blob_zero(pHdr); 99 102 i = strlen(g.urlPath); 100 103 if( i>0 && g.urlPath[i-1]=='/' ){ 101 104 zSep = ""; 102 105 }else{ 103 106 zSep = "/"; 104 107 } 105 - blob_appendf(pHdr, "POST %s%sxfer HTTP/1.0\r\n", g.urlPath, zSep); 108 + blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep); 106 109 if( g.urlProxyAuth ){ 107 110 blob_appendf(pHdr, "Proxy-Authorization: %s\n", g.urlProxyAuth); 108 111 } 109 112 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); 110 113 blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n"); 111 114 if( g.fHttpTrace ){ 112 115 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); ................................................................................ 132 135 Blob hdr; /* The HTTP request header */ 133 136 int closeConnection; /* True to close the connection when done */ 134 137 int iLength; /* Length of the reply payload */ 135 138 int rc; /* Result code */ 136 139 int iHttpVersion; /* Which version of HTTP protocol server uses */ 137 140 char *zLine; /* A single line of the reply header */ 138 141 int i; /* Loop counter */ 142 + int isError = 0; /* True if the reply is an error message */ 139 143 140 144 if( transport_open() ){ 141 145 fossil_fatal(transport_errmsg()); 142 146 } 143 147 144 148 /* Construct the login card and prepare the complete payload */ 145 149 blob_zero(&login); ................................................................................ 188 192 189 193 /* 190 194 ** Read and interpret the server reply 191 195 */ 192 196 closeConnection = 1; 193 197 iLength = -1; 194 198 while( (zLine = transport_receive_line())!=0 && zLine[0]!=0 ){ 199 + /* printf("[%s]\n", zLine); fflush(stdout); */ 195 200 if( strncasecmp(zLine, "http/1.", 7)==0 ){ 196 201 if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err; 197 202 if( rc!=200 && rc!=302 ){ 198 203 int ii; 199 204 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} 200 205 while( zLine[ii]==' ' ) ii++; 201 206 fossil_fatal("server says: %s\n", &zLine[ii]); ................................................................................ 203 208 } 204 209 if( iHttpVersion==0 ){ 205 210 closeConnection = 1; 206 211 }else{ 207 212 closeConnection = 0; 208 213 } 209 214 }else if( strncasecmp(zLine, "content-length:", 15)==0 ){ 210 - for(i=15; isspace(zLine[i]); i++){} 215 + for(i=15; fossil_isspace(zLine[i]); i++){} 211 216 iLength = atoi(&zLine[i]); 212 217 }else if( strncasecmp(zLine, "connection:", 11)==0 ){ 213 218 char c; 214 - for(i=11; isspace(zLine[i]); i++){} 219 + for(i=11; fossil_isspace(zLine[i]); i++){} 215 220 c = zLine[i]; 216 221 if( c=='c' || c=='C' ){ 217 222 closeConnection = 1; 218 223 }else if( c=='k' || c=='K' ){ 219 224 closeConnection = 0; 220 225 } 221 226 }else if( rc==302 && strncasecmp(zLine, "location:", 9)==0 ){ 222 227 int i, j; 223 228 for(i=9; zLine[i] && zLine[i]==' '; i++){} 224 229 if( zLine[i]==0 ) fossil_fatal("malformed redirect: %s", zLine); 225 230 j = strlen(zLine) - 1; 226 - if( j>4 && strcmp(&zLine[j-4],"/xfer")==0 ) zLine[j-4] = 0; 231 + while( j>4 && strcmp(&zLine[j-4],"/xfer")==0 ){ 232 + j -= 4; 233 + zLine[j] = 0; 234 + } 227 235 fossil_print("redirect to %s\n", &zLine[i]); 228 236 url_parse(&zLine[i]); 229 237 transport_close(); 230 238 http_exchange(pSend, pReply, useLogin); 231 239 return; 240 + }else if( strncasecmp(zLine, "content-type: text/html", 23)==0 ){ 241 + isError = 1; 232 242 } 233 243 } 234 244 if( rc!=200 ){ 235 245 fossil_fatal("\"location:\" missing from 302 redirect reply"); 236 246 goto write_err; 237 247 } 238 248 ................................................................................ 243 253 fossil_fatal("server did not reply"); 244 254 goto write_err; 245 255 } 246 256 blob_zero(pReply); 247 257 blob_resize(pReply, iLength); 248 258 iLength = transport_receive(blob_buffer(pReply), iLength); 249 259 blob_resize(pReply, iLength); 260 + if( isError ){ 261 + char *z; 262 + int i, j; 263 + z = blob_str(pReply); 264 + for(i=j=0; z[i]; i++, j++){ 265 + if( z[i]=='<' ){ 266 + while( z[i] && z[i]!='>' ) i++; 267 + if( z[i]==0 ) break; 268 + } 269 + z[j] = z[i]; 270 + } 271 + z[j] = 0; 272 + fossil_fatal("server sends error: %s", z); 273 + } 250 274 if( g.fHttpTrace ){ 251 - printf("HTTP RECEIVE:\n%s\n=======================\n", blob_str(pReply)); 275 + /*printf("HTTP RECEIVE:\n%s\n=======================\n",blob_str(pReply));*/ 252 276 }else{ 253 277 blob_uncompress(pReply, pReply); 254 278 } 255 279 256 280 /* 257 281 ** Close the connection to the server if appropriate. 258 282 **
Changes to src/http_socket.c.
24 24 ** 25 25 ** Low-level sockets are abstracted out into this module because they 26 26 ** are handled different on Unix and windows. 27 27 */ 28 28 29 29 #include "config.h" 30 30 #include "http_socket.h" 31 -#ifdef __MINGW32__ 32 -# include <windows.h> 33 -# include <winsock2.h> 31 +#if defined(_WIN32) 32 +# include <windows.h> /* for Sleep once server works again */ 33 +# define sleep Sleep /* windows does not have sleep, but Sleep */ 34 +# if defined(__MINGW32__) 35 +# include <ws2tcpip.h> 36 +# endif 34 37 #else 35 38 # include <arpa/inet.h> 36 39 # include <sys/socket.h> 37 40 # include <netdb.h> 38 41 # include <netinet/in.h> 39 42 #endif 40 43 #include <assert.h> ................................................................................ 43 46 44 47 /* 45 48 ** There can only be a single socket connection open at a time. 46 49 ** State information about that socket is stored in the following 47 50 ** local variables: 48 51 */ 49 52 static int socketIsInit = 0; /* True after global initialization */ 50 -#ifdef __MINGW32__ 53 +#if defined(_WIN32) 51 54 static WSADATA socketInfo; /* Windows socket initialize data */ 52 55 #endif 53 56 static int iSocket = -1; /* The socket on which we talk to the server */ 54 57 static char *socketErrMsg = 0; /* Text of most recent socket error */ 55 58 56 59 57 60 /* ................................................................................ 82 85 83 86 /* 84 87 ** Call this routine once before any other use of the socket interface. 85 88 ** This routine does initial configuration of the socket module. 86 89 */ 87 90 void socket_global_init(void){ 88 91 if( socketIsInit==0 ){ 89 -#ifdef __MINGW32__ 92 +#if defined(_WIN32) 90 93 if( WSAStartup(MAKEWORD(2,0), &socketInfo)!=0 ){ 91 94 fossil_panic("can't initialize winsock"); 92 95 } 93 96 #endif 94 97 socketIsInit = 1; 95 98 } 96 99 } ................................................................................ 97 100 98 101 /* 99 102 ** Call this routine to shutdown the socket module prior to program 100 103 ** exit. 101 104 */ 102 105 void socket_global_shutdown(void){ 103 106 if( socketIsInit ){ 104 -#ifdef __MINGW32__ 107 +#if defined(_WIN32) 105 108 WSACleanup(); 106 109 #endif 107 110 socket_clear_errmsg(); 108 111 socketIsInit = 0; 109 112 } 110 113 } 111 114 112 115 /* 113 116 ** Close the currently open socket. If no socket is open, this routine 114 117 ** is a no-op. 115 118 */ 116 119 void socket_close(void){ 117 120 if( iSocket>=0 ){ 118 -#ifdef __MINGW32__ 121 +#if defined(_WIN32) 119 122 closesocket(iSocket); 120 123 #else 121 124 close(iSocket); 122 125 #endif 123 126 iSocket = -1; 124 127 } 125 128 } ................................................................................ 169 172 return 1; 170 173 } 171 174 if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){ 172 175 socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort); 173 176 socket_close(); 174 177 return 1; 175 178 } 176 -#ifndef __MINGW32__ 179 +#if !defined(_WIN32) 177 180 signal(SIGPIPE, SIG_IGN); 178 181 #endif 179 182 return 0; 180 183 } 181 184 182 185 /* 183 186 ** Send content out over the open socket connection.
Changes to src/http_ssl.c.
88 88 void ssl_global_init(void){ 89 89 if( sslIsInit==0 ){ 90 90 SSL_library_init(); 91 91 SSL_load_error_strings(); 92 92 ERR_load_BIO_strings(); 93 93 OpenSSL_add_all_algorithms(); 94 94 sslCtx = SSL_CTX_new(SSLv23_client_method()); 95 + X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx)); 95 96 sslIsInit = 1; 96 97 } 97 98 } 98 99 99 100 /* 100 101 ** Call this routine to shutdown the SSL module prior to program exit. 101 102 */ ................................................................................ 126 127 ** g.urlPort TCP/IP port to use. Ex: 80 127 128 ** 128 129 ** Return the number of errors. 129 130 */ 130 131 int ssl_open(void){ 131 132 X509 *cert; 132 133 int hasSavedCertificate = 0; 133 - 134 +char *connStr ; 134 135 ssl_global_init(); 135 136 136 137 /* Get certificate for current server from global config and 137 138 * (if we have it in config) add it to certificate store. 138 139 */ 139 140 cert = ssl_get_certificate(); 140 141 if ( cert!=NULL ){ ................................................................................ 148 149 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 149 150 if( iBio==NULL ) { 150 151 ssl_set_errmsg("SSL: cannot open SSL (%s)", 151 152 ERR_reason_error_string(ERR_get_error())); 152 153 return 1; 153 154 } 154 155 155 - char *connStr = mprintf("%s:%d", g.urlName, g.urlPort); 156 + connStr = mprintf("%s:%d", g.urlName, g.urlPort); 156 157 BIO_set_conn_hostname(iBio, connStr); 157 158 free(connStr); 158 159 159 160 if( BIO_do_connect(iBio)<=0 ){ 160 161 ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)", 161 162 g.urlName, g.urlPort, ERR_reason_error_string(ERR_get_error())); 162 163 ssl_close(); ................................................................................ 176 177 ssl_set_errmsg("No SSL certificate was presented by the peer"); 177 178 ssl_close(); 178 179 return 1; 179 180 } 180 181 181 182 if( SSL_get_verify_result(ssl) != X509_V_OK ){ 182 183 char *desc, *prompt; 184 + char *warning = ""; 185 + Blob ans; 183 186 BIO *mem; 184 187 185 188 mem = BIO_new(BIO_s_mem()); 186 189 X509_NAME_print_ex(mem, X509_get_subject_name(cert), 2, XN_FLAG_MULTILINE); 187 190 BIO_puts(mem, "\n\nIssued By:\n\n"); 188 191 X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_MULTILINE); 189 192 BIO_write(mem, "", 1); // null-terminate mem buffer 190 193 BIO_get_mem_data(mem, &desc); 191 194 192 - char *warning = ""; 193 195 if( hasSavedCertificate ){ 194 196 warning = "WARNING: Certificate doesn't match the " 195 197 "saved certificate for this host!"; 196 198 } 197 199 prompt = mprintf("\nUnknown SSL certificate:\n\n%s\n\n%s\n" 198 200 "Accept certificate [a=always/y/N]? ", desc, warning); 199 201 BIO_free(mem); 200 202 201 - Blob ans; 202 203 prompt_user(prompt, &ans); 203 204 free(prompt); 204 205 if( blob_str(&ans)[0]!='y' && blob_str(&ans)[0]!='a' ) { 205 206 X509_free(cert); 206 207 ssl_set_errmsg("SSL certificate declined"); 207 208 ssl_close(); 208 209 return 1;
Changes to src/http_transport.c.
36 36 int nRcvd; /* Number of bytes received */ 37 37 FILE *pFile; /* File I/O for FILE: */ 38 38 char *zOutFile; /* Name of outbound file for FILE: */ 39 39 char *zInFile; /* Name of inbound file for FILE: */ 40 40 } transport = { 41 41 0, 0, 0, 0, 0, 0, 0 42 42 }; 43 + 44 +/* 45 +** Information about the connection to the SSH subprocess when 46 +** using the ssh:// sync method. 47 +*/ 48 +static int sshPid; /* Process id of ssh subprocess */ 49 +static int sshIn; /* From ssh subprocess to this process */ 50 +static FILE *sshOut; /* From this to ssh subprocess */ 51 + 43 52 44 53 /* 45 54 ** Return the current transport error message. 46 55 */ 47 56 const char *transport_errmsg(void){ 48 57 #ifdef FOSSIL_ENABLE_SSL 49 58 if( g.urlIsHttps ){ ................................................................................ 61 70 if( pnSent ) *pnSent = transport.nSent; 62 71 if( pnRcvd ) *pnRcvd = transport.nRcvd; 63 72 if( resetFlag ){ 64 73 transport.nSent = 0; 65 74 transport.nRcvd = 0; 66 75 } 67 76 } 77 + 78 +/* 79 +** Read text from sshIn. Zero-terminate and remove trailing 80 +** whitespace. 81 +*/ 82 +static void sshin_read(char *zBuf, int szBuf){ 83 + int got; 84 + zBuf[0] = 0; 85 + got = read(sshIn, zBuf, szBuf-1); 86 + while( got>=0 ){ 87 + zBuf[got] = 0; 88 + if( got==0 || !fossil_isspace(zBuf[got-1]) ) break; 89 + got--; 90 + } 91 +} 92 + 93 +/* 94 +** Default SSH command 95 +*/ 96 +#ifdef __MINGW32__ 97 +static char zDefaultSshCmd[] = "ssh -T"; 98 +#else 99 +static char zDefaultSshCmd[] = "ssh -e none -T"; 100 +#endif 101 + 102 +/* 103 +** Global initialization of the transport layer 104 +*/ 105 +void transport_global_startup(void){ 106 + if( g.urlIsSsh ){ 107 + /* Only SSH requires a global initialization. For SSH we need to create 108 + ** and run an SSH command to talk to the remote machine. 109 + */ 110 + const char *zSsh; /* The base SSH command */ 111 + Blob zCmd; /* The SSH command */ 112 + char *zHost; /* The host name to contact */ 113 + char zIn[200]; /* An input line received back from remote */ 114 + 115 + zSsh = db_get("ssh-command", zDefaultSshCmd); 116 + blob_init(&zCmd, zSsh, -1); 117 + if( g.urlPort!=g.urlDfltPort ){ 118 +#ifdef __MINGW32__ 119 + blob_appendf(&zCmd, " -P %d", g.urlPort); 120 +#else 121 + blob_appendf(&zCmd, " -p %d", g.urlPort); 122 +#endif 123 + } 124 + if( g.urlUser && g.urlUser[0] ){ 125 + zHost = mprintf("%s@%s", g.urlUser, g.urlName); 126 +#ifdef __MINGW32__ 127 + /* Only win32 (and specifically PLINK.EXE support the -pw option */ 128 + if( g.urlPasswd && g.urlPasswd[0] ){ 129 + Blob pw; 130 + blob_zero(&pw); 131 + if( g.urlPasswd[0]=='*' ){ 132 + char *zPrompt; 133 + zPrompt = mprintf("Password for [%s]: ", zHost); 134 + prompt_for_password(zPrompt, &pw, 0); 135 + free(zPrompt); 136 + }else{ 137 + blob_init(&pw, g.urlPasswd, -1); 138 + } 139 + blob_append(&zCmd, " -pw ", -1); 140 + shell_escape(&zCmd, blob_str(&pw)); 141 + blob_reset(&pw); 142 + } 143 +#endif 144 + }else{ 145 + zHost = mprintf("%s", g.urlName); 146 + } 147 + blob_append(&zCmd, " ", 1); 148 + shell_escape(&zCmd, zHost); 149 + free(zHost); 150 + /* printf("%s\n", blob_str(&zCmd)); */ 151 + popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid); 152 + if( sshPid==0 ){ 153 + fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd); 154 + } 155 + blob_reset(&zCmd); 156 + 157 + /* Send an "echo" command to the other side to make sure that the 158 + ** connection is up and working. 159 + */ 160 + fprintf(sshOut, "echo test\n"); 161 + fflush(sshOut); 162 + sshin_read(zIn, sizeof(zIn)); 163 + if( memcmp(zIn, "test", 4)!=0 ){ 164 + pclose2(sshIn, sshOut, sshPid); 165 + fossil_fatal("ssh connection failed: [%s]", zIn); 166 + } 167 + } 168 +} 68 169 69 170 /* 70 171 ** Open a connection to the server. The server is defined by the following 71 172 ** global variables: 72 173 ** 73 174 ** g.urlName Name of the server. Ex: www.fossil-scm.org 74 175 ** g.urlPort TCP/IP port. Ex: 80 ................................................................................ 75 176 ** g.urlIsHttps Use TLS for the connection 76 177 ** 77 178 ** Return the number of errors. 78 179 */ 79 180 int transport_open(void){ 80 181 int rc = 0; 81 182 if( transport.isOpen==0 ){ 82 - if( g.urlIsHttps ){ 183 + if( g.urlIsSsh ){ 184 + Blob cmd; 185 + blob_zero(&cmd); 186 + shell_escape(&cmd, g.urlFossil); 187 + blob_append(&cmd, " test-http ", -1); 188 + shell_escape(&cmd, g.urlPath); 189 + /* fprintf(stdout, "%s\n", blob_str(&cmd)); */ 190 + fprintf(sshOut, "%s\n", blob_str(&cmd)); 191 + fflush(sshOut); 192 + blob_reset(&cmd); 193 + }else if( g.urlIsHttps ){ 83 194 #ifdef FOSSIL_ENABLE_SSL 84 195 rc = ssl_open(); 85 196 if( rc==0 ) transport.isOpen = 1; 86 197 #else 87 198 socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support"); 88 199 rc = 1; 89 200 #endif ................................................................................ 113 224 void transport_close(void){ 114 225 if( transport.isOpen ){ 115 226 free(transport.pBuf); 116 227 transport.pBuf = 0; 117 228 transport.nAlloc = 0; 118 229 transport.nUsed = 0; 119 230 transport.iCursor = 0; 120 - if( g.urlIsHttps ){ 231 + if( g.urlIsSsh ){ 232 + /* No-op */ 233 + }else if( g.urlIsHttps ){ 121 234 #ifdef FOSSIL_ENABLE_SSL 122 235 ssl_close(); 123 236 #endif 124 237 }else if( g.urlIsFile ){ 125 238 if( transport.pFile ){ 126 239 fclose(transport.pFile); 127 240 transport.pFile = 0; ................................................................................ 140 253 /* 141 254 ** Send content over the wire. 142 255 */ 143 256 void transport_send(Blob *toSend){ 144 257 char *z = blob_buffer(toSend); 145 258 int n = blob_size(toSend); 146 259 transport.nSent += n; 147 - if( g.urlIsHttps ){ 260 + if( g.urlIsSsh ){ 261 + int sent; 262 + sent = fwrite(z, 1, n, sshOut); 263 + fflush(sshOut); 264 + /* printf("sent %d of %d bytes\n", sent, n); fflush(stdout); */ 265 + }else if( g.urlIsHttps ){ 148 266 #ifdef FOSSIL_ENABLE_SSL 149 267 int sent; 150 268 while( n>0 ){ 151 269 sent = ssl_send(0, z, n); 152 270 /* printf("Sent %d of %d bytes\n", sent, n); fflush(stdout); */ 153 271 if( sent<=0 ) break; 154 272 n -= sent; ................................................................................ 168 286 } 169 287 170 288 /* 171 289 ** This routine is called when the outbound message is complete and 172 290 ** it is time to being recieving a reply. 173 291 */ 174 292 void transport_flip(void){ 175 - if( g.urlIsFile ){ 293 + if( g.urlIsSsh ){ 294 + fprintf(sshOut, "\n\n"); 295 + }else if( g.urlIsFile ){ 176 296 char *zCmd; 177 297 fclose(transport.pFile); 178 298 zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1", 179 299 g.argv[0], g.urlName, transport.zOutFile, transport.zInFile 180 300 ); 181 - portable_system(zCmd); 301 + fossil_system(zCmd); 182 302 free(zCmd); 183 303 transport.pFile = fopen(transport.zInFile, "rb"); 184 304 } 185 305 } 186 306 187 307 /* 188 308 ** This routine is called when the inbound message has been received ................................................................................ 189 309 ** and it is time to start sending again. 190 310 */ 191 311 void transport_rewind(void){ 192 312 if( g.urlIsFile ){ 193 313 transport_close(); 194 314 } 195 315 } 316 + 317 +/* 318 +** Read N bytes of content directly from the wire and write into 319 +** the buffer. 320 +*/ 321 +static int transport_fetch(char *zBuf, int N){ 322 + int got; 323 + if( sshIn ){ 324 + int x; 325 + int wanted = N; 326 + got = 0; 327 + while( wanted>0 ){ 328 + x = read(sshIn, &zBuf[got], wanted); 329 + if( x<=0 ) break; 330 + got += x; 331 + wanted -= x; 332 + } 333 + }else if( g.urlIsHttps ){ 334 + #ifdef FOSSIL_ENABLE_SSL 335 + got = ssl_receive(0, zBuf, N); 336 + #else 337 + got = 0; 338 + #endif 339 + }else if( g.urlIsFile ){ 340 + got = fread(zBuf, 1, N, transport.pFile); 341 + }else{ 342 + got = socket_receive(0, zBuf, N); 343 + } 344 + /* printf("received %d of %d bytes\n", got, N); fflush(stdout); */ 345 + return got; 346 +} 196 347 197 348 /* 198 349 ** Read N bytes of content from the wire and store in the supplied buffer. 199 350 ** Return the number of bytes actually received. 200 351 */ 201 352 int transport_receive(char *zBuf, int N){ 202 353 int onHand; /* Bytes current held in the transport buffer */ 203 354 int nByte = 0; /* Bytes of content received */ 204 355 205 356 onHand = transport.nUsed - transport.iCursor; 357 + /* printf("request %d with %d on hand\n", N, onHand); fflush(stdout); */ 206 358 if( onHand>0 ){ 207 359 int toMove = onHand; 208 360 if( toMove>N ) toMove = N; 209 361 /* printf("bytes on hand: %d of %d\n", toMove, N); fflush(stdout); */ 210 362 memcpy(zBuf, &transport.pBuf[transport.iCursor], toMove); 211 363 transport.iCursor += toMove; 212 364 if( transport.iCursor>=transport.nUsed ){ ................................................................................ 214 366 transport.iCursor = 0; 215 367 } 216 368 N -= toMove; 217 369 zBuf += toMove; 218 370 nByte += toMove; 219 371 } 220 372 if( N>0 ){ 221 - int got; 222 - if( g.urlIsHttps ){ 223 - #ifdef FOSSIL_ENABLE_SSL 224 - got = ssl_receive(0, zBuf, N); 225 - /* printf("received %d of %d bytes\n", got, N); fflush(stdout); */ 226 - #else 227 - got = 0; 228 - #endif 229 - }else if( g.urlIsFile ){ 230 - got = fread(zBuf, 1, N, transport.pFile); 231 - }else{ 232 - got = socket_receive(0, zBuf, N); 233 - /* printf("received %d of %d bytes\n", got, N); fflush(stdout); */ 234 - } 373 + int got = transport_fetch(zBuf, N); 235 374 if( got>0 ){ 236 375 nByte += got; 237 376 transport.nRcvd += got; 238 377 } 239 378 } 240 379 return nByte; 241 380 } ................................................................................ 245 384 ** The buffer itself might be moved. And the transport.iCursor value 246 385 ** might be reset to 0. 247 386 */ 248 387 static void transport_load_buffer(int N){ 249 388 int i, j; 250 389 if( transport.nAlloc==0 ){ 251 390 transport.nAlloc = N; 252 - transport.pBuf = malloc( N ); 253 - if( transport.pBuf==0 ) fossil_panic("out of memory"); 391 + transport.pBuf = fossil_malloc( N ); 254 392 transport.iCursor = 0; 255 393 transport.nUsed = 0; 256 394 } 257 395 if( transport.iCursor>0 ){ 258 396 for(i=0, j=transport.iCursor; j<transport.nUsed; i++, j++){ 259 397 transport.pBuf[i] = transport.pBuf[j]; 260 398 } 261 399 transport.nUsed -= transport.iCursor; 262 400 transport.iCursor = 0; 263 401 } 264 402 if( transport.nUsed + N > transport.nAlloc ){ 265 403 char *pNew; 266 404 transport.nAlloc = transport.nUsed + N; 267 - pNew = realloc(transport.pBuf, transport.nAlloc); 268 - if( pNew==0 ) fossil_panic("out of memory"); 405 + pNew = fossil_realloc(transport.pBuf, transport.nAlloc); 269 406 transport.pBuf = pNew; 270 407 } 271 408 if( N>0 ){ 272 - i = transport_receive(&transport.pBuf[transport.nUsed], N); 409 + i = transport_fetch(&transport.pBuf[transport.nUsed], N); 273 410 if( i>0 ){ 274 411 transport.nUsed += i; 275 412 } 276 413 } 277 414 } 278 415 279 416 /* ................................................................................ 298 435 transport.pBuf[i] = 0; 299 436 transport.iCursor = i; 300 437 break; 301 438 } 302 439 } 303 440 if( transport.pBuf[i]=='\n' ){ 304 441 transport.iCursor = i+1; 305 - while( i>=iStart && isspace(transport.pBuf[i]) ){ 442 + while( i>=iStart && fossil_isspace(transport.pBuf[i]) ){ 306 443 transport.pBuf[i] = 0; 307 444 i--; 308 445 } 309 446 break; 310 447 } 311 448 i++; 312 449 } 313 450 /* printf("Got line: [%s]\n", &transport.pBuf[iStart]); */ 314 451 return &transport.pBuf[iStart]; 315 452 } 316 453 317 454 void transport_global_shutdown(void){ 455 + if( g.urlIsSsh && sshPid ){ 456 + printf("Closing SSH tunnel: "); 457 + fflush(stdout); 458 + pclose2(sshIn, sshOut, sshPid); 459 + sshPid = 0; 460 + } 318 461 if( g.urlIsHttps ){ 319 462 #ifdef FOSSIL_ENABLE_SSL 320 463 ssl_global_shutdown(); 321 464 #endif 322 465 }else{ 323 466 socket_global_shutdown(); 324 467 } 325 468 }
Changes to src/info.c.
63 63 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", 64 64 rid 65 65 ); 66 66 /* 01234567890123 */ 67 67 printf("%-13s %s %s\n", zUuidName, zUuid, zDate ? zDate : ""); 68 68 free(zUuid); 69 69 free(zDate); 70 + } 71 + if( zUuid && showComment ){ 72 + zComment = db_text(0, 73 + "SELECT coalesce(ecomment,comment) || ' (user: ' || coalesce(euser,user,'?') || ')' FROM event WHERE objid=%d", 74 + rid 75 + ); 70 76 } 71 77 db_prepare(&q, "SELECT uuid, pid FROM plink JOIN blob ON pid=rid " 72 78 " WHERE cid=%d", rid); 73 79 while( db_step(&q)==SQLITE_ROW ){ 74 80 const char *zUuid = db_column_text(&q, 0); 75 81 zDate = db_text("", 76 82 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", ................................................................................ 94 100 db_finalize(&q); 95 101 zTags = info_tags_of_checkin(rid, 0); 96 102 if( zTags && zTags[0] ){ 97 103 printf("tags: %s\n", zTags); 98 104 } 99 105 free(zTags); 100 106 if( zComment ){ 101 - printf("comment:\n%s\n", zComment); 107 + printf("comment: "); 108 + comment_print(zComment, 14, 79); 102 109 free(zComment); 103 110 } 104 111 } 105 112 106 113 107 114 /* 108 115 ** COMMAND: info ................................................................................ 133 140 if( g.argc==2 ){ 134 141 int vid; 135 142 /* 012345678901234 */ 136 143 db_record_repository_filename(0); 137 144 printf("project-name: %s\n", db_get("project-name", "<unnamed>")); 138 145 printf("repository: %s\n", db_lget("repository", "")); 139 146 printf("local-root: %s\n", g.zLocalRoot); 140 -#ifdef __MINGW32__ 147 +#if defined(_WIN32) 141 148 if( g.zHome ){ 142 149 printf("user-home: %s\n", g.zHome); 143 150 } 144 151 #endif 145 152 printf("project-code: %s\n", db_get("project-code", "")); 146 153 printf("server-code: %s\n", db_get("server-code", "")); 147 154 vid = db_lget_int("checkout", 0); ................................................................................ 185 192 cnt++; 186 193 if( cnt==1 ){ 187 194 @ <div class="section">Tags And Properties</div> 188 195 @ <ul> 189 196 } 190 197 @ <li> 191 198 if( tagtype==0 ){ 192 - @ <b><s>%h(zTagname)</s></b> cancelled 199 + @ <span class="infoTagCancelled">%h(zTagname)</span> cancelled 193 200 }else if( zValue ){ 194 - @ <b>%h(zTagname)=%h(zValue)</b> 201 + @ <span class="infoTag">%h(zTagname)=%h(zValue)</span> 195 202 }else { 196 - @ <b>%h(zTagname)</b> 203 + @ <span class="infoTag">%h(zTagname)</span> 197 204 } 198 205 if( tagtype==2 ){ 199 206 if( zOrigUuid && zOrigUuid[0] ){ 200 207 @ inherited from 201 208 hyperlink_to_uuid(zOrigUuid); 202 209 }else{ 203 210 @ propagates to descendants ................................................................................ 213 220 }else{ 214 221 @ added by 215 222 } 216 223 hyperlink_to_uuid(zSrcUuid); 217 224 @ on 218 225 hyperlink_to_date(zDate,0); 219 226 } 227 + @ </li> 220 228 } 221 229 db_finalize(&q); 222 230 if( cnt ){ 223 231 @ </ul> 224 232 } 225 233 } 226 234 227 235 228 236 /* 229 237 ** Append the difference between two RIDs to the output 230 238 */ 231 -static void append_diff(int fromid, int toid){ 239 +static void append_diff(const char *zFrom, const char *zTo){ 240 + int fromid; 241 + int toid; 232 242 Blob from, to, out; 233 - content_get(fromid, &from); 234 - content_get(toid, &to); 243 + if( zFrom ){ 244 + fromid = uuid_to_rid(zFrom, 0); 245 + content_get(fromid, &from); 246 + }else{ 247 + blob_zero(&from); 248 + } 249 + if( zTo ){ 250 + toid = uuid_to_rid(zTo, 0); 251 + content_get(toid, &to); 252 + }else{ 253 + blob_zero(&to); 254 + } 235 255 blob_zero(&out); 236 - text_diff(&from, &to, &out, 5); 256 + text_diff(&from, &to, &out, 5, 1); 237 257 @ %h(blob_str(&out)) 238 258 blob_reset(&from); 239 259 blob_reset(&to); 240 260 blob_reset(&out); 241 261 } 242 262 243 263 /* ................................................................................ 254 274 if( zNew==0 ){ 255 275 @ <p>Deleted %h(zName)</p> 256 276 }else if( zOld==0 ){ 257 277 @ <p>Added %h(zName)</p> 258 278 }else{ 259 279 @ <p>Changes to %h(zName)</p> 260 280 } 261 - }else if( zOld && zNew ){ 262 - @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> 263 - @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> 264 - @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a> 265 - if( !showDiff ){ 266 - @ 267 - @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)">[diff]</a> 281 + if( showDiff ){ 282 + @ <blockquote><pre> 283 + append_diff(zOld, zNew); 284 + @ </pre></blockquote> 285 + } 286 + }else{ 287 + if( zOld && zNew ){ 288 + @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> 289 + @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> 290 + @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a> 291 + }else if( zOld ){ 292 + @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> 293 + @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> 268 294 }else{ 269 - int rid1 = uuid_to_rid(zOld, 0); 270 - int rid2 = uuid_to_rid(zNew, 0); 295 + @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> 296 + @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a> 297 + } 298 + if( showDiff ){ 271 299 @ <blockquote><pre> 272 - append_diff(rid1, rid2); 300 + append_diff(zOld, zNew); 273 301 @ </pre></blockquote> 302 + }else if( zOld && zNew ){ 303 + @ 304 + @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)">[diff]</a> 274 305 } 275 - }else if( zOld ){ 276 - @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> 277 - @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a></p> 278 - }else{ 279 - @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> 280 - @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a></p> 306 + @ </p> 281 307 } 282 308 } 283 309 284 310 285 311 /* 286 312 ** WEBPAGE: vinfo 287 313 ** WEBPAGE: ci ................................................................................ 338 364 zEComment = db_text(0, 339 365 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d", 340 366 TAG_COMMENT, rid); 341 367 zUser = db_column_text(&q, 2); 342 368 zComment = db_column_text(&q, 3); 343 369 zDate = db_column_text(&q,1); 344 370 @ <div class="section">Overview</div> 345 - @ <p><table class="label-value"> 371 + @ <table class="label-value"> 346 372 @ <tr><th>SHA1 Hash:</th><td>%s(zUuid) 347 373 if( g.okSetup ){ 348 374 @ (Record ID: %d(rid)) 349 375 } 350 376 @ </td></tr> 351 377 @ <tr><th>Date:</th><td> 352 378 hyperlink_to_date(zDate, "</td></tr>"); ................................................................................ 381 407 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> 382 408 } 383 409 db_finalize(&q); 384 410 } 385 411 if( g.okHistory ){ 386 412 const char *zProjName = db_get("project-name", "unnamed"); 387 413 @ <tr><th>Timelines:</th><td> 388 - @ <a href="%s(g.zBaseURL)/timeline?p=%S(zUuid)">ancestors</a> 389 - @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)">descendants</a> 390 - @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a> 414 + @ <a href="%s(g.zBaseURL)/timeline?p=%S(zUuid)">ancestors</a> 415 + @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)">descendants</a> 416 + @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a> 391 417 db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " 392 418 " WHERE rid=%d AND tagtype>0 " 393 419 " AND tag.tagid=tagxref.tagid " 394 420 " AND +tag.tagname GLOB 'sym-*'", rid); 395 421 while( db_step(&q)==SQLITE_ROW ){ 396 422 const char *zTagName = db_column_text(&q, 0); 397 423 @ | <a href="%s(g.zTop)/timeline?r=%T(zTagName)">%h(zTagName)</a> 398 424 } 399 425 db_finalize(&q); 400 426 @ </td></tr> 401 427 @ <tr><th>Other Links:</th> 402 428 @ <td> 403 429 @ <a href="%s(g.zTop)/dir?ci=%S(zUuid)">files</a> 404 - @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)"> 405 - @ ZIP archive</a> 430 + if( g.okZip ){ 431 + @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)"> 432 + @ ZIP archive</a> 433 + } 406 434 @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">manifest</a> 407 435 if( g.okWrite ){ 408 436 @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a> 409 437 } 410 438 @ </td> 411 439 @ </tr> 412 440 } 413 - @ </table></p> 441 + @ </table> 414 442 }else{ 415 443 style_header("Check-in Information"); 416 444 login_anonymous_available(); 417 445 } 418 446 db_finalize(&q); 419 447 showTags(rid, ""); 420 448 @ <div class="section">Changes</div> ................................................................................ 513 541 }else{ 514 542 style_header("Wiki Information"); 515 543 rid = 0; 516 544 } 517 545 db_finalize(&q); 518 546 showTags(rid, "wiki-*"); 519 547 if( rid ){ 520 - Blob content; 521 - Manifest m; 522 - memset(&m, 0, sizeof(m)); 523 - blob_zero(&m.content); 524 - content_get(rid, &content); 525 - manifest_parse(&m, &content); 526 - if( m.type==CFTYPE_WIKI ){ 548 + Manifest *pWiki; 549 + pWiki = manifest_get(rid, CFTYPE_WIKI); 550 + if( pWiki ){ 527 551 Blob wiki; 528 - blob_init(&wiki, m.zWiki, -1); 552 + blob_init(&wiki, pWiki->zWiki, -1); 529 553 @ <div class="section">Content</div> 530 554 wiki_convert(&wiki, 0, 0); 531 555 blob_reset(&wiki); 532 556 } 533 - manifest_clear(&m); 557 + manifest_destroy(pWiki); 534 558 } 535 559 style_footer(); 536 560 } 537 561 538 562 /* 539 563 ** Show a webpage error message 540 564 */ ................................................................................ 550 574 style_footer(); 551 575 } 552 576 553 577 /* 554 578 ** Find an checkin based on query parameter zParam and parse its 555 579 ** manifest. Return the number of errors. 556 580 */ 557 -static int vdiff_parse_manifest(const char *zParam, int *pRid, Manifest *pM){ 581 +static Manifest *vdiff_parse_manifest(const char *zParam, int *pRid){ 558 582 int rid; 559 - Blob content; 560 583 561 584 *pRid = rid = name_to_rid_www(zParam); 562 585 if( rid==0 ){ 563 586 webpage_error("Missing \"%s\" query parameter.", zParam); 564 - return 1; 587 + return 0; 565 588 } 566 589 if( !is_a_version(rid) ){ 567 590 webpage_error("Artifact %s is not a checkin.", P(zParam)); 568 - return 1; 591 + return 0; 569 592 } 570 - content_get(rid, &content); 571 - manifest_parse(pM, &content); 572 - return 0; 593 + return manifest_get(rid, CFTYPE_MANIFEST); 573 594 } 574 595 575 596 /* 576 597 ** Output a description of a check-in 577 598 */ 578 599 void checkin_description(int rid){ 579 600 Stmt q; ................................................................................ 598 619 } 599 620 db_finalize(&q); 600 621 } 601 622 602 623 603 624 /* 604 625 ** WEBPAGE: vdiff 605 -** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN 626 +** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN 606 627 ** 607 628 ** Show all differences between two checkins. 608 629 */ 609 630 void vdiff_page(void){ 610 631 int ridFrom, ridTo; 611 632 int showDetail = 0; 612 - int iFrom, iTo; 613 - Manifest mFrom, mTo; 633 + Manifest *pFrom, *pTo; 634 + ManifestFile *pFileFrom, *pFileTo; 614 635 615 636 login_check_credentials(); 616 637 if( !g.okRead ){ login_needed(); return; } 617 638 login_anonymous_available(); 618 639 619 - if( vdiff_parse_manifest("from", &ridFrom, &mFrom) ) return; 620 - if( vdiff_parse_manifest("to", &ridTo, &mTo) ) return; 640 + pFrom = vdiff_parse_manifest("from", &ridFrom); 641 + if( pFrom==0 ) return; 642 + pTo = vdiff_parse_manifest("to", &ridTo); 643 + if( pTo==0 ) return; 621 644 showDetail = atoi(PD("detail","0")); 622 645 style_header("Check-in Differences"); 623 646 @ <h2>Difference From:</h2><blockquote> 624 647 checkin_description(ridFrom); 625 648 @ </blockquote><h2>To:</h2><blockquote> 626 649 checkin_description(ridTo); 627 - @ </blockquote><hr><p> 650 + @ </blockquote><hr /><p> 628 651 629 - iFrom = iTo = 0; 630 - while( iFrom<mFrom.nFile && iTo<mTo.nFile ){ 652 + manifest_file_rewind(pFrom); 653 + pFileFrom = manifest_file_next(pFrom, 0); 654 + manifest_file_rewind(pTo); 655 + pFileTo = manifest_file_next(pTo, 0); 656 + while( pFileFrom || pFileTo ){ 631 657 int cmp; 632 - if( iFrom>=mFrom.nFile ){ 658 + if( pFileFrom==0 ){ 633 659 cmp = +1; 634 - }else if( iTo>=mTo.nFile ){ 660 + }else if( pFileTo==0 ){ 635 661 cmp = -1; 636 662 }else{ 637 - cmp = strcmp(mFrom.aFile[iFrom].zName, mTo.aFile[iTo].zName); 663 + cmp = strcmp(pFileFrom->zName, pFileTo->zName); 638 664 } 639 665 if( cmp<0 ){ 640 - append_file_change_line(mFrom.aFile[iFrom].zName, 641 - mFrom.aFile[iFrom].zUuid, 0, 0); 642 - iFrom++; 666 + append_file_change_line(pFileFrom->zName, 667 + pFileFrom->zUuid, 0, 0); 668 + pFileFrom = manifest_file_next(pFrom, 0); 643 669 }else if( cmp>0 ){ 644 - append_file_change_line(mTo.aFile[iTo].zName, 645 - 0, mTo.aFile[iTo].zUuid, 0); 646 - iTo++; 647 - }else if( strcmp(mFrom.aFile[iFrom].zUuid, mTo.aFile[iTo].zUuid)==0 ){ 670 + append_file_change_line(pFileTo->zName, 671 + 0, pFileTo->zUuid, 0); 672 + pFileTo = manifest_file_next(pTo, 0); 673 + }else if( strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){ 648 674 /* No changes */ 649 - iFrom++; 650 - iTo++; 675 + pFileFrom = manifest_file_next(pFrom, 0); 676 + pFileTo = manifest_file_next(pTo, 0); 651 677 }else{ 652 - append_file_change_line(mFrom.aFile[iFrom].zName, 653 - mFrom.aFile[iFrom].zUuid, 654 - mTo.aFile[iTo].zUuid, showDetail); 655 - iFrom++; 656 - iTo++; 678 + append_file_change_line(pFileFrom->zName, 679 + pFileFrom->zUuid, 680 + pFileTo->zUuid, showDetail); 681 + pFileFrom = manifest_file_next(pFrom, 0); 682 + pFileTo = manifest_file_next(pTo, 0); 657 683 } 658 684 } 659 - manifest_clear(&mFrom); 660 - manifest_clear(&mTo); 685 + manifest_destroy(pFrom); 686 + manifest_destroy(pTo); 661 687 662 688 style_footer(); 663 689 } 664 690 665 691 /* 666 692 ** Write a description of an object to the www reply. 667 693 ** ................................................................................ 759 785 if( pDownloadName && blob_size(pDownloadName)==0 ){ 760 786 blob_appendf(pDownloadName, "%s.wiki", zPagename); 761 787 } 762 788 } 763 789 db_finalize(&q); 764 790 if( nWiki==0 ){ 765 791 db_prepare(&q, 766 - "SELECT datetime(mtime), user, comment, type, uuid" 792 + "SELECT datetime(mtime), user, comment, type, uuid, tagid" 767 793 " FROM event, blob" 768 794 " WHERE event.objid=%d" 769 795 " AND blob.rid=%d", 770 796 rid, rid 771 797 ); 772 798 while( db_step(&q)==SQLITE_ROW ){ 773 799 const char *zDate = db_column_text(&q, 0); ................................................................................ 780 806 } 781 807 if( zType[0]=='w' ){ 782 808 @ Wiki edit 783 809 }else if( zType[0]=='t' ){ 784 810 @ Ticket change 785 811 }else if( zType[0]=='c' ){ 786 812 @ Manifest of check-in 813 + }else if( zType[0]=='e' ){ 814 + @ Instance of event 815 + hyperlink_to_event_tagid(db_column_int(&q, 5)); 787 816 }else{ 788 817 @ Control file referencing 789 818 } 790 - hyperlink_to_uuid(zUuid); 819 + if( zType[0]!='e' ){ 820 + hyperlink_to_uuid(zUuid); 821 + } 791 822 @ - %w(zCom) by 792 823 hyperlink_to_user(zUser,zDate," on"); 793 824 hyperlink_to_date(zDate, "."); 794 825 if( pDownloadName && blob_size(pDownloadName)==0 ){ 795 826 blob_appendf(pDownloadName, "%.10s.txt", zUuid); 796 827 } 797 828 cnt++; ................................................................................ 862 893 login_check_credentials(); 863 894 if( !g.okRead ){ login_needed(); return; } 864 895 v1 = name_to_rid_www("v1"); 865 896 v2 = name_to_rid_www("v2"); 866 897 if( v1==0 || v2==0 ) fossil_redirect_home(); 867 898 style_header("Diff"); 868 899 @ <h2>Differences From:</h2> 869 - @ <blockquote> 900 + @ <blockquote><p> 870 901 object_description(v1, 1, 0); 871 - @ </blockquote> 902 + @ </p></blockquote> 872 903 @ <h2>To:</h2> 873 - @ <blockquote> 904 + @ <blockquote><p> 874 905 object_description(v2, 1, 0); 875 - @ </blockquote> 876 - @ <hr> 906 + @ </p></blockquote> 907 + @ <hr /> 877 908 @ <blockquote><pre> 878 909 content_get(v1, &c1); 879 910 content_get(v2, &c2); 880 911 blob_zero(&diff); 881 - text_diff(&c1, &c2, &diff, 4); 912 + text_diff(&c1, &c2, &diff, 4, 1); 882 913 blob_reset(&c1); 883 914 blob_reset(&c2); 884 915 @ %h(blob_str(&diff)) 885 916 @ </pre></blockquote> 886 917 blob_reset(&diff); 887 918 style_footer(); 888 919 } ................................................................................ 976 1007 rid = name_to_rid_www("name"); 977 1008 login_check_credentials(); 978 1009 if( !g.okRead ){ login_needed(); return; } 979 1010 if( rid==0 ) fossil_redirect_home(); 980 1011 if( g.okAdmin ){ 981 1012 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); 982 1013 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ 983 - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", 1014 + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", 984 1015 g.zTop, zUuid); 985 1016 }else{ 986 1017 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", 987 1018 g.zTop, zUuid); 988 1019 } 989 1020 } 990 1021 style_header("Hex Artifact Content"); 991 1022 zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); 992 1023 @ <h2>Artifact %s(zUuid):</h2> 993 - @ <blockquote> 1024 + @ <blockquote><p> 994 1025 blob_zero(&downloadName); 995 1026 object_description(rid, 0, &downloadName); 996 1027 style_submenu_element("Download", "Download", 997 1028 "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); 998 - @ </blockquote> 999 - @ <hr> 1029 + @ </p></blockquote> 1030 + @ <hr /> 1000 1031 content_get(rid, &content); 1001 1032 @ <blockquote><pre> 1002 1033 hexdump(&content); 1003 1034 @ </pre></blockquote> 1004 1035 style_footer(); 1005 1036 } 1006 1037 ................................................................................ 1008 1039 ** Look for "ci" and "filename" query parameters. If found, try to 1009 1040 ** use them to extract the record ID of an artifact for the file. 1010 1041 */ 1011 1042 int artifact_from_ci_and_filename(void){ 1012 1043 const char *zFilename; 1013 1044 const char *zCI; 1014 1045 int cirid; 1015 - Blob content; 1016 - Manifest m; 1017 - int i; 1046 + Manifest *pManifest; 1047 + ManifestFile *pFile; 1018 1048 1019 1049 zCI = P("ci"); 1020 1050 if( zCI==0 ) return 0; 1021 1051 zFilename = P("filename"); 1022 1052 if( zFilename==0 ) return 0; 1023 1053 cirid = name_to_rid_www("ci"); 1024 - if( !content_get(cirid, &content) ) return 0; 1025 - if( !manifest_parse(&m, &content) ) return 0; 1026 - if( m.type!=CFTYPE_MANIFEST ) return 0; 1027 - for(i=0; i<m.nFile; i++){ 1028 - if( strcmp(zFilename, m.aFile[i].zName)==0 ){ 1029 - return db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", m.aFile[i].zUuid); 1054 + pManifest = manifest_get(cirid, CFTYPE_MANIFEST); 1055 + if( pManifest==0 ) return 0; 1056 + manifest_file_rewind(pManifest); 1057 + while( (pFile = manifest_file_next(pManifest,0))!=0 ){ 1058 + if( strcmp(zFilename, pFile->zName)==0 ){ 1059 + int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); 1060 + manifest_destroy(pManifest); 1061 + return rid; 1030 1062 } 1031 1063 } 1032 1064 return 0; 1033 1065 } 1034 1066 1035 1067 1036 1068 /* ................................................................................ 1058 1090 1059 1091 login_check_credentials(); 1060 1092 if( !g.okRead ){ login_needed(); return; } 1061 1093 if( rid==0 ) fossil_redirect_home(); 1062 1094 if( g.okAdmin ){ 1063 1095 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); 1064 1096 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ 1065 - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", 1097 + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", 1066 1098 g.zTop, zUuid); 1067 1099 }else{ 1068 1100 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", 1069 1101 g.zTop, zUuid); 1070 1102 } 1071 1103 } 1072 1104 style_header("Artifact Content"); 1073 1105 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); 1074 1106 @ <h2>Artifact %s(zUuid)</h2> 1075 - @ <blockquote> 1107 + @ <blockquote><p> 1076 1108 blob_zero(&downloadName); 1077 1109 object_description(rid, 0, &downloadName); 1078 1110 style_submenu_element("Download", "Download", 1079 1111 "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); 1080 1112 zMime = mimetype_from_name(blob_str(&downloadName)); 1081 1113 if( zMime ){ 1082 1114 if( strcmp(zMime, "text/html")==0 ){ 1083 1115 if( P("txt") ){ 1084 1116 style_submenu_element("Html", "Html", 1085 1117 "%s/artifact?name=%s", g.zTop, zUuid); 1086 1118 }else{ 1087 1119 renderAsHtml = 1; 1088 1120 style_submenu_element("Text", "Text", 1089 - "%s/artifact?name=%s&txt=1", g.zTop, zUuid); 1121 + "%s/artifact?name=%s&txt=1", g.zTop, zUuid); 1090 1122 } 1091 1123 }else if( strcmp(zMime, "application/x-fossil-wiki")==0 ){ 1092 1124 if( P("txt") ){ 1093 1125 style_submenu_element("Wiki", "Wiki", 1094 1126 "%s/artifact?name=%s", g.zTop, zUuid); 1095 1127 }else{ 1096 1128 renderAsWiki = 1; 1097 1129 style_submenu_element("Text", "Text", 1098 - "%s/artifact?name=%s&txt=1", g.zTop, zUuid); 1130 + "%s/artifact?name=%s&txt=1", g.zTop, zUuid); 1099 1131 } 1100 1132 } 1101 1133 } 1102 - @ </blockquote> 1103 - @ <hr> 1134 + @ </p></blockquote> 1135 + @ <hr /> 1104 1136 content_get(rid, &content); 1105 1137 if( renderAsWiki ){ 1106 1138 wiki_convert(&content, 0, 0); 1107 1139 }else if( renderAsHtml ){ 1108 1140 @ <div> 1109 1141 cgi_append_content(blob_buffer(&content), blob_size(&content)); 1110 1142 @ </div> ................................................................................ 1113 1145 @ <blockquote> 1114 1146 if( zMime==0 ){ 1115 1147 @ <pre> 1116 1148 @ %h(blob_str(&content)) 1117 1149 @ </pre> 1118 1150 style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid); 1119 1151 }else if( strncmp(zMime, "image/", 6)==0 ){ 1120 - @ <img src="%s(g.zBaseURL)/raw?name=%s(zUuid)&m=%s(zMime)"></img> 1152 + @ <img src="%s(g.zBaseURL)/raw?name=%s(zUuid)&m=%s(zMime)"></img> 1121 1153 style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid); 1122 1154 }else{ 1123 1155 @ <pre> 1124 1156 hexdump(&content); 1125 1157 @ </pre> 1126 1158 } 1127 1159 @ </blockquote> ................................................................................ 1133 1165 ** WEBPAGE: tinfo 1134 1166 ** URL: /tinfo?name=ARTIFACTID 1135 1167 ** 1136 1168 ** Show the details of a ticket change control artifact. 1137 1169 */ 1138 1170 void tinfo_page(void){ 1139 1171 int rid; 1140 - Blob content; 1141 1172 char *zDate; 1142 1173 const char *zUuid; 1143 1174 char zTktName[20]; 1144 - Manifest m; 1175 + Manifest *pTktChng; 1145 1176 1146 1177 login_check_credentials(); 1147 1178 if( !g.okRdTkt ){ login_needed(); return; } 1148 1179 rid = name_to_rid_www("name"); 1149 1180 if( rid==0 ){ fossil_redirect_home(); } 1150 1181 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); 1151 1182 if( g.okAdmin ){ 1152 1183 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ 1153 - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", 1184 + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", 1154 1185 g.zTop, zUuid); 1155 1186 }else{ 1156 1187 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", 1157 1188 g.zTop, zUuid); 1158 1189 } 1159 1190 } 1160 - content_get(rid, &content); 1161 - if( manifest_parse(&m, &content)==0 ){ 1162 - fossil_redirect_home(); 1163 - } 1164 - if( m.type!=CFTYPE_TICKET ){ 1191 + pTktChng = manifest_get(rid, CFTYPE_TICKET); 1192 + if( pTktChng==0 ){ 1165 1193 fossil_redirect_home(); 1166 1194 } 1167 1195 style_header("Ticket Change Details"); 1168 - zDate = db_text(0, "SELECT datetime(%.12f)", m.rDate); 1169 - memcpy(zTktName, m.zTicketUuid, 10); 1196 + zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); 1197 + memcpy(zTktName, pTktChng->zTicketUuid, 10); 1170 1198 zTktName[10] = 0; 1171 1199 if( g.okHistory ){ 1172 - @ <h2>Changes to ticket <a href="%s(m.zTicketUuid)">%s(zTktName)</a></h2> 1200 + @ <h2>Changes to ticket 1201 + @ <a href="%s(pTktChng->zTicketUuid)">%s(zTktName)</a></h2> 1173 1202 @ 1174 - @ <p>By %h(m.zUser) on %s(zDate). See also: 1203 + @ <p>By %h(pTktChng->zUser) on %s(zDate). See also: 1175 1204 @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and 1176 - @ <a href="%s(g.zTop)/tkthistory/%s(m.zTicketUuid)">ticket history</a> 1177 - @ </p> 1205 + @ <a href="%s(g.zTop)/tkthistory/%s(pTktChng->zTicketUuid)">ticket 1206 + @ history</a></p> 1178 1207 }else{ 1179 1208 @ <h2>Changes to ticket %s(zTktName)</h2> 1180 1209 @ 1181 - @ <p>By %h(m.zUser) on %s(zDate). 1210 + @ <p>By %h(pTktChng->zUser) on %s(zDate). 1182 1211 @ </p> 1183 1212 } 1184 1213 @ 1185 1214 @ <ol> 1186 1215 free(zDate); 1187 - ticket_output_change_artifact(&m); 1188 - manifest_clear(&m); 1216 + ticket_output_change_artifact(pTktChng); 1217 + manifest_destroy(pTktChng); 1189 1218 style_footer(); 1190 1219 } 1191 1220 1192 1221 1193 1222 /* 1194 1223 ** WEBPAGE: info 1195 1224 ** URL: info/ARTIFACTID ................................................................................ 1240 1269 if( db_exists("SELECT 1 FROM plink WHERE pid=%d", rid) ){ 1241 1270 ci_page(); 1242 1271 }else 1243 1272 { 1244 1273 artifact_page(); 1245 1274 } 1246 1275 } 1276 + 1277 +/* 1278 +** Generate HTML that will present the user with a selection of 1279 +** potential background colors for timeline entries. 1280 +*/ 1281 +void render_color_chooser( 1282 + int fPropagate, /* Default value for propagation */ 1283 + const char *zDefaultColor, /* The current default color */ 1284 + const char *zIdPropagate, /* ID of form element checkbox. NULL for none */ 1285 + const char *zId, /* The ID of the form element */ 1286 + const char *zIdCustom /* ID of text box for custom color */ 1287 +){ 1288 + static const struct SampleColors { 1289 + const char *zCName; 1290 + const char *zColor; 1291 + } aColor[] = { 1292 + { "(none)", "" }, 1293 + { "#f2dcdc", "#f2dcdc" }, 1294 + { "#f0ffc0", "#f0ffc0" }, 1295 + { "#bde5d6", "#bde5d6" }, 1296 + { "#c0ffc0", "#c0ffc0" }, 1297 + { "#c0fff0", "#c0fff0" }, 1298 + { "#c0f0ff", "#c0f0ff" }, 1299 + { "#d0c0ff", "#d0c0ff" }, 1300 + { "#ffc0ff", "#ffc0ff" }, 1301 + { "#ffc0d0", "#ffc0d0" }, 1302 + { "#fff0c0", "#fff0c0" }, 1303 + { "#c0c0c0", "#c0c0c0" }, 1304 + { "custom", "##" }, 1305 + }; 1306 + int nColor = sizeof(aColor)/sizeof(aColor[0])-1; 1307 + int stdClrFound = 0; 1308 + int i; 1309 + 1310 + @ <table border="0" cellpadding="0" cellspacing="1"> 1311 + if( zIdPropagate ){ 1312 + @ <tr><td colspan="6" align="left"> 1313 + if( fPropagate ){ 1314 + @ <input type="checkbox" name="%s(zIdPropagate)" checked="checked" /> 1315 + }else{ 1316 + @ <input type="checkbox" name="%s(zIdPropagate)" /> 1317 + } 1318 + @ Propagate color to descendants</td></tr> 1319 + } 1320 + @ <tr> 1321 + for(i=0; i<nColor; i++){ 1322 + if( aColor[i].zColor[0] ){ 1323 + @ <td style="background-color: %h(aColor[i].zColor);"> 1324 + }else{ 1325 + @ <td> 1326 + } 1327 + if( strcmp(zDefaultColor, aColor[i].zColor)==0 ){ 1328 + @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)" 1329 + @ checked="checked" /> 1330 + stdClrFound=1; 1331 + }else{ 1332 + @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)" /> 1333 + } 1334 + @ %h(aColor[i].zCName)</td> 1335 + if( (i%6)==5 && i+1<nColor ){ 1336 + @ </tr><tr> 1337 + } 1338 + } 1339 + @ </tr><tr> 1340 + if (stdClrFound){ 1341 + @ <td colspan="6"> 1342 + @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)" /> 1343 + }else{ 1344 + @ <td style="background-color: %h(zDefaultColor);" colspan="6"> 1345 + @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)" 1346 + @ checked="checked" /> 1347 + } 1348 + @ %h(aColor[i].zCName) 1349 + @ <input type="text" name="%s(zIdCustom)" 1350 + @ id="%s(zIdCustom)" class="checkinUserColor" 1351 + @ value="%h(stdClrFound?"":zDefaultColor)" /> 1352 + @ </td> 1353 + @ </tr> 1354 + @ </table> 1355 +} 1247 1356 1248 1357 /* 1249 1358 ** WEBPAGE: ci_edit 1250 1359 ** URL: ci_edit?r=RID&c=NEWCOMMENT&u=NEWUSER 1251 1360 ** 1252 1361 ** Present a dialog for updating properties of a baseline: 1253 1362 ** ................................................................................ 1270 1379 const char *zNewBrFlag; 1271 1380 const char *zNewBranch; 1272 1381 const char *zCloseFlag; 1273 1382 int fPropagateColor; 1274 1383 char *zUuid; 1275 1384 Blob comment; 1276 1385 Stmt q; 1277 - static const struct SampleColors { 1278 - const char *zCName; 1279 - const char *zColor; 1280 - } aColor[] = { 1281 - { "(none)", "" }, 1282 - { "#f2dcdc", "#f2dcdc" }, 1283 - { "#f0ffc0", "#f0ffc0" }, 1284 - { "#bde5d6", "#bde5d6" }, 1285 - { "#c0ffc0", "#c0ffc0" }, 1286 - { "#c0fff0", "#c0fff0" }, 1287 - { "#c0f0ff", "#c0f0ff" }, 1288 - { "#d0c0ff", "#d0c0ff" }, 1289 - { "#ffc0ff", "#ffc0ff" }, 1290 - { "#ffc0d0", "#ffc0d0" }, 1291 - { "#fff0c0", "#fff0c0" }, 1292 - { "#c0c0c0", "#c0c0c0" }, 1293 - }; 1294 - int nColor = sizeof(aColor)/sizeof(aColor[0]); 1295 - int i; 1296 1386 1297 1387 login_check_credentials(); 1298 1388 if( !g.okWrite ){ login_needed(); return; } 1299 1389 rid = name_to_rid(P("r")); 1300 1390 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); 1301 1391 zComment = db_text(0, "SELECT coalesce(ecomment,comment)" 1302 1392 " FROM event WHERE objid=%d", rid); ................................................................................ 1312 1402 zDate = db_text(0, "SELECT datetime(mtime)" 1313 1403 " FROM event WHERE objid=%d", rid); 1314 1404 if( zDate==0 ) fossil_redirect_home(); 1315 1405 zNewDate = PD("dt",zDate); 1316 1406 zColor = db_text("", "SELECT bgcolor" 1317 1407 " FROM event WHERE objid=%d", rid); 1318 1408 zNewColor = PD("clr",zColor); 1409 + if( strcmp(zNewColor,"##")==0 ){ 1410 + zNewColor = P("clrcust"); 1411 + } 1319 1412 fPropagateColor = P("pclr")!=0; 1320 1413 zNewTagFlag = P("newtag") ? " checked" : ""; 1321 1414 zNewTag = PD("tagname",""); 1322 1415 zNewBrFlag = P("newbr") ? " checked" : ""; 1323 1416 zNewBranch = PD("brname",""); 1324 1417 zCloseFlag = P("close") ? " checked" : ""; 1325 1418 if( P("apply") ){ ................................................................................ 1424 1517 if( P("preview") ){ 1425 1518 Blob suffix; 1426 1519 int nTag = 0; 1427 1520 @ <b>Preview:</b> 1428 1521 @ <blockquote> 1429 1522 @ <table border=0> 1430 1523 if( zNewColor && zNewColor[0] ){ 1431 - @ <tr><td bgcolor="%h(zNewColor)"> 1524 + @ <tr><td style="background-color: %h(zNewColor);"> 1432 1525 }else{ 1433 1526 @ <tr><td> 1434 1527 } 1435 1528 wiki_convert(&comment, 0, WIKI_INLINE); 1436 1529 blob_zero(&suffix); 1437 1530 blob_appendf(&suffix, "(user: %h", zNewUser); 1438 1531 db_prepare(&q, "SELECT substr(tagname,5) FROM tagxref, tag" ................................................................................ 1449 1542 nTag++; 1450 1543 } 1451 1544 db_finalize(&q); 1452 1545 blob_appendf(&suffix, ")"); 1453 1546 @ %s(blob_str(&suffix)) 1454 1547 @ </td></tr></table> 1455 1548 @ </blockquote> 1456 - @ <hr> 1549 + @ <hr /> 1457 1550 blob_reset(&suffix); 1458 1551 } 1459 1552 @ <p>Make changes to attributes of check-in 1460 1553 @ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p> 1461 - @ <form action="%s(g.zBaseURL)/ci_edit" method="POST"> 1554 + @ <form action="%s(g.zBaseURL)/ci_edit" method="post"><div> 1462 1555 login_insert_csrf_secret(); 1463 - @ <input type="hidden" name="r" value="%S(zUuid)"> 1556 + @ <input type="hidden" name="r" value="%S(zUuid)" /> 1464 1557 @ <table border="0" cellspacing="10"> 1465 1558 1466 1559 @ <tr><td align="right" valign="top"><b>User:</b></td> 1467 1560 @ <td valign="top"> 1468 - @ <input type="text" name="u" size="20" value="%h(zNewUser)"> 1561 + @ <input type="text" name="u" size="20" value="%h(zNewUser)" /> 1469 1562 @ </td></tr> 1470 1563 1471 1564 @ <tr><td align="right" valign="top"><b>Comment:</b></td> 1472 1565 @ <td valign="top"> 1473 1566 @ <textarea name="c" rows="10" cols="80">%h(zNewComment)</textarea> 1474 1567 @ </td></tr> 1475 1568 1476 1569 @ <tr><td align="right" valign="top"><b>Check-in Time:</b></td> 1477 1570 @ <td valign="top"> 1478 - @ <input type="text" name="dt" size="20" value="%h(zNewDate)"> 1571 + @ <input type="text" name="dt" size="20" value="%h(zNewDate)" /> 1479 1572 @ </td></tr> 1480 1573 1481 1574 @ <tr><td align="right" valign="top"><b>Background Color:</b></td> 1482 1575 @ <td valign="top"> 1483 - @ <table border=0 cellpadding=0 cellspacing=1> 1484 - @ <tr><td colspan="6" align="left"> 1485 - if( fPropagateColor ){ 1486 - @ <input type="checkbox" name="pclr" checked> 1487 - }else{ 1488 - @ <input type="checkbox" name="pclr"> 1489 - } 1490 - @ Propagate color to descendants</input></td></tr> 1491 - @ <tr> 1492 - for(i=0; i<nColor; i++){ 1493 - if( aColor[i].zColor[0] ){ 1494 - @ <td bgcolor="%h(aColor[i].zColor)"> 1495 - }else{ 1496 - @ <td> 1497 - } 1498 - if( strcmp(zNewColor, aColor[i].zColor)==0 ){ 1499 - @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" checked> 1500 - }else{ 1501 - @ <input type="radio" name="clr" value="%h(aColor[i].zColor)"> 1502 - } 1503 - @ %h(aColor[i].zCName)</input></td> 1504 - if( (i%6)==5 && i+1<nColor ){ 1505 - @ </tr><tr> 1506 - } 1507 - } 1508 - @ </tr> 1509 - @ </table> 1576 + render_color_chooser(fPropagateColor, zNewColor, "pclr", "clr", "clrcust"); 1510 1577 @ </td></tr> 1511 1578 1512 1579 @ <tr><td align="right" valign="top"><b>Tags:</b></td> 1513 1580 @ <td valign="top"> 1514 - @ <input type="checkbox" name="newtag"%s(zNewTagFlag)> 1581 + @ <input type="checkbox" name="newtag"%s(zNewTagFlag) /> 1515 1582 @ Add the following new tag name to this check-in: 1516 - @ <input type="text" width="15" name="tagname" value="%h(zNewTag)"> 1583 + @ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)" /> 1517 1584 db_prepare(&q, 1518 1585 "SELECT tag.tagid, tagname FROM tagxref, tag" 1519 1586 " WHERE tagxref.rid=%d AND tagtype>0 AND tagxref.tagid=tag.tagid" 1520 1587 " ORDER BY CASE WHEN tagname GLOB 'sym-*' THEN substr(tagname,5)" 1521 1588 " ELSE tagname END", 1522 1589 rid 1523 1590 ); 1524 1591 while( db_step(&q)==SQLITE_ROW ){ 1525 1592 int tagid = db_column_int(&q, 0); 1526 1593 const char *zTagName = db_column_text(&q, 1); 1527 1594 char zLabel[30]; 1528 1595 sprintf(zLabel, "c%d", tagid); 1529 1596 if( P(zLabel) ){ 1530 - @ <br><input type="checkbox" name="c%d(tagid)" checked> 1597 + @ <br /><input type="checkbox" name="c%d(tagid)" checked="checked" /> 1531 1598 }else{ 1532 - @ <br><input type="checkbox" name="c%d(tagid)"> 1599 + @ <br /><input type="checkbox" name="c%d(tagid)" /> 1533 1600 } 1534 1601 if( strncmp(zTagName, "sym-", 4)==0 ){ 1535 1602 @ Cancel tag <b>%h(&zTagName[4])</b> 1536 1603 }else{ 1537 1604 @ Cancel special tag <b>%h(zTagName)</b> 1538 1605 } 1539 1606 } 1540 1607 db_finalize(&q); 1541 1608 @ </td></tr> 1542 1609 1543 1610 @ <tr><td align="right" valign="top"><b>Branching:</b></td> 1544 1611 @ <td valign="top"> 1545 - @ <input type="checkbox" name="newbr"%s(zNewBrFlag)> 1612 + @ <input type="checkbox" name="newbr"%s(zNewBrFlag) /> 1546 1613 @ Make this check-in the start of a new branch named: 1547 - @ <input type="text" width="15" name="brname" value="%h(zNewBranch)"> 1614 + @ <input type="text" style="width:15;" name="brname" value="%h(zNewBranch)" /> 1548 1615 @ </td></tr> 1549 1616 1550 1617 if( is_a_leaf(rid) 1551 1618 && !db_exists("SELECT 1 FROM tagxref " 1552 1619 " WHERE tagid=%d AND rid=%d AND tagtype>0", 1553 1620 TAG_CLOSED, rid) 1554 1621 ){ 1555 1622 @ <tr><td align="right" valign="top"><b>Leaf Closure:</b></td> 1556 1623 @ <td valign="top"> 1557 - @ <input type="checkbox" name="close"%s(zCloseFlag)> 1624 + @ <input type="checkbox" name="close"%s(zCloseFlag) /> 1558 1625 @ Mark this leaf as "closed" so that it no longer appears on the 1559 1626 @ "leaves" page and is no longer labeled as a "<b>Leaf</b>". 1560 1627 @ </td></tr> 1561 1628 } 1562 1629 1563 1630 1564 1631 @ <tr><td colspan="2"> 1565 - @ <input type="submit" name="preview" value="Preview"> 1566 - @ <input type="submit" name="apply" value="Apply Changes"> 1567 - @ <input type="submit" name="cancel" value="Cancel"> 1632 + @ <input type="submit" name="preview" value="Preview" /> 1633 + @ <input type="submit" name="apply" value="Apply Changes" /> 1634 + @ <input type="submit" name="cancel" value="Cancel" /> 1568 1635 @ </td></tr> 1569 1636 @ </table> 1570 - @ </form> 1637 + @ </div></form> 1571 1638 style_footer(); 1572 1639 }
Changes to src/login.c.
35 35 ** not really the point. The anonymous login keeps search-engine 36 36 ** crawlers and site download tools like wget from walking change 37 37 ** logs and downloading diffs of very version of the archive that 38 38 ** has ever existed, and things like that. 39 39 */ 40 40 #include "config.h" 41 41 #include "login.h" 42 -#ifdef __MINGW32__ 42 +#if defined(_WIN32) 43 43 # include <windows.h> /* for Sleep */ 44 -# define sleep Sleep /* windows does not have sleep, but Sleep */ 44 +# if defined(__MINGW32__) || defined(_MSC_VER) 45 +# define sleep Sleep /* windows does not have sleep, but Sleep */ 46 +# endif 45 47 #endif 46 48 #include <time.h> 47 49 48 50 /* 49 51 ** Return the name of the login cookie 50 52 */ 51 53 static char *login_cookie_name(void){ 52 54 static char *zCookieName = 0; 53 55 if( zCookieName==0 ){ 54 - int n = strlen(g.zTop); 55 - zCookieName = malloc( n*2+16 ); 56 - /* 0123456789 12345 */ 57 - strcpy(zCookieName, "fossil_login_"); 58 - encode16((unsigned char*)g.zTop, (unsigned char*)&zCookieName[13], n); 56 + unsigned int h = 0; 57 + const char *z = g.zBaseURL; 58 + while( *z ){ h = (h<<3) ^ (h>>26) ^ *(z++); } 59 + zCookieName = mprintf("fossil_login_%08x", h); 59 60 } 60 61 return zCookieName; 61 62 } 62 63 63 64 /* 64 65 ** Redirect to the page specified by the "g" query parameter. 65 66 ** Or if there is no "g" query parameter, redirect to the homepage. ................................................................................ 149 150 if( g.okPassword && zPasswd && (zNew1 = P("n1"))!=0 && (zNew2 = P("n2"))!=0 ){ 150 151 zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin); 151 152 if( db_int(1, "SELECT 0 FROM user" 152 153 " WHERE uid=%d AND (pw=%Q OR pw=%Q)", 153 154 g.userUid, zPasswd, zSha1Pw) ){ 154 155 sleep(1); 155 156 zErrMsg = 156 - @ <p><font color="red"> 157 + @ <p><span class="loginError"> 157 158 @ You entered an incorrect old password while attempting to change 158 159 @ your password. Your password is unchanged. 159 - @ </font></p> 160 + @ </span></p> 160 161 ; 161 162 }else if( strcmp(zNew1,zNew2)!=0 ){ 162 163 zErrMsg = 163 - @ <p><font color="red"> 164 + @ <p><span class="loginError"> 164 165 @ The two copies of your new passwords do not match. 165 166 @ Your password is unchanged. 166 - @ </font></p> 167 + @ </span></p> 167 168 ; 168 169 }else{ 169 170 char *zNewPw = sha1_shared_secret(zNew1, g.zLogin); 170 171 db_multi_exec( 171 172 "UPDATE user SET pw=%Q WHERE uid=%d", zNewPw, g.userUid 172 173 ); 173 174 redirect_to_g(); ................................................................................ 202 203 " AND login NOT IN ('anonymous','nobody','developer','reader')" 203 204 " AND (pw=%Q OR pw=%Q)", 204 205 zUsername, zPasswd, zSha1Pw 205 206 ); 206 207 if( uid<=0 ){ 207 208 sleep(1); 208 209 zErrMsg = 209 - @ <p><font color="red"> 210 + @ <p><span class="loginError"> 210 211 @ You entered an unknown user or an incorrect password. 211 - @ </font></p> 212 + @ </span></p> 212 213 ; 213 214 }else{ 214 215 char *zCookie; 215 216 const char *zCookieName = login_cookie_name(); 216 217 const char *zExpire = db_get("cookie-expire","8766"); 217 218 int expires = atoi(zExpire)*3600; 218 219 const char *zIpAddr = PD("REMOTE_ADDR","nil"); ................................................................................ 225 226 zCookie, zIpAddr, expires, uid 226 227 ); 227 228 redirect_to_g(); 228 229 } 229 230 } 230 231 style_header("Login/Logout"); 231 232 @ %s(zErrMsg) 232 - @ <form action="login" method="POST"> 233 + @ <form action="login" method="post"> 233 234 if( P("g") ){ 234 - @ <input type="hidden" name="g" value="%h(P("g"))"> 235 + @ <input type="hidden" name="g" value="%h(P("g"))" /> 235 236 } 236 - @ <table align="left" hspace="10"> 237 + @ <table class="login_out"> 237 238 @ <tr> 238 - @ <td align="right">User ID:</td> 239 + @ <td class="login_out_label">User ID:</td> 239 240 if( anonFlag ){ 240 - @ <td><input type="text" id="u" name="u" value="anonymous" size=30></td> 241 + @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td> 241 242 }else{ 242 - @ <td><input type="text" id="u" name="u" value="" size=30></td> 243 + @ <td><input type="text" id="u" name="u" value="" size="30" /></td> 243 244 } 244 245 @ </tr> 245 246 @ <tr> 246 - @ <td align="right">Password:</td> 247 - @ <td><input type="password" id="p" name="p" value="" size=30></td> 247 + @ <td class="login_out_label">Password:</td> 248 + @ <td><input type="password" id="p" name="p" value="" size="30" /></td> 248 249 @ </tr> 249 250 if( g.zLogin==0 ){ 250 251 zAnonPw = db_text(0, "SELECT pw FROM user" 251 252 " WHERE login='anonymous'" 252 253 " AND cap!=''"); 253 254 } 254 255 @ <tr> 255 256 @ <td></td> 256 - @ <td><input type="submit" name="in" value="Login"></td> 257 + @ <td><input type="submit" name="in" value="Login" /></td> 257 258 @ </tr> 258 259 @ </table> 259 - @ <script>document.getElementById('u').focus()</script> 260 + @ <script type="text/JavaScript">document.getElementById('u').focus()</script> 260 261 if( g.zLogin==0 ){ 261 262 @ <p>Enter 262 263 }else{ 263 264 @ <p>You are currently logged in as <b>%h(g.zLogin)</b></p> 264 265 @ <p>To change your login to a different user, enter 265 266 } 266 267 @ your user-id and password at the left and press the ................................................................................ 269 270 @ the login to take.</p> 270 271 if( zAnonPw ){ 271 272 unsigned int uSeed = captcha_seed(); 272 273 char const *zDecoded = captcha_decode(uSeed); 273 274 int bAutoCaptcha = db_get_boolean("auto-captcha", 1); 274 275 char *zCaptcha = captcha_render(zDecoded); 275 276 276 - @ <input type="hidden" name="cs" value="%u(uSeed)"/> 277 - @ <p>Visitors may enter <b>anonymous</b> as the user-ID with 277 + @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> 278 + @ Visitors may enter <b>anonymous</b> as the user-ID with 278 279 @ the 8-character hexadecimal password shown below:</p> 279 - @ <center><table border="1" cellpadding="10"><tr><td><pre> 280 + @ <div class="captcha"><table class="captcha"><tr><td><pre> 280 281 @ %s(zCaptcha) 281 282 @ </pre></td></tr></table> 282 283 if( bAutoCaptcha ) { 283 284 @ <input type="button" value="Fill out captcha" 284 285 @ onclick="document.getElementById('u').value='anonymous'; 285 - @ document.getElementById('p').value='%s(zDecoded)';"/> 286 + @ document.getElementById('p').value='%s(zDecoded)';" /> 286 287 } 287 - @ </center> 288 + @ </div> 288 289 free(zCaptcha); 289 290 } 290 291 if( g.zLogin ){ 291 - @ <br clear="both"><hr> 292 + @ <hr /> 292 293 @ <p>To log off the system (and delete your login cookie) 293 - @ press the following button:<br> 294 - @ <input type="submit" name="out" value="Logout"></p> 294 + @ press the following button:<br /> 295 + @ <input type="submit" name="out" value="Logout" /></p> 295 296 } 296 297 @ </form> 297 298 if( g.okPassword ){ 298 - @ <br clear="both"><hr> 299 + @ <hr /> 299 300 @ <p>To change your password, enter your old password and your 300 301 @ new password twice below then press the "Change Password" 301 302 @ button.</p> 302 - @ <form action="login" method="POST"> 303 + @ <form action="login" method="post"> 303 304 @ <table> 304 - @ <tr><td align="right">Old Password:</td> 305 - @ <td><input type="password" name="p" size=30></td></tr> 306 - @ <tr><td align="right">New Password:</td> 307 - @ <td><input type="password" name="n1" size=30></td></tr> 308 - @ <tr><td align="right">Repeat New Password:</td> 309 - @ <td><input type="password" name="n2" size=30></td></tr> 305 + @ <tr><td class="login_out_label">Old Password:</td> 306 + @ <td><input type="password" name="p" size="30" /></td></tr> 307 + @ <tr><td class="login_out_label">New Password:</td> 308 + @ <td><input type="password" name="n1" size="30" /></td></tr> 309 + @ <tr><td class="login_out_label">Repeat New Password:</td> 310 + @ <td><input type="password" name="n2" size="30" /></td></tr> 310 311 @ <tr><td></td> 311 - @ <td><input type="submit" value="Change Password"></td></tr> 312 + @ <td><input type="submit" value="Change Password" /></td></tr> 312 313 @ </table> 313 314 @ </form> 314 315 } 315 316 style_footer(); 316 317 } 317 318 318 319 ................................................................................ 349 350 g.noPswd = 1; 350 351 strcpy(g.zCsrfToken, "localhost"); 351 352 } 352 353 353 354 /* Check the login cookie to see if it matches a known valid user. 354 355 */ 355 356 if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){ 356 - if( isdigit(zCookie[0]) ){ 357 + if( fossil_isdigit(zCookie[0]) ){ 357 358 /* Cookies of the form "uid/randomness". There must be a 358 359 ** corresponding entry in the user table. */ 359 360 uid = db_int(0, 360 361 "SELECT uid FROM user" 361 362 " WHERE uid=%d" 362 363 " AND cookie=%Q" 363 364 " AND ipaddr=%Q" ................................................................................ 592 593 */ 593 594 void login_anonymous_available(void){ 594 595 if( !g.okHistory && 595 596 db_exists("SELECT 1 FROM user" 596 597 " WHERE login='anonymous'" 597 598 " AND cap LIKE '%%h%%'") ){ 598 599 const char *zUrl = PD("REQUEST_URI", "index"); 599 - @ <p>Many <font color="red">hyperlinks are disabled.</font><br /> 600 - @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> 600 + @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br /> 601 + @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> 601 602 @ to enable hyperlinks.</p> 602 603 } 603 604 } 604 605 605 606 /* 606 607 ** While rendering a form, call this routine to add the Anti-CSRF token 607 608 ** as a hidden element of the form. 608 609 */ 609 610 void login_insert_csrf_secret(void){ 610 - @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)"> 611 + @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)" /> 611 612 } 612 613 613 614 /* 614 615 ** Before using the results of a form, first call this routine to verify 615 616 ** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token 616 617 ** is missing or is incorrect, that indicates a cross-site scripting attach 617 618 ** so emits an error message and abort.
Changes to src/main.c.
81 81 Th_Interp *interp; /* The TH1 interpreter */ 82 82 FILE *httpIn; /* Accept HTTP input from here */ 83 83 FILE *httpOut; /* Send HTTP output here */ 84 84 int xlinkClusterOnly; /* Set when cloning. Only process clusters */ 85 85 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ 86 86 int *aCommitFile; /* Array of files to be committed */ 87 87 int markPrivate; /* All new artifacts are private if true */ 88 + int clockSkewSeen; /* True if clocks on client and server out of sync */ 88 89 89 90 int urlIsFile; /* True if a "file:" url */ 90 91 int urlIsHttps; /* True if a "https:" url */ 92 + int urlIsSsh; /* True if an "ssh:" url */ 91 93 char *urlName; /* Hostname for http: or filename for file: */ 92 94 char *urlHostname; /* The HOST: parameter on http headers */ 93 95 char *urlProtocol; /* "http" or "https" */ 94 96 int urlPort; /* TCP port number for http: or https: */ 95 97 int urlDfltPort; /* The default port for the given protocol */ 96 98 char *urlPath; /* Pathname for http: */ 97 99 char *urlUser; /* User id for http: */ 98 100 char *urlPasswd; /* Password for http: */ 99 101 char *urlCanonical; /* Canonical representation of the URL */ 100 102 char *urlProxyAuth; /* Proxy-Authorizer: string */ 103 + char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */ 101 104 int dontKeepUrl; /* Do not persist the URL */ 102 105 103 106 const char *zLogin; /* Login name. "" if not logged in. */ 104 107 int noPswd; /* Logged in without password (on 127.0.0.1) */ 105 108 int userUid; /* Integer user id */ 106 109 107 110 /* Information used to populate the RCVFROM table */ ................................................................................ 218 221 /* 219 222 ** This procedure runs first. 220 223 */ 221 224 int main(int argc, char **argv){ 222 225 const char *zCmdName = "unknown"; 223 226 int idx; 224 227 int rc; 228 + int mightBeCgi; 225 229 226 230 sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0); 227 231 g.now = time(0); 228 232 g.argc = argc; 229 233 g.argv = argv; 230 - if( getenv("GATEWAY_INTERFACE")!=0 ){ 231 - zCmdName = "cgi"; 232 - }else if( argc<2 ){ 233 - fprintf(stderr, "Usage: %s COMMAND ...\n" 234 - "\"%s help\" for a list of available commands\n" 235 - "\"%s help COMMAND\" for specific details\n", 236 - argv[0], argv[0], argv[0]); 237 - fossil_exit(1); 234 + mightBeCgi = getenv("GATEWAY_INTERFACE")!=0; 235 + if( argc<2 ){ 236 + if( mightBeCgi ){ 237 + zCmdName = "cgi"; 238 + }else{ 239 + fprintf(stderr, "Usage: %s COMMAND ...\n" 240 + "\"%s help\" for a list of available commands\n" 241 + "\"%s help COMMAND\" for specific details\n", 242 + argv[0], argv[0], argv[0]); 243 + fossil_exit(1); 244 + } 238 245 }else{ 239 246 g.fQuiet = find_option("quiet", 0, 0)!=0; 240 247 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0; 241 248 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0; 242 249 g.fHttpTrace = find_option("httptrace", 0, 0)!=0; 243 250 g.zLogin = find_option("user", "U", 1); 244 251 zCmdName = argv[1]; 245 252 } 246 253 rc = name_search(zCmdName, aCommand, count(aCommand), &idx); 254 + if( rc==1 && mightBeCgi ){ 255 + rc = name_search("cgi", aCommand, count(aCommand), &idx); 256 + } 247 257 if( rc==1 ){ 248 258 fprintf(stderr,"%s: unknown command: %s\n" 249 259 "%s: use \"help\" for more information\n", 250 260 argv[0], zCmdName, argv[0]); 251 261 fossil_exit(1); 252 262 }else if( rc==2 ){ 253 263 fprintf(stderr,"%s: ambiguous command prefix: %s\n" ................................................................................ 286 296 static int once = 1; 287 297 mainInFatalError = 1; 288 298 va_start(ap, zFormat); 289 299 z = vmprintf(zFormat, ap); 290 300 va_end(ap); 291 301 if( g.cgiOutput && once ){ 292 302 once = 0; 293 - cgi_printf("<p><font color=\"red\">%h</font></p>", z); 303 + cgi_printf("<p class=\"generalError\">%h</p>", z); 294 304 cgi_reply(); 295 305 }else{ 296 306 fprintf(stderr, "%s: %s\n", g.argv[0], z); 297 307 } 298 308 db_force_rollback(); 299 309 fossil_exit(1); 300 310 } ................................................................................ 303 313 va_list ap; 304 314 mainInFatalError = 1; 305 315 va_start(ap, zFormat); 306 316 z = vmprintf(zFormat, ap); 307 317 va_end(ap); 308 318 if( g.cgiOutput ){ 309 319 g.cgiOutput = 0; 310 - cgi_printf("<p><font color=\"red\">%h</font></p>", z); 320 + cgi_printf("<p class=\"generalError\">%h</p>", z); 311 321 cgi_reply(); 312 322 }else{ 313 323 fprintf(stderr, "%s: %s\n", g.argv[0], z); 314 324 } 315 325 db_force_rollback(); 316 326 fossil_exit(1); 317 327 } ................................................................................ 331 341 if( mainInFatalError ) return; 332 342 mainInFatalError = 1; 333 343 va_start(ap, zFormat); 334 344 z = vmprintf(zFormat, ap); 335 345 va_end(ap); 336 346 if( g.cgiOutput ){ 337 347 g.cgiOutput = 0; 338 - cgi_printf("<p><font color=\"red\">%h</font></p>", z); 348 + cgi_printf("<p class=\"generalError\">%h</p>", z); 339 349 cgi_reply(); 340 350 }else{ 341 351 fprintf(stderr, "%s: %s\n", g.argv[0], z); 342 352 } 343 353 db_force_rollback(); 344 354 fossil_exit(1); 345 355 } ................................................................................ 349 359 void fossil_warning(const char *zFormat, ...){ 350 360 char *z; 351 361 va_list ap; 352 362 va_start(ap, zFormat); 353 363 z = vmprintf(zFormat, ap); 354 364 va_end(ap); 355 365 if( g.cgiOutput ){ 356 - cgi_printf("<p><font color=\"red\">%h</font></p>", z); 366 + cgi_printf("<p class=\"generalError\">%h</p>", z); 357 367 }else{ 358 368 fprintf(stderr, "%s: %s\n", g.argv[0], z); 359 369 } 360 370 } 371 + 372 +/* 373 +** Malloc and free routines that cannot fail 374 +*/ 375 +void *fossil_malloc(size_t n){ 376 + void *p = malloc(n); 377 + if( p==0 ) fossil_panic("out of memory"); 378 + return p; 379 +} 380 +void fossil_free(void *p){ 381 + free(p); 382 +} 383 +void *fossil_realloc(void *p, size_t n){ 384 + p = realloc(p, n); 385 + if( p==0 ) fossil_panic("out of memory"); 386 + return p; 387 +} 388 + 389 +/* 390 +** This function implements a cross-platform "system()" interface. 391 +*/ 392 +int fossil_system(const char *zOrigCmd){ 393 + int rc; 394 +#if defined(_WIN32) 395 + /* On windows, we have to put double-quotes around the entire command. 396 + ** Who knows why - this is just the way windows works. 397 + */ 398 + char *zNewCmd = mprintf("\"%s\"", zOrigCmd); 399 + rc = system(zNewCmd); 400 + free(zNewCmd); 401 +#else 402 + /* On unix, evaluate the command directly. 403 + */ 404 + rc = system(zOrigCmd); 405 +#endif 406 + return rc; 407 +} 408 + 409 + 361 410 362 411 /* 363 412 ** Return a name for an SQLite error code 364 413 */ 365 414 static const char *sqlite_error_code_name(int iCode){ 366 415 static char zCode[30]; 367 416 switch( iCode & 0xff ){ ................................................................................ 586 635 }else{ 587 636 putchar(*z); 588 637 z++; 589 638 } 590 639 } 591 640 putchar('\n'); 592 641 } 642 + 643 +/* 644 +** WEBPAGE: help 645 +** URL: /help?cmd=CMD 646 +*/ 647 +void help_page(void){ 648 + const char * zCmd = P("cmd"); 649 + 650 + style_header("Command line help %s%s",zCmd?" - ":"",zCmd?zCmd:""); 651 + if( zCmd ){ 652 + int rc, idx; 653 + char *z, *s, *d; 654 + 655 + @ <h1>%s(zCmd)</h1> 656 + rc = name_search(zCmd, aCommand, count(aCommand), &idx); 657 + if( rc==1 ){ 658 + @ unknown command: %s(zCmd) 659 + }else if( rc==2 ){ 660 + @ ambiguous command prefix: %s(zCmd) 661 + }else{ 662 + z = (char*)aCmdHelp[idx]; 663 + if( z==0 ){ 664 + @ no help available for the %s(aCommand[idx].zName) command 665 + }else{ 666 + z=s=d=mprintf("%s",z); 667 + while( *s ){ 668 + if( *s=='%' && strncmp(s, "%fossil", 7)==0 ){ 669 + s++; 670 + }else{ 671 + *d++ = *s++; 672 + } 673 + } 674 + *d = 0; 675 + @ <pre>%s(z)</pre> 676 + free(z); 677 + } 678 + } 679 + @ <hr/><a href="help">available commands</a> in fossil 680 + @ version %s(MANIFEST_VERSION" "MANIFEST_DATE) UTC 681 + }else{ 682 + int i; 683 + 684 + @ <h1>Available commands</h1> 685 + for(i=0; i<count(aCommand); i++){ 686 + if( strncmp(aCommand[i].zName,"test",4)==0 ) continue; 687 + @ <kbd><a href="help?cmd=%s(aCommand[i].zName)"> 688 + @ %s(aCommand[i].zName)</a></kbd> 689 + } 690 + @ <hr/>fossil version %s(MANIFEST_VERSION" "MANIFEST_DATE) UTC 691 + } 692 + style_footer(); 693 +} 593 694 594 695 /* 595 696 ** Set the g.zBaseURL value to the full URL for the toplevel of 596 697 ** the fossil tree. Set g.zTop to g.zBaseURL without the 597 698 ** leading "http://" and the host and port. 598 699 */ 599 700 void set_base_url(void){ ................................................................................ 628 729 ** zRepo might be a directory itself. In that case chroot into 629 730 ** the directory zRepo. 630 731 ** 631 732 ** Assume the user-id and group-id of the repository, or if zRepo 632 733 ** is a directory, of that directory. 633 734 */ 634 735 static char *enter_chroot_jail(char *zRepo){ 635 -#if !defined(__MINGW32__) 736 +#if !defined(_WIN32) 636 737 if( getuid()==0 ){ 637 738 int i; 638 739 struct stat sStat; 639 740 Blob dir; 640 741 char *zDir; 641 742 642 743 file_canonical_name(zRepo, &dir); ................................................................................ 700 801 while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; } 701 802 zRepo = mprintf("%s%.*s.fossil",g.zRepositoryName,i,zPathInfo); 702 803 703 804 /* To avoid mischief, make sure the repository basename contains no 704 805 ** characters other than alphanumerics, "-", and "_". 705 806 */ 706 807 for(j=strlen(g.zRepositoryName)+1, k=0; k<i-1; j++, k++){ 707 - if( !isalnum(zRepo[j]) && zRepo[j]!='-' ) zRepo[j] = '_'; 808 + if( !fossil_isalnum(zRepo[j]) && zRepo[j]!='-' ) zRepo[j] = '_'; 708 809 } 709 810 if( zRepo[0]=='/' && zRepo[1]=='/' ) zRepo++; 710 811 711 812 if( file_size(zRepo)<1024 ){ 712 813 if( zNotFound ){ 713 814 cgi_redirect(zNotFound); 714 815 }else{ ................................................................................ 806 907 if( g.argc==3 && strcmp(g.argv[1],"cgi")==0 ){ 807 908 zFile = g.argv[2]; 808 909 }else{ 809 910 zFile = g.argv[1]; 810 911 } 811 912 g.httpOut = stdout; 812 913 g.httpIn = stdin; 813 -#ifdef __MINGW32__ 914 +#if defined(_WIN32) 814 915 /* Set binary mode on windows to avoid undesired translations 815 916 ** between \n and \r\n. */ 816 917 setmode(_fileno(g.httpOut), _O_BINARY); 817 918 setmode(_fileno(g.httpIn), _O_BINARY); 818 919 #endif 819 920 #ifdef __EMX__ 820 921 /* Similar hack for OS/2 */ ................................................................................ 912 1013 ** not select a valid repository and the --notfound option is available, 913 1014 ** then the server redirects (HTTP code 302) to the URL of --notfound. 914 1015 */ 915 1016 void cmd_http(void){ 916 1017 const char *zIpAddr; 917 1018 const char *zNotFound; 918 1019 zNotFound = find_option("notfound", 0, 1); 1020 + g.cgiOutput = 1; 919 1021 if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){ 920 - cgi_panic("no repository specified"); 1022 + fossil_fatal("no repository specified"); 921 1023 } 922 - g.cgiOutput = 1; 923 1024 g.fullHttpReply = 1; 924 1025 if( g.argc==6 ){ 925 1026 g.httpIn = fopen(g.argv[3], "rb"); 926 1027 g.httpOut = fopen(g.argv[4], "wb"); 927 1028 zIpAddr = g.argv[5]; 928 1029 }else{ 929 1030 g.httpIn = stdin; ................................................................................ 933 1034 find_server_repository(0); 934 1035 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName); 935 1036 cgi_handle_http_request(zIpAddr); 936 1037 process_one_web_page(zNotFound); 937 1038 } 938 1039 939 1040 /* 1041 +** Note that the following command is used by ssh:// processing. 1042 +** 940 1043 ** COMMAND: test-http 941 1044 ** Works like the http command but gives setup permission to all users. 942 1045 */ 943 1046 void cmd_test_http(void){ 944 1047 login_set_capabilities("s"); 945 - cmd_http(); 1048 + g.httpIn = stdin; 1049 + g.httpOut = stdout; 1050 + find_server_repository(0); 1051 + g.cgiOutput = 1; 1052 + g.fullHttpReply = 1; 1053 + cgi_handle_http_request(0); 1054 + process_one_web_page(0); 946 1055 } 947 1056 948 -#ifndef __MINGW32__ 1057 +#if !defined(_WIN32) 949 1058 #if !defined(__DARWIN__) && !defined(__APPLE__) 950 1059 /* 951 1060 ** Search for an executable on the PATH environment variable. 952 1061 ** Return true (1) if found and false (0) if not found. 953 1062 */ 954 1063 static int binaryOnPath(const char *zBinary){ 955 1064 const char *zPath = getenv("PATH"); ................................................................................ 980 1089 ** Open a socket and begin listening and responding to HTTP requests on 981 1090 ** TCP port 8080, or on any other TCP port defined by the -P or 982 1091 ** --port option. The optional argument is the name of the repository. 983 1092 ** The repository argument may be omitted if the working directory is 984 1093 ** within an open checkout. 985 1094 ** 986 1095 ** The "ui" command automatically starts a web browser after initializing 987 -** the web server. 1096 +** the web server. The "ui" command also binds to 127.0.0.1 and so will 1097 +** only process HTTP traffic from the local machine. 988 1098 ** 989 1099 ** In the "server" command, the REPOSITORY can be a directory (aka folder) 990 1100 ** that contains one or more respositories with names ending in ".fossil". 991 1101 ** In that case, the first element of the URL is used to select among the 992 1102 ** various repositories. 993 1103 */ 994 1104 void cmd_webserver(void){ 995 1105 int iPort, mxPort; /* Range of TCP ports allowed */ 996 1106 const char *zPort; /* Value of the --port option */ 997 1107 char *zBrowser; /* Name of web browser program */ 998 1108 char *zBrowserCmd = 0; /* Command to launch the web browser */ 999 1109 int isUiCmd; /* True if command is "ui", not "server' */ 1000 1110 const char *zNotFound; /* The --notfound option or NULL */ 1111 + int flags = 0; /* Server flags */ 1001 1112 1002 -#ifdef __MINGW32__ 1113 +#if defined(_WIN32) 1003 1114 const char *zStopperFile; /* Name of file used to terminate server */ 1004 1115 zStopperFile = find_option("stopper", 0, 1); 1005 1116 #endif 1006 1117 1007 1118 g.thTrace = find_option("th-trace", 0, 0)!=0; 1008 1119 if( g.thTrace ){ 1009 1120 blob_zero(&g.thLog); 1010 1121 } 1011 1122 zPort = find_option("port", "P", 1); 1012 1123 zNotFound = find_option("notfound", 0, 1); 1013 1124 if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); 1014 1125 isUiCmd = g.argv[1][0]=='u'; 1126 + if( isUiCmd ) flags |= HTTP_SERVER_LOCALHOST; 1015 1127 find_server_repository(isUiCmd); 1016 1128 if( zPort ){ 1017 1129 iPort = mxPort = atoi(zPort); 1018 1130 }else{ 1019 1131 iPort = db_get_int("http-port", 8080); 1020 1132 mxPort = iPort+100; 1021 1133 } 1022 -#ifndef __MINGW32__ 1134 +#if !defined(_WIN32) 1023 1135 /* Unix implementation */ 1024 1136 if( isUiCmd ){ 1025 1137 #if !defined(__DARWIN__) && !defined(__APPLE__) 1026 1138 zBrowser = db_get("web-browser", 0); 1027 1139 if( zBrowser==0 ){ 1028 1140 static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" }; 1029 1141 int i; ................................................................................ 1037 1149 } 1038 1150 #else 1039 1151 zBrowser = db_get("web-browser", "open"); 1040 1152 #endif 1041 1153 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser); 1042 1154 } 1043 1155 db_close(); 1044 - if( cgi_http_server(iPort, mxPort, zBrowserCmd) ){ 1156 + if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){ 1045 1157 fossil_fatal("unable to listen on TCP socket %d", iPort); 1046 1158 } 1047 1159 g.httpIn = stdin; 1048 1160 g.httpOut = stdout; 1049 1161 if( g.fHttpTrace || g.fSqlTrace ){ 1050 1162 fprintf(stderr, "====== SERVER pid %d =======\n", getpid()); 1051 1163 } ................................................................................ 1057 1169 #else 1058 1170 /* Win32 implementation */ 1059 1171 if( isUiCmd ){ 1060 1172 zBrowser = db_get("web-browser", "start"); 1061 1173 zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser); 1062 1174 } 1063 1175 db_close(); 1064 - win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile, zNotFound); 1176 + win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile, zNotFound, flags); 1065 1177 #endif 1066 1178 } 1179 + 1180 +/* 1181 +** COMMAND: sqlite3 1182 +** 1183 +** Usage: %fossil sqlite3 ?DATABASE? ?OPTIONS? 1184 +** 1185 +** Run the standalone sqlite3 command-line shell on DATABASE with OPTIONS. 1186 +** If DATABASE is omitted, then the repository that serves the working 1187 +** directory is opened. 1188 +** 1189 +** WARNING: Careless use of this command can corrupt a Fossil repository 1190 +** in ways that are unrecoverable. Be sure you know what you are doing before 1191 +** running any SQL commands that modifies the repository database. 1192 +*/ 1193 +void sqlite3_cmd(void){ 1194 + extern int sqlite3_shell(int, char**); 1195 + sqlite3_shell(g.argc-1, g.argv+1); 1196 +} 1197 + 1198 +/* 1199 +** This routine is called by the patched sqlite3 command-line shell in order 1200 +** to load the name and database connection for the open Fossil database. 1201 +*/ 1202 +void fossil_open(sqlite3 **pDb, const char **pzRepoName){ 1203 + db_must_be_within_tree(); 1204 + *pDb = 0; 1205 + *pzRepoName = g.zRepositoryName; 1206 +}
Changes to src/main.mk.
33 33 $(SRCDIR)/delta.c \ 34 34 $(SRCDIR)/deltacmd.c \ 35 35 $(SRCDIR)/descendants.c \ 36 36 $(SRCDIR)/diff.c \ 37 37 $(SRCDIR)/diffcmd.c \ 38 38 $(SRCDIR)/doc.c \ 39 39 $(SRCDIR)/encode.c \ 40 + $(SRCDIR)/event.c \ 40 41 $(SRCDIR)/file.c \ 41 42 $(SRCDIR)/finfo.c \ 42 43 $(SRCDIR)/graph.c \ 43 44 $(SRCDIR)/http.c \ 44 45 $(SRCDIR)/http_socket.c \ 45 46 $(SRCDIR)/http_ssl.c \ 46 47 $(SRCDIR)/http_transport.c \ ................................................................................ 49 50 $(SRCDIR)/main.c \ 50 51 $(SRCDIR)/manifest.c \ 51 52 $(SRCDIR)/md5.c \ 52 53 $(SRCDIR)/merge.c \ 53 54 $(SRCDIR)/merge3.c \ 54 55 $(SRCDIR)/name.c \ 55 56 $(SRCDIR)/pivot.c \ 57 + $(SRCDIR)/popen.c \ 56 58 $(SRCDIR)/pqueue.c \ 57 59 $(SRCDIR)/printf.c \ 58 60 $(SRCDIR)/rebuild.c \ 59 61 $(SRCDIR)/report.c \ 60 62 $(SRCDIR)/rss.c \ 61 63 $(SRCDIR)/schema.c \ 62 64 $(SRCDIR)/search.c \ ................................................................................ 105 107 delta_.c \ 106 108 deltacmd_.c \ 107 109 descendants_.c \ 108 110 diff_.c \ 109 111 diffcmd_.c \ 110 112 doc_.c \ 111 113 encode_.c \ 114 + event_.c \ 112 115 file_.c \ 113 116 finfo_.c \ 114 117 graph_.c \ 115 118 http_.c \ 116 119 http_socket_.c \ 117 120 http_ssl_.c \ 118 121 http_transport_.c \ ................................................................................ 121 124 main_.c \ 122 125 manifest_.c \ 123 126 md5_.c \ 124 127 merge_.c \ 125 128 merge3_.c \ 126 129 name_.c \ 127 130 pivot_.c \ 131 + popen_.c \ 128 132 pqueue_.c \ 129 133 printf_.c \ 130 134 rebuild_.c \ 131 135 report_.c \ 132 136 rss_.c \ 133 137 schema_.c \ 134 138 search_.c \ ................................................................................ 177 181 $(OBJDIR)/delta.o \ 178 182 $(OBJDIR)/deltacmd.o \ 179 183 $(OBJDIR)/descendants.o \ 180 184 $(OBJDIR)/diff.o \ 181 185 $(OBJDIR)/diffcmd.o \ 182 186 $(OBJDIR)/doc.o \ 183 187 $(OBJDIR)/encode.o \ 188 + $(OBJDIR)/event.o \ 184 189 $(OBJDIR)/file.o \ 185 190 $(OBJDIR)/finfo.o \ 186 191 $(OBJDIR)/graph.o \ 187 192 $(OBJDIR)/http.o \ 188 193 $(OBJDIR)/http_socket.o \ 189 194 $(OBJDIR)/http_ssl.o \ 190 195 $(OBJDIR)/http_transport.o \ ................................................................................ 193 198 $(OBJDIR)/main.o \ 194 199 $(OBJDIR)/manifest.o \ 195 200 $(OBJDIR)/md5.o \ 196 201 $(OBJDIR)/merge.o \ 197 202 $(OBJDIR)/merge3.o \ 198 203 $(OBJDIR)/name.o \ 199 204 $(OBJDIR)/pivot.o \ 205 + $(OBJDIR)/popen.o \ 200 206 $(OBJDIR)/pqueue.o \ 201 207 $(OBJDIR)/printf.o \ 202 208 $(OBJDIR)/rebuild.o \ 203 209 $(OBJDIR)/report.o \ 204 210 $(OBJDIR)/rss.o \ 205 211 $(OBJDIR)/schema.o \ 206 212 $(OBJDIR)/search.o \ ................................................................................ 256 262 $(TCLSH) test/tester.tcl $(APPNAME) 257 263 258 264 VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest 259 265 awk '{ printf "#define MANIFEST_UUID \"%s\"\n", $$1}' $(SRCDIR)/../manifest.uuid >VERSION.h 260 266 awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' $(SRCDIR)/../manifest.uuid >>VERSION.h 261 267 awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n", substr($$2,1,10),substr($$2,12)}' $(SRCDIR)/../manifest >>VERSION.h 262 268 263 -$(APPNAME): headers $(OBJ) $(OBJDIR)/sqlite3.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o 264 - $(TCC) -o $(APPNAME) $(OBJ) $(OBJDIR)/sqlite3.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o $(LIB) 269 +EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o 270 + 271 +$(APPNAME): headers $(OBJ) $(EXTRAOBJ) 272 + $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) 265 273 266 274 # This rule prevents make from using its default rules to try build 267 275 # an executable named "manifest" out of the file named "manifest.c" 268 276 # 269 277 $(SRCDIR)/../manifest: 270 278 # noop 271 279 272 280 clean: 273 281 rm -f $(OBJDIR)/*.o *_.c $(APPNAME) VERSION.h 274 282 rm -f translate makeheaders mkindex page_index.h headers 275 - rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h 283 + rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h event.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h 276 284 277 285 page_index.h: $(TRANS_SRC) mkindex 278 286 ./mkindex $(TRANS_SRC) >$@ 279 287 headers: page_index.h makeheaders VERSION.h 280 - ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h 288 + ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h 281 289 touch headers 282 290 headers: Makefile 283 291 Makefile: 284 292 add_.c: $(SRCDIR)/add.c translate 285 293 ./translate $(SRCDIR)/add.c >add_.c 286 294 287 295 $(OBJDIR)/add.o: add_.c add.h $(SRCDIR)/config.h ................................................................................ 445 453 encode_.c: $(SRCDIR)/encode.c translate 446 454 ./translate $(SRCDIR)/encode.c >encode_.c 447 455 448 456 $(OBJDIR)/encode.o: encode_.c encode.h $(SRCDIR)/config.h 449 457 $(XTCC) -o $(OBJDIR)/encode.o -c encode_.c 450 458 451 459 encode.h: headers 460 +event_.c: $(SRCDIR)/event.c translate 461 + ./translate $(SRCDIR)/event.c >event_.c 462 + 463 +$(OBJDIR)/event.o: event_.c event.h $(SRCDIR)/config.h 464 + $(XTCC) -o $(OBJDIR)/event.o -c event_.c 465 + 466 +event.h: headers 452 467 file_.c: $(SRCDIR)/file.c translate 453 468 ./translate $(SRCDIR)/file.c >file_.c 454 469 455 470 $(OBJDIR)/file.o: file_.c file.h $(SRCDIR)/config.h 456 471 $(XTCC) -o $(OBJDIR)/file.o -c file_.c 457 472 458 473 file.h: headers ................................................................................ 557 572 pivot_.c: $(SRCDIR)/pivot.c translate 558 573 ./translate $(SRCDIR)/pivot.c >pivot_.c 559 574 560 575 $(OBJDIR)/pivot.o: pivot_.c pivot.h $(SRCDIR)/config.h 561 576 $(XTCC) -o $(OBJDIR)/pivot.o -c pivot_.c 562 577 563 578 pivot.h: headers 579 +popen_.c: $(SRCDIR)/popen.c translate 580 + ./translate $(SRCDIR)/popen.c >popen_.c 581 + 582 +$(OBJDIR)/popen.o: popen_.c popen.h $(SRCDIR)/config.h 583 + $(XTCC) -o $(OBJDIR)/popen.o -c popen_.c 584 + 585 +popen.h: headers 564 586 pqueue_.c: $(SRCDIR)/pqueue.c translate 565 587 ./translate $(SRCDIR)/pqueue.c >pqueue_.c 566 588 567 589 $(OBJDIR)/pqueue.o: pqueue_.c pqueue.h $(SRCDIR)/config.h 568 590 $(XTCC) -o $(OBJDIR)/pqueue.o -c pqueue_.c 569 591 570 592 pqueue.h: headers ................................................................................ 770 792 $(OBJDIR)/zip.o: zip_.c zip.h $(SRCDIR)/config.h 771 793 $(XTCC) -o $(OBJDIR)/zip.o -c zip_.c 772 794 773 795 zip.h: headers 774 796 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c 775 797 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o 776 798 799 +$(OBJDIR)/shell.o: $(SRCDIR)/shell.c 800 + $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o 801 + 777 802 $(OBJDIR)/th.o: $(SRCDIR)/th.c 778 803 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o 779 804 780 805 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c 781 806 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o 782 807
Changes to src/makeheaders.c.
11 11 */ 12 12 #include <stdio.h> 13 13 #include <stdlib.h> 14 14 #include <ctype.h> 15 15 #include <memory.h> 16 16 #include <sys/stat.h> 17 17 #include <assert.h> 18 -#ifndef WIN32 19 -# include <unistd.h> 20 -#else 18 +#if defined( __MINGW32__) || defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__) 19 +# ifndef WIN32 20 +# define WIN32 21 +# endif 21 22 # include <string.h> 23 +#else 24 +# include <unistd.h> 22 25 #endif 23 26 24 27 /* 25 28 ** Macros for debugging. 26 29 */ 27 30 #ifdef DEBUG 28 31 static int debugMask = 0; ................................................................................ 2139 2142 ** and EXPORT_INTERFACE and LOCAL_INTERFACE 2140 2143 */ 2141 2144 zArg = &zCmd[2]; 2142 2145 while( *zArg && isspace(*zArg) && *zArg!='\n' ){ 2143 2146 zArg++; 2144 2147 } 2145 2148 if( *zArg==0 || *zArg=='\n' ){ return 0; } 2146 - nArg = pToken->nText + (int)pToken->zText - (int)zArg; 2149 + nArg = pToken->nText + (int)(pToken->zText - zArg); 2147 2150 if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){ 2148 2151 PushIfMacro(0,0,0,pToken->nLine,PS_Interface); 2149 2152 }else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){ 2150 2153 PushIfMacro(0,0,0,pToken->nLine,PS_Export); 2151 2154 }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){ 2152 2155 PushIfMacro(0,0,0,pToken->nLine,PS_Local); 2153 2156 }else{ ................................................................................ 2158 2161 ** Push an #ifdef. 2159 2162 */ 2160 2163 zArg = &zCmd[5]; 2161 2164 while( *zArg && isspace(*zArg) && *zArg!='\n' ){ 2162 2165 zArg++; 2163 2166 } 2164 2167 if( *zArg==0 || *zArg=='\n' ){ return 0; } 2165 - nArg = pToken->nText + (int)pToken->zText - (int)zArg; 2168 + nArg = pToken->nText + (int)(pToken->zText - zArg); 2166 2169 PushIfMacro("defined",zArg,nArg,pToken->nLine,0); 2167 2170 }else if( nCmd==6 && strncmp(zCmd,"ifndef",6)==0 ){ 2168 2171 /* 2169 2172 ** Push an #ifndef. 2170 2173 */ 2171 2174 zArg = &zCmd[6]; 2172 2175 while( *zArg && isspace(*zArg) && *zArg!='\n' ){ 2173 2176 zArg++; 2174 2177 } 2175 2178 if( *zArg==0 || *zArg=='\n' ){ return 0; } 2176 - nArg = pToken->nText + (int)pToken->zText - (int)zArg; 2179 + nArg = pToken->nText + (int)(pToken->zText - zArg); 2177 2180 PushIfMacro("!defined",zArg,nArg,pToken->nLine,0); 2178 2181 }else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){ 2179 2182 /* 2180 2183 ** Invert the #if on the top of the stack 2181 2184 */ 2182 2185 if( ifStack==0 ){ 2183 2186 fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename, ................................................................................ 2795 2798 nErr++; 2796 2799 } 2797 2800 }else if( strncmp(zOldVersion,zTopLine,nTopLine)!=0 ){ 2798 2801 if( report ) fprintf(report,"error!\n"); 2799 2802 fprintf(stderr, 2800 2803 "%s: Can't overwrite this file because it wasn't previously\n" 2801 2804 "%*s generated by 'makeheaders'.\n", 2802 - pFile->zHdr, strlen(pFile->zHdr), ""); 2805 + pFile->zHdr, (int)strlen(pFile->zHdr), ""); 2803 2806 nErr++; 2804 2807 }else if( strcmp(zOldVersion,zNewVersion)!=0 ){ 2805 2808 if( report ) fprintf(report,"updated\n"); 2806 2809 if( WriteFile(pFile->zHdr,zNewVersion) ){ 2807 2810 fprintf(stderr,"%s: Can't write to file\n",pFile->zHdr); 2808 2811 nErr++; 2809 2812 } ................................................................................ 2950 2953 } 2951 2954 } 2952 2955 if( nLabel==0 ) continue; 2953 2956 zLabel[nLabel] = 0; 2954 2957 InsertExtraDecl(pDecl); 2955 2958 zDecl = pDecl->zDecl; 2956 2959 if( zDecl==0 ) zDecl = pDecl->zFwd; 2957 - printf("%s %s %s %d %d %d %d %d %d\n", 2960 + printf("%s %s %s %p %d %d %d %d %d\n", 2958 2961 pDecl->zName, 2959 2962 zLabel, 2960 2963 pDecl->zFile, 2961 - pDecl->pComment ? (int)pDecl->pComment/sizeof(Token) : 0, 2964 + pDecl->pComment, 2962 2965 pDecl->pComment ? pDecl->pComment->nText+1 : 0, 2963 - pDecl->zIf ? strlen(pDecl->zIf)+1 : 0, 2964 - zDecl ? strlen(zDecl) : 0, 2966 + pDecl->zIf ? (int)strlen(pDecl->zIf)+1 : 0, 2967 + zDecl ? (int)strlen(zDecl) : 0, 2965 2968 pDecl->pComment ? pDecl->pComment->nLine : 0, 2966 2969 pDecl->tokenCode.nText ? pDecl->tokenCode.nText+1 : 0 2967 2970 ); 2968 2971 if( pDecl->pComment ){ 2969 2972 printf("%.*s\n",pDecl->pComment->nText, pDecl->pComment->zText); 2970 2973 } 2971 2974 if( pDecl->zIf ){
Changes to src/makemake.tcl.
27 27 delta 28 28 deltacmd 29 29 descendants 30 30 diff 31 31 diffcmd 32 32 doc 33 33 encode 34 + event 34 35 file 35 36 finfo 36 37 graph 37 38 http 38 39 http_socket 39 40 http_transport 40 41 info ................................................................................ 42 43 main 43 44 manifest 44 45 md5 45 46 merge 46 47 merge3 47 48 name 48 49 pivot 50 + popen 49 51 pqueue 50 52 printf 51 53 rebuild 52 54 report 53 55 rss 54 56 schema 55 57 search ................................................................................ 78 80 zip 79 81 http_ssl 80 82 } 81 83 82 84 # Name of the final application 83 85 # 84 86 set name fossil 85 - 87 +if { 0 == $argc } { 86 88 puts {# DO NOT EDIT 87 89 # 88 90 # This file is automatically generated. Instead of editing this 89 91 # file, edit "makemake.tcl" then run "tclsh makemake.tcl >main.mk" 90 92 # to regenerate this file. 91 93 # 92 94 # This file is included by linux-gcc.mk or linux-mingw.mk or possible ................................................................................ 144 146 $(SRCDIR)/../manifest.uuid >VERSION.h 145 147 awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' \ 146 148 $(SRCDIR)/../manifest.uuid >>VERSION.h 147 149 awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n",\ 148 150 substr($$2,1,10),substr($$2,12)}' \ 149 151 $(SRCDIR)/../manifest >>VERSION.h 150 152 151 -$(APPNAME): headers $(OBJ) $(OBJDIR)/sqlite3.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o 152 - $(TCC) -o $(APPNAME) $(OBJ) $(OBJDIR)/sqlite3.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o $(LIB) 153 +EXTRAOBJ = \ 154 + $(OBJDIR)/sqlite3.o \ 155 + $(OBJDIR)/shell.o \ 156 + $(OBJDIR)/th.o \ 157 + $(OBJDIR)/th_lang.o 158 + 159 +$(APPNAME): headers $(OBJ) $(EXTRAOBJ) 160 + $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) 153 161 154 162 # This rule prevents make from using its default rules to try build 155 163 # an executable named "manifest" out of the file named "manifest.c" 156 164 # 157 165 $(SRCDIR)/../manifest: 158 166 # noop 159 167 ................................................................................ 197 205 set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1} 198 206 append opt " -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4" 199 207 #append opt " -DSQLITE_ENABLE_FTS3=1" 200 208 append opt " -Dlocaltime=fossil_localtime" 201 209 append opt " -DSQLITE_ENABLE_LOCKING_STYLE=0" 202 210 puts "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n" 203 211 212 +puts "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c" 213 +set opt {-Dmain=sqlite3_shell} 214 +append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1" 215 +puts "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n" 216 + 204 217 puts "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c" 205 218 puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n" 206 219 207 220 puts "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c" 208 221 puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n" 222 +exit 223 +} 224 +if { "dmc" == [lindex $argv 0] } { 225 + 226 +puts {# DO NOT EDIT 227 +# 228 +# This file is automatically generated. Instead of editing this 229 +# file, edit "makemake.tcl" then run 230 +# "tclsh src/makemake.tcl dmc > win/Makefile.dmc" 231 +# to regenerate this file. 232 +B = .. 233 +SRCDIR = $B\src 234 +OBJDIR = . 235 +O = .obj 236 +E = .exe 237 + 238 + 239 +# Maybe DMDIR, SSL or INCL needs adjustment 240 +DMDIR = c:\DM 241 +INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(DMDIR)\extra\include 242 + 243 +#SSL = -DFOSSIL_ENABLE_SSL=1 244 +SSL = 245 + 246 +DMCDEF = -Dstrncasecmp=memicmp -Dstrcasecmp=stricmp 247 +I18N = -DFOSSIL_I18N=0 248 + 249 +CFLAGS = -o 250 +BCC = $(DMDIR)\bin\dmc $(CFLAGS) 251 +TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL) 252 +LIBS = $(DMDIR)\extra\lib\ zlib wsock32 253 +} 254 +puts -nonewline "SRC = " 255 +foreach s [lsort $src] { 256 + puts -nonewline "${s}_.c " 257 +} 258 +puts "\n" 259 +puts -nonewline "OBJ = " 260 +foreach s [lsort $src] { 261 + puts -nonewline "\$(OBJDIR)\\$s\$O " 262 +} 263 +puts "\$(OBJDIR)\\sqlite3\$O \$(OBJDIR)\\th\$O \$(OBJDIR)\\th_lang\$O " 264 +puts { 265 + 266 +APPNAME = $(OBJDIR)\fossil$(E) 267 + 268 +all: $(APPNAME) 269 + 270 +$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OBJDIR)\link 271 + cd $(OBJDIR) 272 + $(DMDIR)\bin\link @link 273 + 274 +$(OBJDIR)\link: $B\win\Makefile.dmc} 275 +puts -nonewline "\t+echo " 276 +foreach s [lsort $src] { 277 + puts -nonewline "$s " 278 +} 279 +puts "sqlite3 th th_lang > \$@" 280 +puts "\t+echo fossil >> \$@" 281 +puts "\t+echo fossil >> \$@" 282 +puts "\t+echo \$(LIBS) >> \$@\n\n" 283 + 284 +puts { 285 +translate$E: $(SRCDIR)\translate.c 286 + $(BCC) -o$@ $** 287 + 288 +makeheaders$E: $(SRCDIR)\makeheaders.c 289 + $(BCC) -o$@ $** 290 + 291 +mkindex$E: $(SRCDIR)\mkindex.c 292 + $(BCC) -o$@ $** 293 + 294 +version$E: $B\win\version.c 295 + $(BCC) -o$@ $** 296 + 297 +$(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c 298 + $(TCC) -o$@ -c -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 $** 299 + 300 +$(OBJDIR)\th$O : $(SRCDIR)\th.c 301 + $(TCC) -o$@ -c $** 302 + 303 +$(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c 304 + $(TCC) -o$@ -c $** 305 + 306 +VERSION.h : version$E $B\manifest.uuid $B\manifest 307 + +$** > $@ 308 + 309 +page_index.h: mkindex$E $(SRC) 310 + +$** > $@ 311 + 312 +clean: 313 + -del $(OBJDIR)\*.obj 314 + -del *.obj *_.c *.h *.map 315 + 316 +realclean: 317 + -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E 318 + 319 +} 320 +foreach s [lsort $src] { 321 + puts "\$(OBJDIR)\\$s\$O : ${s}_.c ${s}.h" 322 + puts "\t\$(TCC) -o\$@ -c ${s}_.c\n" 323 + puts "${s}_.c : \$(SRCDIR)\\$s.c" 324 + puts "\t+translate\$E \$** > \$@\n" 325 +} 326 + 327 +puts -nonewline "headers: makeheaders\$E page_index.h VERSION.h\n\t +makeheaders\$E " 328 +foreach s [lsort $src] { 329 + puts -nonewline "${s}_.c:$s.h " 330 +} 331 +puts "\$(SRCDIR)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h" 332 +puts "\t@copy /Y nul: headers" 333 +exit 334 +} 335 + 336 +if { "msc" == [lindex $argv 0] } { 337 + 338 +puts {# DO NOT EDIT 339 +# 340 +# This file is automatically generated. Instead of editing this 341 +# file, edit "makemake.tcl" then run 342 +# "tclsh src/makemake.tcl msc > win/Makefile.msc" 343 +# to regenerate this file. 344 +B = .. 345 +SRCDIR = $B\src 346 +OBJDIR = . 347 +O = .obj 348 +E = .exe 349 + 350 +# Maybe MSCDIR, SSL, ZLIB, or INCL needs adjustment 351 +MSCDIR = c:\msc 352 + 353 +# Uncomment below for SSL support 354 +SSL = 355 +SSLLIB = 356 +#SSL = -DFOSSIL_ENABLE_SSL=1 357 +#SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib advapi32.lib 358 + 359 +# zlib options 360 +# When using precompiled from http://zlib.net/zlib125-dll.zip 361 +#ZINCDIR = C:\zlib125-dll\include 362 +#ZLIBDIR = C:\zlib125-dll\lib 363 +#ZLIB = zdll.lib 364 +ZINCDIR = $(MSCDIR)\extra\include 365 +ZLIBDIR = $(MSCDIR)\extra\lib 366 +ZLIB = zlib.lib 367 + 368 +INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR) 369 + 370 +MSCDEF = -Dstrncasecmp=memicmp -Dstrcasecmp=stricmp 371 +I18N = -DFOSSIL_I18N=0 372 + 373 +CFLAGS = -nologo -MT -O2 374 +BCC = $(CC) $(CFLAGS) 375 +TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(I18N) $(SSL) $(INCL) 376 +LIBS = $(ZLIB) ws2_32.lib $(SSLLIB) 377 +LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR) 378 +} 379 +puts -nonewline "SRC = " 380 +foreach s [lsort $src] { 381 + puts -nonewline "${s}_.c " 382 +} 383 +puts "\n" 384 +puts -nonewline "OBJ = " 385 +foreach s [lsort $src] { 386 + puts -nonewline "\$(OBJDIR)\\$s\$O " 387 +} 388 +puts "\$(OBJDIR)\\sqlite3\$O \$(OBJDIR)\\th\$O \$(OBJDIR)\\th_lang\$O " 389 +puts { 390 + 391 +APPNAME = $(OBJDIR)\fossil$(E) 392 + 393 +all: $(OBJDIR) $(APPNAME) 394 + 395 +$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OBJDIR)\linkopts 396 + cd $(OBJDIR) 397 + link -LINK -OUT:$@ $(LIBDIR) @linkopts 398 + 399 +$(OBJDIR)\linkopts: $B\win\Makefile.msc} 400 +puts -nonewline "\techo " 401 +foreach s [lsort $src] { 402 + puts -nonewline "$s " 403 +} 404 +puts "sqlite3 th th_lang > \$@" 405 +puts "\techo \$(LIBS) >> \$@\n\n" 406 + 407 +puts { 408 + 409 +$(OBJDIR): 410 + @-mkdir $@ 411 + 412 +translate$E: $(SRCDIR)\translate.c 413 + $(BCC) $** 414 + 415 +makeheaders$E: $(SRCDIR)\makeheaders.c 416 + $(BCC) $** 417 + 418 +mkindex$E: $(SRCDIR)\mkindex.c 419 + $(BCC) $** 420 + 421 +version$E: $B\win\version.c 422 + $(BCC) $** 423 + 424 +$(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c 425 + $(TCC) /Fo$@ -c -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 $** 426 + 427 +$(OBJDIR)\th$O : $(SRCDIR)\th.c 428 + $(TCC) /Fo$@ -c $** 429 + 430 +$(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c 431 + $(TCC) /Fo$@ -c $** 432 + 433 +VERSION.h : version$E $B\manifest.uuid $B\manifest 434 + $** > $@ 435 + 436 +page_index.h: mkindex$E $(SRC) 437 + $** > $@ 438 + 439 +clean: 440 + -del $(OBJDIR)\*.obj 441 + -del *.obj *_.c *.h *.map 442 + -del headers linkopts 443 + 444 +realclean: 445 + -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E 446 + 447 +} 448 +foreach s [lsort $src] { 449 + puts "\$(OBJDIR)\\$s\$O : ${s}_.c ${s}.h" 450 + puts "\t\$(TCC) /Fo\$@ -c ${s}_.c\n" 451 + puts "${s}_.c : \$(SRCDIR)\\$s.c" 452 + puts "\ttranslate\$E \$** > \$@\n" 453 +} 454 + 455 +puts -nonewline "headers: makeheaders\$E page_index.h VERSION.h\n\tmakeheaders\$E " 456 +foreach s [lsort $src] { 457 + puts -nonewline "${s}_.c:$s.h " 458 +} 459 +puts "\$(SRCDIR)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h" 460 +puts "\t@copy /Y nul: headers" 461 + 462 +}
Added src/makeskins.c.
1 +/* 2 +** Copyright (c) 2010 Michael T. Richter, assigned to the Fossil SCM project. 3 +** 4 +** This program is free software; you can redistribute it and/or 5 +** modify it under the terms of the Simplified BSD License (also 6 +** known as the "2-Clause License" or "FreeBSD License".) 7 +** 8 +** This program is distributed in the hope that it will be useful, 9 +** but without any warranty; without even the implied warranty of 10 +** merchantability or fitness for a particular purpose. 11 +** 12 +** Author contact information: 13 +** ttmrichter@gmail.com 14 +** 15 +******************************************************************************* 16 +** 17 +** This utility is a preprocessor that takes raw CSS and HTML files, along with 18 +** plain text descriptions, and generates the skins.c file that is used to embed 19 +** the distributed default skins into Fossil. 20 +** 21 +** The intent of the utility is to make adding new skins to a Fossil build 22 +** easier without involving error-prone C programming. 23 +** 24 +** This utility must be run BEFORE the translate program is executed on the C 25 +** source files. (This is in retrospect obvious since it generates one of the 26 +** said C files.) 27 +*/ 28 +#include <stdio.h> 29 +#include <ctype.h> 30 +#include <stdlib.h> 31 +#include <string.h> 32 + 33 +int main(int argc, char **argv){ 34 + if( argc==3 ){ 35 + /* 36 + ** 1. Validate the arguments: <skins> and <src> directory. 37 + ** 2. Open the <src>/skins.c file. 38 + ** 3. Write the initial boilerplate. 39 + ** 4. Walk the directory structure of <skins>. 40 + ** 5. For each one: 41 + ** a) Store the title and author information. (info.txt) 42 + ** b) Write out the description as a comment. (info.txt) 43 + ** c) Write out the CSS information. (style.css) 44 + ** d) Write out the header information. (header.html) 45 + ** e) Write out the footer information. (footer.html) 46 + ** 6. Write out the built-in skins table. 47 + ** 7. Write the trailing boilerplate. 48 + */ 49 + }else{ 50 + /* error -- need a pair of directories */ 51 + } 52 + return 0; 53 +}
Changes to src/manifest.c.
24 24 #include "manifest.h" 25 25 #include <assert.h> 26 26 27 27 #if INTERFACE 28 28 /* 29 29 ** Types of control files 30 30 */ 31 +#define CFTYPE_ANY 0 31 32 #define CFTYPE_MANIFEST 1 32 33 #define CFTYPE_CLUSTER 2 33 34 #define CFTYPE_CONTROL 3 34 35 #define CFTYPE_WIKI 4 35 36 #define CFTYPE_TICKET 5 36 37 #define CFTYPE_ATTACHMENT 6 38 +#define CFTYPE_EVENT 7 39 + 40 +/* 41 +** A single F-card within a manifest 42 +*/ 43 +struct ManifestFile { 44 + char *zName; /* Name of a file */ 45 + char *zUuid; /* UUID of the file */ 46 + char *zPerm; /* File permissions */ 47 + char *zPrior; /* Prior name if the name was changed */ 48 +}; 49 + 37 50 38 51 /* 39 52 ** A parsed manifest or cluster. 40 53 */ 41 54 struct Manifest { 42 55 Blob content; /* The original content blob */ 43 56 int type; /* Type of artifact. One of CFTYPE_xxxxx */ 57 + int rid; /* The blob-id for this manifest */ 58 + char *zBaseline; /* Baseline manifest. The B card. */ 59 + Manifest *pBaseline; /* The actual baseline manifest */ 44 60 char *zComment; /* Decoded comment. The C card. */ 45 61 double rDate; /* Date and time from D card. 0.0 if no D card. */ 46 62 char *zUser; /* Name of the user from the U card. */ 47 63 char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ 48 64 char *zWiki; /* Text of the wiki page. W card. */ 49 65 char *zWikiTitle; /* Name of the wiki page. L card. */ 66 + double rEventDate; /* Date of an event. E card. */ 67 + char *zEventId; /* UUID for an event. E card. */ 50 68 char *zTicketUuid; /* UUID for a ticket. K card. */ 51 69 char *zAttachName; /* Filename of an attachment. A card. */ 52 70 char *zAttachSrc; /* UUID of document being attached. A card. */ 53 71 char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ 54 72 int nFile; /* Number of F cards */ 55 73 int nFileAlloc; /* Slots allocated in aFile[] */ 56 - struct { 57 - char *zName; /* Name of a file */ 58 - char *zUuid; /* UUID of the file */ 59 - char *zPerm; /* File permissions */ 60 - char *zPrior; /* Prior name if the name was changed */ 61 - int iRename; /* index of renamed name in prior/next manifest */ 62 - } *aFile; /* One entry for each F card */ 74 + int iFile; /* Index of current file in iterator */ 75 + ManifestFile *aFile; /* One entry for each F-card */ 63 76 int nParent; /* Number of parents. */ 64 77 int nParentAlloc; /* Slots allocated in azParent[] */ 65 78 char **azParent; /* UUIDs of parents. One for each P card argument */ 66 79 int nCChild; /* Number of cluster children */ 67 80 int nCChildAlloc; /* Number of closts allocated in azCChild[] */ 68 81 char **azCChild; /* UUIDs of referenced objects in a cluster. M cards */ 69 82 int nTag; /* Number of T Cards */ ................................................................................ 78 91 struct { 79 92 char *zName; /* Key or field name */ 80 93 char *zValue; /* Value of the field */ 81 94 } *aField; /* One for each J card */ 82 95 }; 83 96 #endif 84 97 98 +/* 99 +** A cache of parsed manifests. This reduces the number of 100 +** calls to manifest_parse() when doing a rebuild. 101 +*/ 102 +#define MX_MANIFEST_CACHE 6 103 +static struct { 104 + int nxAge; 105 + int aAge[MX_MANIFEST_CACHE]; 106 + Manifest *apManifest[MX_MANIFEST_CACHE]; 107 +} manifestCache; 108 + 85 109 86 110 /* 87 111 ** Clear the memory allocated in a manifest object 88 112 */ 89 -void manifest_clear(Manifest *p){ 90 - blob_reset(&p->content); 91 - free(p->aFile); 92 - free(p->azParent); 93 - free(p->azCChild); 94 - free(p->aTag); 95 - free(p->aField); 96 - memset(p, 0, sizeof(*p)); 113 +void manifest_destroy(Manifest *p){ 114 + if( p ){ 115 + blob_reset(&p->content); 116 + free(p->aFile); 117 + free(p->azParent); 118 + free(p->azCChild); 119 + free(p->aTag); 120 + free(p->aField); 121 + if( p->pBaseline ) manifest_destroy(p->pBaseline); 122 + fossil_free(p); 123 + } 124 +} 125 + 126 +/* 127 +** Add an element to the manifest cache using LRU replacement. 128 +*/ 129 +void manifest_cache_insert(Manifest *p){ 130 + while( p ){ 131 + int i; 132 + Manifest *pBaseline = p->pBaseline; 133 + p->pBaseline = 0; 134 + for(i=0; i<MX_MANIFEST_CACHE; i++){ 135 + if( manifestCache.apManifest[i]==0 ) break; 136 + } 137 + if( i>=MX_MANIFEST_CACHE ){ 138 + int oldest = 0; 139 + int oldestAge = manifestCache.aAge[0]; 140 + for(i=1; i<MX_MANIFEST_CACHE; i++){ 141 + if( manifestCache.aAge[i]<oldestAge ){ 142 + oldest = i; 143 + oldestAge = manifestCache.aAge[i]; 144 + } 145 + } 146 + manifest_destroy(manifestCache.apManifest[oldest]); 147 + i = oldest; 148 + } 149 + manifestCache.aAge[i] = ++manifestCache.nxAge; 150 + manifestCache.apManifest[i] = p; 151 + p = pBaseline; 152 + } 153 +} 154 + 155 +/* 156 +** Try to extract a line from the manifest cache. Return 1 if found. 157 +** Return 0 if not found. 158 +*/ 159 +static Manifest *manifest_cache_find(int rid){ 160 + int i; 161 + Manifest *p; 162 + for(i=0; i<MX_MANIFEST_CACHE; i++){ 163 + if( manifestCache.apManifest[i] && manifestCache.apManifest[i]->rid==rid ){ 164 + p = manifestCache.apManifest[i]; 165 + manifestCache.apManifest[i] = 0; 166 + return p; 167 + } 168 + } 169 + return 0; 170 +} 171 + 172 +/* 173 +** Clear the manifest cache. 174 +*/ 175 +void manifest_cache_clear(void){ 176 + int i; 177 + for(i=0; i<MX_MANIFEST_CACHE; i++){ 178 + if( manifestCache.apManifest[i] ){ 179 + manifest_destroy(manifestCache.apManifest[i]); 180 + } 181 + } 182 + memset(&manifestCache, 0, sizeof(manifestCache)); 183 +} 184 + 185 +#ifdef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM 186 +# define md5sum_init(X) 187 +# define md5sum_step_text(X,Y) 188 +#endif 189 + 190 +/* 191 +** Remove the PGP signature from the artifact, if there is one. 192 +*/ 193 +static void remove_pgp_signature(char **pz, int *pn){ 194 + char *z = *pz; 195 + int n = *pn; 196 + int i; 197 + if( memcmp(z, "-----BEGIN PGP SIGNED MESSAGE-----", 34)!=0 ) return; 198 + for(i=34; i<n && (z[i-1]!='\n' || z[i-2]!='\n'); i++){} 199 + if( i>=n ) return; 200 + z += i; 201 + n -= i; 202 + *pz = z; 203 + for(i=n-1; i>=0; i--){ 204 + if( z[i]=='\n' && memcmp(&z[i],"\n-----BEGIN PGP SIGNATURE-", 25)==0 ){ 205 + n = i+1; 206 + break; 207 + } 208 + } 209 + *pn = n; 210 + return; 211 +} 212 + 213 +/* 214 +** Verify the Z-card checksum on the artifact, if there is such a 215 +** checksum. Return 0 if there is no Z-card. Return 1 if the Z-card 216 +** exists and is correct. Return 2 if the Z-card exists and has the wrong 217 +** value. 218 +** 219 +** 0123456789 123456789 123456789 123456789 220 +** Z aea84f4f863865a8d59d0384e4d2a41c 221 +*/ 222 +static int verify_z_card(const char *z, int n){ 223 + if( n<35 ) return 0; 224 + if( z[n-35]!='Z' || z[n-34]!=' ' ) return 0; 225 + md5sum_init(); 226 + md5sum_step_text(z, n-35); 227 + if( memcmp(&z[n-33], md5sum_finish(0), 32)==0 ){ 228 + return 1; 229 + }else{ 230 + return 2; 231 + } 232 +} 233 + 234 +/* 235 +** A structure used for rapid parsing of the Manifest file 236 +*/ 237 +typedef struct ManifestText ManifestText; 238 +struct ManifestText { 239 + char *z; /* The first character of the next token */ 240 + char *zEnd; /* One character beyond the end of the manifest */ 241 + int atEol; /* True if z points to the start of a new line */ 242 +}; 243 + 244 +/* 245 +** Return a pointer to the next token. The token is zero-terminated. 246 +** Return NULL if there are no more tokens on the current line. 247 +*/ 248 +static char *next_token(ManifestText *p, int *pLen){ 249 + char *z; 250 + char *zStart; 251 + int c; 252 + if( p->atEol ) return 0; 253 + zStart = z = p->z; 254 + while( (c=(*z))!=' ' && c!='\n' ){ z++; } 255 + *z = 0; 256 + p->z = &z[1]; 257 + p->atEol = c=='\n'; 258 + if( pLen ) *pLen = z - zStart; 259 + return zStart; 260 +} 261 + 262 +/* 263 +** Return the card-type for the next card. Or, return 0 if there are no 264 +** more cards or if we are not at the end of the current card. 265 +*/ 266 +static char next_card(ManifestText *p){ 267 + char c; 268 + if( !p->atEol || p->z>=p->zEnd ) return 0; 269 + c = p->z[0]; 270 + if( p->z[1]==' ' ){ 271 + p->z += 2; 272 + p->atEol = 0; 273 + }else if( p->z[1]=='\n' ){ 274 + p->z += 2; 275 + p->atEol = 1; 276 + }else{ 277 + c = 0; 278 + } 279 + return c; 97 280 } 98 281 99 282 /* 100 283 ** Parse a blob into a Manifest object. The Manifest object 101 284 ** takes over the input blob and will free it when the 102 285 ** Manifest object is freed. Zeros are inserted into the blob 103 286 ** as string terminators so that blob should not be used again. ................................................................................ 119 302 ** The file consists of zero or more cards, one card per line. 120 303 ** (Except: the content of the W card can extend of multiple lines.) 121 304 ** Each card is divided into tokens by a single space character. 122 305 ** The first token is a single upper-case letter which is the card type. 123 306 ** The card type determines the other parameters to the card. 124 307 ** Cards must occur in lexicographical order. 125 308 */ 126 -int manifest_parse(Manifest *p, Blob *pContent){ 127 - int seenHeader = 0; 309 +static Manifest *manifest_parse(Blob *pContent, int rid){ 310 + Manifest *p; 128 311 int seenZ = 0; 129 312 int i, lineNo=0; 130 - Blob line, token, a1, a2, a3, a4; 313 + ManifestText x; 131 314 char cPrevType = 0; 315 + char cType; 316 + char *z; 317 + int n; 318 + char *zUuid; 319 + int sz = 0; 132 320 321 + /* Every control artifact ends with a '\n' character. Exit early 322 + ** if that is not the case for this artifact. 323 + */ 324 + z = blob_buffer(pContent); 325 + n = blob_size(pContent); 326 + if( n<=0 || z[n-1]!='\n' ){ 327 + blob_reset(pContent); 328 + return 0; 329 + } 330 + 331 + /* Strip off the PGP signature if there is one. Then verify the 332 + ** Z-card. 333 + */ 334 + remove_pgp_signature(&z, &n); 335 + if( verify_z_card(z, n)==0 ){ 336 + blob_reset(pContent); 337 + return 0; 338 + } 339 + 340 + /* Verify that the first few characters of the artifact look like 341 + ** a control artifact. 342 + */ 343 + if( n<10 || z[0]<'A' || z[0]>'Z' || z[1]!=' ' ){ 344 + blob_reset(pContent); 345 + return 0; 346 + } 347 + 348 + /* Allocate a Manifest object to hold the parsed control artifact. 349 + */ 350 + p = fossil_malloc( sizeof(*p) ); 133 351 memset(p, 0, sizeof(*p)); 134 352 memcpy(&p->content, pContent, sizeof(p->content)); 353 + p->rid = rid; 135 354 blob_zero(pContent); 136 355 pContent = &p->content; 137 356 138 - blob_zero(&a1); 139 - blob_zero(&a2); 140 - blob_zero(&a3); 141 - md5sum_init(); 142 - while( blob_line(pContent, &line) ){ 143 - char *z = blob_buffer(&line); 357 + /* Begin parsing, card by card. 358 + */ 359 + x.z = z; 360 + x.zEnd = &z[n]; 361 + x.atEol = 1; 362 + while( (cType = next_card(&x))!=0 && cType>=cPrevType ){ 144 363 lineNo++; 145 - if( z[0]=='-' ){ 146 - if( strncmp(z, "-----BEGIN PGP ", 15)!=0 ){ 147 - goto manifest_syntax_error; 148 - } 149 - if( seenHeader ){ 150 - break; 151 - } 152 - while( blob_line(pContent, &line)>2 ){} 153 - if( blob_line(pContent, &line)==0 ) break; 154 - z = blob_buffer(&line); 155 - } 156 - if( z[0]<cPrevType ){ 157 - /* Lines of a manifest must occur in lexicographical order */ 158 - goto manifest_syntax_error; 159 - } 160 - cPrevType = z[0]; 161 - seenHeader = 1; 162 - if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error; 163 - switch( z[0] ){ 364 + switch( cType ){ 164 365 /* 165 366 ** A <filename> <target> ?<source>? 166 367 ** 167 368 ** Identifies an attachment to either a wiki page or a ticket. 168 369 ** <source> is the artifact that is the attachment. <source> 169 370 ** is omitted to delete an attachment. <target> is the name of 170 371 ** a wiki page or ticket to which that attachment is connected. 171 372 */ 172 373 case 'A': { 173 374 char *zName, *zTarget, *zSrc; 174 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 175 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 176 - if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error; 375 + int nTarget = 0, nSrc = 0; 376 + zName = next_token(&x, 0); 377 + zTarget = next_token(&x, &nTarget); 378 + zSrc = next_token(&x, &nSrc); 379 + if( zName==0 || zTarget==0 ) goto manifest_syntax_error; 177 380 if( p->zAttachName!=0 ) goto manifest_syntax_error; 178 - zName = blob_terminate(&a1); 179 - zTarget = blob_terminate(&a2); 180 - blob_token(&line, &a3); 181 - zSrc = blob_terminate(&a3); 182 381 defossilize(zName); 183 382 if( !file_is_simple_pathname(zName) ){ 184 383 goto manifest_syntax_error; 185 384 } 186 385 defossilize(zTarget); 187 - if( (blob_size(&a2)!=UUID_SIZE || !validate16(zTarget, UUID_SIZE)) 386 + if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE)) 188 387 && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ 189 388 goto manifest_syntax_error; 190 389 } 191 - if( blob_size(&a3)>0 192 - && (blob_size(&a3)!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){ 390 + if( zSrc && (nSrc!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){ 193 391 goto manifest_syntax_error; 194 392 } 195 393 p->zAttachName = (char*)file_tail(zName); 196 394 p->zAttachSrc = zSrc; 197 395 p->zAttachTarget = zTarget; 198 396 break; 199 397 } 398 + 399 + /* 400 + ** B <uuid> 401 + ** 402 + ** A B-line gives the UUID for the baselinen of a delta-manifest. 403 + */ 404 + case 'B': { 405 + if( p->zBaseline ) goto manifest_syntax_error; 406 + p->zBaseline = next_token(&x, &sz); 407 + if( p->zBaseline==0 ) goto manifest_syntax_error; 408 + if( sz!=UUID_SIZE ) goto manifest_syntax_error; 409 + if( !validate16(p->zBaseline, UUID_SIZE) ) goto manifest_syntax_error; 410 + break; 411 + } 412 + 200 413 201 414 /* 202 415 ** C <comment> 203 416 ** 204 417 ** Comment text is fossil-encoded. There may be no more than 205 418 ** one C line. C lines are required for manifests and are 206 419 ** disallowed on all other control files. 207 420 */ 208 421 case 'C': { 209 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 210 422 if( p->zComment!=0 ) goto manifest_syntax_error; 211 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 212 - if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; 213 - p->zComment = blob_terminate(&a1); 423 + p->zComment = next_token(&x, 0); 424 + if( p->zComment==0 ) goto manifest_syntax_error; 214 425 defossilize(p->zComment); 215 426 break; 216 427 } 217 428 218 429 /* 219 430 ** D <timestamp> 220 431 ** 221 432 ** The timestamp should be ISO 8601. YYYY-MM-DDtHH:MM:SS 222 433 ** There can be no more than 1 D line. D lines are required 223 434 ** for all control files except for clusters. 224 435 */ 225 436 case 'D': { 226 - char *zDate; 227 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 228 - if( p->rDate!=0.0 ) goto manifest_syntax_error; 229 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 230 - if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; 231 - zDate = blob_terminate(&a1); 232 - p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); 437 + if( p->rDate>0.0 ) goto manifest_syntax_error; 438 + p->rDate = db_double(0.0, "SELECT julianday(%Q)", next_token(&x,0)); 439 + if( p->rDate<=0.0 ) goto manifest_syntax_error; 440 + break; 441 + } 442 + 443 + /* 444 + ** E <timestamp> <uuid> 445 + ** 446 + ** An "event" card that contains the timestamp of the event in the 447 + ** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event. 448 + ** The event timestamp is distinct from the D timestamp. The D 449 + ** timestamp is when the artifact was created whereas the E timestamp 450 + ** is when the specific event is said to occur. 451 + */ 452 + case 'E': { 453 + if( p->rEventDate>0.0 ) goto manifest_syntax_error; 454 + p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0)); 455 + if( p->rEventDate<=0.0 ) goto manifest_syntax_error; 456 + p->zEventId = next_token(&x, &sz); 457 + if( sz!=UUID_SIZE ) goto manifest_syntax_error; 458 + if( !validate16(p->zEventId, UUID_SIZE) ) goto manifest_syntax_error; 233 459 break; 234 460 } 235 461 236 462 /* 237 - ** F <filename> <uuid> ?<permissions>? ?<old-name>? 463 + ** F <filename> ?<uuid>? ?<permissions>? ?<old-name>? 238 464 ** 239 465 ** Identifies a file in a manifest. Multiple F lines are 240 466 ** allowed in a manifest. F lines are not allowed in any 241 467 ** other control file. The filename and old-name are fossil-encoded. 242 468 */ 243 469 case 'F': { 244 - char *zName, *zUuid, *zPerm, *zPriorName; 245 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 246 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 247 - if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error; 248 - zName = blob_terminate(&a1); 249 - zUuid = blob_terminate(&a2); 250 - blob_token(&line, &a3); 251 - zPerm = blob_terminate(&a3); 252 - if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error; 253 - if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error; 470 + char *zName, *zPerm, *zPriorName; 471 + zName = next_token(&x,0); 472 + if( zName==0 ) goto manifest_syntax_error; 254 473 defossilize(zName); 255 474 if( !file_is_simple_pathname(zName) ){ 256 475 goto manifest_syntax_error; 257 476 } 258 - blob_token(&line, &a4); 259 - zPriorName = blob_terminate(&a4); 260 - if( zPriorName[0] ){ 477 + zUuid = next_token(&x, &sz); 478 + if( p->zBaseline==0 || zUuid!=0 ){ 479 + if( sz!=UUID_SIZE ) goto manifest_syntax_error; 480 + if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error; 481 + } 482 + zPerm = next_token(&x,0); 483 + zPriorName = next_token(&x,0); 484 + if( zPriorName ){ 261 485 defossilize(zPriorName); 262 486 if( !file_is_simple_pathname(zPriorName) ){ 263 487 goto manifest_syntax_error; 264 488 } 265 - }else{ 266 - zPriorName = 0; 267 489 } 268 490 if( p->nFile>=p->nFileAlloc ){ 269 491 p->nFileAlloc = p->nFileAlloc*2 + 10; 270 - p->aFile = realloc(p->aFile, p->nFileAlloc*sizeof(p->aFile[0]) ); 271 - if( p->aFile==0 ) fossil_panic("out of memory"); 492 + p->aFile = fossil_realloc(p->aFile, 493 + p->nFileAlloc*sizeof(p->aFile[0]) ); 272 494 } 273 495 i = p->nFile++; 274 496 p->aFile[i].zName = zName; 275 497 p->aFile[i].zUuid = zUuid; 276 498 p->aFile[i].zPerm = zPerm; 277 499 p->aFile[i].zPrior = zPriorName; 278 - p->aFile[i].iRename = -1; 279 500 if( i>0 && strcmp(p->aFile[i-1].zName, zName)>=0 ){ 280 501 goto manifest_syntax_error; 281 502 } 282 503 break; 283 504 } 284 505 285 506 /* ................................................................................ 288 509 ** Specifies a name value pair for ticket. If the first character 289 510 ** of <name> is "+" then the <value> is appended to any preexisting 290 511 ** value. If <value> is omitted then it is understood to be an 291 512 ** empty string. 292 513 */ 293 514 case 'J': { 294 515 char *zName, *zValue; 295 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 296 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 297 - blob_token(&line, &a2); 298 - if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error; 299 - zName = blob_terminate(&a1); 300 - zValue = blob_terminate(&a2); 516 + zName = next_token(&x,0); 517 + zValue = next_token(&x,0); 518 + if( zName==0 ) goto manifest_syntax_error; 519 + if( zValue==0 ) zValue = ""; 301 520 defossilize(zValue); 302 521 if( p->nField>=p->nFieldAlloc ){ 303 522 p->nFieldAlloc = p->nFieldAlloc*2 + 10; 304 - p->aField = realloc(p->aField, 523 + p->aField = fossil_realloc(p->aField, 305 524 p->nFieldAlloc*sizeof(p->aField[0]) ); 306 - if( p->aField==0 ) fossil_panic("out of memory"); 307 525 } 308 526 i = p->nField++; 309 527 p->aField[i].zName = zName; 310 528 p->aField[i].zValue = zValue; 311 529 if( i>0 && strcmp(p->aField[i-1].zName, zName)>=0 ){ 312 530 goto manifest_syntax_error; 313 531 } ................................................................................ 318 536 /* 319 537 ** K <uuid> 320 538 ** 321 539 ** A K-line gives the UUID for the ticket which this control file 322 540 ** is amending. 323 541 */ 324 542 case 'K': { 325 - char *zUuid; 326 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 327 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 328 - zUuid = blob_terminate(&a1); 329 - if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error; 330 - if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error; 331 543 if( p->zTicketUuid!=0 ) goto manifest_syntax_error; 332 - p->zTicketUuid = zUuid; 544 + p->zTicketUuid = next_token(&x, &sz); 545 + if( sz!=UUID_SIZE ) goto manifest_syntax_error; 546 + if( !validate16(p->zTicketUuid, UUID_SIZE) ) goto manifest_syntax_error; 333 547 break; 334 548 } 335 549 336 550 /* 337 551 ** L <wikititle> 338 552 ** 339 553 ** The wiki page title is fossil-encoded. There may be no more than 340 554 ** one L line. 341 555 */ 342 556 case 'L': { 343 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 344 557 if( p->zWikiTitle!=0 ) goto manifest_syntax_error; 345 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 346 - if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; 347 - p->zWikiTitle = blob_terminate(&a1); 558 + p->zWikiTitle = next_token(&x,0); 559 + if( p->zWikiTitle==0 ) goto manifest_syntax_error; 348 560 defossilize(p->zWikiTitle); 349 561 if( !wiki_name_is_wellformed((const unsigned char *)p->zWikiTitle) ){ 350 562 goto manifest_syntax_error; 351 563 } 352 564 break; 353 565 } 354 566 ................................................................................ 355 567 /* 356 568 ** M <uuid> 357 569 ** 358 570 ** An M-line identifies another artifact by its UUID. M-lines 359 571 ** occur in clusters only. 360 572 */ 361 573 case 'M': { 362 - char *zUuid; 363 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 364 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 365 - zUuid = blob_terminate(&a1); 366 - if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error; 574 + zUuid = next_token(&x, &sz); 575 + if( zUuid==0 ) goto manifest_syntax_error; 576 + if( sz!=UUID_SIZE ) goto manifest_syntax_error; 367 577 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error; 368 578 if( p->nCChild>=p->nCChildAlloc ){ 369 579 p->nCChildAlloc = p->nCChildAlloc*2 + 10; 370 - p->azCChild = 371 - realloc(p->azCChild, p->nCChildAlloc*sizeof(p->azCChild[0]) ); 372 - if( p->azCChild==0 ) fossil_panic("out of memory"); 580 + p->azCChild = fossil_realloc(p->azCChild 581 + , p->nCChildAlloc*sizeof(p->azCChild[0]) ); 373 582 } 374 583 i = p->nCChild++; 375 584 p->azCChild[i] = zUuid; 376 585 if( i>0 && strcmp(p->azCChild[i-1], zUuid)>=0 ){ 377 586 goto manifest_syntax_error; 378 587 } 379 588 break; ................................................................................ 383 592 ** P <uuid> ... 384 593 ** 385 594 ** Specify one or more other artifacts where are the parents of 386 595 ** this artifact. The first parent is the primary parent. All 387 596 ** others are parents by merge. 388 597 */ 389 598 case 'P': { 390 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 391 - while( blob_token(&line, &a1) ){ 392 - char *zUuid; 393 - if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error; 394 - zUuid = blob_terminate(&a1); 599 + while( (zUuid = next_token(&x, &sz))!=0 ){ 600 + if( sz!=UUID_SIZE ) goto manifest_syntax_error; 395 601 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error; 396 602 if( p->nParent>=p->nParentAlloc ){ 397 603 p->nParentAlloc = p->nParentAlloc*2 + 5; 398 - p->azParent = realloc(p->azParent, p->nParentAlloc*sizeof(char*)); 399 - if( p->azParent==0 ) fossil_panic("out of memory"); 604 + p->azParent = fossil_realloc(p->azParent, 605 + p->nParentAlloc*sizeof(char*)); 400 606 } 401 607 i = p->nParent++; 402 608 p->azParent[i] = zUuid; 403 609 } 404 610 break; 405 611 } 406 612 407 613 /* 408 614 ** R <md5sum> 409 615 ** 410 - ** Specify the MD5 checksum of the entire baseline in a 411 - ** manifest. 616 + ** Specify the MD5 checksum over the name and content of all files 617 + ** in the manifest. 412 618 */ 413 619 case 'R': { 414 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 415 620 if( p->zRepoCksum!=0 ) goto manifest_syntax_error; 416 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 417 - if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; 418 - if( blob_size(&a1)!=32 ) goto manifest_syntax_error; 419 - p->zRepoCksum = blob_terminate(&a1); 621 + p->zRepoCksum = next_token(&x, &sz); 622 + if( sz!=32 ) goto manifest_syntax_error; 420 623 if( !validate16(p->zRepoCksum, 32) ) goto manifest_syntax_error; 421 624 break; 422 625 } 423 626 424 627 /* 425 628 ** T (+|*|-)<tagname> <uuid> ?<value>? 426 629 ** ................................................................................ 433 636 ** The tag is applied to <uuid>. If <uuid> is "*" then the tag is 434 637 ** applied to the current manifest. If <value> is provided then 435 638 ** the tag is really a property with the given value. 436 639 ** 437 640 ** Tags are not allowed in clusters. Multiple T lines are allowed. 438 641 */ 439 642 case 'T': { 440 - char *zName, *zUuid, *zValue; 441 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 442 - if( blob_token(&line, &a1)==0 ){ 443 - goto manifest_syntax_error; 444 - } 445 - if( blob_token(&line, &a2)==0 ){ 446 - goto manifest_syntax_error; 447 - } 448 - zName = blob_terminate(&a1); 449 - zUuid = blob_terminate(&a2); 450 - if( blob_token(&line, &a3)==0 ){ 451 - zValue = 0; 452 - }else{ 453 - zValue = blob_terminate(&a3); 454 - defossilize(zValue); 455 - } 456 - if( blob_size(&a2)==UUID_SIZE && validate16(zUuid, UUID_SIZE) ){ 643 + char *zName, *zValue; 644 + zName = next_token(&x, 0); 645 + if( zName==0 ) goto manifest_syntax_error; 646 + zUuid = next_token(&x, &sz); 647 + if( zUuid==0 ) goto manifest_syntax_error; 648 + zValue = next_token(&x, 0); 649 + if( zValue ) defossilize(zValue); 650 + if( sz==UUID_SIZE && validate16(zUuid, UUID_SIZE) ){ 457 651 /* A valid uuid */ 458 - }else if( blob_size(&a2)==1 && zUuid[0]=='*' ){ 652 + }else if( sz==1 && zUuid[0]=='*' ){ 459 653 zUuid = 0; 460 654 }else{ 461 655 goto manifest_syntax_error; 462 656 } 463 657 defossilize(zName); 464 658 if( zName[0]!='-' && zName[0]!='+' && zName[0]!='*' ){ 465 659 goto manifest_syntax_error; ................................................................................ 466 660 } 467 661 if( validate16(&zName[1], strlen(&zName[1])) ){ 468 662 /* Do not allow tags whose names look like UUIDs */ 469 663 goto manifest_syntax_error; 470 664 } 471 665 if( p->nTag>=p->nTagAlloc ){ 472 666 p->nTagAlloc = p->nTagAlloc*2 + 10; 473 - p->aTag = realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) ); 474 - if( p->aTag==0 ) fossil_panic("out of memory"); 667 + p->aTag = fossil_realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) ); 475 668 } 476 669 i = p->nTag++; 477 670 p->aTag[i].zName = zName; 478 671 p->aTag[i].zUuid = zUuid; 479 672 p->aTag[i].zValue = zValue; 480 673 if( i>0 && strcmp(p->aTag[i-1].zName, zName)>=0 ){ 481 674 goto manifest_syntax_error; ................................................................................ 487 680 ** U ?<login>? 488 681 ** 489 682 ** Identify the user who created this control file by their 490 683 ** login. Only one U line is allowed. Prohibited in clusters. 491 684 ** If the user name is omitted, take that to be "anonymous". 492 685 */ 493 686 case 'U': { 494 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 495 687 if( p->zUser!=0 ) goto manifest_syntax_error; 496 - if( blob_token(&line, &a1)==0 ){ 688 + p->zUser = next_token(&x, 0); 689 + if( p->zUser==0 ){ 497 690 p->zUser = "anonymous"; 498 691 }else{ 499 - p->zUser = blob_terminate(&a1); 500 692 defossilize(p->zUser); 501 693 } 502 - if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; 503 694 break; 504 695 } 505 696 506 697 /* 507 698 ** W <size> 508 699 ** 509 700 ** The next <size> bytes of the file contain the text of the wiki 510 701 ** page. There is always an extra \n before the start of the next 511 702 ** record. 512 703 */ 513 704 case 'W': { 514 - int size; 705 + char *zSize; 706 + int size, c; 515 707 Blob wiki; 516 - md5sum_step_text(blob_buffer(&line), blob_size(&line)); 517 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 518 - if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; 519 - if( !blob_is_int(&a1, &size) ) goto manifest_syntax_error; 708 + zSize = next_token(&x, 0); 709 + if( zSize==0 ) goto manifest_syntax_error; 710 + if( x.atEol==0 ) goto manifest_syntax_error; 711 + for(size=0; (c = zSize[0])>='0' && c<='9'; zSize++){ 712 + size = size*10 + c - '0'; 713 + } 520 714 if( size<0 ) goto manifest_syntax_error; 521 715 if( p->zWiki!=0 ) goto manifest_syntax_error; 522 716 blob_zero(&wiki); 523 - if( blob_extract(pContent, size+1, &wiki)!=size+1 ){ 524 - goto manifest_syntax_error; 525 - } 526 - p->zWiki = blob_buffer(&wiki); 527 - md5sum_step_text(p->zWiki, size+1); 528 - if( p->zWiki[size]!='\n' ) goto manifest_syntax_error; 529 - p->zWiki[size] = 0; 717 + if( (&x.z[size+1])>=x.zEnd ) goto manifest_syntax_error; 718 + p->zWiki = x.z; 719 + x.z += size; 720 + if( x.z[0]!='\n' ) goto manifest_syntax_error; 721 + x.z[0] = 0; 722 + x.z++; 530 723 break; 531 724 } 532 725 533 726 534 727 /* 535 728 ** Z <md5sum> 536 729 ** ................................................................................ 539 732 ** line. This must be the last record. 540 733 ** 541 734 ** This card is required for all control file types except for 542 735 ** Manifest. It is not required for manifest only for historical 543 736 ** compatibility reasons. 544 737 */ 545 738 case 'Z': { 546 - int rc; 547 - Blob hash; 548 - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; 549 - if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; 550 - if( blob_size(&a1)!=32 ) goto manifest_syntax_error; 551 - if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error; 552 - md5sum_finish(&hash); 553 - rc = blob_compare(&hash, &a1); 554 - blob_reset(&hash); 555 - if( rc!=0 ) goto manifest_syntax_error; 739 + zUuid = next_token(&x, &sz); 740 + if( sz!=32 ) goto manifest_syntax_error; 741 + if( !validate16(zUuid, 32) ) goto manifest_syntax_error; 556 742 seenZ = 1; 557 743 break; 558 744 } 559 745 default: { 560 746 goto manifest_syntax_error; 561 747 } 562 748 } 563 749 } 564 - if( !seenHeader ) goto manifest_syntax_error; 750 + if( x.z<x.zEnd ) goto manifest_syntax_error; 565 751 566 - if( p->nFile>0 || p->zRepoCksum!=0 ){ 752 + if( p->nFile>0 || p->zRepoCksum!=0 || p->zBaseline ){ 567 753 if( p->nCChild>0 ) goto manifest_syntax_error; 568 - if( p->rDate==0.0 ) goto manifest_syntax_error; 754 + if( p->rDate<=0.0 ) goto manifest_syntax_error; 569 755 if( p->nField>0 ) goto manifest_syntax_error; 570 756 if( p->zTicketUuid ) goto manifest_syntax_error; 571 757 if( p->zWiki ) goto manifest_syntax_error; 572 758 if( p->zWikiTitle ) goto manifest_syntax_error; 759 + if( p->zEventId ) goto manifest_syntax_error; 573 760 if( p->zTicketUuid ) goto manifest_syntax_error; 574 761 if( p->zAttachName ) goto manifest_syntax_error; 575 762 p->type = CFTYPE_MANIFEST; 576 763 }else if( p->nCChild>0 ){ 577 764 if( p->rDate>0.0 ) goto manifest_syntax_error; 578 765 if( p->zComment!=0 ) goto manifest_syntax_error; 579 766 if( p->zUser!=0 ) goto manifest_syntax_error; 580 767 if( p->nTag>0 ) goto manifest_syntax_error; 581 768 if( p->nParent>0 ) goto manifest_syntax_error; 582 769 if( p->nField>0 ) goto manifest_syntax_error; 583 770 if( p->zTicketUuid ) goto manifest_syntax_error; 584 771 if( p->zWiki ) goto manifest_syntax_error; 585 772 if( p->zWikiTitle ) goto manifest_syntax_error; 773 + if( p->zEventId ) goto manifest_syntax_error; 586 774 if( p->zAttachName ) goto manifest_syntax_error; 587 775 if( !seenZ ) goto manifest_syntax_error; 588 776 p->type = CFTYPE_CLUSTER; 589 777 }else if( p->nField>0 ){ 590 - if( p->rDate==0.0 ) goto manifest_syntax_error; 778 + if( p->rDate<=0.0 ) goto manifest_syntax_error; 591 779 if( p->zWiki ) goto manifest_syntax_error; 592 780 if( p->zWikiTitle ) goto manifest_syntax_error; 781 + if( p->zEventId ) goto manifest_syntax_error; 593 782 if( p->nCChild>0 ) goto manifest_syntax_error; 594 783 if( p->nTag>0 ) goto manifest_syntax_error; 595 784 if( p->zTicketUuid==0 ) goto manifest_syntax_error; 596 785 if( p->zUser==0 ) goto manifest_syntax_error; 597 786 if( p->zAttachName ) goto manifest_syntax_error; 598 787 if( !seenZ ) goto manifest_syntax_error; 599 788 p->type = CFTYPE_TICKET; 789 + }else if( p->zEventId ){ 790 + if( p->rDate<=0.0 ) goto manifest_syntax_error; 791 + if( p->nCChild>0 ) goto manifest_syntax_error; 792 + if( p->zTicketUuid!=0 ) goto manifest_syntax_error; 793 + if( p->zWikiTitle!=0 ) goto manifest_syntax_error; 794 + if( p->zWiki==0 ) goto manifest_syntax_error; 795 + if( p->zAttachName ) goto manifest_syntax_error; 796 + for(i=0; i<p->nTag; i++){ 797 + if( p->aTag[i].zName[0]!='+' ) goto manifest_syntax_error; 798 + if( p->aTag[i].zUuid!=0 ) goto manifest_syntax_error; 799 + } 800 + if( !seenZ ) goto manifest_syntax_error; 801 + p->type = CFTYPE_EVENT; 600 802 }else if( p->zWiki!=0 ){ 601 - if( p->rDate==0.0 ) goto manifest_syntax_error; 803 + if( p->rDate<=0.0 ) goto manifest_syntax_error; 602 804 if( p->nCChild>0 ) goto manifest_syntax_error; 603 805 if( p->nTag>0 ) goto manifest_syntax_error; 604 806 if( p->zTicketUuid!=0 ) goto manifest_syntax_error; 605 807 if( p->zWikiTitle==0 ) goto manifest_syntax_error; 606 808 if( p->zAttachName ) goto manifest_syntax_error; 607 809 if( !seenZ ) goto manifest_syntax_error; 608 810 p->type = CFTYPE_WIKI; ................................................................................ 612 814 if( p->zWikiTitle ) goto manifest_syntax_error; 613 815 if( p->zTicketUuid ) goto manifest_syntax_error; 614 816 if( p->zAttachName ) goto manifest_syntax_error; 615 817 if( !seenZ ) goto manifest_syntax_error; 616 818 p->type = CFTYPE_CONTROL; 617 819 }else if( p->zAttachName ){ 618 820 if( p->nCChild>0 ) goto manifest_syntax_error; 619 - if( p->rDate==0.0 ) goto manifest_syntax_error; 821 + if( p->rDate<=0.0 ) goto manifest_syntax_error; 620 822 if( p->zTicketUuid ) goto manifest_syntax_error; 621 823 if( p->zWikiTitle ) goto manifest_syntax_error; 622 824 if( !seenZ ) goto manifest_syntax_error; 623 825 p->type = CFTYPE_ATTACHMENT; 624 826 }else{ 625 827 if( p->nCChild>0 ) goto manifest_syntax_error; 626 828 if( p->rDate<=0.0 ) goto manifest_syntax_error; 627 829 if( p->nParent>0 ) goto manifest_syntax_error; 628 830 if( p->nField>0 ) goto manifest_syntax_error; 629 831 if( p->zTicketUuid ) goto manifest_syntax_error; 630 - if( p->zWiki ) goto manifest_syntax_error; 631 832 if( p->zWikiTitle ) goto manifest_syntax_error; 632 833 if( p->zTicketUuid ) goto manifest_syntax_error; 633 - if( p->zAttachName ) goto manifest_syntax_error; 634 834 p->type = CFTYPE_MANIFEST; 635 835 } 636 836 md5sum_init(); 637 - return 1; 837 + return p; 638 838 639 839 manifest_syntax_error: 640 840 /*fprintf(stderr, "Manifest error on line %i\n", lineNo);fflush(stderr);*/ 641 841 md5sum_init(); 642 - manifest_clear(p); 842 + manifest_destroy(p); 643 843 return 0; 644 844 } 845 + 846 +/* 847 +** Get a manifest given the rid for the control artifact. Return 848 +** a pointer to the manifest on success or NULL if there is a failure. 849 +*/ 850 +Manifest *manifest_get(int rid, int cfType){ 851 + Blob content; 852 + Manifest *p; 853 + p = manifest_cache_find(rid); 854 + if( p ){ 855 + if( cfType!=CFTYPE_ANY && cfType!=p->type ){ 856 + manifest_cache_insert(p); 857 + p = 0; 858 + } 859 + return p; 860 + } 861 + content_get(rid, &content); 862 + p = manifest_parse(&content, rid); 863 + if( p && cfType!=CFTYPE_ANY && cfType!=p->type ){ 864 + manifest_destroy(p); 865 + p = 0; 866 + } 867 + return p; 868 +} 869 + 870 +/* 871 +** Given a checkin name, load and parse the manifest for that checkin. 872 +** Throw a fatal error if anything goes wrong. 873 +*/ 874 +Manifest *manifest_get_by_name(const char *zName, int *pRid){ 875 + int rid; 876 + Manifest *p; 877 + 878 + rid = name_to_rid(zName); 879 + if( !is_a_version(rid) ){ 880 + fossil_fatal("no such checkin: %s", zName); 881 + } 882 + if( pRid ) *pRid = rid; 883 + p = manifest_get(rid, CFTYPE_MANIFEST); 884 + if( p==0 ){ 885 + fossil_fatal("cannot parse manifest for checkin: %s", zName); 886 + } 887 + return p; 888 +} 645 889 646 890 /* 647 891 ** COMMAND: test-parse-manifest 648 892 ** 649 -** Usage: %fossil test-parse-manifest FILENAME 893 +** Usage: %fossil test-parse-manifest FILENAME ?N? 650 894 ** 651 895 ** Parse the manifest and discarded. Use for testing only. 652 896 */ 653 897 void manifest_test_parse_cmd(void){ 654 - Manifest m; 898 + Manifest *p; 655 899 Blob b; 656 - if( g.argc!=3 ){ 900 + int i; 901 + int n = 1; 902 + sqlite3_open(":memory:", &g.db); 903 + if( g.argc!=3 && g.argc!=4 ){ 657 904 usage("FILENAME"); 658 905 } 659 - db_must_be_within_tree(); 660 906 blob_read_from_file(&b, g.argv[2]); 661 - manifest_parse(&m, &b); 662 - manifest_clear(&m); 907 + if( g.argc>3 ) n = atoi(g.argv[3]); 908 + for(i=0; i<n; i++){ 909 + Blob b2; 910 + blob_copy(&b2, &b); 911 + p = manifest_parse(&b2, 0); 912 + manifest_destroy(p); 913 + } 914 +} 915 + 916 +/* 917 +** Fetch the baseline associated with the delta-manifest p. 918 +** Return 0 on success. If unable to parse the baseline, 919 +** throw an error. If the baseline is a manifest, throw an 920 +** error if throwError is true, or record that p is an orphan 921 +** and return 1 throwError is false. 922 +*/ 923 +static int fetch_baseline(Manifest *p, int throwError){ 924 + if( p->zBaseline!=0 && p->pBaseline==0 ){ 925 + int rid = uuid_to_rid(p->zBaseline, 0); 926 + if( rid==0 && !throwError ){ 927 + rid = content_new(p->zBaseline); 928 + db_multi_exec( 929 + "INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)", 930 + rid, p->rid 931 + ); 932 + return 1; 933 + } 934 + p->pBaseline = manifest_get(rid, CFTYPE_MANIFEST); 935 + if( p->pBaseline==0 ){ 936 + if( !throwError && db_exists("SELECT 1 FROM phantom WHERE rid=%d",rid) ){ 937 + db_multi_exec( 938 + "INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)", 939 + rid, p->rid 940 + ); 941 + return 1; 942 + } 943 + fossil_fatal("cannot access baseline manifest %S", p->zBaseline); 944 + } 945 + } 946 + return 0; 947 +} 948 + 949 +/* 950 +** Rewind a manifest-file iterator back to the beginning of the manifest. 951 +*/ 952 +void manifest_file_rewind(Manifest *p){ 953 + p->iFile = 0; 954 + fetch_baseline(p, 1); 955 + if( p->pBaseline ){ 956 + p->pBaseline->iFile = 0; 957 + } 958 +} 959 + 960 +/* 961 +** Advance to the next manifest-file. 962 +** 963 +** Return NULL for end-of-records or if there is an error. If an error 964 +** occurs and pErr!=0 then store 1 in *pErr. 965 +*/ 966 +ManifestFile *manifest_file_next( 967 + Manifest *p, 968 + int *pErr 969 +){ 970 + ManifestFile *pOut = 0; 971 + if( pErr ) *pErr = 0; 972 + if( p->pBaseline==0 ){ 973 + /* Manifest p is a baseline-manifest. Just scan down the list 974 + ** of files. */ 975 + if( p->iFile<p->nFile ) pOut = &p->aFile[p->iFile++]; 976 + }else{ 977 + /* Manifest p is a delta-manifest. Scan the baseline but amend the 978 + ** file list in the baseline with changes described by p. 979 + */ 980 + Manifest *pB = p->pBaseline; 981 + int cmp; 982 + while(1){ 983 + if( pB->iFile>=pB->nFile ){ 984 + /* We have used all entries out of the baseline. Return the next 985 + ** entry from the delta. */ 986 + if( p->iFile<p->nFile ) pOut = &p->aFile[p->iFile++]; 987 + break; 988 + }else if( p->iFile>=p->nFile ){ 989 + /* We have used all entries from the delta. Return the next 990 + ** entry from the baseline. */ 991 + if( pB->iFile<pB->nFile ) pOut = &pB->aFile[pB->iFile++]; 992 + break; 993 + }else if( (cmp = strcmp(pB->aFile[pB->iFile].zName, 994 + p->aFile[p->iFile].zName)) < 0 ){ 995 + /* The next baseline entry comes before the next delta entry. 996 + ** So return the baseline entry. */ 997 + pOut = &pB->aFile[pB->iFile++]; 998 + break; 999 + }else if( cmp>0 ){ 1000 + /* The next delta entry comes before the next baseline 1001 + ** entry so return the delta entry */ 1002 + pOut = &p->aFile[p->iFile++]; 1003 + break; 1004 + }else if( p->aFile[p->iFile].zUuid ){ 1005 + /* The next delta entry is a replacement for the next baseline 1006 + ** entry. Skip the baseline entry and return the delta entry */ 1007 + pB->iFile++; 1008 + pOut = &p->aFile[p->iFile++]; 1009 + break; 1010 + }else{ 1011 + /* The next delta entry is a delete of the next baseline 1012 + ** entry. Skip them both. Repeat the loop to find the next 1013 + ** non-delete entry. */ 1014 + pB->iFile++; 1015 + p->iFile++; 1016 + continue; 1017 + } 1018 + } 1019 + } 1020 + return pOut; 663 1021 } 664 1022 665 1023 /* 666 1024 ** Translate a filename into a filename-id (fnid). Create a new fnid 667 1025 ** if no previously exists. 668 1026 */ 669 1027 static int filename_to_fnid(const char *zFilename){ ................................................................................ 687 1045 688 1046 /* 689 1047 ** Add a single entry to the mlink table. Also add the filename to 690 1048 ** the filename table if it is not there already. 691 1049 */ 692 1050 static void add_one_mlink( 693 1051 int mid, /* The record ID of the manifest */ 694 - const char *zFromUuid, /* UUID for the mlink.pid field */ 695 - const char *zToUuid, /* UUID for the mlink.fid field */ 1052 + const char *zFromUuid, /* UUID for the mlink.pid. "" to add file */ 1053 + const char *zToUuid, /* UUID for the mlink.fid. "" to delele */ 696 1054 const char *zFilename, /* Filename */ 697 - const char *zPrior /* Previous filename. NULL if unchanged */ 1055 + const char *zPrior /* Previous filename. NULL if unchanged */ 698 1056 ){ 699 1057 int fnid, pfnid, pid, fid; 700 1058 static Stmt s1; 701 1059 702 1060 fnid = filename_to_fnid(zFilename); 703 1061 if( zPrior==0 ){ 704 1062 pfnid = 0; 705 1063 }else{ 706 1064 pfnid = filename_to_fnid(zPrior); 707 1065 } 708 - if( zFromUuid==0 ){ 1066 + if( zFromUuid==0 || zFromUuid[0]==0 ){ 709 1067 pid = 0; 710 1068 }else{ 711 1069 pid = uuid_to_rid(zFromUuid, 1); 712 1070 } 713 - if( zToUuid==0 ){ 1071 + if( zToUuid==0 || zToUuid[0]==0 ){ 714 1072 fid = 0; 715 1073 }else{ 716 1074 fid = uuid_to_rid(zToUuid, 1); 717 1075 } 718 1076 db_static_prepare(&s1, 719 1077 "INSERT INTO mlink(mid,pid,fid,fnid,pfnid)" 720 1078 "VALUES(:m,:p,:f,:n,:pfn)" ................................................................................ 727 1085 db_exec(&s1); 728 1086 if( pid && fid ){ 729 1087 content_deltify(pid, fid, 0); 730 1088 } 731 1089 } 732 1090 733 1091 /* 734 -** Locate a file named zName in the aFile[] array of the given 735 -** manifest. We assume that filenames are in sorted order. 736 -** Use a binary search. Return turn the index of the matching 737 -** entry. Or return -1 if not found. 1092 +** Do a binary search to find a file in the p->aFile[] array. 1093 +** 1094 +** As an optimization, guess that the file we seek is at index p->iFile. 1095 +** That will usually be the case. If it is not found there, then do the 1096 +** actual binary search. 1097 +** 1098 +** Update p->iFile to be the index of the file that is found. 738 1099 */ 739 -static int find_file_in_manifest(Manifest *p, const char *zName){ 1100 +static ManifestFile *manifest_file_seek_base(Manifest *p, const char *zName){ 740 1101 int lwr, upr; 741 1102 int c; 742 1103 int i; 743 1104 lwr = 0; 744 1105 upr = p->nFile - 1; 1106 + if( p->iFile>=lwr && p->iFile<upr ){ 1107 + c = strcmp(p->aFile[p->iFile+1].zName, zName); 1108 + if( c==0 ){ 1109 + return &p->aFile[++p->iFile]; 1110 + }else if( c>0 ){ 1111 + upr = p->iFile; 1112 + }else{ 1113 + lwr = p->iFile+1; 1114 + } 1115 + } 745 1116 while( lwr<=upr ){ 746 1117 i = (lwr+upr)/2; 747 1118 c = strcmp(p->aFile[i].zName, zName); 748 1119 if( c<0 ){ 749 1120 lwr = i+1; 750 1121 }else if( c>0 ){ 751 1122 upr = i-1; 752 1123 }else{ 753 - return i; 1124 + p->iFile = i; 1125 + return &p->aFile[i]; 754 1126 } 755 1127 } 756 - return -1; 1128 + return 0; 1129 +} 1130 + 1131 +/* 1132 +** Locate a file named zName in the aFile[] array of the given manifest. 1133 +** Return a pointer to the appropriate ManifestFile object. Return NULL 1134 +** if not found. 1135 +** 1136 +** This routine works even if p is a delta-manifest. The pointer 1137 +** returned might be to the baseline. 1138 +** 1139 +** We assume that filenames are in sorted order and use a binary search. 1140 +*/ 1141 +ManifestFile *manifest_file_seek(Manifest *p, const char *zName){ 1142 + ManifestFile *pFile; 1143 + 1144 + pFile = manifest_file_seek_base(p, zName); 1145 + if( pFile && pFile->zUuid==0 ) return 0; 1146 + if( pFile==0 && p->zBaseline ){ 1147 + fetch_baseline(p, 1); 1148 + pFile = manifest_file_seek_base(p->pBaseline, zName); 1149 + } 1150 + return pFile; 1151 +} 1152 + 1153 +/* 1154 +** This strcmp() function handles NULL arguments. NULLs sort first. 1155 +*/ 1156 +static int strcmp_null(const char *zOne, const char *zTwo){ 1157 + if( zOne==0 ){ 1158 + if( zTwo==0 ) return 0; 1159 + return -1; 1160 + }else if( zTwo==0 ){ 1161 + return +1; 1162 + }else{ 1163 + return strcmp(zOne, zTwo); 1164 + } 757 1165 } 758 1166 759 1167 /* 760 1168 ** Add mlink table entries associated with manifest cid. The 761 1169 ** parent manifest is pid. 762 1170 ** 763 1171 ** A single mlink entry is added for every file that changed content ................................................................................ 764 1172 ** and/or name going from pid to cid. 765 1173 ** 766 1174 ** Deleted files have mlink.fid=0. 767 1175 ** Added files have mlink.pid=0. 768 1176 ** Edited files have both mlink.pid!=0 and mlink.fid!=0 769 1177 */ 770 1178 static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){ 771 - Manifest other; 772 1179 Blob otherContent; 773 - int i, j; 1180 + int otherRid; 1181 + int i, rc; 1182 + ManifestFile *pChildFile, *pParentFile; 1183 + Manifest **ppOther; 1184 + static Stmt eq; 774 1185 775 - if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", cid) ){ 776 - return; 777 - } 1186 + db_static_prepare(&eq, "SELECT 1 FROM mlink WHERE mid=:mid"); 1187 + db_bind_int(&eq, ":mid", cid); 1188 + rc = db_step(&eq); 1189 + db_reset(&eq); 1190 + if( rc==SQLITE_ROW ) return; 1191 + 778 1192 assert( pParent==0 || pChild==0 ); 779 1193 if( pParent==0 ){ 780 - pParent = &other; 781 - content_get(pid, &otherContent); 1194 + ppOther = &pParent; 1195 + otherRid = pid; 782 1196 }else{ 783 - pChild = &other; 784 - content_get(cid, &otherContent); 785 - } 786 - if( blob_size(&otherContent)==0 ) return; 787 - if( manifest_parse(&other, &otherContent)==0 ) return; 788 - content_deltify(pid, cid, 0); 789 - 790 - /* Use the iRename fields to find the cross-linkage between 791 - ** renamed files. */ 792 - for(j=0; j<pChild->nFile; j++){ 793 - const char *zPrior = pChild->aFile[j].zPrior; 794 - if( zPrior && zPrior[0] ){ 795 - i = find_file_in_manifest(pParent, zPrior); 796 - if( i>=0 ){ 797 - pChild->aFile[j].iRename = i; 798 - pParent->aFile[i].iRename = j; 1197 + ppOther = &pChild; 1198 + otherRid = cid; 1199 + } 1200 + if( (*ppOther = manifest_cache_find(otherRid))==0 ){ 1201 + content_get(otherRid, &otherContent); 1202 + if( blob_size(&otherContent)==0 ) return; 1203 + *ppOther = manifest_parse(&otherContent, otherRid); 1204 + if( *ppOther==0 ) return; 1205 + } 1206 + if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){ 1207 + manifest_destroy(*ppOther); 1208 + return; 1209 + } 1210 + if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){ 1211 + content_deltify(pid, cid, 0); 1212 + }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){ 1213 + content_deltify(pParent->pBaseline->rid, cid, 0); 1214 + } 1215 + 1216 + for(i=0, pChildFile=pChild->aFile; i<pChild->nFile; i++, pChildFile++){ 1217 + if( pChildFile->zPrior ){ 1218 + pParentFile = manifest_file_seek(pParent, pChildFile->zPrior); 1219 + if( pParentFile ){ 1220 + add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid, 1221 + pChildFile->zName, pChildFile->zPrior); 1222 + } 1223 + }else{ 1224 + pParentFile = manifest_file_seek(pParent, pChildFile->zName); 1225 + if( pParentFile==0 ){ 1226 + if( pChildFile->zUuid ){ 1227 + add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0); 1228 + } 1229 + }else if( strcmp_null(pChildFile->zUuid, pParentFile->zUuid)!=0 ){ 1230 + add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid, 1231 + pChildFile->zName, 0); 1232 + } 1233 + } 1234 + } 1235 + if( pParent->zBaseline && pChild->zBaseline ){ 1236 + for(i=0, pParentFile=pParent->aFile; i<pParent->nFile; i++, pParentFile++){ 1237 + if( pParentFile->zUuid ) continue; 1238 + pChildFile = manifest_file_seek(pChild, pParentFile->zName); 1239 + if( pChildFile ){ 1240 + add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0); 799 1241 } 800 1242 } 801 1243 } 802 - 803 - /* Construct the mlink entries */ 804 - for(i=j=0; i<pParent->nFile && j<pChild->nFile; ){ 805 - int c; 806 - if( pParent->aFile[i].iRename>=0 ){ 807 - i++; 808 - }else if( (c = strcmp(pParent->aFile[i].zName, pChild->aFile[j].zName))<0 ){ 809 - add_one_mlink(cid, pParent->aFile[i].zUuid,0,pParent->aFile[i].zName,0); 810 - i++; 811 - }else if( c>0 ){ 812 - int rn = pChild->aFile[j].iRename; 813 - if( rn>=0 ){ 814 - add_one_mlink(cid, pParent->aFile[rn].zUuid, pChild->aFile[j].zUuid, 815 - pChild->aFile[j].zName, pParent->aFile[rn].zName); 816 - }else{ 817 - add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0); 818 - } 819 - j++; 820 - }else{ 821 - if( strcmp(pParent->aFile[i].zUuid, pChild->aFile[j].zUuid)!=0 ){ 822 - add_one_mlink(cid, pParent->aFile[i].zUuid, pChild->aFile[j].zUuid, 823 - pChild->aFile[j].zName, 0); 824 - } 825 - i++; 826 - j++; 827 - } 828 - } 829 - while( i<pParent->nFile ){ 830 - if( pParent->aFile[i].iRename<0 ){ 831 - add_one_mlink(cid, pParent->aFile[i].zUuid, 0, pParent->aFile[i].zName,0); 832 - } 833 - i++; 834 - } 835 - while( j<pChild->nFile ){ 836 - int rn = pChild->aFile[j].iRename; 837 - if( rn>=0 ){ 838 - add_one_mlink(cid, pParent->aFile[rn].zUuid, pChild->aFile[j].zUuid, 839 - pChild->aFile[j].zName, pParent->aFile[rn].zName); 840 - }else{ 841 - add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0); 842 - } 843 - j++; 844 - } 845 - manifest_clear(&other); 1244 + manifest_cache_insert(*ppOther); 846 1245 } 847 1246 848 1247 /* 849 1248 ** True if manifest_crosslink_begin() has been called but 850 1249 ** manifest_crosslink_end() is still pending. 851 1250 */ 852 1251 static int manifest_crosslink_busy = 0; ................................................................................ 962 1361 ** any key: 963 1362 ** 964 1363 ** * Manifest 965 1364 ** * Control 966 1365 ** * Wiki Page 967 1366 ** * Ticket Change 968 1367 ** * Cluster 1368 +** * Attachment 1369 +** * Event 969 1370 ** 970 1371 ** If the input is a control artifact, then make appropriate entries 971 1372 ** in the auxiliary tables of the database in order to crosslink the 972 1373 ** artifact. 973 1374 ** 974 1375 ** If global variable g.xlinkClusterOnly is true, then ignore all 975 1376 ** control artifacts other than clusters. ................................................................................ 977 1378 ** Historical note: This routine original processed manifests only. 978 1379 ** Processing for other control artifacts was added later. The name 979 1380 ** of the routine, "manifest_crosslink", and the name of this source 980 1381 ** file, is a legacy of its original use. 981 1382 */ 982 1383 int manifest_crosslink(int rid, Blob *pContent){ 983 1384 int i; 984 - Manifest m; 1385 + Manifest *p; 985 1386 Stmt q; 986 1387 int parentid = 0; 987 1388 988 - if( manifest_parse(&m, pContent)==0 ){ 1389 + if( (p = manifest_cache_find(rid))!=0 ){ 1390 + blob_reset(pContent); 1391 + }else if( (p = manifest_parse(pContent, rid))==0 ){ 1392 + return 0; 1393 + } 1394 + if( g.xlinkClusterOnly && p->type!=CFTYPE_CLUSTER ){ 1395 + manifest_destroy(p); 989 1396 return 0; 990 1397 } 991 - if( g.xlinkClusterOnly && m.type!=CFTYPE_CLUSTER ){ 992 - manifest_clear(&m); 1398 + if( p->type==CFTYPE_MANIFEST && fetch_baseline(p, 0) ){ 1399 + manifest_destroy(p); 993 1400 return 0; 994 1401 } 995 1402 db_begin_transaction(); 996 - if( m.type==CFTYPE_MANIFEST ){ 1403 + if( p->type==CFTYPE_MANIFEST ){ 997 1404 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){ 998 1405 char *zCom; 999 - for(i=0; i<m.nParent; i++){ 1000 - int pid = uuid_to_rid(m.azParent[i], 1); 1406 + for(i=0; i<p->nParent; i++){ 1407 + int pid = uuid_to_rid(p->azParent[i], 1); 1001 1408 db_multi_exec("INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)" 1002 - "VALUES(%d, %d, %d, %.17g)", pid, rid, i==0, m.rDate); 1409 + "VALUES(%d, %d, %d, %.17g)", pid, rid, i==0, p->rDate); 1003 1410 if( i==0 ){ 1004 - add_mlink(pid, 0, rid, &m); 1411 + add_mlink(pid, 0, rid, p); 1005 1412 parentid = pid; 1006 1413 } 1007 1414 } 1008 1415 db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid); 1009 1416 while( db_step(&q)==SQLITE_ROW ){ 1010 1417 int cid = db_column_int(&q, 0); 1011 - add_mlink(rid, &m, cid, 0); 1418 + add_mlink(rid, p, cid, 0); 1012 1419 } 1013 1420 db_finalize(&q); 1014 1421 db_multi_exec( 1015 1422 "REPLACE INTO event(type,mtime,objid,user,comment," 1016 1423 "bgcolor,euser,ecomment)" 1017 1424 "VALUES('ci'," 1018 1425 " coalesce(" ................................................................................ 1019 1426 " (SELECT julianday(value) FROM tagxref WHERE tagid=%d AND rid=%d)," 1020 1427 " %.17g" 1021 1428 " )," 1022 1429 " %d,%Q,%Q," 1023 1430 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>0)," 1024 1431 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d)," 1025 1432 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));", 1026 - TAG_DATE, rid, m.rDate, 1027 - rid, m.zUser, m.zComment, 1433 + TAG_DATE, rid, p->rDate, 1434 + rid, p->zUser, p->zComment, 1028 1435 TAG_BGCOLOR, rid, 1029 1436 TAG_USER, rid, 1030 1437 TAG_COMMENT, rid 1031 1438 ); 1032 1439 zCom = db_text(0, "SELECT coalesce(ecomment, comment) FROM event" 1033 1440 " WHERE rowid=last_insert_rowid()"); 1034 - wiki_extract_links(zCom, rid, 0, m.rDate, 1, WIKI_INLINE); 1441 + wiki_extract_links(zCom, rid, 0, p->rDate, 1, WIKI_INLINE); 1035 1442 free(zCom); 1443 + 1444 + /* If this is a delta-manifest, record the fact that this repository 1445 + ** contains delta manifests, to free the "commit" logic to generate 1446 + ** new delta manifests. 1447 + */ 1448 + if( p->zBaseline!=0 ){ 1449 + static int once = 0; 1450 + if( !once ){ 1451 + db_set_int("seen-delta-manifest", 1, 0); 1452 + once = 0; 1453 + } 1454 + } 1036 1455 } 1037 1456 } 1038 - if( m.type==CFTYPE_CLUSTER ){ 1039 - tag_insert("cluster", 1, 0, rid, m.rDate, rid); 1040 - for(i=0; i<m.nCChild; i++){ 1457 + if( p->type==CFTYPE_CLUSTER ){ 1458 + static Stmt del1; 1459 + tag_insert("cluster", 1, 0, rid, p->rDate, rid); 1460 + db_static_prepare(&del1, "DELETE FROM unclustered WHERE rid=:rid"); 1461 + for(i=0; i<p->nCChild; i++){ 1041 1462 int mid; 1042 - mid = uuid_to_rid(m.azCChild[i], 1); 1463 + mid = uuid_to_rid(p->azCChild[i], 1); 1043 1464 if( mid>0 ){ 1044 - db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid); 1465 + db_bind_int(&del1, ":rid", mid); 1466 + db_step(&del1); 1467 + db_reset(&del1); 1045 1468 } 1046 1469 } 1047 1470 } 1048 - if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){ 1049 - for(i=0; i<m.nTag; i++){ 1471 + if( p->type==CFTYPE_CONTROL 1472 + || p->type==CFTYPE_MANIFEST 1473 + || p->type==CFTYPE_EVENT 1474 + ){ 1475 + for(i=0; i<p->nTag; i++){ 1050 1476 int tid; 1051 1477 int type; 1052 - if( m.aTag[i].zUuid ){ 1053 - tid = uuid_to_rid(m.aTag[i].zUuid, 1); 1478 + if( p->aTag[i].zUuid ){ 1479 + tid = uuid_to_rid(p->aTag[i].zUuid, 1); 1054 1480 }else{ 1055 1481 tid = rid; 1056 1482 } 1057 1483 if( tid ){ 1058 - switch( m.aTag[i].zName[0] ){ 1484 + switch( p->aTag[i].zName[0] ){ 1059 1485 case '-': type = 0; break; /* Cancel prior occurances */ 1060 1486 case '+': type = 1; break; /* Apply to target only */ 1061 1487 case '*': type = 2; break; /* Propagate to descendants */ 1062 1488 default: 1063 - fossil_fatal("unknown tag type in manifest: %s", m.aTag); 1489 + fossil_fatal("unknown tag type in manifest: %s", p->aTag); 1064 1490 return 0; 1065 1491 } 1066 - tag_insert(&m.aTag[i].zName[1], type, m.aTag[i].zValue, 1067 - rid, m.rDate, tid); 1492 + tag_insert(&p->aTag[i].zName[1], type, p->aTag[i].zValue, 1493 + rid, p->rDate, tid); 1068 1494 } 1069 1495 } 1070 1496 if( parentid ){ 1071 1497 tag_propagate_all(parentid); 1072 1498 } 1073 1499 } 1074 - if( m.type==CFTYPE_WIKI ){ 1075 - char *zTag = mprintf("wiki-%s", m.zWikiTitle); 1500 + if( p->type==CFTYPE_WIKI ){ 1501 + char *zTag = mprintf("wiki-%s", p->zWikiTitle); 1076 1502 int tagid = tag_findid(zTag, 1); 1077 1503 int prior; 1078 1504 char *zComment; 1079 1505 int nWiki; 1080 1506 char zLength[40]; 1081 - while( isspace(m.zWiki[0]) ) m.zWiki++; 1082 - nWiki = strlen(m.zWiki); 1507 + while( fossil_isspace(p->zWiki[0]) ) p->zWiki++; 1508 + nWiki = strlen(p->zWiki); 1083 1509 sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki); 1084 - tag_insert(zTag, 1, zLength, rid, m.rDate, rid); 1510 + tag_insert(zTag, 1, zLength, rid, p->rDate, rid); 1085 1511 free(zTag); 1086 1512 prior = db_int(0, 1087 1513 "SELECT rid FROM tagxref" 1088 1514 " WHERE tagid=%d AND mtime<%.17g" 1089 1515 " ORDER BY mtime DESC", 1090 - tagid, m.rDate 1516 + tagid, p->rDate 1091 1517 ); 1092 1518 if( prior ){ 1093 1519 content_deltify(prior, rid, 0); 1094 1520 } 1095 1521 if( nWiki>0 ){ 1096 - zComment = mprintf("Changes to wiki page [%h]", m.zWikiTitle); 1522 + zComment = mprintf("Changes to wiki page [%h]", p->zWikiTitle); 1097 1523 }else{ 1098 - zComment = mprintf("Deleted wiki page [%h]", m.zWikiTitle); 1524 + zComment = mprintf("Deleted wiki page [%h]", p->zWikiTitle); 1099 1525 } 1100 1526 db_multi_exec( 1101 1527 "REPLACE INTO event(type,mtime,objid,user,comment," 1102 1528 " bgcolor,euser,ecomment)" 1103 1529 "VALUES('w',%.17g,%d,%Q,%Q," 1104 1530 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>1)," 1105 1531 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d)," 1106 1532 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));", 1107 - m.rDate, rid, m.zUser, zComment, 1533 + p->rDate, rid, p->zUser, zComment, 1108 1534 TAG_BGCOLOR, rid, 1109 1535 TAG_BGCOLOR, rid, 1110 1536 TAG_USER, rid, 1111 1537 TAG_COMMENT, rid 1112 1538 ); 1113 1539 free(zComment); 1114 1540 } 1115 - if( m.type==CFTYPE_TICKET ){ 1541 + if( p->type==CFTYPE_EVENT ){ 1542 + char *zTag = mprintf("event-%s", p->zEventId); 1543 + int tagid = tag_findid(zTag, 1); 1544 + int prior, subsequent; 1545 + int nWiki; 1546 + char zLength[40]; 1547 + while( fossil_isspace(p->zWiki[0]) ) p->zWiki++; 1548 + nWiki = strlen(p->zWiki); 1549 + sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki); 1550 + tag_insert(zTag, 1, zLength, rid, p->rDate, rid); 1551 + free(zTag); 1552 + prior = db_int(0, 1553 + "SELECT rid FROM tagxref" 1554 + " WHERE tagid=%d AND mtime<%.17g" 1555 + " ORDER BY mtime DESC", 1556 + tagid, p->rDate 1557 + ); 1558 + if( prior ){ 1559 + content_deltify(prior, rid, 0); 1560 + db_multi_exec( 1561 + "DELETE FROM event" 1562 + " WHERE type='e'" 1563 + " AND tagid=%d" 1564 + " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)", 1565 + tagid, tagid 1566 + ); 1567 + } 1568 + subsequent = db_int(0, 1569 + "SELECT rid FROM tagxref" 1570 + " WHERE tagid=%d AND mtime>%.17g" 1571 + " ORDER BY mtime", 1572 + tagid, p->rDate 1573 + ); 1574 + if( subsequent ){ 1575 + content_deltify(rid, subsequent, 0); 1576 + }else{ 1577 + db_multi_exec( 1578 + "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)" 1579 + "VALUES('e',%.17g,%d,%d,%Q,%Q," 1580 + " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));", 1581 + p->rEventDate, rid, tagid, p->zUser, p->zComment, 1582 + TAG_BGCOLOR, rid 1583 + ); 1584 + } 1585 + } 1586 + if( p->type==CFTYPE_TICKET ){ 1116 1587 char *zTag; 1117 1588 1118 1589 assert( manifest_crosslink_busy==1 ); 1119 - zTag = mprintf("tkt-%s", m.zTicketUuid); 1120 - tag_insert(zTag, 1, 0, rid, m.rDate, rid); 1590 + zTag = mprintf("tkt-%s", p->zTicketUuid); 1591 + tag_insert(zTag, 1, 0, rid, p->rDate, rid); 1121 1592 free(zTag); 1122 1593 db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)", 1123 - m.zTicketUuid); 1594 + p->zTicketUuid); 1124 1595 } 1125 - if( m.type==CFTYPE_ATTACHMENT ){ 1596 + if( p->type==CFTYPE_ATTACHMENT ){ 1126 1597 db_multi_exec( 1127 1598 "INSERT INTO attachment(attachid, mtime, src, target," 1128 1599 "filename, comment, user)" 1129 1600 "VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);", 1130 - rid, m.rDate, m.zAttachSrc, m.zAttachTarget, m.zAttachName, 1131 - (m.zComment ? m.zComment : ""), m.zUser 1601 + rid, p->rDate, p->zAttachSrc, p->zAttachTarget, p->zAttachName, 1602 + (p->zComment ? p->zComment : ""), p->zUser 1132 1603 ); 1133 1604 db_multi_exec( 1134 1605 "UPDATE attachment SET isLatest = (mtime==" 1135 1606 "(SELECT max(mtime) FROM attachment" 1136 1607 " WHERE target=%Q AND filename=%Q))" 1137 1608 " WHERE target=%Q AND filename=%Q", 1138 - m.zAttachTarget, m.zAttachName, 1139 - m.zAttachTarget, m.zAttachName 1609 + p->zAttachTarget, p->zAttachName, 1610 + p->zAttachTarget, p->zAttachName 1140 1611 ); 1141 - if( strlen(m.zAttachTarget)!=UUID_SIZE 1142 - || !validate16(m.zAttachTarget, UUID_SIZE) 1612 + if( strlen(p->zAttachTarget)!=UUID_SIZE 1613 + || !validate16(p->zAttachTarget, UUID_SIZE) 1143 1614 ){ 1144 1615 char *zComment; 1145 - if( m.zAttachSrc && m.zAttachSrc[0] ){ 1616 + if( p->zAttachSrc && p->zAttachSrc[0] ){ 1146 1617 zComment = mprintf("Add attachment \"%h\" to wiki page [%h]", 1147 - m.zAttachName, m.zAttachTarget); 1618 + p->zAttachName, p->zAttachTarget); 1148 1619 }else{ 1149 1620 zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]", 1150 - m.zAttachName, m.zAttachTarget); 1621 + p->zAttachName, p->zAttachTarget); 1151 1622 } 1152 1623 db_multi_exec( 1153 1624 "REPLACE INTO event(type,mtime,objid,user,comment)" 1154 1625 "VALUES('w',%.17g,%d,%Q,%Q)", 1155 - m.rDate, rid, m.zUser, zComment 1626 + p->rDate, rid, p->zUser, zComment 1156 1627 ); 1157 1628 free(zComment); 1158 1629 }else{ 1159 1630 char *zComment; 1160 - if( m.zAttachSrc && m.zAttachSrc[0] ){ 1631 + if( p->zAttachSrc && p->zAttachSrc[0] ){ 1161 1632 zComment = mprintf("Add attachment \"%h\" to ticket [%.10s]", 1162 - m.zAttachName, m.zAttachTarget); 1633 + p->zAttachName, p->zAttachTarget); 1163 1634 }else{ 1164 1635 zComment = mprintf("Delete attachment \"%h\" from ticket [%.10s]", 1165 - m.zAttachName, m.zAttachTarget); 1636 + p->zAttachName, p->zAttachTarget); 1166 1637 } 1167 1638 db_multi_exec( 1168 1639 "REPLACE INTO event(type,mtime,objid,user,comment)" 1169 1640 "VALUES('t',%.17g,%d,%Q,%Q)", 1170 - m.rDate, rid, m.zUser, zComment 1641 + p->rDate, rid, p->zUser, zComment 1171 1642 ); 1172 1643 free(zComment); 1173 1644 } 1174 1645 } 1175 1646 db_end_transaction(0); 1176 - manifest_clear(&m); 1177 - return 1; 1178 -} 1179 - 1180 -/* 1181 -** Given a checkin name, load and parse the manifest for that checkin. 1182 -** Throw a fatal error if anything goes wrong. 1183 -*/ 1184 -void manifest_from_name( 1185 - const char *zName, 1186 - Manifest *pM 1187 -){ 1188 - int rid; 1189 - Blob content; 1190 - 1191 - rid = name_to_rid(zName); 1192 - if( !is_a_version(rid) ){ 1193 - fossil_fatal("no such checkin: %s", zName); 1647 + if( p->type==CFTYPE_MANIFEST ){ 1648 + manifest_cache_insert(p); 1649 + }else{ 1650 + manifest_destroy(p); 1194 1651 } 1195 - content_get(rid, &content); 1196 - if( !manifest_parse(pM, &content) ){ 1197 - fossil_fatal("cannot parse manifest for checkin: %s", zName); 1198 - } 1652 + return 1; 1199 1653 }
Changes to src/md5.c.
39 39 int isInit; 40 40 uint32 buf[4]; 41 41 uint32 bits[2]; 42 42 unsigned char in[64]; 43 43 }; 44 44 typedef struct Context MD5Context; 45 45 46 +#if defined(__i386__) || defined(__x86_64__) || defined(_WIN32) 47 +# define byteReverse(A,B) 48 +#else 46 49 /* 47 - * Note: this code is harmless on little-endian machines. 50 + * Convert an array of integers to little-endian. 51 + * Note: this code is a no-op on little-endian machines. 48 52 */ 49 53 static void byteReverse (unsigned char *buf, unsigned longs){ 50 54 uint32 t; 51 55 do { 52 56 t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 | 53 57 ((unsigned)buf[1]<<8 | buf[0]); 54 58 *(uint32 *)buf = t; 55 59 buf += 4; 56 60 } while (--longs); 57 61 } 62 +#endif 63 + 58 64 /* The four core functions - F1 is optimized somewhat */ 59 65 60 66 /* #define F1(x, y, z) (x & y | ~x & z) */ 61 67 #define F1(x, y, z) (z ^ (x & (y ^ z))) 62 68 #define F2(x, y, z) F1(z, x, y) 63 69 #define F3(x, y, z) (x ^ y ^ z) 64 70 #define F4(x, y, z) (y ^ (x | ~z)) ................................................................................ 312 318 313 319 /* 314 320 ** Add the content of a blob to the incremental MD5 checksum. 315 321 */ 316 322 void md5sum_step_blob(Blob *p){ 317 323 md5sum_step_text(blob_buffer(p), blob_size(p)); 318 324 } 325 + 326 +/* 327 +** For trouble-shooting only: 328 +** 329 +** Report the current state of the incremental checksum. 330 +*/ 331 +const char *md5sum_current_state(void){ 332 + unsigned int cksum = 0; 333 + unsigned int *pFirst, *pLast; 334 + static char zResult[12]; 335 + 336 + pFirst = (unsigned int*)&incrCtx; 337 + pLast = (unsigned int*)((&incrCtx)+1); 338 + while( pFirst<pLast ){ 339 + cksum += *pFirst; 340 + pFirst++; 341 + } 342 + sqlite3_snprintf(sizeof(zResult), zResult, "%08x", cksum); 343 + return zResult; 344 +} 319 345 320 346 /* 321 347 ** Finish the incremental MD5 checksum. Store the result in blob pOut 322 348 ** if pOut!=0. Also return a pointer to the result. 323 349 ** 324 350 ** This resets the incremental checksum preparing for the next round 325 351 ** of computation. The return pointer points to a static buffer that
Changes to src/merge3.c.
149 149 int blob_merge(Blob *pPivot, Blob *pV1, Blob *pV2, Blob *pOut){ 150 150 int *aC1; /* Changes from pPivot to pV1 */ 151 151 int *aC2; /* Changes from pPivot to pV2 */ 152 152 int i1, i2; /* Index into aC1[] and aC2[] */ 153 153 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */ 154 154 int limit1, limit2; /* Sizes of aC1[] and aC2[] */ 155 155 int nConflict = 0; /* Number of merge conflicts seen so far */ 156 - static const char zBegin[] = ">>>>>>> BEGIN MERGE CONFLICT\n"; 156 + static const char zBegin[] = "<<<<<<< BEGIN MERGE CONFLICT\n"; 157 157 static const char zMid[] = "============================\n"; 158 - static const char zEnd[] = "<<<<<<< END MERGE CONFLICT\n"; 158 + static const char zEnd[] = ">>>>>>> END MERGE CONFLICT\n"; 159 159 160 160 blob_zero(pOut); /* Merge results stored in pOut */ 161 161 162 162 /* Compute the edits that occur from pPivot => pV1 (into aC1) 163 163 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is 164 164 ** an array of integer triples. Within each triple, the first integer 165 165 ** is the number of lines of text to copy directly from the pivot, 166 166 ** the second integer is the number of lines of text to omit from the 167 167 ** pivot, and the third integer is the number of lines of text that are 168 168 ** inserted. The edit array ends with a triple of 0,0,0. 169 169 */ 170 - aC1 = text_diff(pPivot, pV1, 0, 0); 171 - aC2 = text_diff(pPivot, pV2, 0, 0); 170 + aC1 = text_diff(pPivot, pV1, 0, 0, 1); 171 + aC2 = text_diff(pPivot, pV2, 0, 0, 1); 172 172 if( aC1==0 || aC2==0 ){ 173 173 free(aC1); 174 174 free(aC2); 175 175 return -1; 176 176 } 177 177 178 178 blob_rewind(pV1); /* Rewind inputs: Needed to reconstruct output */
Changes to src/name.c.
109 109 return rc; 110 110 } 111 111 112 112 /* 113 113 ** Return TRUE if the string begins with an ISO8601 date: YYYY-MM-DD. 114 114 */ 115 115 static int is_date(const char *z){ 116 - if( !isdigit(z[0]) ) return 0; 117 - if( !isdigit(z[1]) ) return 0; 118 - if( !isdigit(z[2]) ) return 0; 119 - if( !isdigit(z[3]) ) return 0; 116 + if( !fossil_isdigit(z[0]) ) return 0; 117 + if( !fossil_isdigit(z[1]) ) return 0; 118 + if( !fossil_isdigit(z[2]) ) return 0; 119 + if( !fossil_isdigit(z[3]) ) return 0; 120 120 if( z[4]!='-') return 0; 121 - if( !isdigit(z[5]) ) return 0; 122 - if( !isdigit(z[6]) ) return 0; 121 + if( !fossil_isdigit(z[5]) ) return 0; 122 + if( !fossil_isdigit(z[6]) ) return 0; 123 123 if( z[7]!='-') return 0; 124 - if( !isdigit(z[8]) ) return 0; 125 - if( !isdigit(z[9]) ) return 0; 124 + if( !fossil_isdigit(z[8]) ) return 0; 125 + if( !fossil_isdigit(z[9]) ) return 0; 126 126 return 1; 127 127 } 128 128 129 129 /* 130 130 ** Convert a symbolic tag name into the UUID of a check-in that contains 131 131 ** that tag. If the tag appears on multiple check-ins, return the UUID 132 132 ** of the most recent check-in with the tag. ................................................................................ 278 278 int rid; 279 279 Blob name; 280 280 281 281 if( zName==0 || zName[0]==0 ) return 0; 282 282 blob_init(&name, zName, -1); 283 283 if( name_to_uuid(&name, -1) ){ 284 284 blob_reset(&name); 285 - for(i=0; zName[i] && isdigit(zName[i]); i++){} 285 + for(i=0; zName[i] && fossil_isdigit(zName[i]); i++){} 286 286 if( zName[i]==0 ){ 287 287 rid = atoi(zName); 288 288 if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){ 289 289 return rid; 290 290 } 291 291 } 292 292 fossil_error(1, "no such artifact: %s", zName); ................................................................................ 346 346 Blob name; 347 347 348 348 if( zName==0 || zName[0]==0 ) return 0; 349 349 blob_init(&name, zName, -1); 350 350 rc = name_to_uuid(&name, -1); 351 351 if( rc==1 ){ 352 352 blob_reset(&name); 353 - for(i=0; zName[i] && isdigit(zName[i]); i++){} 353 + for(i=0; zName[i] && fossil_isdigit(zName[i]); i++){} 354 354 if( zName[i]==0 ){ 355 355 rid = atoi(zName); 356 356 if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){ 357 357 return rid; 358 358 } 359 359 } 360 360 return 0;
Added src/popen.c.
1 +/* 2 +** Copyright (c) 2010 D. Richard Hipp 3 +** 4 +** This program is free software; you can redistribute it and/or 5 +** modify it under the terms of the Simplified BSD License (also 6 +** known as the "2-Clause License" or "FreeBSD License".) 7 + 8 +** This program is distributed in the hope that it will be useful, 9 +** but without any warranty; without even the implied warranty of 10 +** merchantability or fitness for a particular purpose. 11 +** 12 +** Author contact information: 13 +** drh@hwaci.com 14 +** http://www.hwaci.com/drh/ 15 +** 16 +******************************************************************************* 17 +** 18 +** This file contains an implementation of a bi-directional popen(). 19 +*/ 20 +#include "config.h" 21 +#include "popen.h" 22 + 23 +#ifdef _WIN32 24 +#include <windows.h> 25 +#include <fcntl.h> 26 +/* 27 +** Print a fatal error and quit. 28 +*/ 29 +static void win32_fatal_error(const char *zMsg){ 30 + fossil_fatal("%s"); 31 +} 32 +#endif 33 + 34 + 35 + 36 +#ifdef _WIN32 37 +/* 38 +** On windows, create a child process and specify the stdin, stdout, 39 +** and stderr channels for that process to use. 40 +** 41 +** Return the number of errors. 42 +*/ 43 +static int win32_create_child_process( 44 + char *zCmd, /* The command that the child process will run */ 45 + HANDLE hIn, /* Standard input */ 46 + HANDLE hOut, /* Standard output */ 47 + HANDLE hErr, /* Standard error */ 48 + DWORD *pChildPid /* OUT: Child process handle */ 49 +){ 50 + STARTUPINFO si; 51 + PROCESS_INFORMATION pi; 52 + BOOL rc; 53 + 54 + memset(&si, 0, sizeof(si)); 55 + si.cb = sizeof(si); 56 + si.dwFlags = STARTF_USESTDHANDLES; 57 + SetHandleInformation(hIn, HANDLE_FLAG_INHERIT, TRUE); 58 + si.hStdInput = hIn; 59 + SetHandleInformation(hOut, HANDLE_FLAG_INHERIT, TRUE); 60 + si.hStdOutput = hOut; 61 + SetHandleInformation(hErr, HANDLE_FLAG_INHERIT, TRUE); 62 + si.hStdError = hErr; 63 + rc = CreateProcess( 64 + NULL, /* Application Name */ 65 + zCmd, /* Command-line */ 66 + NULL, /* Process attributes */ 67 + NULL, /* Thread attributes */ 68 + TRUE, /* Inherit Handles */ 69 + 0, /* Create flags */ 70 + NULL, /* Environment */ 71 + NULL, /* Current directory */ 72 + &si, /* Startup Info */ 73 + &pi /* Process Info */ 74 + ); 75 + if( rc ){ 76 + CloseHandle( pi.hProcess ); 77 + CloseHandle( pi.hThread ); 78 + *pChildPid = pi.dwProcessId; 79 + }else{ 80 + win32_fatal_error("cannot create child process"); 81 + } 82 + return rc!=0; 83 +} 84 +#endif 85 + 86 +/* 87 +** Create a child process running shell command "zCmd". *ppOut is 88 +** a FILE that becomes the standard input of the child process. 89 +** (The caller writes to *ppOut in order to send text to the child.) 90 +** *ppIn is stdout from the child process. (The caller 91 +** reads from *ppIn in order to receive input from the child.) 92 +** Note that *ppIn is an unbuffered file descriptor, not a FILE. 93 +** The process ID of the child is written into *pChildPid. 94 +** 95 +** Return the number of errors. 96 +*/ 97 +int popen2(const char *zCmd, int *pfdIn, FILE **ppOut, int *pChildPid){ 98 +#ifdef _WIN32 99 + HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr, hStderr; 100 + SECURITY_ATTRIBUTES saAttr; 101 + DWORD childPid = 0; 102 + int fd; 103 + 104 + saAttr.nLength = sizeof(saAttr); 105 + saAttr.bInheritHandle = TRUE; 106 + saAttr.lpSecurityDescriptor = NULL; 107 + hStderr = GetStdHandle(STD_ERROR_HANDLE); 108 + if( !CreatePipe(&hStdoutRd, &hStdoutWr, &saAttr, 4096) ){ 109 + win32_fatal_error("cannot create pipe for stdout"); 110 + } 111 + SetHandleInformation( hStdoutRd, HANDLE_FLAG_INHERIT, FALSE); 112 + 113 + if( !CreatePipe(&hStdinRd, &hStdinWr, &saAttr, 4096) ){ 114 + win32_fatal_error("cannot create pipe for stdin"); 115 + } 116 + SetHandleInformation( hStdinWr, HANDLE_FLAG_INHERIT, FALSE); 117 + 118 + win32_create_child_process((char*)zCmd, 119 + hStdinRd, hStdoutWr, hStderr,&childPid); 120 + *pChildPid = childPid; 121 + *pfdIn = _open_osfhandle((long)hStdoutRd, 0); 122 + fd = _open_osfhandle((long)hStdinWr, 0); 123 + *ppOut = _fdopen(fd, "w"); 124 + CloseHandle(hStdinRd); 125 + CloseHandle(hStdoutWr); 126 + return 0; 127 +#else 128 + int pin[2], pout[2]; 129 + *pfdIn = 0; 130 + *ppOut = 0; 131 + *pChildPid = 0; 132 + 133 + if( pipe(pin)<0 ){ 134 + return 1; 135 + } 136 + if( pipe(pout)<0 ){ 137 + close(pin[0]); 138 + close(pin[1]); 139 + return 1; 140 + } 141 + *pChildPid = fork(); 142 + if( *pChildPid<0 ){ 143 + close(pin[0]); 144 + close(pin[1]); 145 + close(pout[0]); 146 + close(pout[1]); 147 + *pChildPid = 0; 148 + return 1; 149 + } 150 + if( *pChildPid==0 ){ 151 + /* This is the child process */ 152 + close(0); 153 + dup(pout[0]); 154 + close(pout[0]); 155 + close(pout[1]); 156 + close(1); 157 + dup(pin[1]); 158 + close(pin[0]); 159 + close(pin[1]); 160 + execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0); 161 + return 1; 162 + }else{ 163 + /* This is the parent process */ 164 + close(pin[1]); 165 + *pfdIn = pin[0]; 166 + close(pout[0]); 167 + *ppOut = fdopen(pout[1], "w"); 168 + return 0; 169 + } 170 +#endif 171 +} 172 + 173 +/* 174 +** Close the connection to a child process previously created using 175 +** popen2(). Kill off the child process, then close the pipes. 176 +*/ 177 +void pclose2(int fdIn, FILE *pOut, int childPid){ 178 +#ifdef _WIN32 179 + /* Not implemented, yet */ 180 + close(fdIn); 181 + fclose(pOut); 182 +#else 183 + close(fdIn); 184 + fclose(pOut); 185 + kill(childPid, SIGINT); 186 +#endif 187 +}
Changes to src/pqueue.c.
60 60 pqueue_init(p); 61 61 } 62 62 63 63 /* 64 64 ** Change the size of the queue so that it contains N slots 65 65 */ 66 66 static void pqueue_resize(PQueue *p, int N){ 67 - p->a = realloc(p->a, sizeof(p->a[0])*N); 67 + p->a = fossil_realloc(p->a, sizeof(p->a[0])*N); 68 68 p->sz = N; 69 69 } 70 70 71 71 /* 72 72 ** Insert element e into the queue. 73 73 */ 74 74 void pqueue_insert(PQueue *p, int e, double v){
Changes to src/printf.c.
42 42 NULL pointers replaced by SQL NULL. %Q */ 43 43 #define etPOINTER 15 /* The %p conversion */ 44 44 #define etHTMLIZE 16 /* Make text safe for HTML */ 45 45 #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */ 46 46 #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */ 47 47 #define etFOSSILIZE 19 /* The fossil header encoding format. */ 48 48 #define etPATH 20 /* Path type */ 49 -#define etWIKISTR 21 /* Wiki text rendered from a char* */ 50 -#define etWIKIBLOB 22 /* Wiki text rendered from a Blob* */ 51 -#define etSTRINGID 23 /* String with length limit for a UUID prefix */ 49 +#define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ 50 +#define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ 51 +#define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ 52 52 53 53 54 54 /* 55 55 ** An "etByte" is an 8-bit unsigned value. 56 56 */ 57 57 typedef unsigned char etByte; 58 58 ................................................................................ 558 558 break; 559 559 case etPATH: { 560 560 int i; 561 561 int limit = flag_alternateform ? va_arg(ap,int) : -1; 562 562 char *e = va_arg(ap,char*); 563 563 if( e==0 ){e="";} 564 564 length = StrNLen32(e, limit); 565 - zExtra = bufpt = malloc(length+1); 565 + zExtra = bufpt = fossil_malloc(length+1); 566 566 for( i=0; i<length; i++ ){ 567 567 if( e[i]=='\\' ){ 568 568 bufpt[i]='/'; 569 569 }else{ 570 570 bufpt[i]=e[i]; 571 571 } 572 572 } ................................................................................ 603 603 Blob *pBlob = va_arg(ap, Blob*); 604 604 char *zOrig = blob_buffer(pBlob); 605 605 int i, j, n, cnt; 606 606 n = blob_size(pBlob); 607 607 if( limit>=0 && limit<n ) n = limit; 608 608 for(cnt=i=0; i<n; i++){ if( zOrig[i]=='\'' ) cnt++; } 609 609 if( n+cnt+2 > etBUFSIZE ){ 610 - bufpt = zExtra = malloc( n + cnt + 2 ); 610 + bufpt = zExtra = fossil_malloc( n + cnt + 2 ); 611 611 }else{ 612 612 bufpt = buf; 613 613 } 614 614 bufpt[0] = '\''; 615 615 for(i=0, j=1; i<n; i++, j++){ 616 616 if( zOrig[i]=='\'' ){ bufpt[j++] = '\''; } 617 617 bufpt[j] = zOrig[i]; ................................................................................ 632 632 if( limit<0 ) limit = strlen(escarg); 633 633 for(i=n=0; i<limit; i++){ 634 634 if( escarg[i]=='\'' ) n++; 635 635 } 636 636 needQuote = !isnull && xtype==etSQLESCAPE2; 637 637 n += i + 1 + needQuote*2; 638 638 if( n>etBUFSIZE ){ 639 - bufpt = zExtra = malloc( n ); 640 - if( bufpt==0 ) return -1; 639 + bufpt = zExtra = fossil_malloc( n ); 641 640 }else{ 642 641 bufpt = buf; 643 642 } 644 643 j = 0; 645 644 if( needQuote ) bufpt[j++] = '\''; 646 645 for(i=0; i<limit; i++){ 647 646 bufpt[j++] = ch = escarg[i];
Changes to src/rebuild.c.
70 70 @ CREATE TABLE IF NOT EXISTS concealed( 71 71 @ hash TEXT PRIMARY KEY, 72 72 @ content TEXT 73 73 @ ); 74 74 ; 75 75 76 76 /* 77 -** Variables used for progress information 77 +** Variables used to store state information about an on-going "rebuild" 78 +** or "deconstruct". 78 79 */ 79 80 static int totalSize; /* Total number of artifacts to process */ 80 81 static int processCnt; /* Number processed so far */ 81 82 static int ttyOutput; /* Do progress output */ 82 83 static Bag bagDone; /* Bag of records rebuilt */ 84 + 85 +static char *zFNameFormat; /* Format string for filenames on deconstruct */ 86 +static int prefixLength; /* Length of directory prefix for deconstruct */ 87 + 88 + 89 +/* 90 +** Draw the percent-complete message. 91 +** The input is actually the permill complete. 92 +*/ 93 +static void percent_complete(int permill){ 94 + static int lastOutput = -1; 95 + if( permill>lastOutput ){ 96 + printf(" %d.%d%% complete...\r", permill/10, permill%10); 97 + fflush(stdout); 98 + lastOutput = permill; 99 + } 100 +} 101 + 83 102 84 103 /* 85 104 ** Called after each artifact is processed 86 105 */ 87 106 static void rebuild_step_done(rid){ 88 107 /* assert( bag_find(&bagDone, rid)==0 ); */ 89 108 bag_insert(&bagDone, rid); 90 109 if( ttyOutput ){ 91 110 processCnt++; 92 - if (!g.fQuiet) { 93 - printf("%d (%d%%)...\r", processCnt, (processCnt*100/totalSize)); 94 - fflush(stdout); 111 + if (!g.fQuiet && totalSize>0) { 112 + percent_complete((processCnt*1000)/totalSize); 95 113 } 96 114 } 97 115 } 98 116 99 117 /* 100 118 ** Rebuild cross-referencing information for the artifact 101 119 ** rid with content pBase and all of its descendants. This 102 120 ** routine clears the content buffer before returning. 121 +** 122 +** If the zFNameFormat variable is set, then this routine is 123 +** called to run "fossil deconstruct" instead of the usual 124 +** "fossil rebuild". In that case, instead of rebuilding the 125 +** cross-referencing information, write the file content out 126 +** to the approriate directory. 127 +** 128 +** In both cases, this routine automatically recurses to process 129 +** other artifacts that are deltas off of the current artifact. 130 +** This is the most efficient way to extract all of the original 131 +** artifact content from the Fossil repository. 103 132 */ 104 133 static void rebuild_step(int rid, int size, Blob *pBase){ 105 134 static Stmt q1; 106 135 Bag children; 107 136 Blob copy; 108 137 Blob *pUse; 109 138 int nChild, i, cid; 110 139 111 - /* Fix up the "blob.size" field if needed. */ 112 - if( size!=blob_size(pBase) ){ 113 - db_multi_exec( 114 - "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid 115 - ); 116 - } 117 - 118 - /* Find all children of artifact rid */ 119 - db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid"); 120 - db_bind_int(&q1, ":rid", rid); 121 - bag_init(&children); 122 - while( db_step(&q1)==SQLITE_ROW ){ 123 - int cid = db_column_int(&q1, 0); 124 - if( !bag_find(&bagDone, cid) ){ 125 - bag_insert(&children, cid); 126 - } 127 - } 128 - nChild = bag_count(&children); 129 - db_reset(&q1); 130 - 131 - /* Crosslink the artifact */ 132 - if( nChild==0 ){ 133 - pUse = pBase; 134 - }else{ 135 - blob_copy(©, pBase); 136 - pUse = © 137 - } 138 - manifest_crosslink(rid, pUse); 139 - blob_reset(pUse); 140 - 141 - /* Call all children recursively */ 142 - for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){ 143 - Stmt q2; 144 - int sz; 145 - if( nChild==i ){ 140 + while( rid>0 ){ 141 + 142 + /* Fix up the "blob.size" field if needed. */ 143 + if( size!=blob_size(pBase) ){ 144 + db_multi_exec( 145 + "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid 146 + ); 147 + } 148 + 149 + /* Find all children of artifact rid */ 150 + db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid"); 151 + db_bind_int(&q1, ":rid", rid); 152 + bag_init(&children); 153 + while( db_step(&q1)==SQLITE_ROW ){ 154 + int cid = db_column_int(&q1, 0); 155 + if( !bag_find(&bagDone, cid) ){ 156 + bag_insert(&children, cid); 157 + } 158 + } 159 + nChild = bag_count(&children); 160 + db_reset(&q1); 161 + 162 + /* Crosslink the artifact */ 163 + if( nChild==0 ){ 146 164 pUse = pBase; 147 165 }else{ 148 166 blob_copy(©, pBase); 149 167 pUse = © 150 168 } 151 - db_prepare(&q2, "SELECT content, size FROM blob WHERE rid=%d", cid); 152 - if( db_step(&q2)==SQLITE_ROW && (sz = db_column_int(&q2,1))>=0 ){ 153 - Blob delta; 154 - db_ephemeral_blob(&q2, 0, &delta); 155 - blob_uncompress(&delta, &delta); 156 - blob_delta_apply(pUse, &delta, pUse); 157 - blob_reset(&delta); 158 - db_finalize(&q2); 159 - rebuild_step(cid, sz, pUse); 169 + if( zFNameFormat==0 ){ 170 + /* We are doing "fossil rebuild" */ 171 + manifest_crosslink(rid, pUse); 160 172 }else{ 161 - db_finalize(&q2); 162 - blob_reset(pUse); 173 + /* We are doing "fossil deconstruct" */ 174 + char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); 175 + char *zFile = mprintf(zFNameFormat, zUuid, zUuid+prefixLength); 176 + blob_write_to_file(pUse,zFile); 177 + free(zFile); 178 + free(zUuid); 179 + } 180 + blob_reset(pUse); 181 + rebuild_step_done(rid); 182 + 183 + /* Call all children recursively */ 184 + rid = 0; 185 + for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){ 186 + static Stmt q2; 187 + int sz; 188 + db_static_prepare(&q2, "SELECT content, size FROM blob WHERE rid=:rid"); 189 + db_bind_int(&q2, ":rid", cid); 190 + if( db_step(&q2)==SQLITE_ROW && (sz = db_column_int(&q2,1))>=0 ){ 191 + Blob delta, next; 192 + db_ephemeral_blob(&q2, 0, &delta); 193 + blob_uncompress(&delta, &delta); 194 + blob_delta_apply(pBase, &delta, &next); 195 + blob_reset(&delta); 196 + db_reset(&q2); 197 + if( i<nChild ){ 198 + rebuild_step(cid, sz, &next); 199 + }else{ 200 + /* Tail recursion */ 201 + rid = cid; 202 + size = sz; 203 + blob_reset(pBase); 204 + *pBase = next; 205 + } 206 + }else{ 207 + db_reset(&q2); 208 + blob_reset(pBase); 209 + } 163 210 } 211 + bag_clear(&children); 164 212 } 165 - bag_clear(&children); 166 - rebuild_step_done(rid); 167 213 } 168 214 169 215 /* 170 216 ** Check to see if the "sym-trunk" tag exists. If not, create it 171 217 ** and attach it to the very first check-in. 172 218 */ 173 219 static void rebuild_tag_trunk(void){ ................................................................................ 179 225 rid = db_int(0, "SELECT pid FROM plink AS x WHERE NOT EXISTS(" 180 226 " SELECT 1 FROM plink WHERE cid=x.pid)"); 181 227 if( rid==0 ) return; 182 228 183 229 /* Add the trunk tag to the root of the whole tree */ 184 230 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); 185 231 if( zUuid==0 ) return; 186 - tag_add_artifact("sym-", "trunk", zUuid, 0, 2); 187 - tag_add_artifact("", "branch", zUuid, "trunk", 2); 232 + tag_add_artifact("sym-", "trunk", zUuid, 0, 2, 0, 0); 233 + tag_add_artifact("", "branch", zUuid, "trunk", 2, 0, 0); 188 234 } 189 235 190 236 /* 191 237 ** Core function to rebuild the infomration in the derived tables of a 192 238 ** fossil repository from the blobs. This function is shared between 193 239 ** 'rebuild_database' ('rebuild') and 'reconstruct_cmd' 194 240 ** ('reconstruct'), both of which have to regenerate this information ................................................................................ 199 245 ** ability of fossil to accept records in any order and still 200 246 ** construct a sane repository. 201 247 */ 202 248 int rebuild_db(int randomize, int doOut){ 203 249 Stmt s; 204 250 int errCnt = 0; 205 251 char *zTable; 252 + int incrSize; 206 253 207 254 bag_init(&bagDone); 208 255 ttyOutput = doOut; 209 256 processCnt = 0; 210 257 if (!g.fQuiet) { 211 - printf("0 (0%%)...\r"); 212 - fflush(stdout); 258 + percent_complete(0); 213 259 } 214 260 db_multi_exec(zSchemaUpdates); 215 261 for(;;){ 216 262 zTable = db_text(0, 217 263 "SELECT name FROM sqlite_master /*scan*/" 218 264 " WHERE type='table'" 219 265 " AND name NOT IN ('blob','delta','rcvfrom','user'," ................................................................................ 237 283 "DELETE FROM unclustered" 238 284 " WHERE rid IN (SELECT rid FROM shun JOIN blob USING(uuid))" 239 285 ); 240 286 db_multi_exec( 241 287 "DELETE FROM config WHERE name IN ('remote-code', 'remote-maxid')" 242 288 ); 243 289 totalSize = db_int(0, "SELECT count(*) FROM blob"); 290 + incrSize = totalSize/100; 291 + totalSize += incrSize*2; 244 292 db_prepare(&s, 245 293 "SELECT rid, size FROM blob /*scan*/" 246 294 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" 247 295 " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)" 248 296 ); 249 297 manifest_crosslink_begin(); 250 298 while( db_step(&s)==SQLITE_ROW ){ ................................................................................ 274 322 db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid); 275 323 rebuild_step_done(rid); 276 324 } 277 325 } 278 326 db_finalize(&s); 279 327 manifest_crosslink_end(); 280 328 rebuild_tag_trunk(); 329 + if( !g.fQuiet && totalSize>0 ){ 330 + processCnt += incrSize; 331 + percent_complete((processCnt*1000)/totalSize); 332 + } 333 + create_cluster(); 334 + if( !g.fQuiet && totalSize>0 ){ 335 + processCnt += incrSize; 336 + percent_complete((processCnt*1000)/totalSize); 337 + } 281 338 if(!g.fQuiet && ttyOutput ){ 282 339 printf("\n"); 283 340 } 284 341 return errCnt; 285 342 } 286 343 287 344 /* ................................................................................ 293 350 ** records. Run this command after updating the fossil 294 351 ** executable in a way that changes the database schema. 295 352 */ 296 353 void rebuild_database(void){ 297 354 int forceFlag; 298 355 int randomizeFlag; 299 356 int errCnt; 357 + int omitVerify; 300 358 359 + omitVerify = find_option("noverify",0,0)!=0; 301 360 forceFlag = find_option("force","f",0)!=0; 302 361 randomizeFlag = find_option("randomize", 0, 0)!=0; 303 362 if( g.argc==3 ){ 304 363 db_open_repository(g.argv[2]); 305 364 }else{ 306 365 db_find_and_open_repository(1); 307 366 if( g.argc!=2 ){ ................................................................................ 314 373 ttyOutput = 1; 315 374 errCnt = rebuild_db(randomizeFlag, 1); 316 375 if( errCnt && !forceFlag ){ 317 376 printf("%d errors. Rolling back changes. Use --force to force a commit.\n", 318 377 errCnt); 319 378 db_end_transaction(1); 320 379 }else{ 380 + if( omitVerify ) verify_cancel(); 321 381 db_end_transaction(0); 322 382 } 323 383 } 324 384 325 385 /* 326 386 ** COMMAND: test-detach 327 387 ** ................................................................................ 338 398 "UPDATE config SET value=lower(hex(randomblob(20)))" 339 399 " WHERE name='project-code';" 340 400 "UPDATE config SET value='detached-' || value" 341 401 " WHERE name='project-name' AND value NOT GLOB 'detached-*';" 342 402 ); 343 403 db_end_transaction(0); 344 404 } 405 + 406 +/* 407 +** COMMAND: test-create-clusters 408 +** 409 +** Create clusters for all unclustered artifacts if the number of unclustered 410 +** artifacts exceeds the current clustering threshold. 411 +*/ 412 +void test_createcluster_cmd(void){ 413 + if( g.argc==3 ){ 414 + db_open_repository(g.argv[2]); 415 + }else{ 416 + db_find_and_open_repository(1); 417 + if( g.argc!=2 ){ 418 + usage("?REPOSITORY-FILENAME?"); 419 + } 420 + db_close(); 421 + db_open_repository(g.zRepositoryName); 422 + } 423 + db_begin_transaction(); 424 + create_cluster(); 425 + db_end_transaction(0); 426 +} 345 427 346 428 /* 347 429 ** COMMAND: scrub 348 430 ** %fossil scrub [--verily] [--force] [REPOSITORY] 349 431 ** 350 432 ** The command removes sensitive information (such as passwords) from a 351 433 ** repository so that the respository can be sent to an untrusted reader. ................................................................................ 399 481 db_end_transaction(0); 400 482 db_multi_exec("VACUUM;"); 401 483 }else{ 402 484 rebuild_db(0, 1); 403 485 db_end_transaction(0); 404 486 } 405 487 } 488 + 489 +/* 490 +** Recursively read all files from the directory zPath and install 491 +** every file read as a new artifact in the repository. 492 +*/ 493 +void recon_read_dir(char *zPath){ 494 + DIR *d; 495 + struct dirent *pEntry; 496 + Blob aContent; /* content of the just read artifact */ 497 + static int nFileRead = 0; 498 + 499 + d = opendir(zPath); 500 + if( d ){ 501 + while( (pEntry=readdir(d))!=0 ){ 502 + Blob path; 503 + char *zSubpath; 504 + 505 + if( pEntry->d_name[0]=='.' ){ 506 + continue; 507 + } 508 + zSubpath = mprintf("%s/%s",zPath,pEntry->d_name); 509 + if( file_isdir(zSubpath)==1 ){ 510 + recon_read_dir(zSubpath); 511 + } 512 + blob_init(&path, 0, 0); 513 + blob_appendf(&path, "%s", zSubpath); 514 + if( blob_read_from_file(&aContent, blob_str(&path))==-1 ){ 515 + fossil_panic("some unknown error occurred while reading \"%s\"", 516 + blob_str(&path)); 517 + } 518 + content_put(&aContent, 0, 0); 519 + blob_reset(&path); 520 + blob_reset(&aContent); 521 + free(zSubpath); 522 + printf("\r%d", ++nFileRead); 523 + fflush(stdout); 524 + } 525 + }else { 526 + fossil_panic("encountered error %d while trying to open \"%s\".", 527 + errno, g.argv[3]); 528 + } 529 +} 406 530 407 531 /* 408 532 ** COMMAND: reconstruct 409 533 ** 410 534 ** Usage: %fossil reconstruct FILENAME DIRECTORY 411 535 ** 412 536 ** This command studies the artifacts (files) in DIRECTORY and 413 537 ** reconstructs the fossil record from them. It places the new 414 -** fossil repository in FILENAME 538 +** fossil repository in FILENAME. Subdirectories are read, files 539 +** with leading '.' in the filename are ignored. 415 540 ** 416 541 */ 417 542 void reconstruct_cmd(void) { 418 543 char *zPassword; 419 - DIR *d; 420 - struct dirent *pEntry; 421 - Blob aContent; /* content of the just read artifact */ 422 544 if( g.argc!=4 ){ 423 545 usage("FILENAME DIRECTORY"); 424 546 } 425 547 if( file_isdir(g.argv[3])!=1 ){ 426 548 printf("\"%s\" is not a directory\n\n", g.argv[3]); 427 549 usage("FILENAME DIRECTORY"); 428 550 } 429 551 db_create_repository(g.argv[2]); 430 552 db_open_repository(g.argv[2]); 431 553 db_open_config(0); 432 554 db_begin_transaction(); 433 555 db_initial_setup(0, 0, 1); 434 556 435 - d = opendir(g.argv[3]); 436 - if( d ){ 437 - while( (pEntry=readdir(d))!=0 ){ 438 - Blob path; 439 - blob_init(&path, 0, 0); 440 - if( pEntry->d_name[0]=='.' ){ 441 - continue; 442 - } 443 - if( file_isdir(pEntry->d_name)==1 ){ 444 - continue; 445 - } 446 - blob_appendf(&path, "%s/%s", g.argv[3], pEntry->d_name); 447 - if( blob_read_from_file(&aContent, blob_str(&path))==-1 ){ 448 - fossil_panic("Some unknown error occurred while reading \"%s\"", blob_str(&path)); 449 - } 450 - content_put(&aContent, 0, 0); 451 - } 452 - } 453 - else { 454 - fossil_panic("Encountered error %d while trying to open \"%s\".", errno, g.argv[3]); 455 - } 557 + printf("Reading files from directory \"%s\"...\n", g.argv[3]); 558 + recon_read_dir(g.argv[3]); 559 + printf("\nBuilding the Fossil repository...\n"); 456 560 457 561 rebuild_db(0, 1); 458 562 563 + /* Skip the verify_before_commit() step on a reconstruct. Most artifacts 564 + ** will have been changed and verification therefore takes a really, really 565 + ** long time. 566 + */ 567 + verify_cancel(); 568 + 459 569 db_end_transaction(0); 460 570 printf("project-id: %s\n", db_get("project-code", 0)); 461 571 printf("server-id: %s\n", db_get("server-code", 0)); 462 572 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); 463 573 printf("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword); 464 574 } 575 + 576 +/* 577 +** COMMAND: deconstruct 578 +** 579 +** Usage %fossil deconstruct ?-R|--repository REPOSITORY? ?-L|--prefixlength N? DESTINATION 580 +** 581 +** This command exports all artifacts of o given repository and 582 +** writes all artifacts to the file system. The DESTINATION directory 583 +** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where 584 +** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters. 585 +** If -L|--prefixlength is given, the length (default 2) of the directory 586 +** prefix can be set to 0,1,..,9 characters. 587 +*/ 588 +void deconstruct_cmd(void){ 589 + const char *zDestDir; 590 + const char *zPrefixOpt; 591 + Stmt s; 592 + 593 + /* check number of arguments */ 594 + if( (g.argc != 3) && (g.argc != 5) && (g.argc != 7)){ 595 + usage ("?-R|--repository REPOSITORY? ?-L|--prefixlength N? DESTINATION"); 596 + } 597 + /* get and check argument destination directory */ 598 + zDestDir = g.argv[g.argc-1]; 599 + if( !*zDestDir || !file_isdir(zDestDir)) { 600 + fossil_panic("DESTINATION(%s) is not a directory!",zDestDir); 601 + } 602 + /* get and check prefix length argument and build format string */ 603 + zPrefixOpt=find_option("prefixlength","L",1); 604 + if( !zPrefixOpt ){ 605 + prefixLength = 2; 606 + }else{ 607 + if( zPrefixOpt[0]>='0' && zPrefixOpt[0]<='9' && !zPrefixOpt[1] ){ 608 + prefixLength = (int)(*zPrefixOpt-'0'); 609 + }else{ 610 + fossil_fatal("N(%s) is not a a valid prefix length!",zPrefixOpt); 611 + } 612 + } 613 +#ifndef _WIN32 614 + if( access(zDestDir, W_OK) ){ 615 + fossil_fatal("DESTINATION(%s) is not writeable!",zDestDir); 616 + } 617 +#else 618 + /* write access on windows is not checked, errors will be 619 + ** dected on blob_write_to_file 620 + */ 621 +#endif 622 + if( prefixLength ){ 623 + zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength); 624 + }else{ 625 + zFNameFormat = mprintf("%s/%%s",zDestDir); 626 + } 627 + /* open repository and open query for all artifacts */ 628 + db_find_and_open_repository(1); 629 + bag_init(&bagDone); 630 + ttyOutput = 1; 631 + processCnt = 0; 632 + if (!g.fQuiet) { 633 + printf("0 (0%%)...\r"); 634 + fflush(stdout); 635 + } 636 + totalSize = db_int(0, "SELECT count(*) FROM blob"); 637 + db_prepare(&s, 638 + "SELECT rid, size FROM blob /*scan*/" 639 + " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" 640 + " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)" 641 + ); 642 + while( db_step(&s)==SQLITE_ROW ){ 643 + int rid = db_column_int(&s, 0); 644 + int size = db_column_int(&s, 1); 645 + if( size>=0 ){ 646 + Blob content; 647 + content_get(rid, &content); 648 + rebuild_step(rid, size, &content); 649 + } 650 + } 651 + db_finalize(&s); 652 + db_prepare(&s, 653 + "SELECT rid, size FROM blob" 654 + " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" 655 + ); 656 + while( db_step(&s)==SQLITE_ROW ){ 657 + int rid = db_column_int(&s, 0); 658 + int size = db_column_int(&s, 1); 659 + if( size>=0 ){ 660 + if( !bag_find(&bagDone, rid) ){ 661 + Blob content; 662 + content_get(rid, &content); 663 + rebuild_step(rid, size, &content); 664 + } 665 + } 666 + } 667 + db_finalize(&s); 668 + if(!g.fQuiet && ttyOutput ){ 669 + printf("\n"); 670 + } 671 + 672 + /* free filename format string */ 673 + free(zFNameFormat); 674 + zFNameFormat = 0; 675 +}
Changes to src/report.c.
86 86 } 87 87 88 88 /* 89 89 ** Remove whitespace from both ends of a string. 90 90 */ 91 91 char *trim_string(const char *zOrig){ 92 92 int i; 93 - while( isspace(*zOrig) ){ zOrig++; } 93 + while( fossil_isspace(*zOrig) ){ zOrig++; } 94 94 i = strlen(zOrig); 95 - while( i>0 && isspace(zOrig[i-1]) ){ i--; } 95 + while( i>0 && fossil_isspace(zOrig[i-1]) ){ i--; } 96 96 return mprintf("%.*s", i, zOrig); 97 97 } 98 98 99 99 /* 100 100 ** Extract a numeric (integer) value from a string. 101 101 */ 102 102 char *extract_integer(const char *zOrig){ 103 103 if( zOrig == NULL || zOrig[0] == 0 ) return ""; 104 - while( *zOrig && !isdigit(*zOrig) ){ zOrig++; } 104 + while( *zOrig && !fossil_isdigit(*zOrig) ){ zOrig++; } 105 105 if( *zOrig ){ 106 106 /* we have a digit. atoi() will get as much of the number as it 107 107 ** can. We'll run it through mprintf() to get a string. Not 108 108 ** an efficient way to do it, but effective. 109 109 */ 110 110 return mprintf("%d", atoi(zOrig)); 111 111 } ................................................................................ 116 116 ** Remove blank lines from the beginning of a string and 117 117 ** all whitespace from the end. Removes whitespace preceeding a NL, 118 118 ** which also converts any CRNL sequence into a single NL. 119 119 */ 120 120 char *remove_blank_lines(const char *zOrig){ 121 121 int i, j, n; 122 122 char *z; 123 - for(i=j=0; isspace(zOrig[i]); i++){ if( zOrig[i]=='\n' ) j = i+1; } 123 + for(i=j=0; fossil_isspace(zOrig[i]); i++){ if( zOrig[i]=='\n' ) j = i+1; } 124 124 n = strlen(&zOrig[j]); 125 - while( n>0 && isspace(zOrig[j+n-1]) ){ n--; } 125 + while( n>0 && fossil_isspace(zOrig[j+n-1]) ){ n--; } 126 126 z = mprintf("%.*s", n, &zOrig[j]); 127 127 for(i=j=0; z[i]; i++){ 128 - if( z[i+1]=='\n' && z[i]!='\n' && isspace(z[i]) ){ 128 + if( z[i+1]=='\n' && z[i]!='\n' && fossil_isspace(z[i]) ){ 129 129 z[j] = z[i]; 130 - while(isspace(z[j]) && z[j] != '\n' ){ j--; } 130 + while(fossil_isspace(z[j]) && z[j] != '\n' ){ j--; } 131 131 j++; 132 132 continue; 133 133 } 134 134 135 135 z[j++] = z[i]; 136 136 } 137 137 z[j] = 0; ................................................................................ 143 143 144 144 /* 145 145 ** This is the SQLite authorizer callback used to make sure that the 146 146 ** SQL statements entered by users do not try to do anything untoward. 147 147 ** If anything suspicious is tried, set *(char**)pError to an error 148 148 ** message obtained from malloc. 149 149 */ 150 -static int report_query_authorizer( 150 +int report_query_authorizer( 151 151 void *pError, 152 152 int code, 153 153 const char *zArg1, 154 154 const char *zArg2, 155 155 const char *zArg3, 156 156 const char *zArg4 157 157 ){ ................................................................................ 210 210 const char *zTail; 211 211 sqlite3_stmt *pStmt; 212 212 int rc; 213 213 214 214 /* First make sure the SQL is a single query command by verifying that 215 215 ** the first token is "SELECT" and that there are no unquoted semicolons. 216 216 */ 217 - for(i=0; isspace(zSql[i]); i++){} 217 + for(i=0; fossil_isspace(zSql[i]); i++){} 218 218 if( strncasecmp(&zSql[i],"select",6)!=0 ){ 219 219 return mprintf("The SQL must be a SELECT statement"); 220 220 } 221 221 for(i=0; zSql[i]; i++){ 222 222 if( zSql[i]==';' ){ 223 223 int bad; 224 224 int c = zSql[i+1]; ................................................................................ 275 275 } 276 276 zTitle = db_column_text(&q, 0); 277 277 zSQL = db_column_text(&q, 1); 278 278 zOwner = db_column_text(&q, 2); 279 279 zClrKey = db_column_text(&q, 3); 280 280 @ <table cellpadding=0 cellspacing=0 border=0> 281 281 @ <tr><td valign="top" align="right">Title:</td><td width=15></td> 282 - @ <td colspan=3>%h(zTitle)</td></tr> 282 + @ <td colspan="3">%h(zTitle)</td></tr> 283 283 @ <tr><td valign="top" align="right">Owner:</td><td></td> 284 - @ <td colspan=3>%h(zOwner)</td></tr> 284 + @ <td colspan="3">%h(zOwner)</td></tr> 285 285 @ <tr><td valign="top" align="right">SQL:</td><td></td> 286 286 @ <td valign="top"><pre> 287 287 @ %h(zSQL) 288 288 @ </pre></td> 289 289 @ <td width=15></td><td valign="top"> 290 290 output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3"); 291 291 @ </td> ................................................................................ 326 326 return; 327 327 }else if( rn>0 && P("del1") ){ 328 328 zTitle = db_text(0, "SELECT title FROM reportfmt " 329 329 "WHERE rn=%d", rn); 330 330 if( zTitle==0 ) cgi_redirect("reportlist"); 331 331 332 332 style_header("Are You Sure?"); 333 - @ <form action="rptedit" method="POST"> 333 + @ <form action="rptedit" method="post"> 334 334 @ <p>You are about to delete all traces of the report 335 335 @ <strong>%h(zTitle)</strong> from 336 336 @ the database. This is an irreversible operation. All records 337 337 @ related to this report will be removed and cannot be recovered.</p> 338 338 @ 339 339 @ <input type="hidden" name="rn" value="%d(rn)"> 340 340 login_insert_csrf_secret(); ................................................................................ 391 391 zTitle = mprintf("Copy Of %s", zTitle); 392 392 zOwner = g.zLogin; 393 393 } 394 394 } 395 395 if( zOwner==0 ) zOwner = g.zLogin; 396 396 style_submenu_element("Cancel", "Cancel", "reportlist"); 397 397 if( rn>0 ){ 398 - style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); 398 + style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); 399 399 } 400 400 style_header(rn>0 ? "Edit Report Format":"Create New Report Format"); 401 401 if( zErr ){ 402 - @ <blockquote><font color="#ff0000"><b>%h(zErr)</b></font></blockquote> 402 + @ <blockquote class="reportError">%h(zErr)</blockquote> 403 403 } 404 - @ <form action="rptedit" method="POST"> 405 - @ <input type="hidden" name="rn" value="%d(rn)"> 406 - @ <p>Report Title:<br> 407 - @ <input type="text" name="t" value="%h(zTitle)" size="60"></p> 408 - @ <p>Enter a complete SQL query statement against the "TICKET" table:<br> 404 + @ <form action="rptedit" method="post"><div> 405 + @ <input type="hidden" name="rn" value="%d(rn)" /> 406 + @ <p>Report Title:<br /> 407 + @ <input type="text" name="t" value="%h(zTitle)" size="60" /></p> 408 + @ <p>Enter a complete SQL query statement against the "TICKET" table:<br /> 409 409 @ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea> 410 410 @ </p> 411 411 login_insert_csrf_secret(); 412 412 if( g.okAdmin ){ 413 413 @ <p>Report owner: 414 - @ <input type="text" name="w" size="20" value="%h(zOwner)"> 414 + @ <input type="text" name="w" size="20" value="%h(zOwner)" /> 415 415 @ </p> 416 416 } else { 417 - @ <input type="hidden" name="w" value="%h(zOwner)"> 417 + @ <input type="hidden" name="w" value="%h(zOwner)" /> 418 418 } 419 419 @ <p>Enter an optional color key in the following box. (If blank, no 420 420 @ color key is displayed.) Each line contains the text for a single 421 421 @ entry in the key. The first token of each line is the background 422 - @ color for that line.<br> 422 + @ color for that line.<br /> 423 423 @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea> 424 424 @ </p> 425 425 if( !g.okAdmin && strcmp(zOwner,g.zLogin)!=0 ){ 426 426 @ <p>This report format is owned by %h(zOwner). You are not allowed 427 427 @ to change it.</p> 428 428 @ </form> 429 429 report_format_hints(); 430 430 style_footer(); 431 431 return; 432 432 } 433 - @ <input type="submit" value="Apply Changes"> 433 + @ <input type="submit" value="Apply Changes" /> 434 434 if( rn>0 ){ 435 - @ <input type="submit" value="Delete This Report" name="del1"> 435 + @ <input type="submit" value="Delete This Report" name="del1" /> 436 436 } 437 - @ </form> 437 + @ </div></form> 438 438 report_format_hints(); 439 439 style_footer(); 440 440 } 441 441 442 442 /* 443 443 ** Output a bunch of text that provides information about report 444 444 ** formats ................................................................................ 446 446 static void report_format_hints(void){ 447 447 char *zSchema; 448 448 zSchema = db_text(0,"SELECT sql FROM sqlite_master WHERE name='ticket'"); 449 449 if( zSchema==0 ){ 450 450 zSchema = db_text(0,"SELECT sql FROM repository.sqlite_master" 451 451 " WHERE name='ticket'"); 452 452 } 453 - @ <hr><h3>TICKET Schema</h3> 453 + @ <hr /><h3>TICKET Schema</h3> 454 454 @ <blockquote><pre> 455 455 @ %h(zSchema) 456 456 @ </pre></blockquote> 457 457 @ <h3>Notes</h3> 458 458 @ <ul> 459 459 @ <li><p>The SQL must consist of a single SELECT statement</p></li> 460 460 @ ................................................................................ 476 476 @ 477 477 @ <h3>Examples</h3> 478 478 @ <p>In this example, the first column in the result set is named 479 479 @ "bgcolor". The value of this column is not displayed. Instead, it 480 480 @ selects the background color of each row based on the TICKET.STATUS 481 481 @ field of the database. The color key at the right shows the various 482 482 @ color codes.</p> 483 - @ <table align="right" style="margin: 0 5px;" border=1 cellspacing=0 width=125> 484 - @ <tr bgcolor="#f2dcdc"><td align="center">new or active</td></tr> 485 - @ <tr bgcolor="#e8e8bd"><td align="center">review</td></tr> 486 - @ <tr bgcolor="#cfe8bd"><td align="center">fixed</td></tr> 487 - @ <tr bgcolor="#bde5d6"><td align="center">tested</td></tr> 488 - @ <tr bgcolor="#cacae5"><td align="center">defer</td></tr> 489 - @ <tr bgcolor="#c8c8c8"><td align="center">closed</td></tr> 483 + @ <table class="rpteditex"> 484 + @ <tr style="background-color:#f2dcdc;"><td class="rpteditex">new or active</td></tr> 485 + @ <tr style="background-color:#e8e8bd;"><td class="rpteditex">review</td></tr> 486 + @ <tr style="background-color:#cfe8bd;"><td class="rpteditex">fixed</td></tr> 487 + @ <tr style="background-color:#bde5d6;"><td class="rpteditex">tested</td></tr> 488 + @ <tr style="background-color:#cacae5;"><td class="rpteditex">defer</td></tr> 489 + @ <tr style="background-color:#c8c8c8;"><td class="rpteditex">closed</td></tr> 490 490 @ </table> 491 491 @ <blockquote><pre> 492 492 @ SELECT 493 493 @ CASE WHEN status IN ('new','active') THEN '#f2dcdc' 494 494 @ WHEN status='review' THEN '#e8e8bd' 495 495 @ WHEN status='fixed' THEN '#cfe8bd' 496 496 @ WHEN status='tested' THEN '#bde5d6' ................................................................................ 508 508 @ priority AS 'Pri', 509 509 @ title AS 'Title' 510 510 @ FROM ticket 511 511 @ </pre></blockquote> 512 512 @ <p>To base the background color on the TICKET.PRIORITY or 513 513 @ TICKET.SEVERITY fields, substitute the following code for the 514 514 @ first column of the query:</p> 515 - @ <table align="right" style="margin: 0 5px;" border=1 cellspacing=0 width=125> 516 - @ <tr bgcolor="#f2dcdc"><td align="center">1</td></tr> 517 - @ <tr bgcolor="#e8e8bd"><td align="center">2</td></tr> 518 - @ <tr bgcolor="#cfe8bd"><td align="center">3</td></tr> 519 - @ <tr bgcolor="#cacae5"><td align="center">4</td></tr> 520 - @ <tr bgcolor="#c8c8c8"><td align="center">5</td></tr> 515 + @ <table class="rpteditex"> 516 + @ <tr style="background-color:#f2dcdc;"><td class="rpteditex">1</td></tr> 517 + @ <tr style="background-color:#e8e8bd;"><td class="rpteditex">2</td></tr> 518 + @ <tr style="background-color:#cfe8bd;"><td class="rpteditex">3</td></tr> 519 + @ <tr style="background-color:#cacae5;"><td class="rpteditex">4</td></tr> 520 + @ <tr style="background-color:#c8c8c8;"><td class="rpteditex">5</td></tr> 521 521 @ </table> 522 522 @ <blockquote><pre> 523 523 @ SELECT 524 524 @ CASE priority WHEN 1 THEN '#f2dcdc' 525 525 @ WHEN 2 THEN '#e8e8bd' 526 526 @ WHEN 3 THEN '#cfe8bd' 527 527 @ WHEN 4 THEN '#cacae5' ................................................................................ 581 581 @ title AS 'Title', 582 582 @ wiki(substr(description,0,80)) AS 'Description' 583 583 @ FROM ticket 584 584 @ </pre></blockquote> 585 585 @ 586 586 } 587 587 588 -#if 0 /* NOT USED */ 589 -static void column_header(int rn,const char *zCol, int nCol, int nSorted, 590 - const char *zDirection, const char *zExtra 591 -){ 592 - int set = (nCol==nSorted); 593 - int desc = !strcmp(zDirection,"DESC"); 594 - 595 - /* 596 - ** Clicking same column header 3 times in a row resets any sorting. 597 - ** Note that we link to rptview, which means embedded reports will get 598 - ** sent to the actual report view page as soon as a user tries to do 599 - ** any sorting. I don't see that as a Bad Thing. 600 - */ 601 - if(set && desc){ 602 - @ <th bgcolor="%s(BG1)" class="bkgnd1"> 603 - @ <a href="rptview?rn=%d(rn)%s(zExtra)">%h(zCol)</a></th> 604 - }else{ 605 - if(set){ 606 - @ <th bgcolor="%s(BG1)" class="bkgnd1"><a 607 - }else{ 608 - @ <th><a 609 - } 610 - @ href="rptview?rn=%d(rn)&order_by=%d(nCol)&\ 611 - @ order_dir=%s(desc?"ASC":"DESC")\ 612 - @ %s(zExtra)">%h(zCol)</a></th> 613 - } 614 -} 615 -#endif 616 - 617 588 /* 618 589 ** The state of the report generation. 619 590 */ 620 591 struct GenerateHTML { 621 592 int rn; /* Report number */ 622 593 int nCount; /* Row number */ 623 594 int nCol; /* Number of columns */ ................................................................................ 721 692 @ <tr><td colspan=%d(pState->nCol)><font size=1> </font></td></tr> 722 693 } 723 694 724 695 /* Output the data for this entry from the database 725 696 */ 726 697 zBg = pState->iBg>=0 ? azArg[pState->iBg] : 0; 727 698 if( zBg==0 ) zBg = "white"; 728 - @ <tr bgcolor="%h(zBg)"> 699 + @ <tr style="background-color:%h(zBg)"> 729 700 zTid = 0; 730 701 zPage[0] = 0; 731 702 for(i=0; i<nArg; i++){ 732 703 char *zData; 733 704 if( i==pState->iBg ) continue; 734 705 zData = azArg[i]; 735 706 if( zData==0 ) zData = ""; ................................................................................ 736 707 if( pState->iNewRow>=0 && i>=pState->iNewRow ){ 737 708 if( zTid && g.okWrite ){ 738 709 @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td> 739 710 zTid = 0; 740 711 } 741 712 if( zData[0] ){ 742 713 Blob content; 743 - @ </tr><tr bgcolor="%h(zBg)"><td colspan=%d(pState->nCol)> 714 + @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)> 744 715 blob_init(&content, zData, -1); 745 716 wiki_convert(&content, 0, 0); 746 717 blob_reset(&content); 747 718 } 748 719 }else if( azName[i][0]=='#' ){ 749 720 zTid = zData; 750 721 if( g.okHistory ){ ................................................................................ 770 741 /* 771 742 ** Output the text given in the argument. Convert tabs and newlines into 772 743 ** spaces. 773 744 */ 774 745 static void output_no_tabs(const char *z){ 775 746 while( z && z[0] ){ 776 747 int i, j; 777 - for(i=0; z[i] && (!isspace(z[i]) || z[i]==' '); i++){} 748 + for(i=0; z[i] && (!fossil_isspace(z[i]) || z[i]==' '); i++){} 778 749 if( i>0 ){ 779 750 cgi_printf("%.*s", i, z); 780 751 } 781 - for(j=i; isspace(z[j]); j++){} 752 + for(j=i; fossil_isspace(z[j]); j++){} 782 753 if( j>i ){ 783 754 cgi_printf("%*s", j-i, ""); 784 755 } 785 756 z += j; 786 757 } 787 758 } 788 759 ................................................................................ 814 785 815 786 /* 816 787 ** Generate HTML that describes a color key. 817 788 */ 818 789 void output_color_key(const char *zClrKey, int horiz, char *zTabArgs){ 819 790 int i, j, k; 820 791 char *zSafeKey, *zToFree; 821 - while( isspace(*zClrKey) ) zClrKey++; 792 + while( fossil_isspace(*zClrKey) ) zClrKey++; 822 793 if( zClrKey[0]==0 ) return; 823 794 @ <table %s(zTabArgs)> 824 795 if( horiz ){ 825 796 @ <tr> 826 797 } 827 798 zToFree = zSafeKey = mprintf("%h", zClrKey); 828 799 while( zSafeKey[0] ){ 829 - while( isspace(*zSafeKey) ) zSafeKey++; 830 - for(i=0; zSafeKey[i] && !isspace(zSafeKey[i]); i++){} 831 - for(j=i; isspace(zSafeKey[j]); j++){} 800 + while( fossil_isspace(*zSafeKey) ) zSafeKey++; 801 + for(i=0; zSafeKey[i] && !fossil_isspace(zSafeKey[i]); i++){} 802 + for(j=i; fossil_isspace(zSafeKey[j]); j++){} 832 803 for(k=j; zSafeKey[k] && zSafeKey[k]!='\n' && zSafeKey[k]!='\r'; k++){} 833 804 if( !horiz ){ 834 - cgi_printf("<tr bgcolor=\"%.*s\"><td>%.*s</td></tr>\n", 805 + cgi_printf("<tr style=\"background-color: %.*s;\"><td>%.*s</td></tr>\n", 835 806 i, zSafeKey, k-j, &zSafeKey[j]); 836 807 }else{ 837 - cgi_printf("<td bgcolor=\"%.*s\">%.*s</td>\n", 808 + cgi_printf("<td style=\"background-color: %.*s;\">%.*s</td>\n", 838 809 i, zSafeKey, k-j, &zSafeKey[j]); 839 810 } 840 811 zSafeKey += k; 841 812 } 842 813 free(zToFree); 843 814 if( horiz ){ 844 815 @ </tr> ................................................................................ 905 876 906 877 count = 0; 907 878 if( !tabs ){ 908 879 struct GenerateHTML sState; 909 880 910 881 db_multi_exec("PRAGMA empty_result_callbacks=ON"); 911 882 style_submenu_element("Raw", "Raw", 912 - "rptview?tablist=1&%s", PD("QUERY_STRING","")); 883 + "rptview?tablist=1&%h", PD("QUERY_STRING","")); 913 884 if( g.okAdmin 914 885 || (g.okTktFmt && g.zLogin && zOwner && strcmp(g.zLogin,zOwner)==0) ){ 915 886 style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn); 916 887 } 917 888 if( g.okTktFmt ){ 918 889 style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn); 919 890 } 920 891 if( g.okNewTkt ){ 921 892 style_submenu_element("New Ticket", "Create a new ticket", 922 893 "%s/tktnew", g.zTop); 923 894 } 924 895 style_header(zTitle); 925 896 output_color_key(zClrKey, 1, 926 - "border=0 cellpadding=3 cellspacing=0 class=\"report\""); 927 - @ <table border=1 cellpadding=2 cellspacing=0 class="report"> 897 + "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\""); 898 + @ <table border="1" cellpadding="2" cellspacing="0" class="report"> 928 899 sState.rn = rn; 929 900 sState.nCount = 0; 930 901 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr1); 931 902 sqlite3_exec(g.db, zSql, generate_html, &sState, &zErr2); 932 903 sqlite3_set_authorizer(g.db, 0, 0); 933 904 @ </table> 934 905 if( zErr1 ){ 935 - @ <p><font color="red"><b>Error: %h(zErr1)</b></font></p> 906 + @ <p class="reportError">Error: %h(zErr1)</p> 936 907 }else if( zErr2 ){ 937 - @ <p><font color="red"><b>Error: %h(zErr2)</b></font></p> 908 + @ <p class="reportError">Error: %h(zErr2)</p> 938 909 } 939 910 style_footer(); 940 911 }else{ 941 912 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr1); 942 913 sqlite3_exec(g.db, zSql, output_tab_separated, &count, &zErr2); 943 914 sqlite3_set_authorizer(g.db, 0, 0); 944 915 cgi_set_content_type("text/plain"); 945 916 } 946 917 } 918 + 919 +/* 920 +** report number for full table ticket export 921 +*/ 922 +static const char zFullTicketRptRn[] = "0"; 923 + 924 +/* 925 +** report title for full table ticket export 926 +*/ 927 +static const char zFullTicketRptTitle[] = "full ticket export"; 928 + 929 +/* 930 +** show all reports, which can be used for ticket show. 931 +** Output is written to stdout as tab delimited table 932 +*/ 933 +void rpt_list_reports(void){ 934 + Stmt q; 935 + char const aRptOutFrmt[] = "%s\t%s\n"; 936 + 937 + printf("Available reports:\n"); 938 + printf(aRptOutFrmt,"report number","report title"); 939 + printf(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle); 940 + db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn"); 941 + while( db_step(&q)==SQLITE_ROW ){ 942 + const char *zRn = db_column_text(&q, 0); 943 + const char *zTitle = db_column_text(&q, 1); 944 + 945 + printf(aRptOutFrmt,zRn,zTitle); 946 + } 947 + db_finalize(&q); 948 +} 949 + 950 +/* 951 +** user defined separator used by ticket show command 952 +*/ 953 +static const char *zSep = 0; 954 + 955 +/* 956 +** select the quoting algorithm for "ticket show" 957 +*/ 958 +#if INTERFACE 959 +typedef enum eTktShowEnc { tktNoTab=0, tktFossilize=1 } tTktShowEncoding; 960 +#endif 961 +static tTktShowEncoding tktEncode = tktNoTab; 962 + 963 +/* 964 +** Output the text given in the argument. Convert tabs and newlines into 965 +** spaces. 966 +*/ 967 +static void output_no_tabs_file(const char *z){ 968 + switch( tktEncode ){ 969 + case tktFossilize: 970 + { char *zFosZ; 971 + 972 + if( z && *z ){ 973 + zFosZ = fossilize(z,-1); 974 + printf("%s",zFosZ); 975 + free(zFosZ); 976 + } 977 + break; 978 + } 979 + default: 980 + while( z && z[0] ){ 981 + int i, j; 982 + for(i=0; z[i] && (!fossil_isspace(z[i]) || z[i]==' '); i++){} 983 + if( i>0 ){ 984 + printf("%.*s", i, z); 985 + } 986 + for(j=i; fossil_isspace(z[j]); j++){} 987 + if( j>i ){ 988 + printf("%*s", j-i, ""); 989 + } 990 + z += j; 991 + } 992 + break; 993 + } 994 +} 995 + 996 +/* 997 +** Output a row as a tab-separated line of text. 998 +*/ 999 +int output_separated_file( 1000 + void *pUser, /* Pointer to row-count integer */ 1001 + int nArg, /* Number of columns in this result row */ 1002 + char **azArg, /* Text of data in all columns */ 1003 + char **azName /* Names of the columns */ 1004 +){ 1005 + int *pCount = (int*)pUser; 1006 + int i; 1007 + 1008 + if( *pCount==0 ){ 1009 + for(i=0; i<nArg; i++){ 1010 + output_no_tabs_file(azName[i]); 1011 + printf("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n"); 1012 + } 1013 + } 1014 + ++*pCount; 1015 + for(i=0; i<nArg; i++){ 1016 + output_no_tabs_file(azArg[i]); 1017 + printf("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n"); 1018 + } 1019 + return 0; 1020 +} 1021 + 1022 +/* 1023 +** Generate a report. The rn query parameter is the report number. 1024 +** The output is written to stdout as flat file. The zFilter paramater 1025 +** is a full WHERE-condition. 1026 +*/ 1027 +void rptshow( 1028 + const char *zRep, 1029 + const char *zSepIn, 1030 + const char *zFilter, 1031 + tTktShowEncoding enc 1032 +){ 1033 + Stmt q; 1034 + char *zSql; 1035 + const char *zTitle; 1036 + const char *zOwner; 1037 + const char *zClrKey; 1038 + char *zErr1 = 0; 1039 + char *zErr2 = 0; 1040 + int count = 0; 1041 + int rn; 1042 + 1043 + if (!zRep || !strcmp(zRep,zFullTicketRptRn) || !strcmp(zRep,zFullTicketRptTitle) ){ 1044 + zTitle = zFullTicketRptTitle; 1045 + zSql = "SELECT * FROM ticket"; 1046 + zOwner = g.zLogin; 1047 + zClrKey = ""; 1048 + }else{ 1049 + rn = atoi(zRep); 1050 + if( rn ){ 1051 + db_prepare(&q, 1052 + "SELECT title, sqlcode, owner, cols FROM reportfmt WHERE rn=%d", rn); 1053 + }else{ 1054 + db_prepare(&q, 1055 + "SELECT title, sqlcode, owner, cols FROM reportfmt WHERE title='%s'", zRep); 1056 + } 1057 + if( db_step(&q)!=SQLITE_ROW ){ 1058 + db_finalize(&q); 1059 + rpt_list_reports(); 1060 + fossil_fatal("unkown report format(%s)!",zRep); 1061 + } 1062 + zTitle = db_column_malloc(&q, 0); 1063 + zSql = db_column_malloc(&q, 1); 1064 + zOwner = db_column_malloc(&q, 2); 1065 + zClrKey = db_column_malloc(&q, 3); 1066 + db_finalize(&q); 1067 + } 1068 + if( zFilter ){ 1069 + zSql = mprintf("SELECT * FROM (%s) WHERE %s",zSql,zFilter); 1070 + } 1071 + count = 0; 1072 + tktEncode = enc; 1073 + zSep = zSepIn; 1074 + sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr1); 1075 + sqlite3_exec(g.db, zSql, output_separated_file, &count, &zErr2); 1076 + sqlite3_set_authorizer(g.db, 0, 0); 1077 + if( zFilter ){ 1078 + free(zSql); 1079 + } 1080 +}
Changes to src/rss.c.
14 14 ** http://www.hwaci.com/drh/ 15 15 ** 16 16 ******************************************************************************* 17 17 ** 18 18 ** This file contains code used to create a RSS feed for the CGI interface. 19 19 */ 20 20 #include "config.h" 21 +#include <time.h> 21 22 #include "rss.h" 22 23 #include <assert.h> 23 -#include <time.h> 24 24 25 25 /* 26 26 ** WEBPAGE: timeline.rss 27 27 */ 28 28 void page_timeline_rss(void){ 29 29 Stmt q; 30 30 int nLine=0;
Changes to src/schema.c.
239 239 @ 240 240 @ -- A record of phantoms. A phantom is a record for which we know the 241 241 @ -- UUID but we do not (yet) know the file content. 242 242 @ -- 243 243 @ CREATE TABLE phantom( 244 244 @ rid INTEGER PRIMARY KEY -- Record ID of the phantom 245 245 @ ); 246 +@ 247 +@ -- A record of orphaned delta-manifests. An orphan is a delta-manifest 248 +@ -- for which we have content, but its baseline-manifest is a phantom. 249 +@ -- We have to track all orphan maniftests so that when the baseline arrives, 250 +@ -- we know to process the orphaned deltas. 251 +@ CREATE TABLE orphan( 252 +@ rid INTEGER PRIMARY KEY, -- Delta manifest with a phantom baseline 253 +@ baseline INTEGER -- Phantom baseline of this orphan 254 +@ ); 255 +@ CREATE INDEX orphan_baseline ON orphan(baseline); 246 256 @ 247 257 @ -- Unclustered records. An unclustered record is a record (including 248 258 @ -- a cluster records themselves) that is not mentioned by some other 249 259 @ -- cluster. 250 260 @ -- 251 261 @ -- Phantoms are usually included in the unclustered table. A new cluster 252 262 @ -- will never be created that contains a phantom. But another repository
Changes to src/search.c.
40 40 */ 41 41 Search *search_init(const char *zPattern){ 42 42 int nPattern = strlen(zPattern); 43 43 Search *p; 44 44 char *z; 45 45 int i; 46 46 47 - p = malloc( nPattern + sizeof(*p) + 1); 48 - if( p==0 ) fossil_panic("out of memory"); 47 + p = fossil_malloc( nPattern + sizeof(*p) + 1); 49 48 z = (char*)&p[1]; 50 49 strcpy(z, zPattern); 51 50 memset(p, 0, sizeof(*p)); 52 51 while( *z && p->nTerm<sizeof(p->a)/sizeof(p->a[0]) ){ 53 - while( !isalnum(*z) && *z ){ z++; } 52 + while( !fossil_isalnum(*z) && *z ){ z++; } 54 53 if( *z==0 ) break; 55 54 p->a[p->nTerm].z = z; 56 - for(i=1; isalnum(z[i]) || z[i]=='_'; i++){} 55 + for(i=1; fossil_isalnum(z[i]) || z[i]=='_'; i++){} 57 56 p->a[p->nTerm].n = i; 58 57 z += i; 59 58 p->nTerm++; 60 59 } 61 60 return p; 62 61 } 63 62
Changes to src/setup.c.
17 17 ** 18 18 ** Implementation of the Setup page 19 19 */ 20 20 #include <assert.h> 21 21 #include "config.h" 22 22 #include "setup.h" 23 23 24 +/* 25 +** The table of web pages supported by this application is generated 26 +** automatically by the "mkindex" program and written into a file 27 +** named "page_index.h". We include that file here to get access 28 +** to the table. 29 +*/ 30 +#include "page_index.h" 24 31 25 32 /* 26 33 ** Output a single entry for a menu generated using an HTML table. 27 34 ** If zLink is not NULL or an empty string, then it is the page that 28 35 ** the menu entry will hyperlink to. If zLink is NULL or "", then 29 36 ** the menu entry has no hyperlink - it is disabled. 30 37 */ ................................................................................ 55 62 @ <table border="0" cellspacing="20"> 56 63 setup_menu_entry("Users", "setup_ulist", 57 64 "Grant privileges to individual users."); 58 65 setup_menu_entry("Access", "setup_access", 59 66 "Control access settings."); 60 67 setup_menu_entry("Configuration", "setup_config", 61 68 "Configure the WWW components of the repository"); 69 + setup_menu_entry("Settings", "setup_settings", 70 + "Web interface to the \"fossil settings\" command"); 62 71 setup_menu_entry("Timeline", "setup_timeline", 63 72 "Timeline display preferences"); 64 73 setup_menu_entry("Tickets", "tktsetup", 65 74 "Configure the trouble-ticketing system for this repository"); 66 75 setup_menu_entry("Skins", "setup_skin", 67 76 "Select from a menu of prepackaged \"skins\" for the web interface"); 68 77 setup_menu_entry("CSS", "setup_editcss", ................................................................................ 97 106 if( !g.okAdmin ){ 98 107 login_needed(); 99 108 return; 100 109 } 101 110 102 111 style_submenu_element("Add", "Add User", "setup_uedit"); 103 112 style_header("User List"); 104 - @ <table border="0" cellpadding="0" cellspacing="25"> 105 - @ <tr><td valign="top"> 106 - @ <b>Users:</b> 107 - @ <table border="1" cellpadding="10"><tr><td> 108 - @ <table cellspacing=0 cellpadding=0 border=0> 113 + @ <table class="usetupLayoutTable"> 114 + @ <tr><td class="usetupColumnLayout"> 115 + @ <span class="note">Users:</span> 116 + @ <table class="usetupUserList"> 109 117 @ <tr> 110 - @ <th align="right">User ID</th><td width="20"> </td> 111 - @ <th>Capabilities</th><td width="15"> </td> 112 - @ <th>Contact Info</th> 118 + @ <th class="usetupListUser" style="text-align: right;padding-right: 20px;">User ID</th> 119 + @ <th class="usetupListCap" style="text-align: center;padding-right: 15px;">Capabilities</th> 120 + @ <th class="usetupListCon" style="text-align: left;">Contact Info</th> 113 121 @ </tr> 114 122 db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login"); 115 123 while( db_step(&s)==SQLITE_ROW ){ 116 124 const char *zCap = db_column_text(&s, 2); 117 125 if( strstr(zCap, "s") ) zCap = "s"; 118 126 @ <tr> 119 - @ <td align="right"> 127 + @ <td class="usetupListUser" style="text-align: right;padding-right: 20px;white-space:nowrap;"> 120 128 if( g.okAdmin && (zCap[0]!='s' || g.okSetup) ){ 121 129 @ <a href="setup_uedit?id=%d(db_column_int(&s,0))"> 122 130 } 123 - @ <nobr>%h(db_column_text(&s,1))</nobr> 131 + @ %h(db_column_text(&s,1)) 124 132 if( g.okAdmin ){ 125 133 @ </a> 126 134 } 127 - @ </td><td> </td> 128 - @ <td align="center">%s(zCap)</td> 129 - @ <td> </td> 130 - @ <td align="left">%s(db_column_text(&s,3))</td> 135 + @ </td> 136 + @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td> 137 + @ <td class="usetupListCon" style="text-align: left;">%s(db_column_text(&s,3))</td> 131 138 @ </tr> 132 139 } 133 - @ </table></td></tr></table> 134 - @ <td valign="top"> 135 - @ <b>Notes:</b> 140 + @ </table> 141 + @ </td><td class="usetupColumnLayout"> 142 + @ <span class="note">Notes:</span> 136 143 @ <ol> 137 144 @ <li><p>The permission flags are as follows:</p> 138 145 @ <table> 139 146 @ <tr><td valign="top"><b>a</b></td> 140 147 @ <td><i>Admin:</i> Create and delete users</td></tr> 141 148 @ <tr><td valign="top"><b>b</b></td> 142 149 @ <td><i>Attach:</i> Add attachments to wiki or tickets</td></tr> ................................................................................ 179 186 @ <tr><td valign="top"><b>v</b></td> 180 187 @ <td><i>Developer:</i> Inherit privileges of 181 188 @ user <tt>developer</tt></td></tr> 182 189 @ <tr><td valign="top"><b>w</b></td> 183 190 @ <td><i>Write-Tkt:</i> Edit tickets</td></tr> 184 191 @ <tr><td valign="top"><b>z</b></td> 185 192 @ <td><i>Zip download:</i> Download a baseline via the 186 - @ <tt>/zip</tt> URL even without check<b>o</b>ut 187 - @ and <b>h</b>istory permissions</td></tr> 193 + @ <tt>/zip</tt> URL even without 194 + @ check<span class="capability">o</span>ut 195 + @ and <span class="capability">h</span>istory permissions</td></tr> 188 196 @ </table> 189 197 @ </li> 190 198 @ 191 199 @ <li><p> 192 - @ Every user, logged in or not, inherits the privileges of <b>nobody</b>. 200 + @ Every user, logged in or not, inherits the privileges of 201 + @ <span class="usertype">nobody</span>. 193 202 @ </p></li> 194 203 @ 195 204 @ <li><p> 196 - @ Any human can login as <b>anonymous</b> since the password is 197 - @ clearly displayed on the login page for them to type. The purpose 198 - @ of requiring anonymous to log in is to prevent access by spiders. 205 + @ Any human can login as <span class="usertype">anonymous</span> since the 206 + @ password is clearly displayed on the login page for them to type. The 207 + @ purpose of requiring anonymous to log in is to prevent access by spiders. 199 208 @ Every logged-in user inherits the combined privileges of 200 - @ <b>anonymous</b> and 201 - @ <b>nobody</b>. 209 + @ <span class="usertype">anonymous</span> and 210 + @ <span class="usertype">nobody</span>. 202 211 @ </p></li> 203 212 @ 204 213 @ <li><p> 205 - @ Users with privilege <b>v</b> inherit the combined privileges of 206 - @ <b>developer</b>, <b>anonymous</b>, and <b>nobody</b>. 214 + @ Users with privilege <span class="capability">v</span> inherit the combined 215 + @ privileges of <span class="usertype">developer</span>, 216 + @ <span class="usertype">anonymous</span>, and 217 + @ <span class="usertype">nobody</span>. 207 218 @ </p></li> 208 219 @ 209 220 @ </ol> 210 221 @ </td></tr></table> 211 222 style_footer(); 212 223 } 213 224 ................................................................................ 321 332 }else{ 322 333 zPw = db_text(0, "SELECT pw FROM user WHERE uid=%d", uid); 323 334 } 324 335 if( uid>0 && 325 336 db_exists("SELECT 1 FROM user WHERE login=%Q AND uid!=%d", zLogin, uid) 326 337 ){ 327 338 style_header("User Creation Error"); 328 - @ <font color="red">Login "%h(zLogin)" is already used by a different 329 - @ user.</font> 339 + @ <span class="loginError">Login "%h(zLogin)" is already used by 340 + @ a different user.</span> 330 341 @ 331 342 @ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p> 332 343 style_footer(); 333 344 return; 334 345 } 335 346 login_verify_csrf_secret(); 336 347 db_multi_exec( ................................................................................ 351 362 oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oam = 352 363 oan = oao = oap = oar = oas = oat = oau = oav = oaw = oaz = ""; 353 364 if( uid ){ 354 365 zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid); 355 366 zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid); 356 367 zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid); 357 368 zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", uid); 358 - if( strchr(zCap, 'a') ) oaa = " checked"; 359 - if( strchr(zCap, 'b') ) oab = " checked"; 360 - if( strchr(zCap, 'c') ) oac = " checked"; 361 - if( strchr(zCap, 'd') ) oad = " checked"; 362 - if( strchr(zCap, 'e') ) oae = " checked"; 363 - if( strchr(zCap, 'f') ) oaf = " checked"; 364 - if( strchr(zCap, 'g') ) oag = " checked"; 365 - if( strchr(zCap, 'h') ) oah = " checked"; 366 - if( strchr(zCap, 'i') ) oai = " checked"; 367 - if( strchr(zCap, 'j') ) oaj = " checked"; 368 - if( strchr(zCap, 'k') ) oak = " checked"; 369 - if( strchr(zCap, 'm') ) oam = " checked"; 370 - if( strchr(zCap, 'n') ) oan = " checked"; 371 - if( strchr(zCap, 'o') ) oao = " checked"; 372 - if( strchr(zCap, 'p') ) oap = " checked"; 373 - if( strchr(zCap, 'r') ) oar = " checked"; 374 - if( strchr(zCap, 's') ) oas = " checked"; 375 - if( strchr(zCap, 't') ) oat = " checked"; 376 - if( strchr(zCap, 'u') ) oau = " checked"; 377 - if( strchr(zCap, 'v') ) oav = " checked"; 378 - if( strchr(zCap, 'w') ) oaw = " checked"; 379 - if( strchr(zCap, 'z') ) oaz = " checked"; 369 + if( strchr(zCap, 'a') ) oaa = " checked=\"checked\""; 370 + if( strchr(zCap, 'b') ) oab = " checked=\"checked\""; 371 + if( strchr(zCap, 'c') ) oac = " checked=\"checked\""; 372 + if( strchr(zCap, 'd') ) oad = " checked=\"checked\""; 373 + if( strchr(zCap, 'e') ) oae = " checked=\"checked\""; 374 + if( strchr(zCap, 'f') ) oaf = " checked=\"checked\""; 375 + if( strchr(zCap, 'g') ) oag = " checked=\"checked\""; 376 + if( strchr(zCap, 'h') ) oah = " checked=\"checked\""; 377 + if( strchr(zCap, 'i') ) oai = " checked=\"checked\""; 378 + if( strchr(zCap, 'j') ) oaj = " checked=\"checked\""; 379 + if( strchr(zCap, 'k') ) oak = " checked=\"checked\""; 380 + if( strchr(zCap, 'm') ) oam = " checked=\"checked\""; 381 + if( strchr(zCap, 'n') ) oan = " checked=\"checked\""; 382 + if( strchr(zCap, 'o') ) oao = " checked=\"checked\""; 383 + if( strchr(zCap, 'p') ) oap = " checked=\"checked\""; 384 + if( strchr(zCap, 'r') ) oar = " checked=\"checked\""; 385 + if( strchr(zCap, 's') ) oas = " checked=\"checked\""; 386 + if( strchr(zCap, 't') ) oat = " checked=\"checked\""; 387 + if( strchr(zCap, 'u') ) oau = " checked=\"checked\""; 388 + if( strchr(zCap, 'v') ) oav = " checked=\"checked\""; 389 + if( strchr(zCap, 'w') ) oaw = " checked=\"checked\""; 390 + if( strchr(zCap, 'z') ) oaz = " checked=\"checked\""; 380 391 } 381 392 382 393 /* figure out inherited permissions */ 383 394 memset(inherit, 0, sizeof(inherit)); 384 395 if( strcmp(zLogin, "developer") ){ 385 396 char *z1, *z2; 386 397 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'"); 387 398 while( z1 && *z1 ){ 388 - inherit[0x7f & *(z1++)] = "<font color=\"red\">•</font>"; 399 + inherit[0x7f & *(z1++)] = 400 + "<span class=\"ueditInheritDeveloper\">•</span>"; 389 401 } 390 402 free(z2); 391 403 } 392 404 if( strcmp(zLogin, "reader") ){ 393 405 char *z1, *z2; 394 406 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='reader'"); 395 407 while( z1 && *z1 ){ 396 - inherit[0x7f & *(z1++)] = "<font color=\"black\">•</font>"; 408 + inherit[0x7f & *(z1++)] = 409 + "<span class=\"ueditInheritReader\">•</span>"; 397 410 } 398 411 free(z2); 399 412 } 400 413 if( strcmp(zLogin, "anonymous") ){ 401 414 char *z1, *z2; 402 415 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='anonymous'"); 403 416 while( z1 && *z1 ){ 404 - inherit[0x7f & *(z1++)] = "<font color=\"blue\">•</font>"; 417 + inherit[0x7f & *(z1++)] = 418 + "<span class=\"ueditInheritAnonymous\">•</span>"; 405 419 } 406 420 free(z2); 407 421 } 408 422 if( strcmp(zLogin, "nobody") ){ 409 423 char *z1, *z2; 410 424 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='nobody'"); 411 425 while( z1 && *z1 ){ 412 - inherit[0x7f & *(z1++)] = "<font color=\"green\">•</font>"; 426 + inherit[0x7f & *(z1++)] = 427 + "<span class=\"ueditInheritNobody\">•</span>"; 413 428 } 414 429 free(z2); 415 430 } 416 431 417 432 /* Begin generating the page 418 433 */ 419 434 style_submenu_element("Cancel", "Cancel", "setup_ulist"); 420 435 if( uid ){ 421 436 style_header(mprintf("Edit User %h", zLogin)); 422 437 }else{ 423 438 style_header("Add A New User"); 424 439 } 425 - @ <table align="left" hspace="20" vspace="10"><tr><td> 426 - @ <form action="%s(g.zPath)" method="POST"> 440 + @ <div class="ueditCapBox"> 441 + @ <form action="%s(g.zPath)" method="post"><div> 427 442 login_insert_csrf_secret(); 428 443 @ <table> 429 444 @ <tr> 430 - @ <td align="right"><nobr>User ID:</nobr></td> 445 + @ <td class="usetupEditLabel">User ID:</td> 431 446 if( uid ){ 432 - @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)"></td> 447 + @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" /></td> 433 448 }else{ 434 - @ <td>(new user)<input type="hidden" name="id" value=0></td> 449 + @ <td>(new user)<input type="hidden" name="id" value="0" /></td> 435 450 } 436 451 @ </tr> 452 + @ <tr> 453 + @ <td class="usetupEditLabel">Login:</td> 454 + @ <td><input type="text" name="login" value="%h(zLogin)" /></td> 455 + @ </tr> 437 456 @ <tr> 438 - @ <td align="right"><nobr>Login:</nobr></td> 439 - @ <td><input type="text" name="login" value="%h(zLogin)"></td> 457 + @ <td class="usetupEditLabel">Contact Info:</td> 458 + @ <td><input type="text" name="info" size="40" value="%h(zInfo)" /></td> 440 459 @ </tr> 441 460 @ <tr> 442 - @ <td align="right"><nobr>Contact Info:</nobr></td> 443 - @ <td><input type="text" name="info" size=40 value="%h(zInfo)"></td> 444 - @ </tr> 445 - @ <tr> 446 - @ <td align="right" valign="top">Capabilities:</td> 461 + @ <td class="usetupEditLabel">Capabilities:</td> 447 462 @ <td> 448 463 #define B(x) inherit[x] 449 464 if( g.okSetup ){ 450 - @ <input type="checkbox" name="as"%s(oas)/>%s(B('s'))Setup<br> 451 - } 452 - @ <input type="checkbox" name="aa"%s(oaa)/>%s(B('a'))Admin<br> 453 - @ <input type="checkbox" name="ad"%s(oad)/>%s(B('d'))Delete<br> 454 - @ <input type="checkbox" name="ae"%s(oae)/>%s(B('e'))Email<br> 455 - @ <input type="checkbox" name="ap"%s(oap)/>%s(B('p'))Password<br> 456 - @ <input type="checkbox" name="ai"%s(oai)/>%s(B('i'))Check-In<br> 457 - @ <input type="checkbox" name="ao"%s(oao)/>%s(B('o'))Check-Out<br> 458 - @ <input type="checkbox" name="ah"%s(oah)/>%s(B('h'))History<br> 459 - @ <input type="checkbox" name="au"%s(oau)/>%s(B('u'))Reader<br> 460 - @ <input type="checkbox" name="av"%s(oav)/>%s(B('v'))Developer<br> 461 - @ <input type="checkbox" name="ag"%s(oag)/>%s(B('g'))Clone<br> 462 - @ <input type="checkbox" name="aj"%s(oaj)/>%s(B('j'))Read Wiki<br> 463 - @ <input type="checkbox" name="af"%s(oaf)/>%s(B('f'))New Wiki<br> 464 - @ <input type="checkbox" name="am"%s(oam)/>%s(B('m'))Append Wiki<br> 465 - @ <input type="checkbox" name="ak"%s(oak)/>%s(B('k'))Write Wiki<br> 466 - @ <input type="checkbox" name="ab"%s(oab)/>%s(B('b'))Attachments<br> 467 - @ <input type="checkbox" name="ar"%s(oar)/>%s(B('r'))Read Ticket<br> 468 - @ <input type="checkbox" name="an"%s(oan)/>%s(B('n'))New Ticket<br> 469 - @ <input type="checkbox" name="ac"%s(oac)/>%s(B('c'))Append Ticket<br> 470 - @ <input type="checkbox" name="aw"%s(oaw)/>%s(B('w'))Write Ticket<br> 471 - @ <input type="checkbox" name="at"%s(oat)/>%s(B('t'))Ticket Report<br> 472 - @ <input type="checkbox" name="az"%s(oaz)/>%s(B('z'))Download Zip 465 + @ <input type="checkbox" name="as"%s(oas) />%s(B('s'))Setup<br /> 466 + } 467 + @ <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br /> 468 + @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br /> 469 + @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br /> 470 + @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br /> 471 + @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br /> 472 + @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br /> 473 + @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))History<br /> 474 + @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br /> 475 + @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br /> 476 + @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br /> 477 + @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br /> 478 + @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br /> 479 + @ <input type="checkbox" name="am"%s(oam) />%s(B('m'))Append Wiki<br /> 480 + @ <input type="checkbox" name="ak"%s(oak) />%s(B('k'))Write Wiki<br /> 481 + @ <input type="checkbox" name="ab"%s(oab) />%s(B('b'))Attachments<br /> 482 + @ <input type="checkbox" name="ar"%s(oar) />%s(B('r'))Read Ticket<br /> 483 + @ <input type="checkbox" name="an"%s(oan) />%s(B('n'))New Ticket<br /> 484 + @ <input type="checkbox" name="ac"%s(oac) />%s(B('c'))Append Ticket<br /> 485 + @ <input type="checkbox" name="aw"%s(oaw) />%s(B('w'))Write Ticket<br /> 486 + @ <input type="checkbox" name="at"%s(oat) />%s(B('t'))Ticket Report<br /> 487 + @ <input type="checkbox" name="az"%s(oaz) />%s(B('z'))Download Zip 473 488 @ </td> 474 489 @ </tr> 475 490 @ <tr> 476 491 @ <td align="right">Password:</td> 477 492 if( zPw[0] ){ 478 493 /* Obscure the password for all users */ 479 - @ <td><input type="password" name="pw" value="**********"></td> 494 + @ <td><input type="password" name="pw" value="**********" /></td> 480 495 }else{ 481 496 /* Show an empty password as an empty input field */ 482 - @ <td><input type="password" name="pw" value=""></td> 497 + @ <td><input type="password" name="pw" value="" /></td> 483 498 } 484 499 @ </tr> 485 500 if( !higherUser ){ 486 501 @ <tr> 487 - @ <td> </td> 488 - @ <td><input type="submit" name="submit" value="Apply Changes"> 502 + @ <td> </td> 503 + @ <td><input type="submit" name="submit" value="Apply Changes" /></td> 489 504 @ </tr> 490 505 } 491 - @ </table></td></tr></table> 506 + @ </table> 507 + @ </div></form> 508 + @ </div> 492 509 @ <h2>Privileges And Capabilities:</h2> 493 510 @ <ul> 494 511 if( higherUser ){ 495 - @ <li><p><font color="blue"><b> 512 + @ <li><p class=missingPriv"> 496 513 @ User %h(zLogin) has Setup privileges and you only have Admin privileges 497 514 @ so you are not permitted to make changes to %h(zLogin). 498 - @ </b></font></p></li> 515 + @ </p></li> 499 516 @ 500 517 } 501 518 @ <li><p> 502 - @ The <b>Setup</b> user can make arbitrary configuration changes. 503 - @ An <b>Admin</b> user can add other users and change user privileges 519 + @ The <span class="capability">Setup</span> user can make arbitrary 520 + @ configuration changes. An <span class="usertype">Admin</span> user 521 + @ can add other users and change user privileges 504 522 @ and reset user passwords. Both automatically get all other privileges 505 523 @ listed below. Use these two settings with discretion. 506 524 @ </p></li> 507 525 @ 508 526 @ <li><p> 509 - @ The "<font color="green"><big>•</big></font>" mark indicates 510 - @ the privileges of "nobody" that are available to all users 511 - @ regardless of whether or not they are logged in. 527 + @ The "<span class="ueditInheritNobody"><big>•</big></span>" mark 528 + @ indicates the privileges of <span class="usertype">nobody</span> that 529 + @ are available to all users regardless of whether or not they are logged in. 530 + @ </p></li> 531 + @ 532 + @ <li><p> 533 + @ The "<span class="ueditInheritAnonymous"><big>•</big></span>" mark 534 + @ indicates the privileges of <span class="usertype">anonymous</span> that 535 + @ are inherited by all logged-in users. 536 + @ </p></li> 537 + @ 538 + @ <li><p> 539 + @ The "<span class="ueditInheritDeveloper"><big>•</big></span>" mark 540 + @ indicates the privileges of <span class="usertype">developer</span> that 541 + @ are inherited by all users with the 542 + @ <span class="capability">Developer</span> privilege. 543 + @ </p></li> 544 + @ 545 + @ <li><p> 546 + @ The "<span class="ueditInheritReader"><big>•</big></span>" mark 547 + @ indicates the privileges of <span class="usertype">reader</span> that 548 + @ are inherited by all users with the <span class="capability">Reader</span> 549 + @ privilege. 550 + @ </p></li> 551 + @ 552 + @ <li><p> 553 + @ The <span class="capability">Delete</span> privilege give the user the 554 + @ ability to erase wiki, tickets, and attachments that have been added 555 + @ by anonymous users. This capability is intended for deletion of spam. 556 + @ The delete capability is only in effect for 24 hours after the item 557 + @ is first posted. The <span class="usertype">Setup</span> user can 558 + @ delete anything at any time. 559 + @ </p></li> 560 + @ 561 + @ <li><p> 562 + @ The <span class="capability">History</span> privilege allows a user 563 + @ to see most hyperlinks. This is recommended ON for most logged-in users 564 + @ but OFF for user "nobody" to avoid problems with spiders trying to walk 565 + @ every historical version of every baseline and file. 566 + @ </p></li> 567 + @ 568 + @ <li><p> 569 + @ The <span class="capability">Zip</span> privilege allows a user to 570 + @ see the "download as ZIP" 571 + @ hyperlink and permits access to the <tt>/zip</tt> page. This allows 572 + @ users to download ZIP archives without granting other rights like 573 + @ <span class="capability">Read</span> or 574 + @ <span class="capability">History</span>. This privilege is recommended for 575 + @ user <span class="usertype">nobody</span> so that automatic package 576 + @ downloaders can obtain the sources without going through the login 577 + @ procedure. 512 578 @ </p></li> 513 579 @ 514 580 @ <li><p> 515 - @ The "<font color="blue"><big>•</big></font>" mark indicates 516 - @ the privileges of "anonymous" that are inherited by all logged-in users. 581 + @ The <span class="capability">Check-in</span> privilege allows remote 582 + @ users to "push". The <span class="capability">Check-out</span> privilege 583 + @ allows remote users to "pull". The <span class="capability">Clone</span> 584 + @ privilege allows remote users to "clone". 517 585 @ </p></li> 518 586 @ 519 587 @ <li><p> 520 - @ The "<font color="red"><big>•</big></font>" mark indicates 521 - @ the privileges of "developer" that are inherited by all users with 522 - @ the <b>Developer</b> privilege. 588 + @ The <span class="capability">Read Wiki</span>, 589 + @ <span class="capability">New Wiki</span>, 590 + @ <span class="capability">Append Wiki</span>, and 591 + @ <b>Write Wiki</b> privileges control access to wiki pages. The 592 + @ <span class="capability">Read Ticket</span>, 593 + @ <span class="capability">New Ticket</span>, 594 + @ <span class="capability">Append Ticket</span>, and 595 + @ <span class="capability">Write Ticket</span> privileges control access 596 + @ to trouble tickets. 597 + @ The <span class="capability">Ticket Report</span> privilege allows 598 + @ the user to create or edit ticket report formats. 523 599 @ </p></li> 524 600 @ 525 601 @ <li><p> 526 - @ The "<font color="black"><big>•</big></font>" mark indicates 527 - @ the privileges of "reader" that are inherited by all users with 528 - @ the <b>Reader</b> privilege. 529 - @ </p></li> 530 - @ 531 - @ <li><p> 532 - @ The <b>Delete</b> privilege give the user the ability to erase 533 - @ wiki, tickets, and attachments that have been added by anonymous 534 - @ users. This capability is intended for deletion of spam. The 535 - @ delete capability is only in effect for 24 hours after the item 536 - @ is first posted. The Setup user can delete anything at any time. 602 + @ Users with the <span class="capability">Password</span> privilege 603 + @ are allowed to change their own password. Recommended ON for most 604 + @ users but OFF for special users <span class="usertype">developer</span>, 605 + @ <span class="usertype">anonymous</span>, 606 + @ and <span class="usertype">nobody</span>. 537 607 @ </p></li> 538 608 @ 539 609 @ <li><p> 540 - @ The <b>History</b> privilege allows a user to see most hyperlinks. 541 - @ This is recommended ON for most logged-in users but OFF for 542 - @ user "nobody" to avoid problems with spiders trying to walk every 543 - @ historical version of every baseline and file. 544 - @ </p></li> 545 - @ 546 - @ <li><p> 547 - @ The <b>Zip</b> privilege allows a user to see the "download as ZIP" 548 - @ hyperlink and permits access to the <tt>/zip</tt> page. This allows 549 - @ users to download ZIP archives without granting other rights like 550 - @ <b>Read</b> or <b>History</b>. This privilege is recommended for 551 - @ user <b>nobody</b> so that automatic package downloaders can obtain 552 - @ the sources without going through the login procedure. 610 + @ The <span class="capability">EMail</span> privilege allows the display of 611 + @ sensitive information such as the email address of users and contact 612 + @ information on tickets. Recommended OFF for 613 + @ <span class="usertype">anonymousy</span> and for 614 + @ <span class="usertype">nobody</span> but ON for 615 + @ <span class="usertype">developer</span>. 553 616 @ </p></li> 554 617 @ 555 618 @ <li><p> 556 - @ The <b>Check-in</b> privilege allows remote users to "push". 557 - @ The <b>Check-out</b> privilege allows remote users to "pull". 558 - @ The <b>Clone</b> privilege allows remote users to "clone". 559 - @ </li><p> 560 - @ 561 - @ <li><p> 562 - @ The <b>Read Wiki</b>, <b>New Wiki</b>, <b>Append Wiki</b>, and 563 - @ <b>Write Wiki</b> privileges control access to wiki pages. The 564 - @ <b>Read Ticket</b>, <b>New Ticket</b>, <b>Append Ticket</b>, and 565 - @ <b>Write Ticket</b> privileges control access to trouble tickets. 566 - @ The <b>Ticket Report</b> privilege allows the user to create or edit 567 - @ ticket report formats. 619 + @ The <span class="capability">Attachment</span> privilege is needed in 620 + @ order to add attachments to tickets or wiki. Write privilege on the 621 + @ ticket or wiki is also required. 568 622 @ </p></li> 569 623 @ 570 - @ <li><p> 571 - @ Users with the <b>Password</b> privilege are allowed to change their 572 - @ own password. Recommended ON for most users but OFF for special 573 - @ users "developer", "anonymous", and "nobody". 574 - @ </p></li> 575 - @ 576 - @ <li><p> 577 - @ The <b>EMail</b> privilege allows the display of sensitive information 578 - @ such as the email address of users and contact information on tickets. 579 - @ Recommended OFF for "anonymous" and for "nobody" but ON for 580 - @ "developer". 581 - @ </p></li> 582 - @ 583 - @ <li><p> 584 - @ The <b>Attachment</b> privilege is needed in order to add attachments 585 - @ to tickets or wiki. Write privilege on the ticket or wiki is also 586 - @ required.</p></li> 587 - @ 588 624 @ <li><p> 589 625 @ Login is prohibited if the password is an empty string. 590 626 @ </p></li> 591 627 @ </ul> 592 628 @ 593 629 @ <h2>Special Logins</h2> 594 630 @ 595 631 @ <ul> 596 632 @ <li><p> 597 - @ No login is required for user "<b>nobody</b>". The capabilities 598 - @ of the <b>nobody</b> user are inherited by all users, regardless of 599 - @ whether or not they are logged in. To disable universal access 600 - @ to the repository, make sure no user named "<b>nobody</b>" exists or 601 - @ that the <b>nobody</b> user has no capabilities enabled. 602 - @ The password for <b>nobody</b> is ignore. To avoid problems with 603 - @ spiders overloading the server, it is recommended 604 - @ that the 'h' (History) capability be turned off for the <b>nobody</b> 605 - @ user. 633 + @ No login is required for user <span class="usertype">nobody</span>. The 634 + @ capabilities of the <span class="usertype">nobody</span> user are 635 + @ inherited by all users, regardless of whether or not they are logged in. 636 + @ To disable universal access to the repository, make sure no user named 637 + @ <span class="usertype">nobody</span> exists or that the 638 + @ <span class="usertype">nobody</span> user has no capabilities 639 + @ enabled. The password for <span class="usertype">nobody</span> is ignore. 640 + @ To avoid problems with spiders overloading the server, it is recommended 641 + @ that the <span class="capability">h</span> (History) capability be turned 642 + @ off for the <span class="usertype">nobody</span> user. 606 643 @ </p></li> 607 644 @ 608 645 @ <li><p> 609 - @ Login is required for user "<b>anonymous</b>" but the password 610 - @ is displayed on the login screen beside the password entry box 646 + @ Login is required for user <span class="usertype">anonymous</span> but the 647 + @ password is displayed on the login screen beside the password entry box 611 648 @ so anybody who can read should be able to login as anonymous. 612 649 @ On the other hand, spiders and web-crawlers will typically not 613 - @ be able to login. Set the capabilities of the anonymous user 614 - @ to things that you want any human to be able to do, but not any 650 + @ be able to login. Set the capabilities of the 651 + @ <span class="usertype">anonymous</span> 652 + @ user to things that you want any human to be able to do, but not any 615 653 @ spider. Every other logged-in user inherits the privileges of 616 - @ <b>anonymous</b>. 654 + @ <span class="usertype">anonymous</span>. 617 655 @ </p></li> 618 656 @ 619 657 @ <li><p> 620 - @ The "<b>developer</b>" user is intended as a template for trusted users 621 - @ with check-in privileges. When adding new trusted users, simply 622 - @ select the <b>Developer</b> privilege to cause the new user to inherit 623 - @ all privileges of the "developer" user. Similarly, the "<b>reader</b>" 624 - @ user is a template for users who are allowed more access than anonymous, 625 - @ but less than a developer. 658 + @ The <span class="usertype">developer</span> user is intended as a template 659 + @ for trusted users with check-in privileges. When adding new trusted users, 660 + @ simply select the <span class="capability">developer</span> privilege to 661 + @ cause the new user to inherit all privileges of the 662 + @ <span class="usertype">developer</span> 663 + @ user. Similarly, the <span class="usertype">reader</span> user is a 664 + @ template for users who are allowed more access than 665 + @ <span class="usertype">anonymous</span>, 666 + @ but less than a <span class="usertype">developer</span>. 626 667 @ </p></li> 627 668 @ </ul> 628 - @ </form> 629 669 style_footer(); 630 670 } 631 671 632 672 633 673 /* 634 674 ** Generate a checkbox for an attribute. 635 675 */ ................................................................................ 649 689 if( iQ!=iVal ){ 650 690 login_verify_csrf_secret(); 651 691 db_set(zVar, iQ ? "1" : "0", 0); 652 692 iVal = iQ; 653 693 } 654 694 } 655 695 if( iVal ){ 656 - @ <input type="checkbox" name="%s(zQParm)" checked><b>%s(zLabel)</b></input> 696 + @ <input type="checkbox" name="%s(zQParm)" checked="checked" /> 697 + @ <b>%s(zLabel)</b> 657 698 }else{ 658 - @ <input type="checkbox" name="%s(zQParm)"><b>%s(zLabel)</b></input> 699 + @ <input type="checkbox" name="%s(zQParm)" /> <b>%s(zLabel)</b> 659 700 } 660 701 } 661 702 662 703 /* 663 704 ** Generate an entry box for an attribute. 664 705 */ 665 706 void entry_attribute( ................................................................................ 672 713 const char *zVal = db_get(zVar, zDflt); 673 714 const char *zQ = P(zQParm); 674 715 if( zQ && strcmp(zQ,zVal)!=0 ){ 675 716 login_verify_csrf_secret(); 676 717 db_set(zVar, zQ, 0); 677 718 zVal = zQ; 678 719 } 679 - @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)"> 720 + @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" /> 680 721 @ <b>%s(zLabel)</b> 681 722 } 682 723 683 724 /* 684 725 ** Generate a text box for an attribute. 685 726 */ 686 727 static void textarea_attribute( ................................................................................ 696 737 if( zQ && strcmp(zQ,z)!=0 ){ 697 738 login_verify_csrf_secret(); 698 739 db_set(zVar, zQ, 0); 699 740 z = zQ; 700 741 } 701 742 if( rows>0 && cols>0 ){ 702 743 @ <textarea name="%s(zQP)" rows="%d(rows)" cols="%d(cols)">%h(z)</textarea> 703 - @ <b>%s(zLabel)</b> 744 + if (zLabel && *zLabel) 745 + @ <span class="textareaLabel">%s(zLabel)</span> 704 746 } 705 747 } 706 748 707 749 708 750 /* 709 751 ** WEBPAGE: setup_access 710 752 */ ................................................................................ 712 754 login_check_credentials(); 713 755 if( !g.okSetup ){ 714 756 login_needed(); 715 757 } 716 758 717 759 style_header("Access Control Settings"); 718 760 db_begin_transaction(); 719 - @ <form action="%s(g.zBaseURL)/setup_access" method="POST"> 761 + @ <form action="%s(g.zBaseURL)/setup_access" method="post"><div> 720 762 login_insert_csrf_secret(); 721 - @ <hr> 763 + @ <hr /> 722 764 onoff_attribute("Require password for local access", 723 765 "localauth", "localauth", 0); 724 766 @ <p>When enabled, the password sign-in is required for 725 767 @ web access coming from 127.0.0.1. When disabled, web access 726 768 @ from 127.0.0.1 is allows without any login - the user id is selected 727 769 @ from the ~/.fossil database. Password login is always required 728 770 @ for incoming web connections on internet addresses other than 729 - @ 127.0.0.1.</p></li> 771 + @ 127.0.0.1.</p> 730 772 731 - @ <hr> 773 + @ <hr /> 732 774 onoff_attribute("Allow REMOTE_USER authentication", 733 775 "remote_user_ok", "remote_user_ok", 0); 734 776 @ <p>When enabled, if the REMOTE_USER environment variable is set to the 735 777 @ login name of a valid user and no other login credentials are available, 736 778 @ then the REMOTE_USER is accepted as an authenticated user. 737 - @ </p></li> 779 + @ </p> 738 780 739 - @ <hr> 781 + @ <hr /> 740 782 entry_attribute("Login expiration time", 6, "cookie-expire", "cex", "8766"); 741 783 @ <p>The number of hours for which a login is valid. This must be a 742 784 @ positive number. The default is 8760 hours which is approximately equal 743 785 @ to a year.</p> 744 786 745 - @ <hr> 787 + @ <hr /> 746 788 entry_attribute("Download packet limit", 10, "max-download", "mxdwn", 747 789 "5000000"); 748 790 @ <p>Fossil tries to limit out-bound sync, clone, and pull packets 749 791 @ to this many bytes, uncompressed. If the client requires more data 750 792 @ than this, then the client will issue multiple HTTP requests. 751 793 @ Values below 1 million are not recommended. 5 million is a 752 794 @ reasonable number.</p> 753 795 754 - @ <hr> 796 + @ <hr /> 755 797 onoff_attribute("Show javascript button to fill in CAPTCHA", 756 798 "auto-captcha", "autocaptcha", 0); 757 799 @ <p>When enabled, a button appears on the login screen for user 758 800 @ "anonymous" that will automatically fill in the CAPTCHA password. 759 801 @ This is less secure that forcing the user to do it manually, but is 760 802 @ probably secure enough and it is certainly more convenient for 761 803 @ anonymous users.</p> 762 804 763 - @ <hr> 764 - @ <p><input type="submit" name="submit" value="Apply Changes"></p> 765 - @ </form> 805 + @ <hr /> 806 + @ <p><input type="submit" name="submit" value="Apply Changes" /></p> 807 + @ </div></form> 766 808 db_end_transaction(0); 767 809 style_footer(); 768 810 } 769 811 770 812 /* 771 813 ** WEBPAGE: setup_timeline 772 814 */ ................................................................................ 774 816 login_check_credentials(); 775 817 if( !g.okSetup ){ 776 818 login_needed(); 777 819 } 778 820 779 821 style_header("Timeline Display Preferences"); 780 822 db_begin_transaction(); 781 - @ <form action="%s(g.zBaseURL)/setup_timeline" method="POST"> 823 + @ <form action="%s(g.zBaseURL)/setup_timeline" method="post"><div> 782 824 login_insert_csrf_secret(); 783 825 784 - @ <hr> 826 + @ <hr /> 785 827 onoff_attribute("Allow block-markup in timeline", 786 828 "timeline-block-markup", "tbm", 0); 787 829 @ <p>In timeline displays, check-in comments can be displayed with or 788 830 @ without block markup (paragraphs, tables, etc.)</p> 789 831 790 - @ <hr> 832 + @ <hr /> 791 833 onoff_attribute("Use Universal Coordinated Time (UTC)", 792 834 "timeline-utc", "utc", 1); 793 835 @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or 794 836 @ Zulu) instead of in local time.</p> 795 837 796 - @ <hr> 838 + @ <hr /> 797 839 onoff_attribute("Show version differences by default", 798 840 "show-version-diffs", "vdiff", 0); 799 841 @ <p>On the version-information pages linked from the timeline can either 800 842 @ show complete diffs of all file changes, or can just list the names of 801 843 @ the files that have changed. Users can get to either page by 802 844 @ clicking. This setting selects the default.</p> 803 845 804 - @ <hr> 846 + @ <hr /> 805 847 entry_attribute("Max timeline comment length", 6, 806 848 "timeline-max-comment", "tmc", "0"); 807 849 @ <p>The maximum length of a comment to be displayed in a timeline. 808 850 @ "0" there is no length limit.</p> 809 851 810 - @ <hr> 811 - @ <p><input type="submit" name="submit" value="Apply Changes"></p> 812 - @ </form> 852 + @ <hr /> 853 + @ <p><input type="submit" name="submit" value="Apply Changes" /></p> 854 + @ </div></form> 855 + db_end_transaction(0); 856 + style_footer(); 857 +} 858 + 859 +/* 860 +** WEBPAGE: setup_settings 861 +*/ 862 +void setup_settings(void){ 863 + struct stControlSettings const *pSet; 864 + 865 + login_check_credentials(); 866 + if( !g.okSetup ){ 867 + login_needed(); 868 + } 869 + 870 + style_header("Settings"); 871 + db_begin_transaction(); 872 + @ <p>This page provides a simple interface to the "fossil setting" command. 873 + @ See the "fossil help setting" output below for further information on 874 + @ the meaning of each setting.</p><hr /> 875 + @ <form action="%s(g.zBaseURL)/setup_settings" method="post"><div> 876 + @ <table border="0"><tr><td valign="top"> 877 + login_insert_csrf_secret(); 878 + for(pSet=ctrlSettings; pSet->name!=0; pSet++){ 879 + if( pSet->width==0 ){ 880 + onoff_attribute(pSet->name, pSet->name, 881 + pSet->var!=0 ? pSet->var : pSet->name, 882 + is_truth(pSet->def)); 883 + @ <br /> 884 + } 885 + } 886 + @ </td><td style="width: 30;"></td><td valign="top"> 887 + for(pSet=ctrlSettings; pSet->name!=0; pSet++){ 888 + if( pSet->width!=0 ){ 889 + entry_attribute(pSet->name, /*pSet->width*/ 40, pSet->name, 890 + pSet->var!=0 ? pSet->var : pSet->name, 891 + (char*)pSet->def); 892 + @ <br /> 893 + } 894 + } 895 + @ </td></tr></table> 896 + @ <p><input type="submit" name="submit" value="Apply Changes" /></p> 897 + @ </div></form> 898 + @ <hr /><p> 899 + @ These settings work in the same way, as the <kbd>set</kbd> commandline:<br /> 900 + @ </p><pre>%s(zHelp_setting_cmd)</pre> 813 901 db_end_transaction(0); 814 902 style_footer(); 815 903 } 816 904 817 905 /* 818 906 ** WEBPAGE: setup_config 819 907 */ ................................................................................ 821 909 login_check_credentials(); 822 910 if( !g.okSetup ){ 823 911 login_needed(); 824 912 } 825 913 826 914 style_header("WWW Configuration"); 827 915 db_begin_transaction(); 828 - @ <form action="%s(g.zBaseURL)/setup_config" method="POST"> 916 + @ <form action="%s(g.zBaseURL)/setup_config" method="post"><div> 829 917 login_insert_csrf_secret(); 830 918 @ <hr /> 831 919 entry_attribute("Project Name", 60, "project-name", "pn", ""); 832 920 @ <p>Give your project a name so visitors know what this site is about. 833 921 @ The project name will also be used as the RSS feed title.</p> 834 922 @ <hr /> 835 923 textarea_attribute("Project Description", 5, 60, ................................................................................ 838 926 @ engines as well as a short RSS description.</p> 839 927 @ <hr /> 840 928 entry_attribute("Index Page", 60, "index-page", "idxpg", "/home"); 841 929 @ <p>Enter the pathname of the page to display when the "Home" menu 842 930 @ option is selected and when no pathname is 843 931 @ specified in the URL. For example, if you visit the url:</p> 844 932 @ 845 - @ <blockquote>%h(g.zBaseURL)</blockquote> 933 + @ <blockquote><p>%h(g.zBaseURL)</p></blockquote> 846 934 @ 847 935 @ <p>And you have specified an index page of "/home" the above will 848 936 @ automatically redirect to:</p> 849 937 @ 850 - @ <blockquote>%h(g.zBaseURL)/home</blockquote> 938 + @ <blockquote><p>%h(g.zBaseURL)/home</p></blockquote> 851 939 @ 852 940 @ <p>The default "/home" page displays a Wiki page with the same name 853 941 @ as the Project Name specified above. Some sites prefer to redirect 854 942 @ to a documentation page (ex: "/doc/tip/index.wiki") or to "/timeline".</p> 943 + @ 944 + @ <p>Note: To avoid a redirect loop or other problems, this entry must 945 + @ begin with "/" and it must specify a valid page. For example, 946 + @ "<b>/home</b>" will work but "<b>home</b>" will not, since it omits the 947 + @ leading "/".</p> 855 948 @ <hr /> 856 949 onoff_attribute("Use HTML as wiki markup language", 857 950 "wiki-use-html", "wiki-use-html", 0); 858 - @ <p>Use HTML as the wiki markup language. Wiki links will still be parsed but 859 - @ all other wiki formatting will be ignored. This option is helpful if you have 860 - @ chosen to use a rich HTML editor for wiki markup such as TinyMCE.</p> 951 + @ <p>Use HTML as the wiki markup language. Wiki links will still be parsed 952 + @ but all other wiki formatting will be ignored. This option is helpful 953 + @ if you have chosen to use a rich HTML editor for wiki markup such as 954 + @ TinyMCE.</p> 861 955 @ <p><strong>CAUTION:</strong> when 862 956 @ enabling, <i>all</i> HTML tags and attributes are accepted in the wiki. 863 957 @ No sanitization is done. This means that it is very possible for malicious 864 958 @ users to inject dangerous HTML, CSS and JavaScript code into your wiki.</p> 865 959 @ <p>This should <strong>only</strong> be enabled when wiki editing is limited 866 960 @ to trusted users. It should <strong>not</strong> be used on a publically 867 961 @ editable wiki.</p> 868 962 @ <hr /> 869 - @ <p><input type="submit" name="submit" value="Apply Changes"></p> 870 - @ </form> 963 + @ <p><input type="submit" name="submit" value="Apply Changes" /></p> 964 + @ </div></form> 871 965 db_end_transaction(0); 872 966 style_footer(); 873 967 } 874 968 875 969 /* 876 970 ** WEBPAGE: setup_editcss 877 971 */ ................................................................................ 890 984 textarea_attribute(0, 0, 0, "css", "css", zDefaultCSS); 891 985 } 892 986 if( P("submit")!=0 ){ 893 987 db_end_transaction(0); 894 988 cgi_redirect("setup_editcss"); 895 989 } 896 990 style_header("Edit CSS"); 897 - @ <form action="%s(g.zBaseURL)/setup_editcss" method="POST"> 991 + @ <form action="%s(g.zBaseURL)/setup_editcss" method="post"><div> 898 992 login_insert_csrf_secret(); 899 993 @ Edit the CSS below:<br /> 900 994 textarea_attribute("", 40, 80, "css", "css", zDefaultCSS); 901 995 @ <br /> 902 - @ <input type="submit" name="submit" value="Apply Changes"> 903 - @ <input type="submit" name="clear" value="Revert To Default"> 904 - @ </form> 905 - @ <p><b>Note:</b> Press your browser Reload button after modifying the 906 - @ CSS in order to pull in the modified CSS file.</p> 907 - @ <hr> 996 + @ <input type="submit" name="submit" value="Apply Changes" /> 997 + @ <input type="submit" name="clear" value="Revert To Default" /> 998 + @ </div></form> 999 + @ <p><span class="note">Note:</span> Press your browser Reload button after 1000 + @ modifying the CSS in order to pull in the modified CSS file.</p> 1001 + @ <hr /> 908 1002 @ The default CSS is shown below for reference. Other examples 909 1003 @ of CSS files can be seen on the <a href="setup_skin">skins page</a>. 910 1004 @ See also the <a href="setup_header">header</a> and 911 1005 @ <a href="setup_footer">footer</a> editing screens. 912 1006 @ <blockquote><pre> 913 - @ %h(zDefaultCSS) 1007 + cgi_append_default_css(); 914 1008 @ </pre></blockquote> 915 1009 style_footer(); 916 1010 db_end_transaction(0); 917 1011 } 918 1012 919 1013 /* 920 1014 ** WEBPAGE: setup_header ................................................................................ 928 1022 if( P("clear")!=0 ){ 929 1023 db_multi_exec("DELETE FROM config WHERE name='header'"); 930 1024 cgi_replace_parameter("header", zDefaultHeader); 931 1025 }else{ 932 1026 textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader); 933 1027 } 934 1028 style_header("Edit Page Header"); 935 - @ <form action="%s(g.zBaseURL)/setup_header" method="POST"> 1029 + @ <form action="%s(g.zBaseURL)/setup_header" method="post"><div> 936 1030 login_insert_csrf_secret(); 937 1031 @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to 938 1032 @ generate the beginning of every page through start of the main 939 1033 @ menu.</p> 940 1034 textarea_attribute("", 40, 80, "header", "header", zDefaultHeader); 941 1035 @ <br /> 942 - @ <input type="submit" name="submit" value="Apply Changes"> 943 - @ <input type="submit" name="clear" value="Revert To Default"> 944 - @ </form> 945 - @ <hr> 1036 + @ <input type="submit" name="submit" value="Apply Changes" /> 1037 + @ <input type="submit" name="clear" value="Revert To Default" /> 1038 + @ </div></form> 1039 + @ <hr /> 946 1040 @ The default header is shown below for reference. Other examples 947 1041 @ of headers can be seen on the <a href="setup_skin">skins page</a>. 948 1042 @ See also the <a href="setup_editcss">CSS</a> and 949 1043 @ <a href="setup_footer">footer</a> editing screeens. 950 1044 @ <blockquote><pre> 951 1045 @ %h(zDefaultHeader) 952 1046 @ </pre></blockquote> ................................................................................ 966 1060 if( P("clear")!=0 ){ 967 1061 db_multi_exec("DELETE FROM config WHERE name='footer'"); 968 1062 cgi_replace_parameter("footer", zDefaultFooter); 969 1063 }else{ 970 1064 textarea_attribute(0, 0, 0, "footer", "footer", zDefaultFooter); 971 1065 } 972 1066 style_header("Edit Page Footer"); 973 - @ <form action="%s(g.zBaseURL)/setup_footer" method="POST"> 1067 + @ <form action="%s(g.zBaseURL)/setup_footer" method="post"><div> 974 1068 login_insert_csrf_secret(); 975 1069 @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to 976 1070 @ generate the end of every page.</p> 977 1071 textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter); 978 1072 @ <br /> 979 - @ <input type="submit" name="submit" value="Apply Changes"> 980 - @ <input type="submit" name="clear" value="Revert To Default"> 981 - @ </form> 982 - @ <hr> 1073 + @ <input type="submit" name="submit" value="Apply Changes" /> 1074 + @ <input type="submit" name="clear" value="Revert To Default" /> 1075 + @ </div></form> 1076 + @ <hr /> 983 1077 @ The default footer is shown below for reference. Other examples 984 1078 @ of footers can be seen on the <a href="setup_skin">skins page</a>. 985 1079 @ See also the <a href="setup_editcss">CSS</a> and 986 1080 @ <a href="setup_header">header</a> editing screens. 987 1081 @ <blockquote><pre> 988 1082 @ %h(zDefaultFooter) 989 1083 @ </pre></blockquote> ................................................................................ 1029 1123 ); 1030 1124 db_end_transaction(0); 1031 1125 cgi_redirect("setup_logo"); 1032 1126 } 1033 1127 style_header("Edit Project Logo"); 1034 1128 @ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks 1035 1129 @ like this:</p> 1036 - @ <blockquote><img src="%s(g.zTop)/logo" alt="logo"></blockquote> 1130 + @ <blockquote><p><img src="%s(g.zTop)/logo" alt="logo" /></p></blockquote> 1037 1131 @ 1038 1132 @ <p>The logo is accessible to all users at this URL: 1039 1133 @ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>. 1040 1134 @ The logo may or may not appear on each 1041 1135 @ page depending on the <a href="setup_editcss">CSS</a> and 1042 1136 @ <a href="setup_header">header setup</a>.</p> 1043 1137 @ 1044 - @ <form action="%s(g.zBaseURL)/setup_logo" method="POST" 1045 - @ enctype="multipart/form-data"> 1138 + @ <form action="%s(g.zBaseURL)/setup_logo" method="post" 1139 + @ enctype="multipart/form-data"><div> 1046 1140 @ <p>To set a new logo image, select a file to use as the logo using 1047 1141 @ the entry box below and then press the "Change Logo" button.</p> 1048 1142 login_insert_csrf_secret(); 1049 1143 @ Logo Image file: 1050 - @ <input type="file" name="im" size="60" accepts="image/*"><br> 1051 - @ <input type="submit" name="set" value="Change Logo"> 1052 - @ <input type="submit" name="clr" value="Revert To Default"> 1053 - @ </form> 1144 + @ <input type="file" name="im" size="60" accept="image/*" /><br /> 1145 + @ <input type="submit" name="set" value="Change Logo" /> 1146 + @ <input type="submit" name="clr" value="Revert To Default" /> 1147 + @ </div></form> 1054 1148 @ 1055 - @ <p><b>Note:</b> Your browser has probably cached the logo image, so 1056 - @ you will probably need to press the Reload button on your browser after 1057 - @ changing the logo to provoke your browser to reload the new logo image. 1058 - @ </p> 1149 + @ <p><span class="note">Note:</span> Your browser has probably cached the 1150 + @ logo image, so you will probably need to press the Reload button on your 1151 + @ browser after changing the logo to provoke your browser to reload the new 1152 + @ logo image. </p> 1059 1153 style_footer(); 1060 1154 db_end_transaction(0); 1061 1155 }
Changes to src/sha1.c.
1 1 /* 2 -** This implementation of SHA1 is adapted from the example implementation 3 -** contained in RFC-3174. 2 +** This implementation of SHA1. 4 3 */ 5 -#include <stdint.h> 6 4 #include <sys/types.h> 7 5 #include "config.h" 8 6 #include "sha1.h" 9 7 10 -/* 11 - * If you do not have the ISO standard stdint.h header file, then you 12 - * must typdef the following: 13 - * name meaning 14 - * uint32_t unsigned 32 bit integer 15 - * uint8_t unsigned 8 bit integer (i.e., unsigned char) 16 - * 17 - */ 18 -#define SHA1HashSize 20 19 -#define shaSuccess 0 20 -#define shaInputTooLong 1 21 -#define shaStateError 2 22 8 23 9 /* 24 - * This structure will hold context information for the SHA-1 25 - * hashing operation 26 - */ 10 +** The SHA1 implementation below is adapted from: 11 +** 12 +** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $ 13 +** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ 14 +** 15 +** SHA-1 in C 16 +** By Steve Reid <steve@edmweb.com> 17 +** 100% Public Domain 18 +*/ 27 19 typedef struct SHA1Context SHA1Context; 28 20 struct SHA1Context { 29 - uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ 30 - 31 - uint32_t Length_Low; /* Message length in bits */ 32 - uint32_t Length_High; /* Message length in bits */ 33 - 34 - int Message_Block_Index; /* Index into message block array */ 35 - uint8_t Message_Block[64]; /* 512-bit message blocks */ 36 - 37 - int Computed; /* Is the digest computed? */ 38 - int Corrupted; /* Is the message digest corrupted? */ 21 + unsigned int state[5]; 22 + unsigned int count[2]; 23 + unsigned char buffer[64]; 39 24 }; 40 25 41 26 /* 42 - * sha1.c 43 - * 44 - * Description: 45 - * This file implements the Secure Hashing Algorithm 1 as 46 - * defined in FIPS PUB 180-1 published April 17, 1995. 27 + * blk0() and blk() perform the initial expand. 28 + * I got the idea of expanding during the round function from SSLeay 47 29 * 48 - * The SHA-1, produces a 160-bit message digest for a given 49 - * data stream. It should take about 2**n steps to find a 50 - * message with the same digest as a given message and 51 - * 2**(n/2) to find any two messages with the same digest, 52 - * when n is the digest size in bits. Therefore, this 53 - * algorithm can serve as a means of providing a 54 - * "fingerprint" for a message. 30 + * blk0le() for little-endian and blk0be() for big-endian. 31 + */ 32 +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 33 +#define blk0le(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ 34 + |(rol(block->l[i],8)&0x00FF00FF)) 35 +#define blk0be(i) block->l[i] 36 +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ 37 + ^block->l[(i+2)&15]^block->l[i&15],1)) 38 + 39 +/* 40 + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 55 41 * 56 - * Portability Issues: 57 - * SHA-1 is defined in terms of 32-bit "words". This code 58 - * uses <stdint.h> (included via "sha1.h" to define 32 and 8 59 - * bit unsigned integer types. If your C compiler does not 60 - * support 32 bit unsigned integers, this code is not 61 - * appropriate. 62 - * 63 - * Caveats: 64 - * SHA-1 is designed to work with messages less than 2^64 bits 65 - * long. Although SHA-1 allows a message digest to be generated 66 - * for messages of any number of bits less than 2^64, this 67 - * implementation only works with messages with a length that is 68 - * a multiple of the size of an 8-bit character. 69 - * 42 + * Rl0() for little-endian and Rb0() for big-endian. Endianness is 43 + * determined at run-time. 44 + */ 45 +#define Rl0(v,w,x,y,z,i) \ 46 + z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=rol(w,30); 47 +#define Rb0(v,w,x,y,z,i) \ 48 + z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=rol(w,30); 49 +#define R1(v,w,x,y,z,i) \ 50 + z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 51 +#define R2(v,w,x,y,z,i) \ 52 + z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 53 +#define R3(v,w,x,y,z,i) \ 54 + z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 55 +#define R4(v,w,x,y,z,i) \ 56 + z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 57 + 58 +typedef union { 59 + unsigned char c[64]; 60 + unsigned int l[16]; 61 +} CHAR64LONG16; 62 + 63 +/* 64 + * Hash a single 512-bit block. This is the core of the algorithm. 70 65 */ 71 - 72 -/* 73 - * Define the SHA1 circular left shift macro 74 - */ 75 -#define SHA1CircularShift(bits,word) \ 76 - (((word) << (bits)) | ((word) >> (32-(bits)))) 77 - 78 -/* Local Function Prototyptes */ 79 -static void SHA1PadMessage(SHA1Context *); 80 -static void SHA1ProcessMessageBlock(SHA1Context *); 81 - 82 -/* 83 - * SHA1Reset 84 - * 85 - * Description: 86 - * This function will initialize the SHA1Context in preparation 87 - * for computing a new SHA1 message digest. 88 - * 89 - * Parameters: 90 - * context: [in/out] 91 - * The context to reset. 92 - * 93 - * Returns: 94 - * sha Error Code. 95 - * 96 - */ 97 -static int SHA1Reset(SHA1Context *context) 66 +void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]) 98 67 { 99 - context->Length_Low = 0; 100 - context->Length_High = 0; 101 - context->Message_Block_Index = 0; 102 - 103 - context->Intermediate_Hash[0] = 0x67452301; 104 - context->Intermediate_Hash[1] = 0xEFCDAB89; 105 - context->Intermediate_Hash[2] = 0x98BADCFE; 106 - context->Intermediate_Hash[3] = 0x10325476; 107 - context->Intermediate_Hash[4] = 0xC3D2E1F0; 108 - 109 - context->Computed = 0; 110 - context->Corrupted = 0; 111 - 112 - return shaSuccess; 113 -} 114 - 115 -/* 116 - * SHA1Result 117 - * 118 - * Description: 119 - * This function will return the 160-bit message digest into the 120 - * Message_Digest array provided by the caller. 121 - * NOTE: The first octet of hash is stored in the 0th element, 122 - * the last octet of hash in the 19th element. 123 - * 124 - * Parameters: 125 - * context: [in/out] 126 - * The context to use to calculate the SHA-1 hash. 127 - * Message_Digest: [out] 128 - * Where the digest is returned. 129 - * 130 - * Returns: 131 - * sha Error Code. 132 - * 68 + unsigned int a, b, c, d, e; 69 + CHAR64LONG16 *block; 70 + static int one = 1; 71 + CHAR64LONG16 workspace; 72 + 73 + block = &workspace; 74 + (void)memcpy(block, buffer, 64); 75 + 76 + /* Copy context->state[] to working vars */ 77 + a = state[0]; 78 + b = state[1]; 79 + c = state[2]; 80 + d = state[3]; 81 + e = state[4]; 82 + 83 + /* 4 rounds of 20 operations each. Loop unrolled. */ 84 + if( 1 == *(unsigned char*)&one ){ 85 + Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3); 86 + Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7); 87 + Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11); 88 + Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15); 89 + }else{ 90 + Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3); 91 + Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7); 92 + Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11); 93 + Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15); 94 + } 95 + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); 96 + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 97 + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); 98 + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); 99 + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 100 + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); 101 + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); 102 + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 103 + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); 104 + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); 105 + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 106 + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); 107 + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); 108 + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 109 + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); 110 + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 111 + 112 + /* Add the working vars back into context.state[] */ 113 + state[0] += a; 114 + state[1] += b; 115 + state[2] += c; 116 + state[3] += d; 117 + state[4] += e; 118 + 119 + /* Wipe variables */ 120 + a = b = c = d = e = 0; 121 +} 122 + 123 + 124 +/* 125 + * SHA1Init - Initialize new context 133 126 */ 134 -static int SHA1Result( SHA1Context *context, 135 - uint8_t Message_Digest[SHA1HashSize]) 136 -{ 137 - int i; 138 - 139 - if (context->Corrupted) 140 - { 141 - return context->Corrupted; 142 - } 143 - 144 - if (!context->Computed) 145 - { 146 - SHA1PadMessage(context); 147 - for(i=0; i<64; ++i) 148 - { 149 - /* message may be sensitive, clear it out */ 150 - context->Message_Block[i] = 0; 151 - } 152 - context->Length_Low = 0; /* and clear length */ 153 - context->Length_High = 0; 154 - context->Computed = 1; 155 - 156 - } 157 - 158 - for(i = 0; i < SHA1HashSize; ++i) 159 - { 160 - Message_Digest[i] = context->Intermediate_Hash[i>>2] 161 - >> 8 * ( 3 - ( i & 0x03 ) ); 162 - } 163 - 164 - return shaSuccess; 127 +static void SHA1Init(SHA1Context *context){ 128 + /* SHA1 initialization constants */ 129 + context->state[0] = 0x67452301; 130 + context->state[1] = 0xEFCDAB89; 131 + context->state[2] = 0x98BADCFE; 132 + context->state[3] = 0x10325476; 133 + context->state[4] = 0xC3D2E1F0; 134 + context->count[0] = context->count[1] = 0; 165 135 } 136 + 166 137 167 138 /* 168 - * SHA1Input 169 - * 170 - * Description: 171 - * This function accepts an array of octets as the next portion 172 - * of the message. 173 - * 174 - * Parameters: 175 - * context: [in/out] 176 - * The SHA context to update 177 - * message_array: [in] 178 - * An array of characters representing the next portion of 179 - * the message. 180 - * length: [in] 181 - * The length of the message in message_array 182 - * 183 - * Returns: 184 - * sha Error Code. 185 - * 139 + * Run your data through this. 186 140 */ 187 -static 188 -int SHA1Input( SHA1Context *context, 189 - const uint8_t *message_array, 190 - unsigned length) 191 -{ 192 - if (!length) 193 - { 194 - return shaSuccess; 141 +static void SHA1Update( 142 + SHA1Context *context, 143 + const unsigned char *data, 144 + unsigned int len 145 +){ 146 + unsigned int i, j; 147 + 148 + j = context->count[0]; 149 + if ((context->count[0] += len << 3) < j) 150 + context->count[1] += (len>>29)+1; 151 + j = (j >> 3) & 63; 152 + if ((j + len) > 63) { 153 + (void)memcpy(&context->buffer[j], data, (i = 64-j)); 154 + SHA1Transform(context->state, context->buffer); 155 + for ( ; i + 63 < len; i += 64) 156 + SHA1Transform(context->state, &data[i]); 157 + j = 0; 158 + } else { 159 + i = 0; 195 160 } 196 - 197 - if (context->Computed) 198 - { 199 - context->Corrupted = shaStateError; 200 - 201 - return shaStateError; 202 - } 203 - 204 - if (context->Corrupted) 205 - { 206 - return context->Corrupted; 207 - } 208 - while(length-- && !context->Corrupted) 209 - { 210 - context->Message_Block[context->Message_Block_Index++] = 211 - (*message_array & 0xFF); 212 - 213 - context->Length_Low += 8; 214 - if (context->Length_Low == 0) 215 - { 216 - context->Length_High++; 217 - if (context->Length_High == 0) 218 - { 219 - /* Message is too long */ 220 - context->Corrupted = 1; 221 - } 222 - } 223 - 224 - if (context->Message_Block_Index == 64) 225 - { 226 - SHA1ProcessMessageBlock(context); 227 - } 228 - 229 - message_array++; 230 - } 231 - 232 - return shaSuccess; 161 + (void)memcpy(&context->buffer[j], &data[i], len - i); 233 162 } 234 163 235 -/* 236 - * SHA1ProcessMessageBlock 237 - * 238 - * Description: 239 - * This function will process the next 512 bits of the message 240 - * stored in the Message_Block array. 241 - * 242 - * Parameters: 243 - * None. 244 - * 245 - * Returns: 246 - * Nothing. 247 - * 248 - * Comments: 249 - * Many of the variable names in this code, especially the 250 - * single character names, were used because those were the 251 - * names used in the publication. 252 - * 253 - * 254 - */ 255 -static void SHA1ProcessMessageBlock(SHA1Context *context) 256 -{ 257 - const uint32_t K[] = { /* Constants defined in SHA-1 */ 258 - 0x5A827999, 259 - 0x6ED9EBA1, 260 - 0x8F1BBCDC, 261 - 0xCA62C1D6 262 - }; 263 - int t; /* Loop counter */ 264 - uint32_t temp; /* Temporary word value */ 265 - uint32_t W[80]; /* Word sequence */ 266 - uint32_t A, B, C, D, E; /* Word buffers */ 267 - 268 - /* 269 - * Initialize the first 16 words in the array W 270 - */ 271 - for(t = 0; t < 16; t++) 272 - { 273 - W[t] = context->Message_Block[t * 4] << 24; 274 - W[t] |= context->Message_Block[t * 4 + 1] << 16; 275 - W[t] |= context->Message_Block[t * 4 + 2] << 8; 276 - W[t] |= context->Message_Block[t * 4 + 3]; 277 - } 278 - 279 - for(t = 16; t < 80; t++) 280 - { 281 - W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 282 - } 283 - 284 - A = context->Intermediate_Hash[0]; 285 - B = context->Intermediate_Hash[1]; 286 - C = context->Intermediate_Hash[2]; 287 - D = context->Intermediate_Hash[3]; 288 - E = context->Intermediate_Hash[4]; 289 - 290 - for(t = 0; t < 20; t++) 291 - { 292 - temp = SHA1CircularShift(5,A) + 293 - ((B & C) | ((~B) & D)) + E + W[t] + K[0]; 294 - E = D; 295 - D = C; 296 - C = SHA1CircularShift(30,B); 297 - 298 - B = A; 299 - A = temp; 300 - } 301 - 302 - for(t = 20; t < 40; t++) 303 - { 304 - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; 305 - E = D; 306 - D = C; 307 - C = SHA1CircularShift(30,B); 308 - B = A; 309 - A = temp; 310 - } 311 - 312 - for(t = 40; t < 60; t++) 313 - { 314 - temp = SHA1CircularShift(5,A) + 315 - ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; 316 - E = D; 317 - D = C; 318 - C = SHA1CircularShift(30,B); 319 - B = A; 320 - A = temp; 321 - } 322 - 323 - for(t = 60; t < 80; t++) 324 - { 325 - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; 326 - E = D; 327 - D = C; 328 - C = SHA1CircularShift(30,B); 329 - B = A; 330 - A = temp; 331 - } 332 - 333 - context->Intermediate_Hash[0] += A; 334 - context->Intermediate_Hash[1] += B; 335 - context->Intermediate_Hash[2] += C; 336 - context->Intermediate_Hash[3] += D; 337 - context->Intermediate_Hash[4] += E; 338 - 339 - context->Message_Block_Index = 0; 340 -} 341 164 342 165 /* 343 - * SHA1PadMessage 344 - * 345 - 346 - * Description: 347 - * According to the standard, the message must be padded to an even 348 - * 512 bits. The first padding bit must be a '1'. The last 64 349 - * bits represent the length of the original message. All bits in 350 - * between should be 0. This function will pad the message 351 - * according to those rules by filling the Message_Block array 352 - * accordingly. It will also call the ProcessMessageBlock function 353 - * provided appropriately. When it returns, it can be assumed that 354 - * the message digest has been computed. 355 - * 356 - * Parameters: 357 - * context: [in/out] 358 - * The context to pad 359 - * ProcessMessageBlock: [in] 360 - * The appropriate SHA*ProcessMessageBlock function 361 - * Returns: 362 - * Nothing. 363 - * 166 + * Add padding and return the message digest. 364 167 */ 365 -static void SHA1PadMessage(SHA1Context *context) 366 -{ 367 - /* 368 - * Check to see if the current message block is too small to hold 369 - * the initial padding bits and length. If so, we will pad the 370 - * block, process it, and then continue padding into a second 371 - * block. 372 - */ 373 - if (context->Message_Block_Index > 55) 374 - { 375 - context->Message_Block[context->Message_Block_Index++] = 0x80; 376 - while(context->Message_Block_Index < 64) 377 - { 378 - context->Message_Block[context->Message_Block_Index++] = 0; 379 - } 168 +static void SHA1Final(SHA1Context *context, unsigned char digest[20]){ 169 + unsigned int i; 170 + unsigned char finalcount[8]; 380 171 381 - SHA1ProcessMessageBlock(context); 382 - 383 - while(context->Message_Block_Index < 56) 384 - { 385 - context->Message_Block[context->Message_Block_Index++] = 0; 386 - } 172 + for (i = 0; i < 8; i++) { 173 + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] 174 + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ 387 175 } 388 - else 389 - { 390 - context->Message_Block[context->Message_Block_Index++] = 0x80; 391 - while(context->Message_Block_Index < 56) 392 - { 176 + SHA1Update(context, (const unsigned char *)"\200", 1); 177 + while ((context->count[0] & 504) != 448) 178 + SHA1Update(context, (const unsigned char *)"\0", 1); 179 + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ 393 180 394 - context->Message_Block[context->Message_Block_Index++] = 0; 395 - } 181 + if (digest) { 182 + for (i = 0; i < 20; i++) 183 + digest[i] = (unsigned char) 184 + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); 396 185 } 397 - 398 - /* 399 - * Store the message length as the last 8 octets 400 - */ 401 - context->Message_Block[56] = context->Length_High >> 24; 402 - context->Message_Block[57] = context->Length_High >> 16; 403 - context->Message_Block[58] = context->Length_High >> 8; 404 - context->Message_Block[59] = context->Length_High; 405 - context->Message_Block[60] = context->Length_Low >> 24; 406 - context->Message_Block[61] = context->Length_Low >> 16; 407 - context->Message_Block[62] = context->Length_Low >> 8; 408 - context->Message_Block[63] = context->Length_Low; 409 - 410 - SHA1ProcessMessageBlock(context); 411 186 } 412 187 413 188 414 189 /* 415 190 ** Convert a digest into base-16. digest should be declared as 416 191 ** "unsigned char digest[20]" in the calling function. The SHA1 417 192 ** digest is stored in the first 20 bytes. zBuf should ................................................................................ 437 212 static int incrInit = 0; 438 213 439 214 /* 440 215 ** Add more text to the incremental SHA1 checksum. 441 216 */ 442 217 void sha1sum_step_text(const char *zText, int nBytes){ 443 218 if( !incrInit ){ 444 - SHA1Reset(&incrCtx); 219 + SHA1Init(&incrCtx); 445 220 incrInit = 1; 446 221 } 447 222 if( nBytes<=0 ){ 448 223 if( nBytes==0 ) return; 449 224 nBytes = strlen(zText); 450 225 } 451 - SHA1Input(&incrCtx, (unsigned char*)zText, nBytes); 226 + SHA1Update(&incrCtx, (unsigned char*)zText, nBytes); 452 227 } 453 228 454 229 /* 455 230 ** Add the content of a blob to the incremental SHA1 checksum. 456 231 */ 457 232 void sha1sum_step_blob(Blob *p){ 458 233 sha1sum_step_text(blob_buffer(p), blob_size(p)); ................................................................................ 466 241 ** of computation. The return pointer points to a static buffer that 467 242 ** is overwritten by subsequent calls to this function. 468 243 */ 469 244 char *sha1sum_finish(Blob *pOut){ 470 245 unsigned char zResult[20]; 471 246 static char zOut[41]; 472 247 sha1sum_step_text(0,0); 473 - SHA1Result(&incrCtx, zResult); 248 + SHA1Final(&incrCtx, zResult); 474 249 incrInit = 0; 475 250 DigestToBase16(zResult, zOut); 476 251 if( pOut ){ 477 252 blob_zero(pOut); 478 253 blob_append(pOut, zOut, 40); 479 254 } 480 255 return zOut; ................................................................................ 493 268 unsigned char zResult[20]; 494 269 char zBuf[10240]; 495 270 496 271 in = fopen(zFilename,"rb"); 497 272 if( in==0 ){ 498 273 return 1; 499 274 } 500 - SHA1Reset(&ctx); 275 + SHA1Init(&ctx); 501 276 for(;;){ 502 277 int n; 503 278 n = fread(zBuf, 1, sizeof(zBuf), in); 504 279 if( n<=0 ) break; 505 - SHA1Input(&ctx, (unsigned char*)zBuf, (unsigned)n); 280 + SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n); 506 281 } 507 282 fclose(in); 508 283 blob_zero(pCksum); 509 284 blob_resize(pCksum, 40); 510 - SHA1Result(&ctx, zResult); 285 + SHA1Final(&ctx, zResult); 511 286 DigestToBase16(zResult, blob_buffer(pCksum)); 512 287 return 0; 513 288 } 514 289 515 290 /* 516 291 ** Compute the SHA1 checksum of a blob in memory. Store the resulting 517 292 ** checksum in the blob pCksum. pCksum is assumed to be either ................................................................................ 519 294 ** 520 295 ** Return the number of errors. 521 296 */ 522 297 int sha1sum_blob(const Blob *pIn, Blob *pCksum){ 523 298 SHA1Context ctx; 524 299 unsigned char zResult[20]; 525 300 526 - SHA1Reset(&ctx); 527 - SHA1Input(&ctx, (unsigned char*)blob_buffer(pIn), blob_size(pIn)); 301 + SHA1Init(&ctx); 302 + SHA1Update(&ctx, (unsigned char*)blob_buffer(pIn), blob_size(pIn)); 528 303 if( pIn==pCksum ){ 529 304 blob_reset(pCksum); 530 305 }else{ 531 306 blob_zero(pCksum); 532 307 } 533 308 blob_resize(pCksum, 40); 534 - SHA1Result(&ctx, zResult); 309 + SHA1Final(&ctx, zResult); 535 310 DigestToBase16(zResult, blob_buffer(pCksum)); 536 311 return 0; 537 312 } 538 313 539 314 /* 540 315 ** Compute the SHA1 checksum of a zero-terminated string. The 541 316 ** result is held in memory obtained from mprintf(). 542 317 */ 543 318 char *sha1sum(const char *zIn){ 544 319 SHA1Context ctx; 545 320 unsigned char zResult[20]; 546 321 char zDigest[41]; 547 322 548 - SHA1Reset(&ctx); 549 - SHA1Input(&ctx, (unsigned const char*)zIn, strlen(zIn)); 550 - SHA1Result(&ctx, zResult); 323 + SHA1Init(&ctx); 324 + SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn)); 325 + SHA1Final(&ctx, zResult); 551 326 DigestToBase16(zResult, zDigest); 552 327 return mprintf("%s", zDigest); 553 328 } 554 329 555 330 /* 556 331 ** Convert a cleartext password for a specific user into a SHA1 hash. 557 332 ** ................................................................................ 571 346 */ 572 347 char *sha1_shared_secret(const char *zPw, const char *zLogin){ 573 348 static char *zProjectId = 0; 574 349 SHA1Context ctx; 575 350 unsigned char zResult[20]; 576 351 char zDigest[41]; 577 352 578 - SHA1Reset(&ctx); 353 + SHA1Init(&ctx); 579 354 if( zProjectId==0 ){ 580 355 zProjectId = db_get("project-code", 0); 581 356 582 357 /* On the first xfer request of a clone, the project-code is not yet 583 358 ** known. Use the cleartext password, since that is all we have. 584 359 */ 585 360 if( zProjectId==0 ){ 586 361 return mprintf("%s", zPw); 587 362 } 588 363 } 589 - SHA1Input(&ctx, (unsigned char*)zProjectId, strlen(zProjectId)); 590 - SHA1Input(&ctx, (unsigned char*)"/", 1); 591 - SHA1Input(&ctx, (unsigned char*)zLogin, strlen(zLogin)); 592 - SHA1Input(&ctx, (unsigned char*)"/", 1); 593 - SHA1Input(&ctx, (unsigned const char*)zPw, strlen(zPw)); 594 - SHA1Result(&ctx, zResult); 364 + SHA1Update(&ctx, (unsigned char*)zProjectId, strlen(zProjectId)); 365 + SHA1Update(&ctx, (unsigned char*)"/", 1); 366 + SHA1Update(&ctx, (unsigned char*)zLogin, strlen(zLogin)); 367 + SHA1Update(&ctx, (unsigned char*)"/", 1); 368 + SHA1Update(&ctx, (unsigned const char*)zPw, strlen(zPw)); 369 + SHA1Final(&ctx, zResult); 595 370 DigestToBase16(zResult, zDigest); 596 371 return mprintf("%s", zDigest); 597 372 } 598 373 599 374 /* 600 375 ** COMMAND: sha1sum 601 376 ** %fossil sha1sum FILE...
Added src/shell.c.
1 +/* 2 +** 2001 September 15 3 +** 4 +** The author disclaims copyright to this source code. In place of 5 +** a legal notice, here is a blessing: 6 +** 7 +** May you do good and not evil. 8 +** May you find forgiveness for yourself and forgive others. 9 +** May you share freely, never taking more than you give. 10 +** 11 +************************************************************************* 12 +** This file contains code to implement the "sqlite" command line 13 +** utility for accessing SQLite databases. 14 +*/ 15 +#if defined(_WIN32) || defined(WIN32) 16 +/* This needs to come before any includes for MSVC compiler */ 17 +#define _CRT_SECURE_NO_WARNINGS 18 +#endif 19 + 20 +#include <stdlib.h> 21 +#include <string.h> 22 +#include <stdio.h> 23 +#include <assert.h> 24 +#include "sqlite3.h" 25 +#include <ctype.h> 26 +#include <stdarg.h> 27 + 28 +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) 29 +# include <signal.h> 30 +# if !defined(__RTP__) && !defined(_WRS_KERNEL) 31 +# include <pwd.h> 32 +# endif 33 +# include <unistd.h> 34 +# include <sys/types.h> 35 +#endif 36 + 37 +#ifdef __OS2__ 38 +# include <unistd.h> 39 +#endif 40 + 41 +#if defined(HAVE_READLINE) && HAVE_READLINE==1 42 +# include <readline/readline.h> 43 +# include <readline/history.h> 44 +#else 45 +# define readline(p) local_getline(p,stdin) 46 +# define add_history(X) 47 +# define read_history(X) 48 +# define write_history(X) 49 +# define stifle_history(X) 50 +#endif 51 + 52 +#if defined(_WIN32) || defined(WIN32) 53 +# include <io.h> 54 +#define isatty(h) _isatty(h) 55 +#define access(f,m) _access((f),(m)) 56 +#else 57 +/* Make sure isatty() has a prototype. 58 +*/ 59 +extern int isatty(); 60 +#endif 61 + 62 +#if defined(_WIN32_WCE) 63 +/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() 64 + * thus we always assume that we have a console. That can be 65 + * overridden with the -batch command line option. 66 + */ 67 +#define isatty(x) 1 68 +#endif 69 + 70 +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL) 71 +#include <sys/time.h> 72 +#include <sys/resource.h> 73 + 74 +/* Saved resource information for the beginning of an operation */ 75 +static struct rusage sBegin; 76 + 77 +/* True if the timer is enabled */ 78 +static int enableTimer = 0; 79 + 80 +/* 81 +** Begin timing an operation 82 +*/ 83 +static void beginTimer(void){ 84 + if( enableTimer ){ 85 + getrusage(RUSAGE_SELF, &sBegin); 86 + } 87 +} 88 + 89 +/* Return the difference of two time_structs in seconds */ 90 +static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ 91 + return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + 92 + (double)(pEnd->tv_sec - pStart->tv_sec); 93 +} 94 + 95 +/* 96 +** Print the timing results. 97 +*/ 98 +static void endTimer(void){ 99 + if( enableTimer ){ 100 + struct rusage sEnd; 101 + getrusage(RUSAGE_SELF, &sEnd); 102 + printf("CPU Time: user %f sys %f\n", 103 + timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), 104 + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); 105 + } 106 +} 107 + 108 +#define BEGIN_TIMER beginTimer() 109 +#define END_TIMER endTimer() 110 +#define HAS_TIMER 1 111 + 112 +#elif (defined(_WIN32) || defined(WIN32)) 113 + 114 +#include <windows.h> 115 + 116 +/* Saved resource information for the beginning of an operation */ 117 +static HANDLE hProcess; 118 +static FILETIME ftKernelBegin; 119 +static FILETIME ftUserBegin; 120 +typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME); 121 +static GETPROCTIMES getProcessTimesAddr = NULL; 122 + 123 +/* True if the timer is enabled */ 124 +static int enableTimer = 0; 125 + 126 +/* 127 +** Check to see if we have timer support. Return 1 if necessary 128 +** support found (or found previously). 129 +*/ 130 +static int hasTimer(void){ 131 + if( getProcessTimesAddr ){ 132 + return 1; 133 + } else { 134 + /* GetProcessTimes() isn't supported in WIN95 and some other Windows versions. 135 + ** See if the version we are running on has it, and if it does, save off 136 + ** a pointer to it and the current process handle. 137 + */ 138 + hProcess = GetCurrentProcess(); 139 + if( hProcess ){ 140 + HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); 141 + if( NULL != hinstLib ){ 142 + getProcessTimesAddr = (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); 143 + if( NULL != getProcessTimesAddr ){ 144 + return 1; 145 + } 146 + FreeLibrary(hinstLib); 147 + } 148 + } 149 + } 150 + return 0; 151 +} 152 + 153 +/* 154 +** Begin timing an operation 155 +*/ 156 +static void beginTimer(void){ 157 + if( enableTimer && getProcessTimesAddr ){ 158 + FILETIME ftCreation, ftExit; 159 + getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelBegin, &ftUserBegin); 160 + } 161 +} 162 + 163 +/* Return the difference of two FILETIME structs in seconds */ 164 +static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ 165 + sqlite_int64 i64Start = *((sqlite_int64 *) pStart); 166 + sqlite_int64 i64End = *((sqlite_int64 *) pEnd); 167 + return (double) ((i64End - i64Start) / 10000000.0); 168 +} 169 + 170 +/* 171 +** Print the timing results. 172 +*/ 173 +static void endTimer(void){ 174 + if( enableTimer && getProcessTimesAddr){ 175 + FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; 176 + getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd); 177 + printf("CPU Time: user %f sys %f\n", 178 + timeDiff(&ftUserBegin, &ftUserEnd), 179 + timeDiff(&ftKernelBegin, &ftKernelEnd)); 180 + } 181 +} 182 + 183 +#define BEGIN_TIMER beginTimer() 184 +#define END_TIMER endTimer() 185 +#define HAS_TIMER hasTimer() 186 + 187 +#else 188 +#define BEGIN_TIMER 189 +#define END_TIMER 190 +#define HAS_TIMER 0 191 +#endif 192 + 193 +/* 194 +** Used to prevent warnings about unused parameters 195 +*/ 196 +#define UNUSED_PARAMETER(x) (void)(x) 197 + 198 +/* 199 +** If the following flag is set, then command execution stops 200 +** at an error if we are not interactive. 201 +*/ 202 +static int bail_on_error = 0; 203 + 204 +/* 205 +** Threat stdin as an interactive input if the following variable 206 +** is true. Otherwise, assume stdin is connected to a file or pipe. 207 +*/ 208 +static int stdin_is_interactive = 1; 209 + 210 +/* 211 +** The following is the open SQLite database. We make a pointer 212 +** to this database a static variable so that it can be accessed 213 +** by the SIGINT handler to interrupt database processing. 214 +*/ 215 +static sqlite3 *db = 0; 216 + 217 +/* 218 +** True if an interrupt (Control-C) has been received. 219 +*/ 220 +static volatile int seenInterrupt = 0; 221 + 222 +/* 223 +** This is the name of our program. It is set in main(), used 224 +** in a number of other places, mostly for error messages. 225 +*/ 226 +static char *Argv0; 227 + 228 +/* 229 +** Prompt strings. Initialized in main. Settable with 230 +** .prompt main continue 231 +*/ 232 +static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ 233 +static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ 234 + 235 +/* 236 +** Write I/O traces to the following stream. 237 +*/ 238 +#ifdef SQLITE_ENABLE_IOTRACE 239 +static FILE *iotrace = 0; 240 +#endif 241 + 242 +/* 243 +** This routine works like printf in that its first argument is a 244 +** format string and subsequent arguments are values to be substituted 245 +** in place of % fields. The result of formatting this string 246 +** is written to iotrace. 247 +*/ 248 +#ifdef SQLITE_ENABLE_IOTRACE 249 +static void iotracePrintf(const char *zFormat, ...){ 250 + va_list ap; 251 + char *z; 252 + if( iotrace==0 ) return; 253 + va_start(ap, zFormat); 254 + z = sqlite3_vmprintf(zFormat, ap); 255 + va_end(ap); 256 + fprintf(iotrace, "%s", z); 257 + sqlite3_free(z); 258 +} 259 +#endif 260 + 261 + 262 +/* 263 +** Determines if a string is a number of not. 264 +*/ 265 +static int isNumber(const char *z, int *realnum){ 266 + if( *z=='-' || *z=='+' ) z++; 267 + if( !isdigit(*z) ){ 268 + return 0; 269 + } 270 + z++; 271 + if( realnum ) *realnum = 0; 272 + while( isdigit(*z) ){ z++; } 273 + if( *z=='.' ){ 274 + z++; 275 + if( !isdigit(*z) ) return 0; 276 + while( isdigit(*z) ){ z++; } 277 + if( realnum ) *realnum = 1; 278 + } 279 + if( *z=='e' || *z=='E' ){ 280 + z++; 281 + if( *z=='+' || *z=='-' ) z++; 282 + if( !isdigit(*z) ) return 0; 283 + while( isdigit(*z) ){ z++; } 284 + if( realnum ) *realnum = 1; 285 + } 286 + return *z==0; 287 +} 288 + 289 +/* 290 +** A global char* and an SQL function to access its current value 291 +** from within an SQL statement. This program used to use the 292 +** sqlite_exec_printf() API to substitue a string into an SQL statement. 293 +** The correct way to do this with sqlite3 is to use the bind API, but 294 +** since the shell is built around the callback paradigm it would be a lot 295 +** of work. Instead just use this hack, which is quite harmless. 296 +*/ 297 +static const char *zShellStatic = 0; 298 +static void shellstaticFunc( 299 + sqlite3_context *context, 300 + int argc, 301 + sqlite3_value **argv 302 +){ 303 + assert( 0==argc ); 304 + assert( zShellStatic ); 305 + UNUSED_PARAMETER(argc); 306 + UNUSED_PARAMETER(argv); 307 + sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC); 308 +} 309 + 310 + 311 +/* 312 +** This routine reads a line of text from FILE in, stores 313 +** the text in memory obtained from malloc() and returns a pointer 314 +** to the text. NULL is returned at end of file, or if malloc() 315 +** fails. 316 +** 317 +** The interface is like "readline" but no command-line editing 318 +** is done. 319 +*/ 320 +static char *local_getline(char *zPrompt, FILE *in){ 321 + char *zLine; 322 + int nLine; 323 + int n; 324 + int eol; 325 + 326 + if( zPrompt && *zPrompt ){ 327 + printf("%s",zPrompt); 328 + fflush(stdout); 329 + } 330 + nLine = 100; 331 + zLine = malloc( nLine ); 332 + if( zLine==0 ) return 0; 333 + n = 0; 334 + eol = 0; 335 + while( !eol ){ 336 + if( n+100>nLine ){ 337 + nLine = nLine*2 + 100; 338 + zLine = realloc(zLine, nLine); 339 + if( zLine==0 ) return 0; 340 + } 341 + if( fgets(&zLine[n], nLine - n, in)==0 ){ 342 + if( n==0 ){ 343 + free(zLine); 344 + return 0; 345 + } 346 + zLine[n] = 0; 347 + eol = 1; 348 + break; 349 + } 350 + while( zLine[n] ){ n++; } 351 + if( n>0 && zLine[n-1]=='\n' ){ 352 + n--; 353 + if( n>0 && zLine[n-1]=='\r' ) n--; 354 + zLine[n] = 0; 355 + eol = 1; 356 + } 357 + } 358 + zLine = realloc( zLine, n+1 ); 359 + return zLine; 360 +} 361 + 362 +/* 363 +** Retrieve a single line of input text. 364 +** 365 +** zPrior is a string of prior text retrieved. If not the empty 366 +** string, then issue a continuation prompt. 367 +*/ 368 +static char *one_input_line(const char *zPrior, FILE *in){ 369 + char *zPrompt; 370 + char *zResult; 371 + if( in!=0 ){ 372 + return local_getline(0, in); 373 + } 374 + if( zPrior && zPrior[0] ){ 375 + zPrompt = continuePrompt; 376 + }else{ 377 + zPrompt = mainPrompt; 378 + } 379 + zResult = readline(zPrompt); 380 +#if defined(HAVE_READLINE) && HAVE_READLINE==1 381 + if( zResult && *zResult ) add_history(zResult); 382 +#endif 383 + return zResult; 384 +} 385 + 386 +struct previous_mode_data { 387 + int valid; /* Is there legit data in here? */ 388 + int mode; 389 + int showHeader; 390 + int colWidth[100]; 391 +}; 392 + 393 +/* 394 +** An pointer to an instance of this structure is passed from 395 +** the main program to the callback. This is used to communicate 396 +** state and mode information. 397 +*/ 398 +struct callback_data { 399 + sqlite3 *db; /* The database */ 400 + int echoOn; /* True to echo input commands */ 401 + int statsOn; /* True to display memory stats before each finalize */ 402 + int cnt; /* Number of records displayed so far */ 403 + FILE *out; /* Write results here */ 404 + int mode; /* An output mode setting */ 405 + int writableSchema; /* True if PRAGMA writable_schema=ON */ 406 + int showHeader; /* True to show column names in List or Column mode */ 407 + char *zDestTable; /* Name of destination table when MODE_Insert */ 408 + char separator[20]; /* Separator character for MODE_List */ 409 + int colWidth[100]; /* Requested width of each column when in column mode*/ 410 + int actualWidth[100]; /* Actual width of each column */ 411 + char nullvalue[20]; /* The text to print when a NULL comes back from 412 + ** the database */ 413 + struct previous_mode_data explainPrev; 414 + /* Holds the mode information just before 415 + ** .explain ON */ 416 + char outfile[FILENAME_MAX]; /* Filename for *out */ 417 + const char *zDbFilename; /* name of the database file */ 418 + sqlite3_stmt *pStmt; /* Current statement if any. */ 419 + FILE *pLog; /* Write log output here */ 420 +}; 421 + 422 +/* 423 +** These are the allowed modes. 424 +*/ 425 +#define MODE_Line 0 /* One column per line. Blank line between records */ 426 +#define MODE_Column 1 /* One record per line in neat columns */ 427 +#define MODE_List 2 /* One record per line with a separator */ 428 +#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ 429 +#define MODE_Html 4 /* Generate an XHTML table */ 430 +#define MODE_Insert 5 /* Generate SQL "insert" statements */ 431 +#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ 432 +#define MODE_Csv 7 /* Quote strings, numbers are plain */ 433 +#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ 434 + 435 +static const char *modeDescr[] = { 436 + "line", 437 + "column", 438 + "list", 439 + "semi", 440 + "html", 441 + "insert", 442 + "tcl", 443 + "csv", 444 + "explain", 445 +}; 446 + 447 +/* 448 +** Number of elements in an array 449 +*/ 450 +#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) 451 + 452 +/* 453 +** Compute a string length that is limited to what can be stored in 454 +** lower 30 bits of a 32-bit signed integer. 455 +*/ 456 +static int strlen30(const char *z){ 457 + const char *z2 = z; 458 + while( *z2 ){ z2++; } 459 + return 0x3fffffff & (int)(z2 - z); 460 +} 461 + 462 +/* 463 +** A callback for the sqlite3_log() interface. 464 +*/ 465 +static void shellLog(void *pArg, int iErrCode, const char *zMsg){ 466 + struct callback_data *p = (struct callback_data*)pArg; 467 + if( p->pLog==0 ) return; 468 + fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); 469 + fflush(p->pLog); 470 +} 471 + 472 +/* 473 +** Output the given string as a hex-encoded blob (eg. X'1234' ) 474 +*/ 475 +static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ 476 + int i; 477 + char *zBlob = (char *)pBlob; 478 + fprintf(out,"X'"); 479 + for(i=0; i<nBlob; i++){ fprintf(out,"%02x",zBlob[i]); } 480 + fprintf(out,"'"); 481 +} 482 + 483 +/* 484 +** Output the given string as a quoted string using SQL quoting conventions. 485 +*/ 486 +static void output_quoted_string(FILE *out, const char *z){ 487 + int i; 488 + int nSingle = 0; 489 + for(i=0; z[i]; i++){ 490 + if( z[i]=='\'' ) nSingle++; 491 + } 492 + if( nSingle==0 ){ 493 + fprintf(out,"'%s'",z); 494 + }else{ 495 + fprintf(out,"'"); 496 + while( *z ){ 497 + for(i=0; z[i] && z[i]!='\''; i++){} 498 + if( i==0 ){ 499 + fprintf(out,"''"); 500 + z++; 501 + }else if( z[i]=='\'' ){ 502 + fprintf(out,"%.*s''",i,z); 503 + z += i+1; 504 + }else{ 505 + fprintf(out,"%s",z); 506 + break; 507 + } 508 + } 509 + fprintf(out,"'"); 510 + } 511 +} 512 + 513 +/* 514 +** Output the given string as a quoted according to C or TCL quoting rules. 515 +*/ 516 +static void output_c_string(FILE *out, const char *z){ 517 + unsigned int c; 518 + fputc('"', out); 519 + while( (c = *(z++))!=0 ){ 520 + if( c=='\\' ){ 521 + fputc(c, out); 522 + fputc(c, out); 523 + }else if( c=='\t' ){ 524 + fputc('\\', out); 525 + fputc('t', out); 526 + }else if( c=='\n' ){ 527 + fputc('\\', out); 528 + fputc('n', out); 529 + }else if( c=='\r' ){ 530 + fputc('\\', out); 531 + fputc('r', out); 532 + }else if( !isprint(c) ){ 533 + fprintf(out, "\\%03o", c&0xff); 534 + }else{ 535 + fputc(c, out); 536 + } 537 + } 538 + fputc('"', out); 539 +} 540 + 541 +/* 542 +** Output the given string with characters that are special to 543 +** HTML escaped. 544 +*/ 545 +static void output_html_string(FILE *out, const char *z){ 546 + int i; 547 + while( *z ){ 548 + for(i=0; z[i] 549 + && z[i]!='<' 550 + && z[i]!='&' 551 + && z[i]!='>' 552 + && z[i]!='\"' 553 + && z[i]!='\''; 554 + i++){} 555 + if( i>0 ){ 556 + fprintf(out,"%.*s",i,z); 557 + } 558 + if( z[i]=='<' ){ 559 + fprintf(out,"<"); 560 + }else if( z[i]=='&' ){ 561 + fprintf(out,"&"); 562 + }else if( z[i]=='>' ){ 563 + fprintf(out,">"); 564 + }else if( z[i]=='\"' ){ 565 + fprintf(out,"""); 566 + }else if( z[i]=='\'' ){ 567 + fprintf(out,"'"); 568 + }else{ 569 + break; 570 + } 571 + z += i + 1; 572 + } 573 +} 574 + 575 +/* 576 +** If a field contains any character identified by a 1 in the following 577 +** array, then the string must be quoted for CSV. 578 +*/ 579 +static const char needCsvQuote[] = { 580 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 581 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 582 + 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 583 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 584 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 585 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 586 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 587 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 588 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 589 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 590 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 591 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 592 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 593 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 594 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 595 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 596 +}; 597 + 598 +/* 599 +** Output a single term of CSV. Actually, p->separator is used for 600 +** the separator, which may or may not be a comma. p->nullvalue is 601 +** the null value. Strings are quoted using ANSI-C rules. Numbers 602 +** appear outside of quotes. 603 +*/ 604 +static void output_csv(struct callback_data *p, const char *z, int bSep){ 605 + FILE *out = p->out; 606 + if( z==0 ){ 607 + fprintf(out,"%s",p->nullvalue); 608 + }else{ 609 + int i; 610 + int nSep = strlen30(p->separator); 611 + for(i=0; z[i]; i++){ 612 + if( needCsvQuote[((unsigned char*)z)[i]] 613 + || (z[i]==p->separator[0] && 614 + (nSep==1 || memcmp(z, p->separator, nSep)==0)) ){ 615 + i = 0; 616 + break; 617 + } 618 + } 619 + if( i==0 ){ 620 + putc('"', out); 621 + for(i=0; z[i]; i++){ 622 + if( z[i]=='"' ) putc('"', out); 623 + putc(z[i], out); 624 + } 625 + putc('"', out); 626 + }else{ 627 + fprintf(out, "%s", z); 628 + } 629 + } 630 + if( bSep ){ 631 + fprintf(p->out, "%s", p->separator); 632 + } 633 +} 634 + 635 +#ifdef SIGINT 636 +/* 637 +** This routine runs when the user presses Ctrl-C 638 +*/ 639 +static void interrupt_handler(int NotUsed){ 640 + UNUSED_PARAMETER(NotUsed); 641 + seenInterrupt = 1; 642 + if( db ) sqlite3_interrupt(db); 643 +} 644 +#endif 645 + 646 +/* 647 +** This is the callback routine that the shell 648 +** invokes for each row of a query result. 649 +*/ 650 +static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){ 651 + int i; 652 + struct callback_data *p = (struct callback_data*)pArg; 653 + 654 + switch( p->mode ){ 655 + case MODE_Line: { 656 + int w = 5; 657 + if( azArg==0 ) break; 658 + for(i=0; i<nArg; i++){ 659 + int len = strlen30(azCol[i] ? azCol[i] : ""); 660 + if( len>w ) w = len; 661 + } 662 + if( p->cnt++>0 ) fprintf(p->out,"\n"); 663 + for(i=0; i<nArg; i++){ 664 + fprintf(p->out,"%*s = %s\n", w, azCol[i], 665 + azArg[i] ? azArg[i] : p->nullvalue); 666 + } 667 + break; 668 + } 669 + case MODE_Explain: 670 + case MODE_Column: { 671 + if( p->cnt++==0 ){ 672 + for(i=0; i<nArg; i++){ 673 + int w, n; 674 + if( i<ArraySize(p->colWidth) ){ 675 + w = p->colWidth[i]; 676 + }else{ 677 + w = 0; 678 + } 679 + if( w<=0 ){ 680 + w = strlen30(azCol[i] ? azCol[i] : ""); 681 + if( w<10 ) w = 10; 682 + n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullvalue); 683 + if( w<n ) w = n; 684 + } 685 + if( i<ArraySize(p->actualWidth) ){ 686 + p->actualWidth[i] = w; 687 + } 688 + if( p->showHeader ){ 689 + fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " "); 690 + } 691 + } 692 + if( p->showHeader ){ 693 + for(i=0; i<nArg; i++){ 694 + int w; 695 + if( i<ArraySize(p->actualWidth) ){ 696 + w = p->actualWidth[i]; 697 + }else{ 698 + w = 10; 699 + } 700 + fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" 701 + "----------------------------------------------------------", 702 + i==nArg-1 ? "\n": " "); 703 + } 704 + } 705 + } 706 + if( azArg==0 ) break; 707 + for(i=0; i<nArg; i++){ 708 + int w; 709 + if( i<ArraySize(p->actualWidth) ){ 710 + w = p->actualWidth[i]; 711 + }else{ 712 + w = 10; 713 + } 714 + if( p->mode==MODE_Explain && azArg[i] && 715 + strlen30(azArg[i])>w ){ 716 + w = strlen30(azArg[i]); 717 + } 718 + fprintf(p->out,"%-*.*s%s",w,w, 719 + azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); 720 + } 721 + break; 722 + } 723 + case MODE_Semi: 724 + case MODE_List: { 725 + if( p->cnt++==0 && p->showHeader ){ 726 + for(i=0; i<nArg; i++){ 727 + fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator); 728 + } 729 + } 730 + if( azArg==0 ) break; 731 + for(i=0; i<nArg; i++){ 732 + char *z = azArg[i]; 733 + if( z==0 ) z = p->nullvalue; 734 + fprintf(p->out, "%s", z); 735 + if( i<nArg-1 ){ 736 + fprintf(p->out, "%s", p->separator); 737 + }else if( p->mode==MODE_Semi ){ 738 + fprintf(p->out, ";\n"); 739 + }else{ 740 + fprintf(p->out, "\n"); 741 + } 742 + } 743 + break; 744 + } 745 + case MODE_Html: { 746 + if( p->cnt++==0 && p->showHeader ){ 747 + fprintf(p->out,"<TR>"); 748 + for(i=0; i<nArg; i++){ 749 + fprintf(p->out,"<TH>"); 750 + output_html_string(p->out, azCol[i]); 751 + fprintf(p->out,"</TH>\n"); 752 + } 753 + fprintf(p->out,"</TR>\n"); 754 + } 755 + if( azArg==0 ) break; 756 + fprintf(p->out,"<TR>"); 757 + for(i=0; i<nArg; i++){ 758 + fprintf(p->out,"<TD>"); 759 + output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); 760 + fprintf(p->out,"</TD>\n"); 761 + } 762 + fprintf(p->out,"</TR>\n"); 763 + break; 764 + } 765 + case MODE_Tcl: { 766 + if( p->cnt++==0 && p->showHeader ){ 767 + for(i=0; i<nArg; i++){ 768 + output_c_string(p->out,azCol[i] ? azCol[i] : ""); 769 + fprintf(p->out, "%s", p->separator); 770 + } 771 + fprintf(p->out,"\n"); 772 + } 773 + if( azArg==0 ) break; 774 + for(i=0; i<nArg; i++){ 775 + output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); 776 + fprintf(p->out, "%s", p->separator); 777 + } 778 + fprintf(p->out,"\n"); 779 + break; 780 + } 781 + case MODE_Csv: { 782 + if( p->cnt++==0 && p->showHeader ){ 783 + for(i=0; i<nArg; i++){ 784 + output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); 785 + } 786 + fprintf(p->out,"\n"); 787 + } 788 + if( azArg==0 ) break; 789 + for(i=0; i<nArg; i++){ 790 + output_csv(p, azArg[i], i<nArg-1); 791 + } 792 + fprintf(p->out,"\n"); 793 + break; 794 + } 795 + case MODE_Insert: { 796 + p->cnt++; 797 + if( azArg==0 ) break; 798 + fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable); 799 + for(i=0; i<nArg; i++){ 800 + char *zSep = i>0 ? ",": ""; 801 + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ 802 + fprintf(p->out,"%sNULL",zSep); 803 + }else if( aiType && aiType[i]==SQLITE_TEXT ){ 804 + if( zSep[0] ) fprintf(p->out,"%s",zSep); 805 + output_quoted_string(p->out, azArg[i]); 806 + }else if( aiType && (aiType[i]==SQLITE_INTEGER || aiType[i]==SQLITE_FLOAT) ){ 807 + fprintf(p->out,"%s%s",zSep, azArg[i]); 808 + }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ 809 + const void *pBlob = sqlite3_column_blob(p->pStmt, i); 810 + int nBlob = sqlite3_column_bytes(p->pStmt, i); 811 + if( zSep[0] ) fprintf(p->out,"%s",zSep); 812 + output_hex_blob(p->out, pBlob, nBlob); 813 + }else if( isNumber(azArg[i], 0) ){ 814 + fprintf(p->out,"%s%s",zSep, azArg[i]); 815 + }else{ 816 + if( zSep[0] ) fprintf(p->out,"%s",zSep); 817 + output_quoted_string(p->out, azArg[i]); 818 + } 819 + } 820 + fprintf(p->out,");\n"); 821 + break; 822 + } 823 + } 824 + return 0; 825 +} 826 + 827 +/* 828 +** This is the callback routine that the SQLite library 829 +** invokes for each row of a query result. 830 +*/ 831 +static int callback(void *pArg, int nArg, char **azArg, char **azCol){ 832 + /* since we don't have type info, call the shell_callback with a NULL value */ 833 + return shell_callback(pArg, nArg, azArg, azCol, NULL); 834 +} 835 + 836 +/* 837 +** Set the destination table field of the callback_data structure to 838 +** the name of the table given. Escape any quote characters in the 839 +** table name. 840 +*/ 841 +static void set_table_name(struct callback_data *p, const char *zName){ 842 + int i, n; 843 + int needQuote; 844 + char *z; 845 + 846 + if( p->zDestTable ){ 847 + free(p->zDestTable); 848 + p->zDestTable = 0; 849 + } 850 + if( zName==0 ) return; 851 + needQuote = !isalpha((unsigned char)*zName) && *zName!='_'; 852 + for(i=n=0; zName[i]; i++, n++){ 853 + if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){ 854 + needQuote = 1; 855 + if( zName[i]=='\'' ) n++; 856 + } 857 + } 858 + if( needQuote ) n += 2; 859 + z = p->zDestTable = malloc( n+1 ); 860 + if( z==0 ){ 861 + fprintf(stderr,"Error: out of memory\n"); 862 + exit(1); 863 + } 864 + n = 0; 865 + if( needQuote ) z[n++] = '\''; 866 + for(i=0; zName[i]; i++){ 867 + z[n++] = zName[i]; 868 + if( zName[i]=='\'' ) z[n++] = '\''; 869 + } 870 + if( needQuote ) z[n++] = '\''; 871 + z[n] = 0; 872 +} 873 + 874 +/* zIn is either a pointer to a NULL-terminated string in memory obtained 875 +** from malloc(), or a NULL pointer. The string pointed to by zAppend is 876 +** added to zIn, and the result returned in memory obtained from malloc(). 877 +** zIn, if it was not NULL, is freed. 878 +** 879 +** If the third argument, quote, is not '\0', then it is used as a 880 +** quote character for zAppend. 881 +*/ 882 +static char *appendText(char *zIn, char const *zAppend, char quote){ 883 + int len; 884 + int i; 885 + int nAppend = strlen30(zAppend); 886 + int nIn = (zIn?strlen30(zIn):0); 887 + 888 + len = nAppend+nIn+1; 889 + if( quote ){ 890 + len += 2; 891 + for(i=0; i<nAppend; i++){ 892 + if( zAppend[i]==quote ) len++; 893 + } 894 + } 895 + 896 + zIn = (char *)realloc(zIn, len); 897 + if( !zIn ){ 898 + return 0; 899 + } 900 + 901 + if( quote ){ 902 + char *zCsr = &zIn[nIn]; 903 + *zCsr++ = quote; 904 + for(i=0; i<nAppend; i++){ 905 + *zCsr++ = zAppend[i]; 906 + if( zAppend[i]==quote ) *zCsr++ = quote; 907 + } 908 + *zCsr++ = quote; 909 + *zCsr++ = '\0'; 910 + assert( (zCsr-zIn)==len ); 911 + }else{ 912 + memcpy(&zIn[nIn], zAppend, nAppend); 913 + zIn[len-1] = '\0'; 914 + } 915 + 916 + return zIn; 917 +} 918 + 919 + 920 +/* 921 +** Execute a query statement that has a single result column. Print 922 +** that result column on a line by itself with a semicolon terminator. 923 +** 924 +** This is used, for example, to show the schema of the database by 925 +** querying the SQLITE_MASTER table. 926 +*/ 927 +static int run_table_dump_query( 928 + FILE *out, /* Send output here */ 929 + sqlite3 *db, /* Database to query */ 930 + const char *zSelect, /* SELECT statement to extract content */ 931 + const char *zFirstRow /* Print before first row, if not NULL */ 932 +){ 933 + sqlite3_stmt *pSelect; 934 + int rc; 935 + rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0); 936 + if( rc!=SQLITE_OK || !pSelect ){ 937 + return rc; 938 + } 939 + rc = sqlite3_step(pSelect); 940 + while( rc==SQLITE_ROW ){ 941 + if( zFirstRow ){ 942 + fprintf(out, "%s", zFirstRow); 943 + zFirstRow = 0; 944 + } 945 + fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0)); 946 + rc = sqlite3_step(pSelect); 947 + } 948 + return sqlite3_finalize(pSelect); 949 +} 950 + 951 +/* 952 +** Allocate space and save off current error string. 953 +*/ 954 +static char *save_err_msg( 955 + sqlite3 *db /* Database to query */ 956 +){ 957 + int nErrMsg = 1+strlen30(sqlite3_errmsg(db)); 958 + char *zErrMsg = sqlite3_malloc(nErrMsg); 959 + if( zErrMsg ){ 960 + memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg); 961 + } 962 + return zErrMsg; 963 +} 964 + 965 +/* 966 +** Display memory stats. 967 +*/ 968 +static int display_stats( 969 + sqlite3 *db, /* Database to query */ 970 + struct callback_data *pArg, /* Pointer to struct callback_data */ 971 + int bReset /* True to reset the stats */ 972 +){ 973 + int iCur; 974 + int iHiwtr; 975 + 976 + if( pArg && pArg->out ){ 977 + 978 + iHiwtr = iCur = -1; 979 + sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); 980 + fprintf(pArg->out, "Memory Used: %d (max %d) bytes\n", iCur, iHiwtr); 981 + iHiwtr = iCur = -1; 982 + sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); 983 + fprintf(pArg->out, "Number of Allocations: %d (max %d)\n", iCur, iHiwtr); 984 +/* 985 +** Not currently used by the CLI. 986 +** iHiwtr = iCur = -1; 987 +** sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); 988 +** fprintf(pArg->out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr); 989 +*/ 990 + iHiwtr = iCur = -1; 991 + sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset); 992 + fprintf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); 993 +/* 994 +** Not currently used by the CLI. 995 +** iHiwtr = iCur = -1; 996 +** sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); 997 +** fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr); 998 +*/ 999 + iHiwtr = iCur = -1; 1000 + sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset); 1001 + fprintf(pArg->out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); 1002 + iHiwtr = iCur = -1; 1003 + sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset); 1004 + fprintf(pArg->out, "Largest Allocation: %d bytes\n", iHiwtr); 1005 + iHiwtr = iCur = -1; 1006 + sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset); 1007 + fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n", iHiwtr); 1008 + iHiwtr = iCur = -1; 1009 + sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset); 1010 + fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n", iHiwtr); 1011 +#ifdef YYTRACKMAXSTACKDEPTH 1012 + iHiwtr = iCur = -1; 1013 + sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset); 1014 + fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", iCur, iHiwtr); 1015 +#endif 1016 + } 1017 + 1018 + if( pArg && pArg->out && db ){ 1019 + iHiwtr = iCur = -1; 1020 + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset); 1021 + fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr); 1022 + iHiwtr = iCur = -1; 1023 + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); 1024 + fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur); 1025 + iHiwtr = iCur = -1; 1026 + sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); 1027 + fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur); 1028 + iHiwtr = iCur = -1; 1029 + sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); 1030 + fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur); 1031 + } 1032 + 1033 + if( pArg && pArg->out && db && pArg->pStmt ){ 1034 + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset); 1035 + fprintf(pArg->out, "Fullscan Steps: %d\n", iCur); 1036 + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); 1037 + fprintf(pArg->out, "Sort Operations: %d\n", iCur); 1038 + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset); 1039 + fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur); 1040 + } 1041 + 1042 + return 0; 1043 +} 1044 + 1045 +/* 1046 +** Execute a statement or set of statements. Print 1047 +** any result rows/columns depending on the current mode 1048 +** set via the supplied callback. 1049 +** 1050 +** This is very similar to SQLite's built-in sqlite3_exec() 1051 +** function except it takes a slightly different callback 1052 +** and callback data argument. 1053 +*/ 1054 +static int shell_exec( 1055 + sqlite3 *db, /* An open database */ 1056 + const char *zSql, /* SQL to be evaluated */ 1057 + int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ 1058 + /* (not the same as sqlite3_exec) */ 1059 + struct callback_data *pArg, /* Pointer to struct callback_data */ 1060 + char **pzErrMsg /* Error msg written here */ 1061 +){ 1062 + sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ 1063 + int rc = SQLITE_OK; /* Return Code */ 1064 + const char *zLeftover; /* Tail of unprocessed SQL */ 1065 + 1066 + if( pzErrMsg ){ 1067 + *pzErrMsg = NULL; 1068 + } 1069 + 1070 + while( zSql[0] && (SQLITE_OK == rc) ){ 1071 + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); 1072 + if( SQLITE_OK != rc ){ 1073 + if( pzErrMsg ){ 1074 + *pzErrMsg = save_err_msg(db); 1075 + } 1076 + }else{ 1077 + if( !pStmt ){ 1078 + /* this happens for a comment or white-space */ 1079 + zSql = zLeftover; 1080 + while( isspace(zSql[0]) ) zSql++; 1081 + continue; 1082 + } 1083 + 1084 + /* save off the prepared statment handle and reset row count */ 1085 + if( pArg ){ 1086 + pArg->pStmt = pStmt; 1087 + pArg->cnt = 0; 1088 + } 1089 + 1090 + /* echo the sql statement if echo on */ 1091 + if( pArg && pArg->echoOn ){ 1092 + const char *zStmtSql = sqlite3_sql(pStmt); 1093 + fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); 1094 + } 1095 + 1096 + /* perform the first step. this will tell us if we 1097 + ** have a result set or not and how wide it is. 1098 + */ 1099 + rc = sqlite3_step(pStmt); 1100 + /* if we have a result set... */ 1101 + if( SQLITE_ROW == rc ){ 1102 + /* if we have a callback... */ 1103 + if( xCallback ){ 1104 + /* allocate space for col name ptr, value ptr, and type */ 1105 + int nCol = sqlite3_column_count(pStmt); 1106 + void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1); 1107 + if( !pData ){ 1108 + rc = SQLITE_NOMEM; 1109 + }else{ 1110 + char **azCols = (char **)pData; /* Names of result columns */ 1111 + char **azVals = &azCols[nCol]; /* Results */ 1112 + int *aiTypes = (int *)&azVals[nCol]; /* Result types */ 1113 + int i; 1114 + assert(sizeof(int) <= sizeof(char *)); 1115 + /* save off ptrs to column names */ 1116 + for(i=0; i<nCol; i++){ 1117 + azCols[i] = (char *)sqlite3_column_name(pStmt, i); 1118 + } 1119 + do{ 1120 + /* extract the data and data types */ 1121 + for(i=0; i<nCol; i++){ 1122 + azVals[i] = (char *)sqlite3_column_text(pStmt, i); 1123 + aiTypes[i] = sqlite3_column_type(pStmt, i); 1124 + if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ 1125 + rc = SQLITE_NOMEM; 1126 + break; /* from for */ 1127 + } 1128 + } /* end for */ 1129 + 1130 + /* if data and types extracted successfully... */ 1131 + if( SQLITE_ROW == rc ){ 1132 + /* call the supplied callback with the result row data */ 1133 + if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){ 1134 + rc = SQLITE_ABORT; 1135 + }else{ 1136 + rc = sqlite3_step(pStmt); 1137 + } 1138 + } 1139 + } while( SQLITE_ROW == rc ); 1140 + sqlite3_free(pData); 1141 + } 1142 + }else{ 1143 + do{ 1144 + rc = sqlite3_step(pStmt); 1145 + } while( rc == SQLITE_ROW ); 1146 + } 1147 + } 1148 + 1149 + /* print usage stats if stats on */ 1150 + if( pArg && pArg->statsOn ){ 1151 + display_stats(db, pArg, 0); 1152 + } 1153 + 1154 + /* Finalize the statement just executed. If this fails, save a 1155 + ** copy of the error message. Otherwise, set zSql to point to the 1156 + ** next statement to execute. */ 1157 + rc = sqlite3_finalize(pStmt); 1158 + if( rc==SQLITE_OK ){ 1159 + zSql = zLeftover; 1160 + while( isspace(zSql[0]) ) zSql++; 1161 + }else if( pzErrMsg ){ 1162 + *pzErrMsg = save_err_msg(db); 1163 + } 1164 + 1165 + /* clear saved stmt handle */ 1166 + if( pArg ){ 1167 + pArg->pStmt = NULL; 1168 + } 1169 + } 1170 + } /* end while */ 1171 + 1172 + return rc; 1173 +} 1174 + 1175 + 1176 +/* 1177 +** This is a different callback routine used for dumping the database. 1178 +** Each row received by this callback consists of a table name, 1179 +** the table type ("index" or "table") and SQL to create the table. 1180 +** This routine should print text sufficient to recreate the table. 1181 +*/ 1182 +static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ 1183 + int rc; 1184 + const char *zTable; 1185 + const char *zType; 1186 + const char *zSql; 1187 + const char *zPrepStmt = 0; 1188 + struct callback_data *p = (struct callback_data *)pArg; 1189 + 1190 + UNUSED_PARAMETER(azCol); 1191 + if( nArg!=3 ) return 1; 1192 + zTable = azArg[0]; 1193 + zType = azArg[1]; 1194 + zSql = azArg[2]; 1195 + 1196 + if( strcmp(zTable, "sqlite_sequence")==0 ){ 1197 + zPrepStmt = "DELETE FROM sqlite_sequence;\n"; 1198 + }else if( strcmp(zTable, "sqlite_stat1")==0 ){ 1199 + fprintf(p->out, "ANALYZE sqlite_master;\n"); 1200 + }else if( strncmp(zTable, "sqlite_", 7)==0 ){ 1201 + return 0; 1202 + }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ 1203 + char *zIns; 1204 + if( !p->writableSchema ){ 1205 + fprintf(p->out, "PRAGMA writable_schema=ON;\n"); 1206 + p->writableSchema = 1; 1207 + } 1208 + zIns = sqlite3_mprintf( 1209 + "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" 1210 + "VALUES('table','%q','%q',0,'%q');", 1211 + zTable, zTable, zSql); 1212 + fprintf(p->out, "%s\n", zIns); 1213 + sqlite3_free(zIns); 1214 + return 0; 1215 + }else{ 1216 + fprintf(p->out, "%s;\n", zSql); 1217 + } 1218 + 1219 + if( strcmp(zType, "table")==0 ){ 1220 + sqlite3_stmt *pTableInfo = 0; 1221 + char *zSelect = 0; 1222 + char *zTableInfo = 0; 1223 + char *zTmp = 0; 1224 + int nRow = 0; 1225 + 1226 + zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); 1227 + zTableInfo = appendText(zTableInfo, zTable, '"'); 1228 + zTableInfo = appendText(zTableInfo, ");", 0); 1229 + 1230 + rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0); 1231 + free(zTableInfo); 1232 + if( rc!=SQLITE_OK || !pTableInfo ){ 1233 + return 1; 1234 + } 1235 + 1236 + zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); 1237 + zTmp = appendText(zTmp, zTable, '"'); 1238 + if( zTmp ){ 1239 + zSelect = appendText(zSelect, zTmp, '\''); 1240 + } 1241 + zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); 1242 + rc = sqlite3_step(pTableInfo); 1243 + while( rc==SQLITE_ROW ){ 1244 + const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); 1245 + zSelect = appendText(zSelect, "quote(", 0); 1246 + zSelect = appendText(zSelect, zText, '"'); 1247 + rc = sqlite3_step(pTableInfo); 1248 + if( rc==SQLITE_ROW ){ 1249 + zSelect = appendText(zSelect, ") || ',' || ", 0); 1250 + }else{ 1251 + zSelect = appendText(zSelect, ") ", 0); 1252 + } 1253 + nRow++; 1254 + } 1255 + rc = sqlite3_finalize(pTableInfo); 1256 + if( rc!=SQLITE_OK || nRow==0 ){ 1257 + free(zSelect); 1258 + return 1; 1259 + } 1260 + zSelect = appendText(zSelect, "|| ')' FROM ", 0); 1261 + zSelect = appendText(zSelect, zTable, '"'); 1262 + 1263 + rc = run_table_dump_query(p->out, p->db, zSelect, zPrepStmt); 1264 + if( rc==SQLITE_CORRUPT ){ 1265 + zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); 1266 + rc = run_table_dump_query(p->out, p->db, zSelect, 0); 1267 + } 1268 + if( zSelect ) free(zSelect); 1269 + } 1270 + return 0; 1271 +} 1272 + 1273 +/* 1274 +** Run zQuery. Use dump_callback() as the callback routine so that 1275 +** the contents of the query are output as SQL statements. 1276 +** 1277 +** If we get a SQLITE_CORRUPT error, rerun the query after appending 1278 +** "ORDER BY rowid DESC" to the end. 1279 +*/ 1280 +static int run_schema_dump_query( 1281 + struct callback_data *p, 1282 + const char *zQuery, 1283 + char **pzErrMsg 1284 +){ 1285 + int rc; 1286 + rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg); 1287 + if( rc==SQLITE_CORRUPT ){ 1288 + char *zQ2; 1289 + int len = strlen30(zQuery); 1290 + if( pzErrMsg ) sqlite3_free(*pzErrMsg); 1291 + zQ2 = malloc( len+100 ); 1292 + if( zQ2==0 ) return rc; 1293 + sqlite3_snprintf(sizeof(zQ2), zQ2, "%s ORDER BY rowid DESC", zQuery); 1294 + rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg); 1295 + free(zQ2); 1296 + } 1297 + return rc; 1298 +} 1299 + 1300 +/* 1301 +** Text of a help message 1302 +*/ 1303 +static char zHelp[] = 1304 + ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" 1305 + ".bail ON|OFF Stop after hitting an error. Default OFF\n" 1306 + ".databases List names and files of attached databases\n" 1307 + ".dump ?TABLE? ... Dump the database in an SQL text format\n" 1308 + " If TABLE specified, only dump tables matching\n" 1309 + " LIKE pattern TABLE.\n" 1310 + ".echo ON|OFF Turn command echo on or off\n" 1311 + ".exit Exit this program\n" 1312 + ".explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.\n" 1313 + " With no args, it turns EXPLAIN on.\n" 1314 + ".header(s) ON|OFF Turn display of headers on or off\n" 1315 + ".help Show this message\n" 1316 + ".import FILE TABLE Import data from FILE into TABLE\n" 1317 + ".indices ?TABLE? Show names of all indices\n" 1318 + " If TABLE specified, only show indices for tables\n" 1319 + " matching LIKE pattern TABLE.\n" 1320 +#ifdef SQLITE_ENABLE_IOTRACE 1321 + ".iotrace FILE Enable I/O diagnostic logging to FILE\n" 1322 +#endif 1323 +#ifndef SQLITE_OMIT_LOAD_EXTENSION 1324 + ".load FILE ?ENTRY? Load an extension library\n" 1325 +#endif 1326 + ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" 1327 + ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" 1328 + " csv Comma-separated values\n" 1329 + " column Left-aligned columns. (See .width)\n" 1330 + " html HTML <table> code\n" 1331 + " insert SQL insert statements for TABLE\n" 1332 + " line One value per line\n" 1333 + " list Values delimited by .separator string\n" 1334 + " tabs Tab-separated values\n" 1335 + " tcl TCL list elements\n" 1336 + ".nullvalue STRING Print STRING in place of NULL values\n" 1337 + ".output FILENAME Send output to FILENAME\n" 1338 + ".output stdout Send output to the screen\n" 1339 + ".prompt MAIN CONTINUE Replace the standard prompts\n" 1340 + ".quit Exit this program\n" 1341 + ".read FILENAME Execute SQL in FILENAME\n" 1342 + ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" 1343 + ".schema ?TABLE? Show the CREATE statements\n" 1344 + " If TABLE specified, only show tables matching\n" 1345 + " LIKE pattern TABLE.\n" 1346 + ".separator STRING Change separator used by output mode and .import\n" 1347 + ".show Show the current values for various settings\n" 1348 + ".stats ON|OFF Turn stats on or off\n" 1349 + ".tables ?TABLE? List names of tables\n" 1350 + " If TABLE specified, only list tables matching\n" 1351 + " LIKE pattern TABLE.\n" 1352 + ".timeout MS Try opening locked tables for MS milliseconds\n" 1353 + ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" 1354 +; 1355 + 1356 +static char zTimerHelp[] = 1357 + ".timer ON|OFF Turn the CPU timer measurement on or off\n" 1358 +; 1359 + 1360 +/* Forward reference */ 1361 +static int process_input(struct callback_data *p, FILE *in); 1362 + 1363 +/* 1364 +** Make sure the database is open. If it is not, then open it. If 1365 +** the database fails to open, print an error message and exit. 1366 +*/ 1367 +static void open_db(struct callback_data *p){ 1368 + if( p->db==0 ){ 1369 + sqlite3_open(p->zDbFilename, &p->db); 1370 + db = p->db; 1371 + if( db && sqlite3_errcode(db)==SQLITE_OK ){ 1372 + sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, 1373 + shellstaticFunc, 0, 0); 1374 + } 1375 + if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){ 1376 + fprintf(stderr,"Error: unable to open database \"%s\": %s\n", 1377 + p->zDbFilename, sqlite3_errmsg(db)); 1378 + exit(1); 1379 + } 1380 +#ifndef SQLITE_OMIT_LOAD_EXTENSION 1381 + sqlite3_enable_load_extension(p->db, 1); 1382 +#endif 1383 + } 1384 +} 1385 + 1386 +/* 1387 +** Do C-language style dequoting. 1388 +** 1389 +** \t -> tab 1390 +** \n -> newline 1391 +** \r -> carriage return 1392 +** \NNN -> ascii character NNN in octal 1393 +** \\ -> backslash 1394 +*/ 1395 +static void resolve_backslashes(char *z){ 1396 + int i, j; 1397 + char c; 1398 + for(i=j=0; (c = z[i])!=0; i++, j++){ 1399 + if( c=='\\' ){ 1400 + c = z[++i]; 1401 + if( c=='n' ){ 1402 + c = '\n'; 1403 + }else if( c=='t' ){ 1404 + c = '\t'; 1405 + }else if( c=='r' ){ 1406 + c = '\r'; 1407 + }else if( c>='0' && c<='7' ){ 1408 + c -= '0'; 1409 + if( z[i+1]>='0' && z[i+1]<='7' ){ 1410 + i++; 1411 + c = (c<<3) + z[i] - '0'; 1412 + if( z[i+1]>='0' && z[i+1]<='7' ){ 1413 + i++; 1414 + c = (c<<3) + z[i] - '0'; 1415 + } 1416 + } 1417 + } 1418 + } 1419 + z[j] = c; 1420 + } 1421 + z[j] = 0; 1422 +} 1423 + 1424 +/* 1425 +** Interpret zArg as a boolean value. Return either 0 or 1. 1426 +*/ 1427 +static int booleanValue(char *zArg){ 1428 + int val = atoi(zArg); 1429 + int j; 1430 + for(j=0; zArg[j]; j++){ 1431 + zArg[j] = (char)tolower(zArg[j]); 1432 + } 1433 + if( strcmp(zArg,"on")==0 ){ 1434 + val = 1; 1435 + }else if( strcmp(zArg,"yes")==0 ){ 1436 + val = 1; 1437 + } 1438 + return val; 1439 +} 1440 + 1441 +/* 1442 +** If an input line begins with "." then invoke this routine to 1443 +** process that line. 1444 +** 1445 +** Return 1 on error, 2 to exit, and 0 otherwise. 1446 +*/ 1447 +static int do_meta_command(char *zLine, struct callback_data *p){ 1448 + int i = 1; 1449 + int nArg = 0; 1450 + int n, c; 1451 + int rc = 0; 1452 + char *azArg[50]; 1453 + 1454 + /* Parse the input line into tokens. 1455 + */ 1456 + while( zLine[i] && nArg<ArraySize(azArg) ){ 1457 + while( isspace((unsigned char)zLine[i]) ){ i++; } 1458 + if( zLine[i]==0 ) break; 1459 + if( zLine[i]=='\'' || zLine[i]=='"' ){ 1460 + int delim = zLine[i++]; 1461 + azArg[nArg++] = &zLine[i]; 1462 + while( zLine[i] && zLine[i]!=delim ){ i++; } 1463 + if( zLine[i]==delim ){ 1464 + zLine[i++] = 0; 1465 + } 1466 + if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); 1467 + }else{ 1468 + azArg[nArg++] = &zLine[i]; 1469 + while( zLine[i] && !isspace((unsigned char)zLine[i]) ){ i++; } 1470 + if( zLine[i] ) zLine[i++] = 0; 1471 + resolve_backslashes(azArg[nArg-1]); 1472 + } 1473 + } 1474 + 1475 + /* Process the input line. 1476 + */ 1477 + if( nArg==0 ) return 0; /* no tokens, no error */ 1478 + n = strlen30(azArg[0]); 1479 + c = azArg[0][0]; 1480 + if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 && nArg>1 && nArg<4){ 1481 + const char *zDestFile; 1482 + const char *zDb; 1483 + sqlite3 *pDest; 1484 + sqlite3_backup *pBackup; 1485 + if( nArg==2 ){ 1486 + zDestFile = azArg[1]; 1487 + zDb = "main"; 1488 + }else{ 1489 + zDestFile = azArg[2]; 1490 + zDb = azArg[1]; 1491 + } 1492 + rc = sqlite3_open(zDestFile, &pDest); 1493 + if( rc!=SQLITE_OK ){ 1494 + fprintf(stderr, "Error: cannot open \"%s\"\n", zDestFile); 1495 + sqlite3_close(pDest); 1496 + return 1; 1497 + } 1498 + open_db(p); 1499 + pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); 1500 + if( pBackup==0 ){ 1501 + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); 1502 + sqlite3_close(pDest); 1503 + return 1; 1504 + } 1505 + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} 1506 + sqlite3_backup_finish(pBackup); 1507 + if( rc==SQLITE_DONE ){ 1508 + rc = 0; 1509 + }else{ 1510 + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); 1511 + rc = 1; 1512 + } 1513 + sqlite3_close(pDest); 1514 + }else 1515 + 1516 + if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 && nArg<3 ){ 1517 + bail_on_error = booleanValue(azArg[1]); 1518 + }else 1519 + 1520 + if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){ 1521 + struct callback_data data; 1522 + char *zErrMsg = 0; 1523 + open_db(p); 1524 + memcpy(&data, p, sizeof(data)); 1525 + data.showHeader = 1; 1526 + data.mode = MODE_Column; 1527 + data.colWidth[0] = 3; 1528 + data.colWidth[1] = 15; 1529 + data.colWidth[2] = 58; 1530 + data.cnt = 0; 1531 + sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); 1532 + if( zErrMsg ){ 1533 + fprintf(stderr,"Error: %s\n", zErrMsg); 1534 + sqlite3_free(zErrMsg); 1535 + rc = 1; 1536 + } 1537 + }else 1538 + 1539 + if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){ 1540 + char *zErrMsg = 0; 1541 + open_db(p); 1542 + /* When playing back a "dump", the content might appear in an order 1543 + ** which causes immediate foreign key constraints to be violated. 1544 + ** So disable foreign-key constraint enforcement to prevent problems. */ 1545 + fprintf(p->out, "PRAGMA foreign_keys=OFF;\n"); 1546 + fprintf(p->out, "BEGIN TRANSACTION;\n"); 1547 + p->writableSchema = 0; 1548 + sqlite3_exec(p->db, "PRAGMA writable_schema=ON", 0, 0, 0); 1549 + if( nArg==1 ){ 1550 + run_schema_dump_query(p, 1551 + "SELECT name, type, sql FROM sqlite_master " 1552 + "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'", 0 1553 + ); 1554 + run_schema_dump_query(p, 1555 + "SELECT name, type, sql FROM sqlite_master " 1556 + "WHERE name=='sqlite_sequence'", 0 1557 + ); 1558 + run_table_dump_query(p->out, p->db, 1559 + "SELECT sql FROM sqlite_master " 1560 + "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 1561 + ); 1562 + }else{ 1563 + int i; 1564 + for(i=1; i<nArg; i++){ 1565 + zShellStatic = azArg[i]; 1566 + run_schema_dump_query(p, 1567 + "SELECT name, type, sql FROM sqlite_master " 1568 + "WHERE tbl_name LIKE shellstatic() AND type=='table'" 1569 + " AND sql NOT NULL", 0); 1570 + run_table_dump_query(p->out, p->db, 1571 + "SELECT sql FROM sqlite_master " 1572 + "WHERE sql NOT NULL" 1573 + " AND type IN ('index','trigger','view')" 1574 + " AND tbl_name LIKE shellstatic()", 0 1575 + ); 1576 + zShellStatic = 0; 1577 + } 1578 + } 1579 + if( p->writableSchema ){ 1580 + fprintf(p->out, "PRAGMA writable_schema=OFF;\n"); 1581 + p->writableSchema = 0; 1582 + } 1583 + sqlite3_exec(p->db, "PRAGMA writable_schema=OFF", 0, 0, 0); 1584 + if( zErrMsg ){ 1585 + fprintf(stderr,"Error: %s\n", zErrMsg); 1586 + sqlite3_free(zErrMsg); 1587 + }else{ 1588 + fprintf(p->out, "COMMIT;\n"); 1589 + } 1590 + }else 1591 + 1592 + if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){ 1593 + p->echoOn = booleanValue(azArg[1]); 1594 + }else 1595 + 1596 + if( c=='e' && strncmp(azArg[0], "exit", n)==0 && nArg==1 ){ 1597 + rc = 2; 1598 + }else 1599 + 1600 + if( c=='e' && strncmp(azArg[0], "explain", n)==0 && nArg<3 ){ 1601 + int val = nArg>=2 ? booleanValue(azArg[1]) : 1; 1602 + if(val == 1) { 1603 + if(!p->explainPrev.valid) { 1604 + p->explainPrev.valid = 1; 1605 + p->explainPrev.mode = p->mode; 1606 + p->explainPrev.showHeader = p->showHeader; 1607 + memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); 1608 + } 1609 + /* We could put this code under the !p->explainValid 1610 + ** condition so that it does not execute if we are already in 1611 + ** explain mode. However, always executing it allows us an easy 1612 + ** was to reset to explain mode in case the user previously 1613 + ** did an .explain followed by a .width, .mode or .header 1614 + ** command. 1615 + */ 1616 + p->mode = MODE_Explain; 1617 + p->showHeader = 1; 1618 + memset(p->colWidth,0,ArraySize(p->colWidth)); 1619 + p->colWidth[0] = 4; /* addr */ 1620 + p->colWidth[1] = 13; /* opcode */ 1621 + p->colWidth[2] = 4; /* P1 */ 1622 + p->colWidth[3] = 4; /* P2 */ 1623 + p->colWidth[4] = 4; /* P3 */ 1624 + p->colWidth[5] = 13; /* P4 */ 1625 + p->colWidth[6] = 2; /* P5 */ 1626 + p->colWidth[7] = 13; /* Comment */ 1627 + }else if (p->explainPrev.valid) { 1628 + p->explainPrev.valid = 0; 1629 + p->mode = p->explainPrev.mode; 1630 + p->showHeader = p->explainPrev.showHeader; 1631 + memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); 1632 + } 1633 + }else 1634 + 1635 + if( c=='h' && (strncmp(azArg[0], "header", n)==0 || 1636 + strncmp(azArg[0], "headers", n)==0) && nArg>1 && nArg<3 ){ 1637 + p->showHeader = booleanValue(azArg[1]); 1638 + }else 1639 + 1640 + if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ 1641 + fprintf(stderr,"%s",zHelp); 1642 + if( HAS_TIMER ){ 1643 + fprintf(stderr,"%s",zTimerHelp); 1644 + } 1645 + }else 1646 + 1647 + if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){ 1648 + char *zTable = azArg[2]; /* Insert data into this table */ 1649 + char *zFile = azArg[1]; /* The file from which to extract data */ 1650 + sqlite3_stmt *pStmt = NULL; /* A statement */ 1651 + int nCol; /* Number of columns in the table */ 1652 + int nByte; /* Number of bytes in an SQL string */ 1653 + int i, j; /* Loop counters */ 1654 + int nSep; /* Number of bytes in p->separator[] */ 1655 + char *zSql; /* An SQL statement */ 1656 + char *zLine; /* A single line of input from the file */ 1657 + char **azCol; /* zLine[] broken up into columns */ 1658 + char *zCommit; /* How to commit changes */ 1659 + FILE *in; /* The input file */ 1660 + int lineno = 0; /* Line number of input file */ 1661 + 1662 + open_db(p); 1663 + nSep = strlen30(p->separator); 1664 + if( nSep==0 ){ 1665 + fprintf(stderr, "Error: non-null separator required for import\n"); 1666 + return 1; 1667 + } 1668 + zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable); 1669 + if( zSql==0 ){ 1670 + fprintf(stderr, "Error: out of memory\n"); 1671 + return 1; 1672 + } 1673 + nByte = strlen30(zSql); 1674 + rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); 1675 + sqlite3_free(zSql); 1676 + if( rc ){ 1677 + if (pStmt) sqlite3_finalize(pStmt); 1678 + fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); 1679 + return 1; 1680 + } 1681 + nCol = sqlite3_column_count(pStmt); 1682 + sqlite3_finalize(pStmt); 1683 + pStmt = 0; 1684 + if( nCol==0 ) return 0; /* no columns, no error */ 1685 + zSql = malloc( nByte + 20 + nCol*2 ); 1686 + if( zSql==0 ){ 1687 + fprintf(stderr, "Error: out of memory\n"); 1688 + return 1; 1689 + } 1690 + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable); 1691 + j = strlen30(zSql); 1692 + for(i=1; i<nCol; i++){ 1693 + zSql[j++] = ','; 1694 + zSql[j++] = '?'; 1695 + } 1696 + zSql[j++] = ')'; 1697 + zSql[j] = 0; 1698 + rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); 1699 + free(zSql); 1700 + if( rc ){ 1701 + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); 1702 + if (pStmt) sqlite3_finalize(pStmt); 1703 + return 1; 1704 + } 1705 + in = fopen(zFile, "rb"); 1706 + if( in==0 ){ 1707 + fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); 1708 + sqlite3_finalize(pStmt); 1709 + return 1; 1710 + } 1711 + azCol = malloc( sizeof(azCol[0])*(nCol+1) ); 1712 + if( azCol==0 ){ 1713 + fprintf(stderr, "Error: out of memory\n"); 1714 + fclose(in); 1715 + sqlite3_finalize(pStmt); 1716 + return 1; 1717 + } 1718 + sqlite3_exec(p->db, "BEGIN", 0, 0, 0); 1719 + zCommit = "COMMIT"; 1720 + while( (zLine = local_getline(0, in))!=0 ){ 1721 + char *z; 1722 + i = 0; 1723 + lineno++; 1724 + azCol[0] = zLine; 1725 + for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){ 1726 + if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){ 1727 + *z = 0; 1728 + i++; 1729 + if( i<nCol ){ 1730 + azCol[i] = &z[nSep]; 1731 + z += nSep-1; 1732 + } 1733 + } 1734 + } /* end for */ 1735 + *z = 0; 1736 + if( i+1!=nCol ){ 1737 + fprintf(stderr, 1738 + "Error: %s line %d: expected %d columns of data but found %d\n", 1739 + zFile, lineno, nCol, i+1); 1740 + zCommit = "ROLLBACK"; 1741 + free(zLine); 1742 + rc = 1; 1743 + break; /* from while */ 1744 + } 1745 + for(i=0; i<nCol; i++){ 1746 + sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); 1747 + } 1748 + sqlite3_step(pStmt); 1749 + rc = sqlite3_reset(pStmt); 1750 + free(zLine); 1751 + if( rc!=SQLITE_OK ){ 1752 + fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); 1753 + zCommit = "ROLLBACK"; 1754 + rc = 1; 1755 + break; /* from while */ 1756 + } 1757 + } /* end while */ 1758 + free(azCol); 1759 + fclose(in); 1760 + sqlite3_finalize(pStmt); 1761 + sqlite3_exec(p->db, zCommit, 0, 0, 0); 1762 + }else 1763 + 1764 + if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){ 1765 + struct callback_data data; 1766 + char *zErrMsg = 0; 1767 + open_db(p); 1768 + memcpy(&data, p, sizeof(data)); 1769 + data.showHeader = 0; 1770 + data.mode = MODE_List; 1771 + if( nArg==1 ){ 1772 + rc = sqlite3_exec(p->db, 1773 + "SELECT name FROM sqlite_master " 1774 + "WHERE type='index' AND name NOT LIKE 'sqlite_%' " 1775 + "UNION ALL " 1776 + "SELECT name FROM sqlite_temp_master " 1777 + "WHERE type='index' " 1778 + "ORDER BY 1", 1779 + callback, &data, &zErrMsg 1780 + ); 1781 + }else{ 1782 + zShellStatic = azArg[1]; 1783 + rc = sqlite3_exec(p->db, 1784 + "SELECT name FROM sqlite_master " 1785 + "WHERE type='index' AND tbl_name LIKE shellstatic() " 1786 + "UNION ALL " 1787 + "SELECT name FROM sqlite_temp_master " 1788 + "WHERE type='index' AND tbl_name LIKE shellstatic() " 1789 + "ORDER BY 1", 1790 + callback, &data, &zErrMsg 1791 + ); 1792 + zShellStatic = 0; 1793 + } 1794 + if( zErrMsg ){ 1795 + fprintf(stderr,"Error: %s\n", zErrMsg); 1796 + sqlite3_free(zErrMsg); 1797 + rc = 1; 1798 + }else if( rc != SQLITE_OK ){ 1799 + fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n"); 1800 + rc = 1; 1801 + } 1802 + }else 1803 + 1804 +#ifdef SQLITE_ENABLE_IOTRACE 1805 + if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ 1806 + extern void (*sqlite3IoTrace)(const char*, ...); 1807 + if( iotrace && iotrace!=stdout ) fclose(iotrace); 1808 + iotrace = 0; 1809 + if( nArg<2 ){ 1810 + sqlite3IoTrace = 0; 1811 + }else if( strcmp(azArg[1], "-")==0 ){ 1812 + sqlite3IoTrace = iotracePrintf; 1813 + iotrace = stdout; 1814 + }else{ 1815 + iotrace = fopen(azArg[1], "w"); 1816 + if( iotrace==0 ){ 1817 + fprintf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); 1818 + sqlite3IoTrace = 0; 1819 + rc = 1; 1820 + }else{ 1821 + sqlite3IoTrace = iotracePrintf; 1822 + } 1823 + } 1824 + }else 1825 +#endif 1826 + 1827 +#ifndef SQLITE_OMIT_LOAD_EXTENSION 1828 + if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){ 1829 + const char *zFile, *zProc; 1830 + char *zErrMsg = 0; 1831 + zFile = azArg[1]; 1832 + zProc = nArg>=3 ? azArg[2] : 0; 1833 + open_db(p); 1834 + rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); 1835 + if( rc!=SQLITE_OK ){ 1836 + fprintf(stderr, "Error: %s\n", zErrMsg); 1837 + sqlite3_free(zErrMsg); 1838 + rc = 1; 1839 + } 1840 + }else 1841 +#endif 1842 + 1843 + if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=1 ){ 1844 + const char *zFile = azArg[1]; 1845 + if( p->pLog && p->pLog!=stdout && p->pLog!=stderr ){ 1846 + fclose(p->pLog); 1847 + p->pLog = 0; 1848 + } 1849 + if( strcmp(zFile,"stdout")==0 ){ 1850 + p->pLog = stdout; 1851 + }else if( strcmp(zFile, "stderr")==0 ){ 1852 + p->pLog = stderr; 1853 + }else if( strcmp(zFile, "off")==0 ){ 1854 + p->pLog = 0; 1855 + }else{ 1856 + p->pLog = fopen(zFile, "w"); 1857 + if( p->pLog==0 ){ 1858 + fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); 1859 + } 1860 + } 1861 + }else 1862 + 1863 + if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){ 1864 + int n2 = strlen30(azArg[1]); 1865 + if( (n2==4 && strncmp(azArg[1],"line",n2)==0) 1866 + || 1867 + (n2==5 && strncmp(azArg[1],"lines",n2)==0) ){ 1868 + p->mode = MODE_Line; 1869 + }else if( (n2==6 && strncmp(azArg[1],"column",n2)==0) 1870 + || 1871 + (n2==7 && strncmp(azArg[1],"columns",n2)==0) ){ 1872 + p->mode = MODE_Column; 1873 + }else if( n2==4 && strncmp(azArg[1],"list",n2)==0 ){ 1874 + p->mode = MODE_List; 1875 + }else if( n2==4 && strncmp(azArg[1],"html",n2)==0 ){ 1876 + p->mode = MODE_Html; 1877 + }else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){ 1878 + p->mode = MODE_Tcl; 1879 + }else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){ 1880 + p->mode = MODE_Csv; 1881 + sqlite3_snprintf(sizeof(p->separator), p->separator, ","); 1882 + }else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){ 1883 + p->mode = MODE_List; 1884 + sqlite3_snprintf(sizeof(p->separator), p->separator, "\t"); 1885 + }else if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){ 1886 + p->mode = MODE_Insert; 1887 + set_table_name(p, "table"); 1888 + }else { 1889 + fprintf(stderr,"Error: mode should be one of: " 1890 + "column csv html insert line list tabs tcl\n"); 1891 + rc = 1; 1892 + } 1893 + }else 1894 + 1895 + if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==3 ){ 1896 + int n2 = strlen30(azArg[1]); 1897 + if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){ 1898 + p->mode = MODE_Insert; 1899 + set_table_name(p, azArg[2]); 1900 + }else { 1901 + fprintf(stderr, "Error: invalid arguments: " 1902 + " \"%s\". Enter \".help\" for help\n", azArg[2]); 1903 + rc = 1; 1904 + } 1905 + }else 1906 + 1907 + if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { 1908 + sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue, 1909 + "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); 1910 + }else 1911 + 1912 + if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ 1913 + if( p->out!=stdout ){ 1914 + fclose(p->out); 1915 + } 1916 + if( strcmp(azArg[1],"stdout")==0 ){ 1917 + p->out = stdout; 1918 + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout"); 1919 + }else{ 1920 + p->out = fopen(azArg[1], "wb"); 1921 + if( p->out==0 ){ 1922 + fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]); 1923 + p->out = stdout; 1924 + rc = 1; 1925 + } else { 1926 + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); 1927 + } 1928 + } 1929 + }else 1930 + 1931 + if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ 1932 + if( nArg >= 2) { 1933 + strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); 1934 + } 1935 + if( nArg >= 3) { 1936 + strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); 1937 + } 1938 + }else 1939 + 1940 + if( c=='q' && strncmp(azArg[0], "quit", n)==0 && nArg==1 ){ 1941 + rc = 2; 1942 + }else 1943 + 1944 + if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 && nArg==2 ){ 1945 + FILE *alt = fopen(azArg[1], "rb"); 1946 + if( alt==0 ){ 1947 + fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); 1948 + rc = 1; 1949 + }else{ 1950 + rc = process_input(p, alt); 1951 + fclose(alt); 1952 + } 1953 + }else 1954 + 1955 + if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 && nArg<4){ 1956 + const char *zSrcFile; 1957 + const char *zDb; 1958 + sqlite3 *pSrc; 1959 + sqlite3_backup *pBackup; 1960 + int nTimeout = 0; 1961 + 1962 + if( nArg==2 ){ 1963 + zSrcFile = azArg[1]; 1964 + zDb = "main"; 1965 + }else{ 1966 + zSrcFile = azArg[2]; 1967 + zDb = azArg[1]; 1968 + } 1969 + rc = sqlite3_open(zSrcFile, &pSrc); 1970 + if( rc!=SQLITE_OK ){ 1971 + fprintf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); 1972 + sqlite3_close(pSrc); 1973 + return 1; 1974 + } 1975 + open_db(p); 1976 + pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); 1977 + if( pBackup==0 ){ 1978 + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); 1979 + sqlite3_close(pSrc); 1980 + return 1; 1981 + } 1982 + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK 1983 + || rc==SQLITE_BUSY ){ 1984 + if( rc==SQLITE_BUSY ){ 1985 + if( nTimeout++ >= 3 ) break; 1986 + sqlite3_sleep(100); 1987 + } 1988 + } 1989 + sqlite3_backup_finish(pBackup); 1990 + if( rc==SQLITE_DONE ){ 1991 + rc = 0; 1992 + }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ 1993 + fprintf(stderr, "Error: source database is busy\n"); 1994 + rc = 1; 1995 + }else{ 1996 + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); 1997 + rc = 1; 1998 + } 1999 + sqlite3_close(pSrc); 2000 + }else 2001 + 2002 + if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){ 2003 + struct callback_data data; 2004 + char *zErrMsg = 0; 2005 + open_db(p); 2006 + memcpy(&data, p, sizeof(data)); 2007 + data.showHeader = 0; 2008 + data.mode = MODE_Semi; 2009 + if( nArg>1 ){ 2010 + int i; 2011 + for(i=0; azArg[1][i]; i++) azArg[1][i] = (char)tolower(azArg[1][i]); 2012 + if( strcmp(azArg[1],"sqlite_master")==0 ){ 2013 + char *new_argv[2], *new_colv[2]; 2014 + new_argv[0] = "CREATE TABLE sqlite_master (\n" 2015 + " type text,\n" 2016 + " name text,\n" 2017 + " tbl_name text,\n" 2018 + " rootpage integer,\n" 2019 + " sql text\n" 2020 + ")"; 2021 + new_argv[1] = 0; 2022 + new_colv[0] = "sql"; 2023 + new_colv[1] = 0; 2024 + callback(&data, 1, new_argv, new_colv); 2025 + rc = SQLITE_OK; 2026 + }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ 2027 + char *new_argv[2], *new_colv[2]; 2028 + new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" 2029 + " type text,\n" 2030 + " name text,\n" 2031 + " tbl_name text,\n" 2032 + " rootpage integer,\n" 2033 + " sql text\n" 2034 + ")"; 2035 + new_argv[1] = 0; 2036 + new_colv[0] = "sql"; 2037 + new_colv[1] = 0; 2038 + callback(&data, 1, new_argv, new_colv); 2039 + rc = SQLITE_OK; 2040 + }else{ 2041 + zShellStatic = azArg[1]; 2042 + rc = sqlite3_exec(p->db, 2043 + "SELECT sql FROM " 2044 + " (SELECT sql sql, type type, tbl_name tbl_name, name name" 2045 + " FROM sqlite_master UNION ALL" 2046 + " SELECT sql, type, tbl_name, name FROM sqlite_temp_master) " 2047 + "WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOTNULL " 2048 + "ORDER BY substr(type,2,1), name", 2049 + callback, &data, &zErrMsg); 2050 + zShellStatic = 0; 2051 + } 2052 + }else{ 2053 + rc = sqlite3_exec(p->db, 2054 + "SELECT sql FROM " 2055 + " (SELECT sql sql, type type, tbl_name tbl_name, name name" 2056 + " FROM sqlite_master UNION ALL" 2057 + " SELECT sql, type, tbl_name, name FROM sqlite_temp_master) " 2058 + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" 2059 + "ORDER BY substr(type,2,1), name", 2060 + callback, &data, &zErrMsg 2061 + ); 2062 + } 2063 + if( zErrMsg ){ 2064 + fprintf(stderr,"Error: %s\n", zErrMsg); 2065 + sqlite3_free(zErrMsg); 2066 + rc = 1; 2067 + }else if( rc != SQLITE_OK ){ 2068 + fprintf(stderr,"Error: querying schema information\n"); 2069 + rc = 1; 2070 + }else{ 2071 + rc = 0; 2072 + } 2073 + }else 2074 + 2075 + if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ 2076 + sqlite3_snprintf(sizeof(p->separator), p->separator, 2077 + "%.*s", (int)sizeof(p->separator)-1, azArg[1]); 2078 + }else 2079 + 2080 + if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){ 2081 + int i; 2082 + fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); 2083 + fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); 2084 + fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); 2085 + fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); 2086 + fprintf(p->out,"%9.9s: ", "nullvalue"); 2087 + output_c_string(p->out, p->nullvalue); 2088 + fprintf(p->out, "\n"); 2089 + fprintf(p->out,"%9.9s: %s\n","output", 2090 + strlen30(p->outfile) ? p->outfile : "stdout"); 2091 + fprintf(p->out,"%9.9s: ", "separator"); 2092 + output_c_string(p->out, p->separator); 2093 + fprintf(p->out, "\n"); 2094 + fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off"); 2095 + fprintf(p->out,"%9.9s: ","width"); 2096 + for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { 2097 + fprintf(p->out,"%d ",p->colWidth[i]); 2098 + } 2099 + fprintf(p->out,"\n"); 2100 + }else 2101 + 2102 + if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){ 2103 + p->statsOn = booleanValue(azArg[1]); 2104 + }else 2105 + 2106 + if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){ 2107 + char **azResult; 2108 + int nRow; 2109 + char *zErrMsg; 2110 + open_db(p); 2111 + if( nArg==1 ){ 2112 + rc = sqlite3_get_table(p->db, 2113 + "SELECT name FROM sqlite_master " 2114 + "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' " 2115 + "UNION ALL " 2116 + "SELECT name FROM sqlite_temp_master " 2117 + "WHERE type IN ('table','view') " 2118 + "ORDER BY 1", 2119 + &azResult, &nRow, 0, &zErrMsg 2120 + ); 2121 + }else{ 2122 + zShellStatic = azArg[1]; 2123 + rc = sqlite3_get_table(p->db, 2124 + "SELECT name FROM sqlite_master " 2125 + "WHERE type IN ('table','view') AND name LIKE shellstatic() " 2126 + "UNION ALL " 2127 + "SELECT name FROM sqlite_temp_master " 2128 + "WHERE type IN ('table','view') AND name LIKE shellstatic() " 2129 + "ORDER BY 1", 2130 + &azResult, &nRow, 0, &zErrMsg 2131 + ); 2132 + zShellStatic = 0; 2133 + } 2134 + if( zErrMsg ){ 2135 + fprintf(stderr,"Error: %s\n", zErrMsg); 2136 + sqlite3_free(zErrMsg); 2137 + rc = 1; 2138 + }else if( rc != SQLITE_OK ){ 2139 + fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n"); 2140 + rc = 1; 2141 + }else{ 2142 + int len, maxlen = 0; 2143 + int i, j; 2144 + int nPrintCol, nPrintRow; 2145 + for(i=1; i<=nRow; i++){ 2146 + if( azResult[i]==0 ) continue; 2147 + len = strlen30(azResult[i]); 2148 + if( len>maxlen ) maxlen = len; 2149 + } 2150 + nPrintCol = 80/(maxlen+2); 2151 + if( nPrintCol<1 ) nPrintCol = 1; 2152 + nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; 2153 + for(i=0; i<nPrintRow; i++){ 2154 + for(j=i+1; j<=nRow; j+=nPrintRow){ 2155 + char *zSp = j<=nPrintRow ? "" : " "; 2156 + printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : ""); 2157 + } 2158 + printf("\n"); 2159 + } 2160 + } 2161 + sqlite3_free_table(azResult); 2162 + }else 2163 + 2164 + if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){ 2165 + open_db(p); 2166 + sqlite3_busy_timeout(p->db, atoi(azArg[1])); 2167 + }else 2168 + 2169 + if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg==2 ){ 2170 + enableTimer = booleanValue(azArg[1]); 2171 + }else 2172 + 2173 + if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){ 2174 + int j; 2175 + assert( nArg<=ArraySize(azArg) ); 2176 + for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ 2177 + p->colWidth[j-1] = atoi(azArg[j]); 2178 + } 2179 + }else 2180 + 2181 + { 2182 + fprintf(stderr, "Error: unknown command or invalid arguments: " 2183 + " \"%s\". Enter \".help\" for help\n", azArg[0]); 2184 + rc = 1; 2185 + } 2186 + 2187 + return rc; 2188 +} 2189 + 2190 +/* 2191 +** Return TRUE if a semicolon occurs anywhere in the first N characters 2192 +** of string z[]. 2193 +*/ 2194 +static int _contains_semicolon(const char *z, int N){ 2195 + int i; 2196 + for(i=0; i<N; i++){ if( z[i]==';' ) return 1; } 2197 + return 0; 2198 +} 2199 + 2200 +/* 2201 +** Test to see if a line consists entirely of whitespace. 2202 +*/ 2203 +static int _all_whitespace(const char *z){ 2204 + for(; *z; z++){ 2205 + if( isspace(*(unsigned char*)z) ) continue; 2206 + if( *z=='/' && z[1]=='*' ){ 2207 + z += 2; 2208 + while( *z && (*z!='*' || z[1]!='/') ){ z++; } 2209 + if( *z==0 ) return 0; 2210 + z++; 2211 + continue; 2212 + } 2213 + if( *z=='-' && z[1]=='-' ){ 2214 + z += 2; 2215 + while( *z && *z!='\n' ){ z++; } 2216 + if( *z==0 ) return 1; 2217 + continue; 2218 + } 2219 + return 0; 2220 + } 2221 + return 1; 2222 +} 2223 + 2224 +/* 2225 +** Return TRUE if the line typed in is an SQL command terminator other 2226 +** than a semi-colon. The SQL Server style "go" command is understood 2227 +** as is the Oracle "/". 2228 +*/ 2229 +static int _is_command_terminator(const char *zLine){ 2230 + while( isspace(*(unsigned char*)zLine) ){ zLine++; }; 2231 + if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){ 2232 + return 1; /* Oracle */ 2233 + } 2234 + if( tolower(zLine[0])=='g' && tolower(zLine[1])=='o' 2235 + && _all_whitespace(&zLine[2]) ){ 2236 + return 1; /* SQL Server */ 2237 + } 2238 + return 0; 2239 +} 2240 + 2241 +/* 2242 +** Return true if zSql is a complete SQL statement. Return false if it 2243 +** ends in the middle of a string literal or C-style comment. 2244 +*/ 2245 +static int _is_complete(char *zSql, int nSql){ 2246 + int rc; 2247 + if( zSql==0 ) return 1; 2248 + zSql[nSql] = ';'; 2249 + zSql[nSql+1] = 0; 2250 + rc = sqlite3_complete(zSql); 2251 + zSql[nSql] = 0; 2252 + return rc; 2253 +} 2254 + 2255 +/* 2256 +** Read input from *in and process it. If *in==0 then input 2257 +** is interactive - the user is typing it it. Otherwise, input 2258 +** is coming from a file or device. A prompt is issued and history 2259 +** is saved only if input is interactive. An interrupt signal will 2260 +** cause this routine to exit immediately, unless input is interactive. 2261 +** 2262 +** Return the number of errors. 2263 +*/ 2264 +static int process_input(struct callback_data *p, FILE *in){ 2265 + char *zLine = 0; 2266 + char *zSql = 0; 2267 + int nSql = 0; 2268 + int nSqlPrior = 0; 2269 + char *zErrMsg; 2270 + int rc; 2271 + int errCnt = 0; 2272 + int lineno = 0; 2273 + int startline = 0; 2274 + 2275 + while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){ 2276 + fflush(p->out); 2277 + free(zLine); 2278 + zLine = one_input_line(zSql, in); 2279 + if( zLine==0 ){ 2280 + break; /* We have reached EOF */ 2281 + } 2282 + if( seenInterrupt ){ 2283 + if( in!=0 ) break; 2284 + seenInterrupt = 0; 2285 + } 2286 + lineno++; 2287 + if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue; 2288 + if( zLine && zLine[0]=='.' && nSql==0 ){ 2289 + if( p->echoOn ) printf("%s\n", zLine); 2290 + rc = do_meta_command(zLine, p); 2291 + if( rc==2 ){ /* exit requested */ 2292 + break; 2293 + }else if( rc ){ 2294 + errCnt++; 2295 + } 2296 + continue; 2297 + } 2298 + if( _is_command_terminator(zLine) && _is_complete(zSql, nSql) ){ 2299 + memcpy(zLine,";",2); 2300 + } 2301 + nSqlPrior = nSql; 2302 + if( zSql==0 ){ 2303 + int i; 2304 + for(i=0; zLine[i] && isspace((unsigned char)zLine[i]); i++){} 2305 + if( zLine[i]!=0 ){ 2306 + nSql = strlen30(zLine); 2307 + zSql = malloc( nSql+3 ); 2308 + if( zSql==0 ){ 2309 + fprintf(stderr, "Error: out of memory\n"); 2310 + exit(1); 2311 + } 2312 + memcpy(zSql, zLine, nSql+1); 2313 + startline = lineno; 2314 + } 2315 + }else{ 2316 + int len = strlen30(zLine); 2317 + zSql = realloc( zSql, nSql + len + 4 ); 2318 + if( zSql==0 ){ 2319 + fprintf(stderr,"Error: out of memory\n"); 2320 + exit(1); 2321 + } 2322 + zSql[nSql++] = '\n'; 2323 + memcpy(&zSql[nSql], zLine, len+1); 2324 + nSql += len; 2325 + } 2326 + if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) 2327 + && sqlite3_complete(zSql) ){ 2328 + p->cnt = 0; 2329 + open_db(p); 2330 + BEGIN_TIMER; 2331 + rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); 2332 + END_TIMER; 2333 + if( rc || zErrMsg ){ 2334 + char zPrefix[100]; 2335 + if( in!=0 || !stdin_is_interactive ){ 2336 + sqlite3_snprintf(sizeof(zPrefix), zPrefix, 2337 + "Error: near line %d:", startline); 2338 + }else{ 2339 + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); 2340 + } 2341 + if( zErrMsg!=0 ){ 2342 + fprintf(stderr, "%s %s\n", zPrefix, zErrMsg); 2343 + sqlite3_free(zErrMsg); 2344 + zErrMsg = 0; 2345 + }else{ 2346 + fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); 2347 + } 2348 + errCnt++; 2349 + } 2350 + free(zSql); 2351 + zSql = 0; 2352 + nSql = 0; 2353 + } 2354 + } 2355 + if( zSql ){ 2356 + if( !_all_whitespace(zSql) ) fprintf(stderr, "Error: incomplete SQL: %s\n", zSql); 2357 + free(zSql); 2358 + } 2359 + free(zLine); 2360 + return errCnt; 2361 +} 2362 + 2363 +/* 2364 +** Return a pathname which is the user's home directory. A 2365 +** 0 return indicates an error of some kind. Space to hold the 2366 +** resulting string is obtained from malloc(). The calling 2367 +** function should free the result. 2368 +*/ 2369 +static char *find_home_dir(void){ 2370 + char *home_dir = NULL; 2371 + 2372 +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL) 2373 + struct passwd *pwent; 2374 + uid_t uid = getuid(); 2375 + if( (pwent=getpwuid(uid)) != NULL) { 2376 + home_dir = pwent->pw_dir; 2377 + } 2378 +#endif 2379 + 2380 +#if defined(_WIN32_WCE) 2381 + /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() 2382 + */ 2383 + home_dir = strdup("/"); 2384 +#else 2385 + 2386 +#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) 2387 + if (!home_dir) { 2388 + home_dir = getenv("USERPROFILE"); 2389 + } 2390 +#endif 2391 + 2392 + if (!home_dir) { 2393 + home_dir = getenv("HOME"); 2394 + } 2395 + 2396 +#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) 2397 + if (!home_dir) { 2398 + char *zDrive, *zPath; 2399 + int n; 2400 + zDrive = getenv("HOMEDRIVE"); 2401 + zPath = getenv("HOMEPATH"); 2402 + if( zDrive && zPath ){ 2403 + n = strlen30(zDrive) + strlen30(zPath) + 1; 2404 + home_dir = malloc( n ); 2405 + if( home_dir==0 ) return 0; 2406 + sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); 2407 + return home_dir; 2408 + } 2409 + home_dir = "c:\\"; 2410 + } 2411 +#endif 2412 + 2413 +#endif /* !_WIN32_WCE */ 2414 + 2415 + if( home_dir ){ 2416 + int n = strlen30(home_dir) + 1; 2417 + char *z = malloc( n ); 2418 + if( z ) memcpy(z, home_dir, n); 2419 + home_dir = z; 2420 + } 2421 + 2422 + return home_dir; 2423 +} 2424 + 2425 +/* 2426 +** Read input from the file given by sqliterc_override. Or if that 2427 +** parameter is NULL, take input from ~/.sqliterc 2428 +** 2429 +** Returns the number of errors. 2430 +*/ 2431 +static int process_sqliterc( 2432 + struct callback_data *p, /* Configuration data */ 2433 + const char *sqliterc_override /* Name of config file. NULL to use default */ 2434 +){ 2435 + char *home_dir = NULL; 2436 + const char *sqliterc = sqliterc_override; 2437 + char *zBuf = 0; 2438 + FILE *in = NULL; 2439 + int nBuf; 2440 + int rc = 0; 2441 + 2442 + if (sqliterc == NULL) { 2443 + home_dir = find_home_dir(); 2444 + if( home_dir==0 ){ 2445 +#if !defined(__RTP__) && !defined(_WRS_KERNEL) 2446 + fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0); 2447 +#endif 2448 + return 1; 2449 + } 2450 + nBuf = strlen30(home_dir) + 16; 2451 + zBuf = malloc( nBuf ); 2452 + if( zBuf==0 ){ 2453 + fprintf(stderr,"%s: Error: out of memory\n",Argv0); 2454 + return 1; 2455 + } 2456 + sqlite3_snprintf(nBuf, zBuf,"%s/.sqliterc",home_dir); 2457 + free(home_dir); 2458 + sqliterc = (const char*)zBuf; 2459 + } 2460 + in = fopen(sqliterc,"rb"); 2461 + if( in ){ 2462 + if( stdin_is_interactive ){ 2463 + fprintf(stderr,"-- Loading resources from %s\n",sqliterc); 2464 + } 2465 + rc = process_input(p,in); 2466 + fclose(in); 2467 + } 2468 + free(zBuf); 2469 + return rc; 2470 +} 2471 + 2472 +/* 2473 +** Show available command line options 2474 +*/ 2475 +static const char zOptions[] = 2476 + " -help show this message\n" 2477 + " -init filename read/process named file\n" 2478 + " -echo print commands before execution\n" 2479 + " -[no]header turn headers on or off\n" 2480 + " -bail stop after hitting an error\n" 2481 + " -interactive force interactive I/O\n" 2482 + " -batch force batch I/O\n" 2483 + " -column set output mode to 'column'\n" 2484 + " -csv set output mode to 'csv'\n" 2485 + " -html set output mode to HTML\n" 2486 + " -line set output mode to 'line'\n" 2487 + " -list set output mode to 'list'\n" 2488 + " -separator 'x' set output field separator (|)\n" 2489 + " -stats print memory stats before each finalize\n" 2490 + " -nullvalue 'text' set text string for NULL values\n" 2491 + " -version show SQLite version\n" 2492 +; 2493 +static void usage(int showDetail){ 2494 + fprintf(stderr, 2495 + "Usage: %s [OPTIONS] FILENAME [SQL]\n" 2496 + "FILENAME is the name of an SQLite database. A new database is created\n" 2497 + "if the file does not previously exist.\n", Argv0); 2498 + if( showDetail ){ 2499 + fprintf(stderr, "OPTIONS include:\n%s", zOptions); 2500 + }else{ 2501 + fprintf(stderr, "Use the -help option for additional information\n"); 2502 + } 2503 + exit(1); 2504 +} 2505 + 2506 +/* 2507 +** Initialize the state information in data 2508 +*/ 2509 +static void main_init(struct callback_data *data) { 2510 + memset(data, 0, sizeof(*data)); 2511 + data->mode = MODE_List; 2512 + memcpy(data->separator,"|", 2); 2513 + data->showHeader = 0; 2514 + sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); 2515 + sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); 2516 + sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); 2517 + sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); 2518 +} 2519 + 2520 +int main(int argc, char **argv){ 2521 + char *zErrMsg = 0; 2522 + struct callback_data data; 2523 + const char *zInitFile = 0; 2524 + char *zFirstCmd = 0; 2525 + int i; 2526 + int rc = 0; 2527 + 2528 + Argv0 = argv[0]; 2529 + main_init(&data); 2530 + stdin_is_interactive = isatty(0); 2531 + 2532 + /* Make sure we have a valid signal handler early, before anything 2533 + ** else is done. 2534 + */ 2535 +#ifdef SIGINT 2536 + signal(SIGINT, interrupt_handler); 2537 +#endif 2538 + 2539 + /* Do an initial pass through the command-line argument to locate 2540 + ** the name of the database file, the name of the initialization file, 2541 + ** and the first command to execute. 2542 + */ 2543 + for(i=1; i<argc-1; i++){ 2544 + char *z; 2545 + if( argv[i][0]!='-' ) break; 2546 + z = argv[i]; 2547 + if( z[0]=='-' && z[1]=='-' ) z++; 2548 + if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){ 2549 + i++; 2550 + }else if( strcmp(argv[i],"-init")==0 ){ 2551 + i++; 2552 + zInitFile = argv[i]; 2553 + /* Need to check for batch mode here to so we can avoid printing 2554 + ** informational messages (like from process_sqliterc) before 2555 + ** we do the actual processing of arguments later in a second pass. 2556 + */ 2557 + }else if( strcmp(argv[i],"-batch")==0 ){ 2558 + stdin_is_interactive = 0; 2559 + } 2560 + } 2561 + if( i<argc ){ 2562 +#if defined(SQLITE_OS_OS2) && SQLITE_OS_OS2 2563 + data.zDbFilename = (const char *)convertCpPathToUtf8( argv[i++] ); 2564 +#else 2565 + data.zDbFilename = argv[i++]; 2566 +#endif 2567 + }else{ 2568 +#ifndef SQLITE_OMIT_MEMORYDB 2569 + data.zDbFilename = ":memory:"; 2570 +#else 2571 + data.zDbFilename = 0; 2572 +#endif 2573 + /***** Begin Fossil Patch *****/ 2574 + { 2575 + extern void fossil_open(sqlite3**, const char **); 2576 + fossil_open(&data.db, &data.zDbFilename); 2577 + } 2578 + /***** End Fossil Patch *****/ 2579 + } 2580 + if( i<argc ){ 2581 + zFirstCmd = argv[i++]; 2582 + } 2583 + if( i<argc ){ 2584 + fprintf(stderr,"%s: Error: too many options: \"%s\"\n", Argv0, argv[i]); 2585 + fprintf(stderr,"Use -help for a list of options.\n"); 2586 + return 1; 2587 + } 2588 + data.out = stdout; 2589 + 2590 +#ifdef SQLITE_OMIT_MEMORYDB 2591 + if( data.zDbFilename==0 ){ 2592 + fprintf(stderr,"%s: Error: no database filename specified\n", Argv0); 2593 + return 1; 2594 + } 2595 +#endif 2596 + 2597 + /* Go ahead and open the database file if it already exists. If the 2598 + ** file does not exist, delay opening it. This prevents empty database 2599 + ** files from being created if a user mistypes the database name argument 2600 + ** to the sqlite command-line tool. 2601 + */ 2602 + if( access(data.zDbFilename, 0)==0 ){ 2603 + open_db(&data); 2604 + } 2605 + 2606 + /* Process the initialization file if there is one. If no -init option 2607 + ** is given on the command line, look for a file named ~/.sqliterc and 2608 + ** try to process it. 2609 + */ 2610 + rc = process_sqliterc(&data,zInitFile); 2611 + if( rc>0 ){ 2612 + return rc; 2613 + } 2614 + 2615 + /* Make a second pass through the command-line argument and set 2616 + ** options. This second pass is delayed until after the initialization 2617 + ** file is processed so that the command-line arguments will override 2618 + ** settings in the initialization file. 2619 + */ 2620 + for(i=1; i<argc && argv[i][0]=='-'; i++){ 2621 + char *z = argv[i]; 2622 + if( z[1]=='-' ){ z++; } 2623 + if( strcmp(z,"-init")==0 ){ 2624 + i++; 2625 + }else if( strcmp(z,"-html")==0 ){ 2626 + data.mode = MODE_Html; 2627 + }else if( strcmp(z,"-list")==0 ){ 2628 + data.mode = MODE_List; 2629 + }else if( strcmp(z,"-line")==0 ){ 2630 + data.mode = MODE_Line; 2631 + }else if( strcmp(z,"-column")==0 ){ 2632 + data.mode = MODE_Column; 2633 + }else if( strcmp(z,"-csv")==0 ){ 2634 + data.mode = MODE_Csv; 2635 + memcpy(data.separator,",",2); 2636 + }else if( strcmp(z,"-separator")==0 ){ 2637 + i++; 2638 + if(i>=argc){ 2639 + fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z); 2640 + fprintf(stderr,"Use -help for a list of options.\n"); 2641 + return 1; 2642 + } 2643 + sqlite3_snprintf(sizeof(data.separator), data.separator, 2644 + "%.*s",(int)sizeof(data.separator)-1,argv[i]); 2645 + }else if( strcmp(z,"-nullvalue")==0 ){ 2646 + i++; 2647 + if(i>=argc){ 2648 + fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z); 2649 + fprintf(stderr,"Use -help for a list of options.\n"); 2650 + return 1; 2651 + } 2652 + sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue, 2653 + "%.*s",(int)sizeof(data.nullvalue)-1,argv[i]); 2654 + }else if( strcmp(z,"-header")==0 ){ 2655 + data.showHeader = 1; 2656 + }else if( strcmp(z,"-noheader")==0 ){ 2657 + data.showHeader = 0; 2658 + }else if( strcmp(z,"-echo")==0 ){ 2659 + data.echoOn = 1; 2660 + }else if( strcmp(z,"-stats")==0 ){ 2661 + data.statsOn = 1; 2662 + }else if( strcmp(z,"-bail")==0 ){ 2663 + bail_on_error = 1; 2664 + }else if( strcmp(z,"-version")==0 ){ 2665 + printf("%s\n", sqlite3_libversion()); 2666 + return 0; 2667 + }else if( strcmp(z,"-interactive")==0 ){ 2668 + stdin_is_interactive = 1; 2669 + }else if( strcmp(z,"-batch")==0 ){ 2670 + stdin_is_interactive = 0; 2671 + }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){ 2672 + usage(1); 2673 + }else{ 2674 + fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); 2675 + fprintf(stderr,"Use -help for a list of options.\n"); 2676 + return 1; 2677 + } 2678 + } 2679 + 2680 + if( zFirstCmd ){ 2681 + /* Run just the command that follows the database name 2682 + */ 2683 + if( zFirstCmd[0]=='.' ){ 2684 + rc = do_meta_command(zFirstCmd, &data); 2685 + }else{ 2686 + open_db(&data); 2687 + rc = shell_exec(data.db, zFirstCmd, shell_callback, &data, &zErrMsg); 2688 + if( zErrMsg!=0 ){ 2689 + fprintf(stderr,"Error: %s\n", zErrMsg); 2690 + return rc!=0 ? rc : 1; 2691 + }else if( rc!=0 ){ 2692 + fprintf(stderr,"Error: unable to process SQL \"%s\"\n", zFirstCmd); 2693 + return rc; 2694 + } 2695 + } 2696 + }else{ 2697 + /* Run commands received from standard input 2698 + */ 2699 + if( stdin_is_interactive ){ 2700 + char *zHome; 2701 + char *zHistory = 0; 2702 + int nHistory; 2703 + printf( 2704 + "SQLite version %s\n" 2705 + "Enter \".help\" for instructions\n" 2706 + "Enter SQL statements terminated with a \";\"\n", 2707 + sqlite3_libversion() 2708 + ); 2709 + zHome = find_home_dir(); 2710 + if( zHome ){ 2711 + nHistory = strlen30(zHome) + 20; 2712 + if( (zHistory = malloc(nHistory))!=0 ){ 2713 + sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); 2714 + } 2715 + } 2716 +#if defined(HAVE_READLINE) && HAVE_READLINE==1 2717 + if( zHistory ) read_history(zHistory); 2718 +#endif 2719 + rc = process_input(&data, 0); 2720 + if( zHistory ){ 2721 + stifle_history(100); 2722 + write_history(zHistory); 2723 + free(zHistory); 2724 + } 2725 + free(zHome); 2726 + }else{ 2727 + rc = process_input(&data, stdin); 2728 + } 2729 + } 2730 + set_table_name(&data, 0); 2731 + if( data.db ){ 2732 + if( sqlite3_close(data.db)!=SQLITE_OK ){ 2733 + fprintf(stderr,"Error: cannot close database \"%s\"\n", 2734 + sqlite3_errmsg(db)); 2735 + rc++; 2736 + } 2737 + } 2738 + return rc; 2739 +}
Changes to src/shun.c.
67 67 } 68 68 } 69 69 style_header("Shunned Artifacts"); 70 70 if( zUuid && P("sub") ){ 71 71 login_verify_csrf_secret(); 72 72 db_multi_exec("DELETE FROM shun WHERE uuid='%s'", zUuid); 73 73 if( db_exists("SELECT 1 FROM blob WHERE uuid='%s'", zUuid) ){ 74 - @ <p><font color="blue">Artifact 74 + @ <p class="noMoreShun">Artifact 75 75 @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> is no 76 - @ longer being shunned.</font></p> 76 + @ longer being shunned.</p> 77 77 }else{ 78 - @ <p><font color="blue">Artifact %s(zUuid)</a> will no longer 78 + @ <p class="noMoreShun">Artifact %s(zUuid) will no longer 79 79 @ be shunned. But it does not exist in the repository. It 80 80 @ may be necessary to rebuild the repository using the 81 81 @ <b>fossil rebuild</b> command-line before the artifact content 82 - @ can pulled in from other respositories.</font></p> 82 + @ can pulled in from other respositories.</p> 83 83 } 84 84 } 85 85 if( zUuid && P("add") ){ 86 86 login_verify_csrf_secret(); 87 87 db_multi_exec("INSERT OR IGNORE INTO shun VALUES('%s')", zUuid); 88 - @ <p><font color="blue">Artifact 88 + @ <p class="shunned">Artifact 89 89 @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> has been 90 90 @ shunned. It will no longer be pushed. 91 91 @ It will be removed from the repository the next time the respository 92 - @ is rebuilt using the <b>fossil rebuild</b> command-line</font></p> 92 + @ is rebuilt using the <b>fossil rebuild</b> command-line</p> 93 93 } 94 94 @ <p>A shunned artifact will not be pushed nor accepted in a pull and the 95 95 @ artifact content will be purged from the repository the next time the 96 96 @ repository is rebuilt. A list of shunned artifacts can be seen at the 97 97 @ bottom of this page.</p> 98 98 @ 99 99 @ <a name="addshun"></a> ................................................................................ 110 110 @ from the repository. Inappropriate content includes such things as 111 111 @ spam added to Wiki, files that violate copyright or patent agreements, 112 112 @ or artifacts that by design or accident interfere with the processing 113 113 @ of the repository. Do not shun artifacts merely to remove them from 114 114 @ sight - set the "hidden" tag on such artifacts instead.</p> 115 115 @ 116 116 @ <blockquote> 117 - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> 117 + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div> 118 118 login_insert_csrf_secret(); 119 - @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50"> 120 - @ <input type="submit" name="add" value="Shun"> 121 - @ </form> 119 + @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50" /> 120 + @ <input type="submit" name="add" value="Shun" /> 121 + @ </div></form> 122 122 @ </blockquote> 123 123 @ 124 124 @ <p>Enter the UUID of a previous shunned artifact to cause it to be 125 125 @ accepted again in the repository. The artifact content is not 126 126 @ restored because the content is unknown. The only change is that 127 127 @ the formerly shunned artifact will be accepted on subsequent sync 128 128 @ operations.</p> 129 129 @ 130 130 @ <blockquote> 131 - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> 131 + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div> 132 132 login_insert_csrf_secret(); 133 - @ <input type="text" name="uuid" size="50"> 134 - @ <input type="submit" name="sub" value="Accept"> 135 - @ </form> 133 + @ <input type="text" name="uuid" size="50" /> 134 + @ <input type="submit" name="sub" value="Accept" /> 135 + @ </div></form> 136 136 @ </blockquote> 137 137 @ 138 138 @ <p>Press the Rebuild button below to rebuild the respository. The 139 139 @ content of newly shunned artifacts is not purged until the repository 140 140 @ is rebuilt. On larger repositories, the rebuild may take minute or 141 141 @ two, so be patient after pressing the button.</p> 142 142 @ 143 143 @ <blockquote> 144 - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> 144 + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div> 145 145 login_insert_csrf_secret(); 146 - @ <input type="submit" name="rebuild" value="Rebuild"> 147 - @ </form> 146 + @ <input type="submit" name="rebuild" value="Rebuild" /> 147 + @ </div></form> 148 148 @ </blockquote> 149 149 @ 150 - @ <hr><p>Shunned Artifacts:</p> 151 - @ <blockquote> 150 + @ <hr /><p>Shunned Artifacts:</p> 151 + @ <blockquote><p> 152 152 db_prepare(&q, 153 153 "SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)" 154 154 " FROM shun ORDER BY uuid"); 155 155 while( db_step(&q)==SQLITE_ROW ){ 156 156 const char *zUuid = db_column_text(&q, 0); 157 157 int stillExists = db_column_int(&q, 1); 158 158 cnt++; 159 159 if( stillExists ){ 160 - @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br> 160 + @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br /> 161 161 }else{ 162 - @ <b>%s(zUuid)</b><br> 162 + @ <b>%s(zUuid)</b><br /> 163 163 } 164 164 } 165 165 if( cnt==0 ){ 166 166 @ <i>no artifacts are shunned on this server</i> 167 167 } 168 168 db_finalize(&q); 169 - @ </blockquote> 169 + @ </p></blockquote> 170 170 style_footer(); 171 171 } 172 172 173 173 /* 174 174 ** Remove from the BLOB table all artifacts that are in the SHUN table. 175 175 */ 176 176 void shun_artifacts(void){ ................................................................................ 227 227 @ finding and fixing attempts to inject illicit content into the 228 228 @ repository.</p> 229 229 @ 230 230 @ <p>Click on the "rcvid" to show a list of specific artifacts received 231 231 @ by a transaction. After identifying illicit artifacts, remove them 232 232 @ using the "Shun" feature.</p> 233 233 @ 234 - @ <table cellpadding=0 cellspacing=0 border=0> 235 - @ <tr><th>rcvid</th><th width=15> 236 - @ <th>Date</th><th width=15><th>User</th> 237 - @ <th width=15><th>IP Address</th></tr> 234 + @ <table cellpadding="0" cellspacing="0" border="0"> 235 + @ <tr><th style="padding-right: 15px;text-align: right;">rcvid</th> 236 + @ <th style="padding-right: 15px;text-align: left;">Date</th> 237 + @ <th style="padding-right: 15px;text-align: left;">User</th> 238 + @ <th style="text-align: left;">IP Address</th></tr> 238 239 cnt = 0; 239 240 while( db_step(&q)==SQLITE_ROW ){ 240 241 int rcvid = db_column_int(&q, 0); 241 242 const char *zUser = db_column_text(&q, 1); 242 243 const char *zDate = db_column_text(&q, 2); 243 244 const char *zIpAddr = db_column_text(&q, 3); 244 245 if( cnt==30 ){ 245 246 style_submenu_element("Older", "Older", 246 247 "rcvfromlist?ofst=%d", ofst+30); 247 248 }else{ 248 249 cnt++; 249 250 @ <tr> 250 - @ <td><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td><td> 251 - @ <td>%s(zDate)</td><td> 252 - @ <td>%h(zUser)</td><td> 253 - @ <td> %s(zIpAddr) </td> 251 + @ <td style="padding-right: 15px;text-align: right;"><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td> 252 + @ <td style="padding-right: 15px;text-align: left;">%s(zDate)</td> 253 + @ <td style="padding-right: 15px;text-align: left;">%h(zUser)</td> 254 + @ <td style="text-align: left;">%s(zIpAddr)</td> 254 255 @ </tr> 255 256 } 256 257 } 257 258 db_finalize(&q); 258 259 @ </table> 259 260 style_footer(); 260 261 } ................................................................................ 275 276 style_header("Content Source %d", rcvid); 276 277 db_prepare(&q, 277 278 "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" 278 279 " FROM rcvfrom LEFT JOIN user USING(uid)" 279 280 " WHERE rcvid=%d", 280 281 rcvid 281 282 ); 282 - @ <table cellspacing=15 cellpadding=0 border=0> 283 + @ <table cellspacing="15" cellpadding="0" border="0"> 283 284 @ <tr><td valign="top" align="right"><b>rcvid:</b></td> 284 285 @ <td valign="top">%d(rcvid)</td></tr> 285 286 if( db_step(&q)==SQLITE_ROW ){ 286 287 const char *zUser = db_column_text(&q, 0); 287 288 const char *zDate = db_column_text(&q, 1); 288 289 const char *zIpAddr = db_column_text(&q, 2); 289 290 @ <tr><td valign="top" align="right"><b>User:</b></td> ................................................................................ 300 301 @ <tr><td valign="top" align="right"><b>Artifacts:</b></td> 301 302 @ <td valign="top"> 302 303 while( db_step(&q)==SQLITE_ROW ){ 303 304 int rid = db_column_int(&q, 0); 304 305 const char *zUuid = db_column_text(&q, 1); 305 306 int size = db_column_int(&q, 2); 306 307 @ <a href="%s(g.zBaseURL)/info/%s(zUuid)">%s(zUuid)</a> 307 - @ (rid: %d(rid), size: %d(size))<br> 308 + @ (rid: %d(rid), size: %d(size))<br /> 308 309 } 309 310 @ </td></tr> 310 311 @ </table> 312 + db_finalize(&q); 313 + style_footer(); 311 314 }
Changes to src/skins.c.
163 163 @ media="screen"> 164 164 @ </head> 165 165 @ <body> 166 166 @ <div class="header"> 167 167 @ <div class="logo"> 168 168 @ <img src="$baseurl/logo" alt="logo"> 169 169 @ </div> 170 -@ <div class="title"><small>$<project_name></small><br>$<title></div> 170 +@ <div class="title"><small>$<project_name></small><br />$<title></div> 171 171 @ <div class="status"><nobr><th1> 172 172 @ if {[info exists login]} { 173 173 @ puts "Logged in as $login" 174 174 @ } else { 175 175 @ puts "Not logged in" 176 176 @ } 177 177 @ </th1></nobr></div> ................................................................................ 598 598 @ <link rel="stylesheet" href="$baseurl/style.css?black2" type="text/css" 599 599 @ media="screen"> 600 600 @ </head> 601 601 @ <body> 602 602 @ <div class="header"> 603 603 @ <div class="logo"> 604 604 @ <!-- <img src="$baseurl/logo" alt="logo"> --> 605 -@ <br><nobr>$<project_name></nobr> 605 +@ <br /><nobr>$<project_name></nobr> 606 606 @ </div> 607 607 @ <div class="title">$<title></div> 608 608 @ <div class="status"><nobr><th1> 609 609 @ if {[info exists login]} { 610 610 @ puts "Logged in as $login" 611 611 @ } else { 612 612 @ puts "Not logged in" ................................................................................ 654 654 ; 655 655 /* 656 656 ** An array of available built-in skins. 657 657 */ 658 658 static struct BuiltinSkin { 659 659 const char *zName; 660 660 const char *zValue; 661 + const char *zAuthor; 661 662 } aBuiltinSkin[] = { 662 - { "Default", 0 /* Filled in at runtime */ }, 663 - { "Plain Gray, No Logo", zBuiltinSkin1 }, 664 - { "Khaki, No Logo", zBuiltinSkin2 }, 665 - { "Black & White, Menu on Left", zBuiltinSkin3 }, 663 + { "Default", 0 /* Filled in at runtime */, 0}, 664 + { "Plain Gray, No Logo", zBuiltinSkin1, "Unknown"}, 665 + { "Khaki, No Logo", zBuiltinSkin2, "Unknown"}, 666 + { "Black & White, Menu on Left", zBuiltinSkin3, "Unknown"}, 666 667 }; 667 668 668 669 /* 669 670 ** For a skin named zSkinName, compute the name of the CONFIG table 670 671 ** entry where that skin is stored and return it. 671 672 ** 672 673 ** Return NULL if zSkinName is NULL or an empty string. ................................................................................ 729 730 login_needed(); 730 731 } 731 732 db_begin_transaction(); 732 733 733 734 /* Process requests to delete a user-defined skin */ 734 735 if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){ 735 736 style_header("Confirm Custom Skin Delete"); 736 - @ <form action="%s(g.zBaseURL)/setup_skin" method="POST"> 737 + @ <form action="%s(g.zBaseURL)/setup_skin" method="post"><div> 737 738 @ <p>Deletion of a custom skin is a permanent action that cannot 738 739 @ be undone. Please confirm that this is what you want to do:</p> 739 - @ <input type="hidden" name="sn" value="%h(P("sn"))"> 740 - @ <input type="submit" name="del2" value="Confirm - Delete The Skin"> 741 - @ <input type="submit" name="cancel" value="Cancel - Do Not Delete"> 740 + @ <input type="hidden" name="sn" value="%h(P("sn"))" /> 741 + @ <input type="submit" name="del2" value="Confirm - Delete The Skin" /> 742 + @ <input type="submit" name="cancel" value="Cancel - Do Not Delete" /> 742 743 login_insert_csrf_secret(); 743 - @ </form> 744 + @ </div></form> 744 745 style_footer(); 745 746 return; 746 747 } 747 748 if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){ 748 749 db_multi_exec("DELETE FROM config WHERE name=%Q", zName); 749 750 } 750 751 ................................................................................ 810 811 @ <h2>Available Skins:</h2> 811 812 @ <ol> 812 813 for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ 813 814 z = aBuiltinSkin[i].zName; 814 815 if( strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){ 815 816 @ <li><p>%h(z). <b>Currently In Use</b></p> 816 817 }else{ 817 - @ <li><form action="%s(g.zBaseURL)/setup_skin" method="POST"> 818 + @ <li><form action="%s(g.zBaseURL)/setup_skin" method="post"><div> 818 819 @ %h(z). 819 - @ <input type="hidden" name="sn" value="%h(z)"> 820 - @ <input type="submit" name="load" value="Use This Skin"> 821 - @ </form></li> 820 + @ <input type="hidden" name="sn" value="%h(z)" /> 821 + @ <input type="submit" name="load" value="Use This Skin" /> 822 + @ </div></form></li> 822 823 } 823 824 } 824 825 db_prepare(&q, 825 826 "SELECT substr(name, 6), value FROM config" 826 827 " WHERE name GLOB 'skin:*'" 827 828 " ORDER BY name" 828 829 ); 829 830 while( db_step(&q)==SQLITE_ROW ){ 830 831 const char *zN = db_column_text(&q, 0); 831 832 const char *zV = db_column_text(&q, 1); 832 833 if( strcmp(zV, zCurrent)==0 ){ 833 834 @ <li><p>%h(zN). <b>Currently In Use</b></p> 834 835 }else{ 835 - @ <li><form action="%s(g.zBaseURL)/setup_skin" method="POST"> 836 + @ <li><form action="%s(g.zBaseURL)/setup_skin" method="post"> 836 837 @ %h(zN). 837 838 @ <input type="hidden" name="sn" value="%h(zN)"> 838 839 @ <input type="submit" name="load" value="Use This Skin"> 839 840 @ <input type="submit" name="del1" value="Delete This Skin"> 840 841 @ </form></li> 841 842 } 842 843 } 843 844 db_finalize(&q); 844 845 @ </ol> 845 846 style_footer(); 846 847 db_end_transaction(0); 847 848 }
Changes to src/sqlite3.c.
1 1 /****************************************************************************** 2 2 ** This file is an amalgamation of many separate C source files from SQLite 3 -** version 3.7.1. By combining all the individual C code files into this 3 +** version 3.7.3. By combining all the individual C code files into this 4 4 ** single large file, the entire code can be compiled as a one translation 5 5 ** unit. This allows many compilers to do optimizations that would not be 6 6 ** possible if the files were compiled separately. Performance improvements 7 7 ** of 5% are more are commonly seen when SQLite is compiled as a single 8 8 ** translation unit. 9 9 ** 10 10 ** This file is all you need to compile SQLite. To use SQLite in other ................................................................................ 211 211 /* 212 212 ** The maximum value of a ?nnn wildcard that the parser will accept. 213 213 */ 214 214 #ifndef SQLITE_MAX_VARIABLE_NUMBER 215 215 # define SQLITE_MAX_VARIABLE_NUMBER 999 216 216 #endif 217 217 218 -/* Maximum page size. The upper bound on this value is 32768. This a limit 219 -** imposed by the necessity of storing the value in a 2-byte unsigned integer 220 -** and the fact that the page size must be a power of 2. 218 +/* Maximum page size. The upper bound on this value is 65536. This a limit 219 +** imposed by the use of 16-bit offsets within each page. 221 220 ** 222 -** If this limit is changed, then the compiled library is technically 223 -** incompatible with an SQLite library compiled with a different limit. If 224 -** a process operating on a database with a page-size of 65536 bytes 225 -** crashes, then an instance of SQLite compiled with the default page-size 226 -** limit will not be able to rollback the aborted transaction. This could 227 -** lead to database corruption. 221 +** Earlier versions of SQLite allowed the user to change this value at 222 +** compile time. This is no longer permitted, on the grounds that it creates 223 +** a library that is technically incompatible with an SQLite library 224 +** compiled with a different limit. If a process operating on a database 225 +** with a page-size of 65536 bytes crashes, then an instance of SQLite 226 +** compiled with the default page-size limit will not be able to rollback 227 +** the aborted transaction. This could lead to database corruption. 228 228 */ 229 -#ifndef SQLITE_MAX_PAGE_SIZE 230 -# define SQLITE_MAX_PAGE_SIZE 32768 229 +#ifdef SQLITE_MAX_PAGE_SIZE 230 +# undef SQLITE_MAX_PAGE_SIZE 231 231 #endif 232 +#define SQLITE_MAX_PAGE_SIZE 65536 232 233 233 234 234 235 /* 235 236 ** The default size of a database page. 236 237 */ 237 238 #ifndef SQLITE_DEFAULT_PAGE_SIZE 238 239 # define SQLITE_DEFAULT_PAGE_SIZE 1024 ................................................................................ 349 350 # define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) 350 351 #else /* Generates a warning - but it always works */ 351 352 # define SQLITE_INT_TO_PTR(X) ((void*)(X)) 352 353 # define SQLITE_PTR_TO_INT(X) ((int)(X)) 353 354 #endif 354 355 355 356 /* 356 -** The SQLITE_THREADSAFE macro must be defined as either 0 or 1. 357 +** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. 358 +** 0 means mutexes are permanently disable and the library is never 359 +** threadsafe. 1 means the library is serialized which is the highest 360 +** level of threadsafety. 2 means the libary is multithreaded - multiple 361 +** threads can use SQLite as long as no two threads try to use the same 362 +** database connection at the same time. 363 +** 357 364 ** Older versions of SQLite used an optional THREADSAFE macro. 358 -** We support that for legacy 365 +** We support that for legacy. 359 366 */ 360 367 #if !defined(SQLITE_THREADSAFE) 361 368 #if defined(THREADSAFE) 362 369 # define SQLITE_THREADSAFE THREADSAFE 363 370 #else 364 -# define SQLITE_THREADSAFE 1 371 +# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ 365 372 #endif 366 373 #endif 367 374 368 375 /* 369 376 ** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1. 370 377 ** It determines whether or not the features related to 371 378 ** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can ................................................................................ 629 636 ** The SQLITE_VERSION_NUMBER for any given release of SQLite will also 630 637 ** be larger than the release from which it is derived. Either Y will 631 638 ** be held constant and Z will be incremented or else Y will be incremented 632 639 ** and Z will be reset to zero. 633 640 ** 634 641 ** Since version 3.6.18, SQLite source code has been stored in the 635 642 ** <a href="http://www.fossil-scm.org/">Fossil configuration management 636 -** system</a>. ^The SQLITE_SOURCE_ID macro evalutes to 643 +** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to 637 644 ** a string which identifies a particular check-in of SQLite 638 645 ** within its configuration management system. ^The SQLITE_SOURCE_ID 639 646 ** string contains the date and time of the check-in (UTC) and an SHA1 640 647 ** hash of the entire source tree. 641 648 ** 642 649 ** See also: [sqlite3_libversion()], 643 650 ** [sqlite3_libversion_number()], [sqlite3_sourceid()], 644 651 ** [sqlite_version()] and [sqlite_source_id()]. 645 652 */ 646 -#define SQLITE_VERSION "3.7.1" 647 -#define SQLITE_VERSION_NUMBER 3007001 648 -#define SQLITE_SOURCE_ID "2010-08-05 03:21:40 fbe70e1106bcc5086ceb9d8f39cc39baf3643092" 653 +#define SQLITE_VERSION "3.7.3" 654 +#define SQLITE_VERSION_NUMBER 3007003 655 +#define SQLITE_SOURCE_ID "2010-10-07 13:29:13 e55ada89246d4cc5f476891c70572dc7c1c3643e" 649 656 650 657 /* 651 658 ** CAPI3REF: Run-Time Library Version Numbers 652 659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid 653 660 ** 654 661 ** These interfaces provide the same information as the [SQLITE_VERSION], 655 662 ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ................................................................................ 686 693 ** CAPI3REF: Run-Time Library Compilation Options Diagnostics 687 694 ** 688 695 ** ^The sqlite3_compileoption_used() function returns 0 or 1 689 696 ** indicating whether the specified option was defined at 690 697 ** compile time. ^The SQLITE_ prefix may be omitted from the 691 698 ** option name passed to sqlite3_compileoption_used(). 692 699 ** 693 -** ^The sqlite3_compileoption_get() function allows interating 700 +** ^The sqlite3_compileoption_get() function allows iterating 694 701 ** over the list of options that were defined at compile time by 695 702 ** returning the N-th compile time option string. ^If N is out of range, 696 703 ** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ 697 704 ** prefix is omitted from any strings returned by 698 705 ** sqlite3_compileoption_get(). 699 706 ** 700 707 ** ^Support for the diagnostic functions sqlite3_compileoption_used() 701 -** and sqlite3_compileoption_get() may be omitted by specifing the 708 +** and sqlite3_compileoption_get() may be omitted by specifying the 702 709 ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. 703 710 ** 704 711 ** See also: SQL functions [sqlite_compileoption_used()] and 705 712 ** [sqlite_compileoption_get()] and the [compile_options pragma]. 706 713 */ 707 714 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS 708 715 SQLITE_API int sqlite3_compileoption_used(const char *zOptName); ................................................................................ 800 807 #endif 801 808 802 809 /* 803 810 ** CAPI3REF: Closing A Database Connection 804 811 ** 805 812 ** ^The sqlite3_close() routine is the destructor for the [sqlite3] object. 806 813 ** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is 807 -** successfullly destroyed and all associated resources are deallocated. 814 +** successfully destroyed and all associated resources are deallocated. 808 815 ** 809 816 ** Applications must [sqlite3_finalize | finalize] all [prepared statements] 810 817 ** and [sqlite3_blob_close | close] all [BLOB handles] associated with 811 818 ** the [sqlite3] object prior to attempting to close the object. ^If 812 819 ** sqlite3_close() is called on a [database connection] that still has 813 820 ** outstanding [prepared statements] or [BLOB handles], then it returns 814 821 ** SQLITE_BUSY. ................................................................................ 1227 1234 ** 1228 1235 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS 1229 1236 ** layer a hint of how large the database file will grow to be during the 1230 1237 ** current transaction. This hint is not guaranteed to be accurate but it 1231 1238 ** is often close. The underlying VFS might choose to preallocate database 1232 1239 ** file space based on this hint in order to help writes to the database 1233 1240 ** file run faster. 1241 +** 1242 +** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS 1243 +** extends and truncates the database file in chunks of a size specified 1244 +** by the user. The fourth argument to [sqlite3_file_control()] should 1245 +** point to an integer (type int) containing the new chunk-size to use 1246 +** for the nominated database. Allocating database file space in large 1247 +** chunks (say 1MB at a time), may reduce file-system fragmentation and 1248 +** improve performance on some systems. 1234 1249 */ 1235 1250 #define SQLITE_FCNTL_LOCKSTATE 1 1236 1251 #define SQLITE_GET_LOCKPROXYFILE 2 1237 1252 #define SQLITE_SET_LOCKPROXYFILE 3 1238 1253 #define SQLITE_LAST_ERRNO 4 1239 1254 #define SQLITE_FCNTL_SIZE_HINT 5 1255 +#define SQLITE_FCNTL_CHUNK_SIZE 6 1240 1256 1241 1257 /* 1242 1258 ** CAPI3REF: Mutex Handle 1243 1259 ** 1244 1260 ** The mutex module within SQLite defines [sqlite3_mutex] to be an 1245 1261 ** abstract type for a mutex object. The SQLite core never looks 1246 1262 ** at the internal representation of an [sqlite3_mutex]. It only ................................................................................ 1280 1296 ** or modify this field while holding a particular static mutex. 1281 1297 ** The application should never modify anything within the sqlite3_vfs 1282 1298 ** object once the object has been registered. 1283 1299 ** 1284 1300 ** The zName field holds the name of the VFS module. The name must 1285 1301 ** be unique across all VFS modules. 1286 1302 ** 1287 -** SQLite will guarantee that the zFilename parameter to xOpen 1303 +** ^SQLite guarantees that the zFilename parameter to xOpen 1288 1304 ** is either a NULL pointer or string obtained 1289 -** from xFullPathname(). SQLite further guarantees that 1305 +** from xFullPathname() with an optional suffix added. 1306 +** ^If a suffix is added to the zFilename parameter, it will 1307 +** consist of a single "-" character followed by no more than 1308 +** 10 alphanumeric and/or "-" characters. 1309 +** ^SQLite further guarantees that 1290 1310 ** the string will be valid and unchanged until xClose() is 1291 1311 ** called. Because of the previous sentence, 1292 1312 ** the [sqlite3_file] can safely store a pointer to the 1293 1313 ** filename if it needs to remember the filename for some reason. 1294 -** If the zFilename parameter is xOpen is a NULL pointer then xOpen 1295 -** must invent its own temporary name for the file. Whenever the 1314 +** If the zFilename parameter to xOpen is a NULL pointer then xOpen 1315 +** must invent its own temporary name for the file. ^Whenever the 1296 1316 ** xFilename parameter is NULL it will also be the case that the 1297 1317 ** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. 1298 1318 ** 1299 1319 ** The flags argument to xOpen() includes all bits set in 1300 1320 ** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] 1301 1321 ** or [sqlite3_open16()] is used, then flags includes at least 1302 1322 ** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. 1303 1323 ** If xOpen() opens a file read-only then it sets *pOutFlags to 1304 1324 ** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. 1305 1325 ** 1306 -** SQLite will also add one of the following flags to the xOpen() 1326 +** ^(SQLite will also add one of the following flags to the xOpen() 1307 1327 ** call, depending on the object being opened: 1308 1328 ** 1309 1329 ** <ul> 1310 1330 ** <li> [SQLITE_OPEN_MAIN_DB] 1311 1331 ** <li> [SQLITE_OPEN_MAIN_JOURNAL] 1312 1332 ** <li> [SQLITE_OPEN_TEMP_DB] 1313 1333 ** <li> [SQLITE_OPEN_TEMP_JOURNAL] 1314 1334 ** <li> [SQLITE_OPEN_TRANSIENT_DB] 1315 1335 ** <li> [SQLITE_OPEN_SUBJOURNAL] 1316 1336 ** <li> [SQLITE_OPEN_MASTER_JOURNAL] 1317 -** </ul> 1337 +** <li> [SQLITE_OPEN_WAL] 1338 +** </ul>)^ 1318 1339 ** 1319 1340 ** The file I/O implementation can use the object type flags to 1320 1341 ** change the way it deals with files. For example, an application 1321 1342 ** that does not care about crash recovery or rollback might make 1322 1343 ** the open of a journal file a no-op. Writes to this journal would 1323 1344 ** also be no-ops, and any attempt to read the journal would return 1324 1345 ** SQLITE_IOERR. Or the implementation might recognize that a database ................................................................................ 1329 1350 ** 1330 1351 ** <ul> 1331 1352 ** <li> [SQLITE_OPEN_DELETEONCLOSE] 1332 1353 ** <li> [SQLITE_OPEN_EXCLUSIVE] 1333 1354 ** </ul> 1334 1355 ** 1335 1356 ** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be 1336 -** deleted when it is closed. The [SQLITE_OPEN_DELETEONCLOSE] 1337 -** will be set for TEMP databases, journals and for subjournals. 1357 +** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] 1358 +** will be set for TEMP databases and their journals, transient 1359 +** databases, and subjournals. 1338 1360 ** 1339 -** The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction 1361 +** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction 1340 1362 ** with the [SQLITE_OPEN_CREATE] flag, which are both directly 1341 1363 ** analogous to the O_EXCL and O_CREAT flags of the POSIX open() 1342 1364 ** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the 1343 1365 ** SQLITE_OPEN_CREATE, is used to indicate that file should always 1344 1366 ** be created, and that it is an error if it already exists. 1345 1367 ** It is <i>not</i> used to indicate the file should be opened 1346 1368 ** for exclusive access. 1347 1369 ** 1348 -** At least szOsFile bytes of memory are allocated by SQLite 1370 +** ^At least szOsFile bytes of memory are allocated by SQLite 1349 1371 ** to hold the [sqlite3_file] structure passed as the third 1350 1372 ** argument to xOpen. The xOpen method does not have to 1351 1373 ** allocate the structure; it should just fill it in. Note that 1352 1374 ** the xOpen method must set the sqlite3_file.pMethods to either 1353 1375 ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do 1354 1376 ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods 1355 1377 ** element will be valid after xOpen returns regardless of the success 1356 1378 ** or failure of the xOpen call. 1357 1379 ** 1358 -** The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] 1380 +** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] 1359 1381 ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to 1360 1382 ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] 1361 1383 ** to test whether a file is at least readable. The file can be a 1362 1384 ** directory. 1363 1385 ** 1364 -** SQLite will always allocate at least mxPathname+1 bytes for the 1386 +** ^SQLite will always allocate at least mxPathname+1 bytes for the 1365 1387 ** output buffer xFullPathname. The exact size of the output buffer 1366 1388 ** is also passed as a parameter to both methods. If the output buffer 1367 1389 ** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is 1368 1390 ** handled as a fatal error by SQLite, vfs implementations should endeavor 1369 1391 ** to prevent this by setting mxPathname to a sufficiently large value. 1370 1392 ** 1371 1393 ** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64() 1372 1394 ** interfaces are not strictly a part of the filesystem, but they are 1373 1395 ** included in the VFS structure for completeness. 1374 1396 ** The xRandomness() function attempts to return nBytes bytes 1375 1397 ** of good-quality randomness into zOut. The return value is 1376 1398 ** the actual number of bytes of randomness obtained. 1377 1399 ** The xSleep() method causes the calling thread to sleep for at 1378 -** least the number of microseconds given. The xCurrentTime() 1400 +** least the number of microseconds given. ^The xCurrentTime() 1379 1401 ** method returns a Julian Day Number for the current date and time as 1380 1402 ** a floating point value. 1381 -** The xCurrentTimeInt64() method returns, as an integer, the Julian 1403 +** ^The xCurrentTimeInt64() method returns, as an integer, the Julian 1382 1404 ** Day Number multipled by 86400000 (the number of milliseconds in 1383 1405 ** a 24-hour day). 1384 1406 ** ^SQLite will use the xCurrentTimeInt64() method to get the current 1385 1407 ** date and time if that method is available (if iVersion is 2 or 1386 1408 ** greater and the function pointer is not NULL) and will fall back 1387 1409 ** to xCurrentTime() if xCurrentTimeInt64() is unavailable. 1388 1410 */ ................................................................................ 1771 1793 ** <dd> ^This option takes single argument of type int, interpreted as a 1772 1794 ** boolean, which enables or disables the collection of memory allocation 1773 1795 ** statistics. ^(When memory allocation statistics are disabled, the 1774 1796 ** following SQLite interfaces become non-operational: 1775 1797 ** <ul> 1776 1798 ** <li> [sqlite3_memory_used()] 1777 1799 ** <li> [sqlite3_memory_highwater()] 1778 -** <li> [sqlite3_soft_heap_limit()] 1800 +** <li> [sqlite3_soft_heap_limit64()] 1779 1801 ** <li> [sqlite3_status()] 1780 1802 ** </ul>)^ 1781 1803 ** ^Memory allocation statistics are enabled by default unless SQLite is 1782 1804 ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory 1783 1805 ** allocation statistics are disabled by default. 1784 1806 ** </dd> 1785 1807 ** 1786 1808 ** <dt>SQLITE_CONFIG_SCRATCH</dt> 1787 1809 ** <dd> ^This option specifies a static memory buffer that SQLite can use for 1788 1810 ** scratch memory. There are three arguments: A pointer an 8-byte 1789 1811 ** aligned memory buffer from which the scrach allocations will be 1790 1812 ** drawn, the size of each scratch allocation (sz), 1791 1813 ** and the maximum number of scratch allocations (N). The sz 1792 -** argument must be a multiple of 16. The sz parameter should be a few bytes 1793 -** larger than the actual scratch space required due to internal overhead. 1814 +** argument must be a multiple of 16. 1794 1815 ** The first argument must be a pointer to an 8-byte aligned buffer 1795 1816 ** of at least sz*N bytes of memory. 1796 -** ^SQLite will use no more than one scratch buffer per thread. So 1797 -** N should be set to the expected maximum number of threads. ^SQLite will 1798 -** never require a scratch buffer that is more than 6 times the database 1799 -** page size. ^If SQLite needs needs additional scratch memory beyond 1800 -** what is provided by this configuration option, then 1817 +** ^SQLite will use no more than two scratch buffers per thread. So 1818 +** N should be set to twice the expected maximum number of threads. 1819 +** ^SQLite will never require a scratch buffer that is more than 6 1820 +** times the database page size. ^If SQLite needs needs additional 1821 +** scratch memory beyond what is provided by this configuration option, then 1801 1822 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd> 1802 1823 ** 1803 1824 ** <dt>SQLITE_CONFIG_PAGECACHE</dt> 1804 1825 ** <dd> ^This option specifies a static memory buffer that SQLite can use for 1805 1826 ** the database page cache with the default page cache implemenation. 1806 1827 ** This configuration should not be used if an application-define page 1807 1828 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option. ................................................................................ 1813 1834 ** the host architecture. ^It is harmless, apart from the wasted memory, 1814 1835 ** to make sz a little too large. The first 1815 1836 ** argument should point to an allocation of at least sz*N bytes of memory. 1816 1837 ** ^SQLite will use the memory provided by the first argument to satisfy its 1817 1838 ** memory needs for the first N pages that it adds to cache. ^If additional 1818 1839 ** page cache memory is needed beyond what is provided by this option, then 1819 1840 ** SQLite goes to [sqlite3_malloc()] for the additional storage space. 1820 -** ^The implementation might use one or more of the N buffers to hold 1821 -** memory accounting information. The pointer in the first argument must 1841 +** The pointer in the first argument must 1822 1842 ** be aligned to an 8-byte boundary or subsequent behavior of SQLite 1823 1843 ** will be undefined.</dd> 1824 1844 ** 1825 1845 ** <dt>SQLITE_CONFIG_HEAP</dt> 1826 1846 ** <dd> ^This option specifies a static memory buffer that SQLite will use 1827 1847 ** for all of its dynamic memory allocation needs beyond those provided 1828 1848 ** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. ................................................................................ 1943 1963 ** may be NULL in which case SQLite will allocate the 1944 1964 ** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the 1945 1965 ** size of each lookaside buffer slot. ^The third argument is the number of 1946 1966 ** slots. The size of the buffer in the first argument must be greater than 1947 1967 ** or equal to the product of the second and third arguments. The buffer 1948 1968 ** must be aligned to an 8-byte boundary. ^If the second argument to 1949 1969 ** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally 1950 -** rounded down to the next smaller 1951 -** multiple of 8. See also: [SQLITE_CONFIG_LOOKASIDE]</dd> 1970 +** rounded down to the next smaller multiple of 8. ^(The lookaside memory 1971 +** configuration for a database connection can only be changed when that 1972 +** connection is not currently using lookaside memory, or in other words 1973 +** when the "current value" returned by 1974 +** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. 1975 +** Any attempt to change the lookaside memory configuration when lookaside 1976 +** memory is in use leaves the configuration unchanged and returns 1977 +** [SQLITE_BUSY].)^</dd> 1952 1978 ** 1953 1979 ** </dl> 1954 1980 */ 1955 1981 #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ 1956 1982 1957 1983 1958 1984 /* ................................................................................ 2248 2274 ** was defined (using [sqlite3_busy_handler()]) prior to calling 2249 2275 ** this routine, that other busy handler is cleared.)^ 2250 2276 */ 2251 2277 SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); 2252 2278 2253 2279 /* 2254 2280 ** CAPI3REF: Convenience Routines For Running Queries 2281 +** 2282 +** This is a legacy interface that is preserved for backwards compatibility. 2283 +** Use of this interface is not recommended. 2255 2284 ** 2256 2285 ** Definition: A <b>result table</b> is memory data structure created by the 2257 2286 ** [sqlite3_get_table()] interface. A result table records the 2258 2287 ** complete query results from one or more queries. 2259 2288 ** 2260 2289 ** The table conceptually has a number of rows and columns. But 2261 2290 ** these numbers are not part of the result table itself. These ................................................................................ 2269 2298 ** in NULL pointers. All other values are in their UTF-8 zero-terminated 2270 2299 ** string representation as returned by [sqlite3_column_text()]. 2271 2300 ** 2272 2301 ** A result table might consist of one or more memory allocations. 2273 2302 ** It is not safe to pass a result table directly to [sqlite3_free()]. 2274 2303 ** A result table should be deallocated using [sqlite3_free_table()]. 2275 2304 ** 2276 -** As an example of the result table format, suppose a query result 2305 +** ^(As an example of the result table format, suppose a query result 2277 2306 ** is as follows: 2278 2307 ** 2279 2308 ** <blockquote><pre> 2280 2309 ** Name | Age 2281 2310 ** ----------------------- 2282 2311 ** Alice | 43 2283 2312 ** Bob | 28 ................................................................................ 2293 2322 ** azResult[1] = "Age"; 2294 2323 ** azResult[2] = "Alice"; 2295 2324 ** azResult[3] = "43"; 2296 2325 ** azResult[4] = "Bob"; 2297 2326 ** azResult[5] = "28"; 2298 2327 ** azResult[6] = "Cindy"; 2299 2328 ** azResult[7] = "21"; 2300 -** </pre></blockquote> 2329 +** </pre></blockquote>)^ 2301 2330 ** 2302 2331 ** ^The sqlite3_get_table() function evaluates one or more 2303 2332 ** semicolon-separated SQL statements in the zero-terminated UTF-8 2304 2333 ** string of its 2nd parameter and returns a result table to the 2305 2334 ** pointer given in its 3rd parameter. 2306 2335 ** 2307 2336 ** After the application has finished with the result from sqlite3_get_table(), 2308 -** it should pass the result table pointer to sqlite3_free_table() in order to 2337 +** it must pass the result table pointer to sqlite3_free_table() in order to 2309 2338 ** release the memory that was malloced. Because of the way the 2310 2339 ** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling 2311 2340 ** function must not try to call [sqlite3_free()] directly. Only 2312 2341 ** [sqlite3_free_table()] is able to release the memory properly and safely. 2313 2342 ** 2314 -** ^(The sqlite3_get_table() interface is implemented as a wrapper around 2343 +** The sqlite3_get_table() interface is implemented as a wrapper around 2315 2344 ** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access 2316 2345 ** to any internal data structures of SQLite. It uses only the public 2317 2346 ** interface defined here. As a consequence, errors that occur in the 2318 2347 ** wrapper layer outside of the internal [sqlite3_exec()] call are not 2319 2348 ** reflected in subsequent calls to [sqlite3_errcode()] or 2320 -** [sqlite3_errmsg()].)^ 2349 +** [sqlite3_errmsg()]. 2321 2350 */ 2322 2351 SQLITE_API int sqlite3_get_table( 2323 2352 sqlite3 *db, /* An open database */ 2324 2353 const char *zSql, /* SQL to be evaluated */ 2325 2354 char ***pazResult, /* Results of the query */ 2326 2355 int *pnRow, /* Number of result rows written here */ 2327 2356 int *pnColumn, /* Number of result columns written here */ ................................................................................ 2465 2494 ** ^If M is the size of the prior allocation, then min(N,M) bytes 2466 2495 ** of the prior allocation are copied into the beginning of buffer returned 2467 2496 ** by sqlite3_realloc() and the prior allocation is freed. 2468 2497 ** ^If sqlite3_realloc() returns NULL, then the prior allocation 2469 2498 ** is not freed. 2470 2499 ** 2471 2500 ** ^The memory returned by sqlite3_malloc() and sqlite3_realloc() 2472 -** is always aligned to at least an 8 byte boundary. 2501 +** is always aligned to at least an 8 byte boundary, or to a 2502 +** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time 2503 +** option is used. 2473 2504 ** 2474 2505 ** In SQLite version 3.5.0 and 3.5.1, it was possible to define 2475 2506 ** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in 2476 2507 ** implementation of these routines to be omitted. That capability 2477 2508 ** is no longer provided. Only built-in memory allocators can be used. 2478 2509 ** 2479 2510 ** The Windows OS interface layer calls ................................................................................ 2723 2754 SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); 2724 2755 SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, 2725 2756 void(*xProfile)(void*,const char*,sqlite3_uint64), void*); 2726 2757 2727 2758 /* 2728 2759 ** CAPI3REF: Query Progress Callbacks 2729 2760 ** 2730 -** ^This routine configures a callback function - the 2731 -** progress callback - that is invoked periodically during long 2732 -** running calls to [sqlite3_exec()], [sqlite3_step()] and 2733 -** [sqlite3_get_table()]. An example use for this 2761 +** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback 2762 +** function X to be invoked periodically during long running calls to 2763 +** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for 2764 +** database connection D. An example use for this 2734 2765 ** interface is to keep a GUI updated during a large query. 2766 +** 2767 +** ^The parameter P is passed through as the only parameter to the 2768 +** callback function X. ^The parameter N is the number of 2769 +** [virtual machine instructions] that are evaluated between successive 2770 +** invocations of the callback X. 2771 +** 2772 +** ^Only a single progress handler may be defined at one time per 2773 +** [database connection]; setting a new progress handler cancels the 2774 +** old one. ^Setting parameter X to NULL disables the progress handler. 2775 +** ^The progress handler is also disabled by setting N to a value less 2776 +** than 1. 2735 2777 ** 2736 2778 ** ^If the progress callback returns non-zero, the operation is 2737 2779 ** interrupted. This feature can be used to implement a 2738 2780 ** "Cancel" button on a GUI progress dialog box. 2739 2781 ** 2740 -** The progress handler must not do anything that will modify 2782 +** The progress handler callback must not do anything that will modify 2741 2783 ** the database connection that invoked the progress handler. 2742 2784 ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their 2743 2785 ** database connections for the meaning of "modify" in this paragraph. 2744 2786 ** 2745 2787 */ 2746 2788 SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); 2747 2789 ................................................................................ 2792 2834 ** it does not already exist. This is the behavior that is always used for 2793 2835 ** sqlite3_open() and sqlite3_open16().</dd>)^ 2794 2836 ** </dl> 2795 2837 ** 2796 2838 ** If the 3rd parameter to sqlite3_open_v2() is not one of the 2797 2839 ** combinations shown above or one of the combinations shown above combined 2798 2840 ** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], 2799 -** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_SHAREDCACHE] flags, 2841 +** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags, 2800 2842 ** then the behavior is undefined. 2801 2843 ** 2802 2844 ** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection 2803 2845 ** opens in the multi-thread [threading mode] as long as the single-thread 2804 2846 ** mode has not been set at compile-time or start-time. ^If the 2805 2847 ** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens 2806 2848 ** in the serialized [threading mode] unless single-thread was ................................................................................ 2917 2959 ** CAPI3REF: Run-time Limits 2918 2960 ** 2919 2961 ** ^(This interface allows the size of various constructs to be limited 2920 2962 ** on a connection by connection basis. The first parameter is the 2921 2963 ** [database connection] whose limit is to be set or queried. The 2922 2964 ** second parameter is one of the [limit categories] that define a 2923 2965 ** class of constructs to be size limited. The third parameter is the 2924 -** new limit for that construct. The function returns the old limit.)^ 2966 +** new limit for that construct.)^ 2925 2967 ** 2926 2968 ** ^If the new limit is a negative number, the limit is unchanged. 2927 -** ^(For the limit category of SQLITE_LIMIT_XYZ there is a 2969 +** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a 2928 2970 ** [limits | hard upper bound] 2929 -** set by a compile-time C preprocessor macro named 2930 -** [limits | SQLITE_MAX_XYZ]. 2971 +** set at compile-time by a C preprocessor macro called 2972 +** [limits | SQLITE_MAX_<i>NAME</i>]. 2931 2973 ** (The "_LIMIT_" in the name is changed to "_MAX_".))^ 2932 2974 ** ^Attempts to increase a limit above its hard upper bound are 2933 2975 ** silently truncated to the hard upper bound. 2934 2976 ** 2977 +** ^Regardless of whether or not the limit was changed, the 2978 +** [sqlite3_limit()] interface returns the prior value of the limit. 2979 +** ^Hence, to find the current value of a limit without changing it, 2980 +** simply invoke this interface with the third parameter set to -1. 2981 +** 2935 2982 ** Run-time limits are intended for use in applications that manage 2936 2983 ** both their own internal database and also databases that are controlled 2937 2984 ** by untrusted external sources. An example application might be a 2938 2985 ** web browser that has its own databases for storing history and 2939 2986 ** separate databases controlled by JavaScript applications downloaded 2940 2987 ** off the Internet. The internal databases can be given the 2941 2988 ** large, default limits. Databases managed by external sources can ................................................................................ 2956 3003 ** These constants define various performance limits 2957 3004 ** that can be lowered at run-time using [sqlite3_limit()]. 2958 3005 ** The synopsis of the meanings of the various limits is shown below. 2959 3006 ** Additional information is available at [limits | Limits in SQLite]. 2960 3007 ** 2961 3008 ** <dl> 2962 3009 ** ^(<dt>SQLITE_LIMIT_LENGTH</dt> 2963 -** <dd>The maximum size of any string or BLOB or table row.<dd>)^ 3010 +** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^ 2964 3011 ** 2965 3012 ** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt> 2966 3013 ** <dd>The maximum length of an SQL statement, in bytes.</dd>)^ 2967 3014 ** 2968 3015 ** ^(<dt>SQLITE_LIMIT_COLUMN</dt> 2969 3016 ** <dd>The maximum number of columns in a table definition or in the 2970 3017 ** result set of a [SELECT] or the maximum number of columns in an index ................................................................................ 2974 3021 ** <dd>The maximum depth of the parse tree on any expression.</dd>)^ 2975 3022 ** 2976 3023 ** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt> 2977 3024 ** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^ 2978 3025 ** 2979 3026 ** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt> 2980 3027 ** <dd>The maximum number of instructions in a virtual machine program 2981 -** used to implement an SQL statement.</dd>)^ 3028 +** used to implement an SQL statement. This limit is not currently 3029 +** enforced, though that might be added in some future release of 3030 +** SQLite.</dd>)^ 2982 3031 ** 2983 3032 ** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt> 2984 3033 ** <dd>The maximum number of arguments on a function.</dd>)^ 2985 3034 ** 2986 3035 ** ^(<dt>SQLITE_LIMIT_ATTACHED</dt> 2987 3036 ** <dd>The maximum number of [ATTACH | attached databases].)^</dd> 2988 3037 ** 2989 3038 ** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt> 2990 3039 ** <dd>The maximum length of the pattern argument to the [LIKE] or 2991 3040 ** [GLOB] operators.</dd>)^ 2992 3041 ** 2993 3042 ** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt> 2994 -** <dd>The maximum number of variables in an SQL statement that can 2995 -** be bound.</dd>)^ 3043 +** <dd>The maximum index number of any [parameter] in an SQL statement.)^ 2996 3044 ** 2997 3045 ** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt> 2998 3046 ** <dd>The maximum depth of recursion for triggers.</dd>)^ 2999 3047 ** </dl> 3000 3048 */ 3001 3049 #define SQLITE_LIMIT_LENGTH 0 3002 3050 #define SQLITE_LIMIT_SQL_LENGTH 1 ................................................................................ 3060 3108 ** original SQL text. This causes the [sqlite3_step()] interface to 3061 3109 ** behave differently in three ways: 3062 3110 ** 3063 3111 ** <ol> 3064 3112 ** <li> 3065 3113 ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it 3066 3114 ** always used to do, [sqlite3_step()] will automatically recompile the SQL 3067 -** statement and try to run it again. ^If the schema has changed in 3068 -** a way that makes the statement no longer valid, [sqlite3_step()] will still 3069 -** return [SQLITE_SCHEMA]. But unlike the legacy behavior, [SQLITE_SCHEMA] is 3070 -** now a fatal error. Calling [sqlite3_prepare_v2()] again will not make the 3071 -** error go away. Note: use [sqlite3_errmsg()] to find the text 3072 -** of the parsing error that results in an [SQLITE_SCHEMA] return. 3115 +** statement and try to run it again. 3073 3116 ** </li> 3074 3117 ** 3075 3118 ** <li> 3076 3119 ** ^When an error occurs, [sqlite3_step()] will return one of the detailed 3077 3120 ** [error codes] or [extended error codes]. ^The legacy behavior was that 3078 3121 ** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code 3079 3122 ** and the application would have to make a second call to [sqlite3_reset()] 3080 3123 ** in order to find the underlying cause of the problem. With the "v2" prepare 3081 3124 ** interfaces, the underlying reason for the error is returned immediately. 3082 3125 ** </li> 3083 3126 ** 3084 3127 ** <li> 3085 -** ^If the value of a [parameter | host parameter] in the WHERE clause might 3086 -** change the query plan for a statement, then the statement may be 3087 -** automatically recompiled (as if there had been a schema change) on the first 3088 -** [sqlite3_step()] call following any change to the 3089 -** [sqlite3_bind_text | bindings] of the [parameter]. 3128 +** ^If the specific value bound to [parameter | host parameter] in the 3129 +** WHERE clause might influence the choice of query plan for a statement, 3130 +** then the statement will be automatically recompiled, as if there had been 3131 +** a schema change, on the first [sqlite3_step()] call following any change 3132 +** to the [sqlite3_bind_text | bindings] of that [parameter]. 3133 +** ^The specific value of WHERE-clause [parameter] might influence the 3134 +** choice of query plan if the parameter is the left-hand side of a [LIKE] 3135 +** or [GLOB] operator or if the parameter is compared to an indexed column 3136 +** and the [SQLITE_ENABLE_STAT2] compile-time option is enabled. 3137 +** the 3090 3138 ** </li> 3091 3139 ** </ol> 3092 3140 */ 3093 3141 SQLITE_API int sqlite3_prepare( 3094 3142 sqlite3 *db, /* Database handle */ 3095 3143 const char *zSql, /* SQL statement, UTF-8 encoded */ 3096 3144 int nByte, /* Maximum length of zSql in bytes. */ ................................................................................ 3149 3197 ** sqlite3_value object. If SQLite is compiled to be single-threaded 3150 3198 ** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) 3151 3199 ** or if SQLite is run in one of reduced mutex modes 3152 3200 ** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] 3153 3201 ** then there is no distinction between protected and unprotected 3154 3202 ** sqlite3_value objects and they can be used interchangeably. However, 3155 3203 ** for maximum code portability it is recommended that applications 3156 -** still make the distinction between between protected and unprotected 3204 +** still make the distinction between protected and unprotected 3157 3205 ** sqlite3_value objects even when not strictly required. 3158 3206 ** 3159 3207 ** ^The sqlite3_value objects that are passed as parameters into the 3160 3208 ** implementation of [application-defined SQL functions] are protected. 3161 3209 ** ^The sqlite3_value object returned by 3162 3210 ** [sqlite3_column_value()] is unprotected. 3163 3211 ** Unprotected sqlite3_value objects may only be used with ................................................................................ 3195 3243 ** <li> ?NNN 3196 3244 ** <li> :VVV 3197 3245 ** <li> @VVV 3198 3246 ** <li> $VVV 3199 3247 ** </ul> 3200 3248 ** 3201 3249 ** In the templates above, NNN represents an integer literal, 3202 -** and VVV represents an alphanumeric identifer.)^ ^The values of these 3250 +** and VVV represents an alphanumeric identifier.)^ ^The values of these 3203 3251 ** parameters (also called "host parameter names" or "SQL parameters") 3204 3252 ** can be set using the sqlite3_bind_*() routines defined here. 3205 3253 ** 3206 3254 ** ^The first argument to the sqlite3_bind_*() routines is always 3207 3255 ** a pointer to the [sqlite3_stmt] object returned from 3208 3256 ** [sqlite3_prepare_v2()] or its variants. 3209 3257 ** ................................................................................ 3344 3392 3345 3393 /* 3346 3394 ** CAPI3REF: Number Of Columns In A Result Set 3347 3395 ** 3348 3396 ** ^Return the number of columns in the result set returned by the 3349 3397 ** [prepared statement]. ^This routine returns 0 if pStmt is an SQL 3350 3398 ** statement that does not return data (for example an [UPDATE]). 3399 +** 3400 +** See also: [sqlite3_data_count()] 3351 3401 */ 3352 3402 SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); 3353 3403 3354 3404 /* 3355 3405 ** CAPI3REF: Column Names In A Result Set 3356 3406 ** 3357 3407 ** ^These routines return the name assigned to a particular column ................................................................................ 3534 3584 ** by sqlite3_step(). The use of the "v2" interface is recommended. 3535 3585 */ 3536 3586 SQLITE_API int sqlite3_step(sqlite3_stmt*); 3537 3587 3538 3588 /* 3539 3589 ** CAPI3REF: Number of columns in a result set 3540 3590 ** 3541 -** ^The sqlite3_data_count(P) the number of columns in the 3542 -** of the result set of [prepared statement] P. 3591 +** ^The sqlite3_data_count(P) interface returns the number of columns in the 3592 +** current row of the result set of [prepared statement] P. 3593 +** ^If prepared statement P does not have results ready to return 3594 +** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of 3595 +** interfaces) then sqlite3_data_count(P) returns 0. 3596 +** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. 3597 +** 3598 +** See also: [sqlite3_column_count()] 3543 3599 */ 3544 3600 SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); 3545 3601 3546 3602 /* 3547 3603 ** CAPI3REF: Fundamental Datatypes 3548 3604 ** KEYWORDS: SQLITE_TEXT 3549 3605 ** ................................................................................ 3615 3671 ** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() 3616 3672 ** routine returns the number of bytes in that BLOB or string. 3617 3673 ** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts 3618 3674 ** the string to UTF-8 and then returns the number of bytes. 3619 3675 ** ^If the result is a numeric value then sqlite3_column_bytes() uses 3620 3676 ** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns 3621 3677 ** the number of bytes in that string. 3622 -** ^The value returned does not include the zero terminator at the end 3623 -** of the string. ^For clarity: the value returned is the number of 3678 +** ^If the result is NULL, then sqlite3_column_bytes() returns zero. 3679 +** 3680 +** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() 3681 +** routine returns the number of bytes in that BLOB or string. 3682 +** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts 3683 +** the string to UTF-16 and then returns the number of bytes. 3684 +** ^If the result is a numeric value then sqlite3_column_bytes16() uses 3685 +** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns 3686 +** the number of bytes in that string. 3687 +** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. 3688 +** 3689 +** ^The values returned by [sqlite3_column_bytes()] and 3690 +** [sqlite3_column_bytes16()] do not include the zero terminators at the end 3691 +** of the string. ^For clarity: the values returned by 3692 +** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of 3624 3693 ** bytes in the string, not the number of characters. 3625 3694 ** 3626 3695 ** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), 3627 3696 ** even empty strings, are always zero terminated. ^The return 3628 -** value from sqlite3_column_blob() for a zero-length BLOB is an arbitrary 3629 -** pointer, possibly even a NULL pointer. 3630 -** 3631 -** ^The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() 3632 -** but leaves the result in UTF-16 in native byte order instead of UTF-8. 3633 -** ^The zero terminator is not included in this count. 3697 +** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. 3634 3698 ** 3635 3699 ** ^The object returned by [sqlite3_column_value()] is an 3636 3700 ** [unprotected sqlite3_value] object. An unprotected sqlite3_value object 3637 3701 ** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. 3638 3702 ** If the [unprotected sqlite3_value] object returned by 3639 3703 ** [sqlite3_column_value()] is used in any other way, including calls 3640 3704 ** to routines like [sqlite3_value_int()], [sqlite3_value_text()], ................................................................................ 3671 3735 ** 3672 3736 ** The table above makes reference to standard C library functions atoi() 3673 3737 ** and atof(). SQLite does not really use these functions. It has its 3674 3738 ** own equivalent internal routines. The atoi() and atof() names are 3675 3739 ** used in the table for brevity and because they are familiar to most 3676 3740 ** C programmers. 3677 3741 ** 3678 -** ^Note that when type conversions occur, pointers returned by prior 3742 +** Note that when type conversions occur, pointers returned by prior 3679 3743 ** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or 3680 3744 ** sqlite3_column_text16() may be invalidated. 3681 -** ^(Type conversions and pointer invalidations might occur 3745 +** Type conversions and pointer invalidations might occur 3682 3746 ** in the following cases: 3683 3747 ** 3684 3748 ** <ul> 3685 3749 ** <li> The initial content is a BLOB and sqlite3_column_text() or 3686 3750 ** sqlite3_column_text16() is called. A zero-terminator might 3687 3751 ** need to be added to the string.</li> 3688 3752 ** <li> The initial content is UTF-8 text and sqlite3_column_bytes16() or 3689 3753 ** sqlite3_column_text16() is called. The content must be converted 3690 3754 ** to UTF-16.</li> 3691 3755 ** <li> The initial content is UTF-16 text and sqlite3_column_bytes() or 3692 3756 ** sqlite3_column_text() is called. The content must be converted 3693 3757 ** to UTF-8.</li> 3694 -** </ul>)^ 3758 +** </ul> 3695 3759 ** 3696 3760 ** ^Conversions between UTF-16be and UTF-16le are always done in place and do 3697 3761 ** not invalidate a prior pointer, though of course the content of the buffer 3698 -** that the prior pointer points to will have been modified. Other kinds 3762 +** that the prior pointer references will have been modified. Other kinds 3699 3763 ** of conversion are done in place when it is possible, but sometimes they 3700 3764 ** are not possible and in those cases prior pointers are invalidated. 3701 3765 ** 3702 -** ^(The safest and easiest to remember policy is to invoke these routines 3766 +** The safest and easiest to remember policy is to invoke these routines 3703 3767 ** in one of the following ways: 3704 3768 ** 3705 3769 ** <ul> 3706 3770 ** <li>sqlite3_column_text() followed by sqlite3_column_bytes()</li> 3707 3771 ** <li>sqlite3_column_blob() followed by sqlite3_column_bytes()</li> 3708 3772 ** <li>sqlite3_column_text16() followed by sqlite3_column_bytes16()</li> 3709 -** </ul>)^ 3773 +** </ul> 3710 3774 ** 3711 3775 ** In other words, you should call sqlite3_column_text(), 3712 3776 ** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result 3713 3777 ** into the desired format, then invoke sqlite3_column_bytes() or 3714 3778 ** sqlite3_column_bytes16() to find the size of the result. Do not mix calls 3715 3779 ** to sqlite3_column_text() or sqlite3_column_blob() with calls to 3716 3780 ** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() ................................................................................ 3740 3804 SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); 3741 3805 SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); 3742 3806 3743 3807 /* 3744 3808 ** CAPI3REF: Destroy A Prepared Statement Object 3745 3809 ** 3746 3810 ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. 3747 -** ^If the statement was executed successfully or not executed at all, then 3748 -** SQLITE_OK is returned. ^If execution of the statement failed then an 3749 -** [error code] or [extended error code] is returned. 3811 +** ^If the most recent evaluation of the statement encountered no errors or 3812 +** or if the statement is never been evaluated, then sqlite3_finalize() returns 3813 +** SQLITE_OK. ^If the most recent evaluation of statement S failed, then 3814 +** sqlite3_finalize(S) returns the appropriate [error code] or 3815 +** [extended error code]. 3750 3816 ** 3751 -** ^This routine can be called at any point during the execution of the 3752 -** [prepared statement]. ^If the virtual machine has not 3753 -** completed execution when this routine is called, that is like 3754 -** encountering an error or an [sqlite3_interrupt | interrupt]. 3755 -** ^Incomplete updates may be rolled back and transactions canceled, 3756 -** depending on the circumstances, and the 3757 -** [error code] returned will be [SQLITE_ABORT]. 3817 +** ^The sqlite3_finalize(S) routine can be called at any point during 3818 +** the life cycle of [prepared statement] S: 3819 +** before statement S is ever evaluated, after 3820 +** one or more calls to [sqlite3_reset()], or after any call 3821 +** to [sqlite3_step()] regardless of whether or not the statement has 3822 +** completed execution. 3823 +** 3824 +** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. 3825 +** 3826 +** The application must finalize every [prepared statement] in order to avoid 3827 +** resource leaks. It is a grievous error for the application to try to use 3828 +** a prepared statement after it has been finalized. Any use of a prepared 3829 +** statement after it has been finalized can result in undefined and 3830 +** undesirable behavior such as segfaults and heap corruption. 3758 3831 */ 3759 3832 SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); 3760 3833 3761 3834 /* 3762 3835 ** CAPI3REF: Reset A Prepared Statement Object 3763 3836 ** 3764 3837 ** The sqlite3_reset() function is called to reset a [prepared statement] ................................................................................ 3786 3859 3787 3860 /* 3788 3861 ** CAPI3REF: Create Or Redefine SQL Functions 3789 3862 ** KEYWORDS: {function creation routines} 3790 3863 ** KEYWORDS: {application-defined SQL function} 3791 3864 ** KEYWORDS: {application-defined SQL functions} 3792 3865 ** 3793 -** ^These two functions (collectively known as "function creation routines") 3866 +** ^These functions (collectively known as "function creation routines") 3794 3867 ** are used to add SQL functions or aggregates or to redefine the behavior 3795 -** of existing SQL functions or aggregates. The only difference between the 3796 -** two is that the second parameter, the name of the (scalar) function or 3797 -** aggregate, is encoded in UTF-8 for sqlite3_create_function() and UTF-16 3798 -** for sqlite3_create_function16(). 3868 +** of existing SQL functions or aggregates. The only differences between 3869 +** these routines are the text encoding expected for 3870 +** the the second parameter (the name of the function being created) 3871 +** and the presence or absence of a destructor callback for 3872 +** the application data pointer. 3799 3873 ** 3800 3874 ** ^The first parameter is the [database connection] to which the SQL 3801 3875 ** function is to be added. ^If an application uses more than one database 3802 3876 ** connection then application-defined SQL functions must be added 3803 3877 ** to each database connection separately. 3804 3878 ** 3805 -** The second parameter is the name of the SQL function to be created or 3806 -** redefined. ^The length of the name is limited to 255 bytes, exclusive of 3807 -** the zero-terminator. Note that the name length limit is in bytes, not 3808 -** characters. ^Any attempt to create a function with a longer name 3809 -** will result in [SQLITE_ERROR] being returned. 3879 +** ^The second parameter is the name of the SQL function to be created or 3880 +** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 3881 +** representation, exclusive of the zero-terminator. ^Note that the name 3882 +** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. 3883 +** ^Any attempt to create a function with a longer name 3884 +** will result in [SQLITE_MISUSE] being returned. 3810 3885 ** 3811 3886 ** ^The third parameter (nArg) 3812 3887 ** is the number of arguments that the SQL function or 3813 3888 ** aggregate takes. ^If this parameter is -1, then the SQL function or 3814 3889 ** aggregate may take any number of arguments between 0 and the limit 3815 3890 ** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third 3816 3891 ** parameter is less than -1 or greater than 127 then the behavior is 3817 3892 ** undefined. 3818 3893 ** 3819 -** The fourth parameter, eTextRep, specifies what 3894 +** ^The fourth parameter, eTextRep, specifies what 3820 3895 ** [SQLITE_UTF8 | text encoding] this SQL function prefers for 3821 -** its parameters. Any SQL function implementation should be able to work 3822 -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be 3896 +** its parameters. Every SQL function implementation must be able to work 3897 +** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be 3823 3898 ** more efficient with one encoding than another. ^An application may 3824 3899 ** invoke sqlite3_create_function() or sqlite3_create_function16() multiple 3825 3900 ** times with the same function but with different values of eTextRep. 3826 3901 ** ^When multiple implementations of the same function are available, SQLite 3827 3902 ** will pick the one that involves the least amount of data conversion. 3828 3903 ** If there is only a single implementation which does not care what text 3829 3904 ** encoding is used, then the fourth argument should be [SQLITE_ANY]. 3830 3905 ** 3831 3906 ** ^(The fifth parameter is an arbitrary pointer. The implementation of the 3832 3907 ** function can gain access to this pointer using [sqlite3_user_data()].)^ 3833 3908 ** 3834 -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are 3909 +** ^The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are 3835 3910 ** pointers to C-language functions that implement the SQL function or 3836 3911 ** aggregate. ^A scalar SQL function requires an implementation of the xFunc 3837 -** callback only; NULL pointers should be passed as the xStep and xFinal 3912 +** callback only; NULL pointers must be passed as the xStep and xFinal 3838 3913 ** parameters. ^An aggregate SQL function requires an implementation of xStep 3839 -** and xFinal and NULL should be passed for xFunc. ^To delete an existing 3840 -** SQL function or aggregate, pass NULL for all three function callbacks. 3914 +** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing 3915 +** SQL function or aggregate, pass NULL poiners for all three function 3916 +** callbacks. 3917 +** 3918 +** ^If the tenth parameter to sqlite3_create_function_v2() is not NULL, 3919 +** then it is invoked when the function is deleted, either by being 3920 +** overloaded or when the database connection closes. 3921 +** ^When the destructure callback of the tenth parameter is invoked, it 3922 +** is passed a single argument which is a copy of the pointer which was 3923 +** the fifth parameter to sqlite3_create_function_v2(). 3841 3924 ** 3842 3925 ** ^It is permitted to register multiple implementations of the same 3843 3926 ** functions with the same name but with either differing numbers of 3844 3927 ** arguments or differing preferred text encodings. ^SQLite will use 3845 3928 ** the implementation that most closely matches the way in which the 3846 3929 ** SQL function is used. ^A function implementation with a non-negative 3847 3930 ** nArg parameter is a better match than a function implementation with ................................................................................ 3849 3932 ** matches the database encoding is a better 3850 3933 ** match than a function where the encoding is different. 3851 3934 ** ^A function where the encoding difference is between UTF16le and UTF16be 3852 3935 ** is a closer match than a function where the encoding difference is 3853 3936 ** between UTF8 and UTF16. 3854 3937 ** 3855 3938 ** ^Built-in functions may be overloaded by new application-defined functions. 3856 -** ^The first application-defined function with a given name overrides all 3857 -** built-in functions in the same [database connection] with the same name. 3858 -** ^Subsequent application-defined functions of the same name only override 3859 -** prior application-defined functions that are an exact match for the 3860 -** number of parameters and preferred encoding. 3861 3939 ** 3862 3940 ** ^An application-defined function is permitted to call other 3863 3941 ** SQLite interfaces. However, such calls must not 3864 3942 ** close the database connection nor finalize or reset the prepared 3865 3943 ** statement in which the function is running. 3866 3944 */ 3867 3945 SQLITE_API int sqlite3_create_function( ................................................................................ 3879 3957 const void *zFunctionName, 3880 3958 int nArg, 3881 3959 int eTextRep, 3882 3960 void *pApp, 3883 3961 void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 3884 3962 void (*xStep)(sqlite3_context*,int,sqlite3_value**), 3885 3963 void (*xFinal)(sqlite3_context*) 3964 +); 3965 +SQLITE_API int sqlite3_create_function_v2( 3966 + sqlite3 *db, 3967 + const char *zFunctionName, 3968 + int nArg, 3969 + int eTextRep, 3970 + void *pApp, 3971 + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 3972 + void (*xStep)(sqlite3_context*,int,sqlite3_value**), 3973 + void (*xFinal)(sqlite3_context*), 3974 + void(*xDestroy)(void*) 3886 3975 ); 3887 3976 3888 3977 /* 3889 3978 ** CAPI3REF: Text Encodings 3890 3979 ** 3891 3980 ** These constant define integer codes that represent the various 3892 3981 ** text encodings supported by SQLite. ................................................................................ 3974 4063 SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); 3975 4064 SQLITE_API int sqlite3_value_type(sqlite3_value*); 3976 4065 SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); 3977 4066 3978 4067 /* 3979 4068 ** CAPI3REF: Obtain Aggregate Function Context 3980 4069 ** 3981 -** Implementions of aggregate SQL functions use this 4070 +** Implementations of aggregate SQL functions use this 3982 4071 ** routine to allocate memory for storing their state. 3983 4072 ** 3984 4073 ** ^The first time the sqlite3_aggregate_context(C,N) routine is called 3985 4074 ** for a particular aggregate function, SQLite 3986 4075 ** allocates N of memory, zeroes out that memory, and returns a pointer 3987 4076 ** to the new memory. ^On second and subsequent calls to 3988 4077 ** sqlite3_aggregate_context() for the same aggregate function instance, ................................................................................ 4226 4315 SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); 4227 4316 SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); 4228 4317 SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); 4229 4318 4230 4319 /* 4231 4320 ** CAPI3REF: Define New Collating Sequences 4232 4321 ** 4233 -** These functions are used to add new collation sequences to the 4234 -** [database connection] specified as the first argument. 4322 +** ^These functions add, remove, or modify a [collation] associated 4323 +** with the [database connection] specified as the first argument. 4235 4324 ** 4236 -** ^The name of the new collation sequence is specified as a UTF-8 string 4325 +** ^The name of the collation is a UTF-8 string 4237 4326 ** for sqlite3_create_collation() and sqlite3_create_collation_v2() 4238 -** and a UTF-16 string for sqlite3_create_collation16(). ^In all cases 4239 -** the name is passed as the second function argument. 4240 -** 4241 -** ^The third argument may be one of the constants [SQLITE_UTF8], 4242 -** [SQLITE_UTF16LE], or [SQLITE_UTF16BE], indicating that the user-supplied 4243 -** routine expects to be passed pointers to strings encoded using UTF-8, 4244 -** UTF-16 little-endian, or UTF-16 big-endian, respectively. ^The 4245 -** third argument might also be [SQLITE_UTF16] to indicate that the routine 4246 -** expects pointers to be UTF-16 strings in the native byte order, or the 4247 -** argument can be [SQLITE_UTF16_ALIGNED] if the 4248 -** the routine expects pointers to 16-bit word aligned strings 4249 -** of UTF-16 in the native byte order. 4250 -** 4251 -** A pointer to the user supplied routine must be passed as the fifth 4252 -** argument. ^If it is NULL, this is the same as deleting the collation 4253 -** sequence (so that SQLite cannot call it anymore). 4254 -** ^Each time the application supplied function is invoked, it is passed 4255 -** as its first parameter a copy of the void* passed as the fourth argument 4256 -** to sqlite3_create_collation() or sqlite3_create_collation16(). 4257 -** 4258 -** ^The remaining arguments to the application-supplied routine are two strings, 4259 -** each represented by a (length, data) pair and encoded in the encoding 4260 -** that was passed as the third argument when the collation sequence was 4261 -** registered. The application defined collation routine should 4262 -** return negative, zero or positive if the first string is less than, 4263 -** equal to, or greater than the second string. i.e. (STRING1 - STRING2). 4327 +** and a UTF-16 string in native byte order for sqlite3_create_collation16(). 4328 +** ^Collation names that compare equal according to [sqlite3_strnicmp()] are 4329 +** considered to be the same name. 4330 +** 4331 +** ^(The third argument (eTextRep) must be one of the constants: 4332 +** <ul> 4333 +** <li> [SQLITE_UTF8], 4334 +** <li> [SQLITE_UTF16LE], 4335 +** <li> [SQLITE_UTF16BE], 4336 +** <li> [SQLITE_UTF16], or 4337 +** <li> [SQLITE_UTF16_ALIGNED]. 4338 +** </ul>)^ 4339 +** ^The eTextRep argument determines the encoding of strings passed 4340 +** to the collating function callback, xCallback. 4341 +** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep 4342 +** force strings to be UTF16 with native byte order. 4343 +** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin 4344 +** on an even byte address. 4345 +** 4346 +** ^The fourth argument, pArg, is a application data pointer that is passed 4347 +** through as the first argument to the collating function callback. 4348 +** 4349 +** ^The fifth argument, xCallback, is a pointer to the collating function. 4350 +** ^Multiple collating functions can be registered using the same name but 4351 +** with different eTextRep parameters and SQLite will use whichever 4352 +** function requires the least amount of data transformation. 4353 +** ^If the xCallback argument is NULL then the collating function is 4354 +** deleted. ^When all collating functions having the same name are deleted, 4355 +** that collation is no longer usable. 4356 +** 4357 +** ^The collating function callback is invoked with a copy of the pArg 4358 +** application data pointer and with two strings in the encoding specified 4359 +** by the eTextRep argument. The collating function must return an 4360 +** integer that is negative, zero, or positive 4361 +** if the first string is less than, equal to, or greater than the second, 4362 +** respectively. A collating function must alway return the same answer 4363 +** given the same inputs. If two or more collating functions are registered 4364 +** to the same collation name (using different eTextRep values) then all 4365 +** must give an equivalent answer when invoked with equivalent strings. 4366 +** The collating function must obey the following properties for all 4367 +** strings A, B, and C: 4368 +** 4369 +** <ol> 4370 +** <li> If A==B then B==A. 4371 +** <li> If A==B and B==C then A==C. 4372 +** <li> If A<B THEN B>A. 4373 +** <li> If A<B and B<C then A<C. 4374 +** </ol> 4375 +** 4376 +** If a collating function fails any of the above constraints and that 4377 +** collating function is registered and used, then the behavior of SQLite 4378 +** is undefined. 4264 4379 ** 4265 4380 ** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() 4266 -** except that it takes an extra argument which is a destructor for 4267 -** the collation. ^The destructor is called when the collation is 4268 -** destroyed and is passed a copy of the fourth parameter void* pointer 4269 -** of the sqlite3_create_collation_v2(). 4270 -** ^Collations are destroyed when they are overridden by later calls to the 4271 -** collation creation functions or when the [database connection] is closed 4272 -** using [sqlite3_close()]. 4381 +** with the addition that the xDestroy callback is invoked on pArg when 4382 +** the collating function is deleted. 4383 +** ^Collating functions are deleted when they are overridden by later 4384 +** calls to the collation creation functions or when the 4385 +** [database connection] is closed using [sqlite3_close()]. 4273 4386 ** 4274 4387 ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. 4275 4388 */ 4276 4389 SQLITE_API int sqlite3_create_collation( 4277 4390 sqlite3*, 4278 4391 const char *zName, 4279 4392 int eTextRep, 4280 - void*, 4393 + void *pArg, 4281 4394 int(*xCompare)(void*,int,const void*,int,const void*) 4282 4395 ); 4283 4396 SQLITE_API int sqlite3_create_collation_v2( 4284 4397 sqlite3*, 4285 4398 const char *zName, 4286 4399 int eTextRep, 4287 - void*, 4400 + void *pArg, 4288 4401 int(*xCompare)(void*,int,const void*,int,const void*), 4289 4402 void(*xDestroy)(void*) 4290 4403 ); 4291 4404 SQLITE_API int sqlite3_create_collation16( 4292 4405 sqlite3*, 4293 4406 const void *zName, 4294 4407 int eTextRep, 4295 - void*, 4408 + void *pArg, 4296 4409 int(*xCompare)(void*,int,const void*,int,const void*) 4297 4410 ); 4298 4411 4299 4412 /* 4300 4413 ** CAPI3REF: Collation Needed Callbacks 4301 4414 ** 4302 4415 ** ^To avoid having to register all collation sequences before a database ................................................................................ 4377 4490 const char *zPassPhrase /* Activation phrase */ 4378 4491 ); 4379 4492 #endif 4380 4493 4381 4494 /* 4382 4495 ** CAPI3REF: Suspend Execution For A Short Time 4383 4496 ** 4384 -** ^The sqlite3_sleep() function causes the current thread to suspend execution 4497 +** The sqlite3_sleep() function causes the current thread to suspend execution 4385 4498 ** for at least a number of milliseconds specified in its parameter. 4386 4499 ** 4387 -** ^If the operating system does not support sleep requests with 4500 +** If the operating system does not support sleep requests with 4388 4501 ** millisecond time resolution, then the time will be rounded up to 4389 -** the nearest second. ^The number of milliseconds of sleep actually 4502 +** the nearest second. The number of milliseconds of sleep actually 4390 4503 ** requested from the operating system is returned. 4391 4504 ** 4392 4505 ** ^SQLite implements this interface by calling the xSleep() 4393 -** method of the default [sqlite3_vfs] object. 4506 +** method of the default [sqlite3_vfs] object. If the xSleep() method 4507 +** of the default VFS is not implemented correctly, or not implemented at 4508 +** all, then the behavior of sqlite3_sleep() may deviate from the description 4509 +** in the previous paragraphs. 4394 4510 */ 4395 4511 SQLITE_API int sqlite3_sleep(int); 4396 4512 4397 4513 /* 4398 4514 ** CAPI3REF: Name Of The Folder Holding Temporary Files 4399 4515 ** 4400 4516 ** ^(If this global variable is made to point to a string which is ................................................................................ 4608 4724 ** 4609 4725 ** ^The sqlite3_release_memory() interface attempts to free N bytes 4610 4726 ** of heap memory by deallocating non-essential memory allocations 4611 4727 ** held by the database library. Memory used to cache database 4612 4728 ** pages to improve performance is an example of non-essential memory. 4613 4729 ** ^sqlite3_release_memory() returns the number of bytes actually freed, 4614 4730 ** which might be more or less than the amount requested. 4731 +** ^The sqlite3_release_memory() routine is a no-op returning zero 4732 +** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. 4615 4733 */ 4616 4734 SQLITE_API int sqlite3_release_memory(int); 4617 4735 4618 4736 /* 4619 4737 ** CAPI3REF: Impose A Limit On Heap Size 4620 4738 ** 4621 -** ^The sqlite3_soft_heap_limit() interface places a "soft" limit 4622 -** on the amount of heap memory that may be allocated by SQLite. 4623 -** ^If an internal allocation is requested that would exceed the 4624 -** soft heap limit, [sqlite3_release_memory()] is invoked one or 4625 -** more times to free up some space before the allocation is performed. 4626 -** 4627 -** ^The limit is called "soft" because if [sqlite3_release_memory()] 4628 -** cannot free sufficient memory to prevent the limit from being exceeded, 4629 -** the memory is allocated anyway and the current operation proceeds. 4630 -** 4631 -** ^A negative or zero value for N means that there is no soft heap limit and 4632 -** [sqlite3_release_memory()] will only be called when memory is exhausted. 4633 -** ^The default value for the soft heap limit is zero. 4634 -** 4635 -** ^(SQLite makes a best effort to honor the soft heap limit. 4636 -** But if the soft heap limit cannot be honored, execution will 4637 -** continue without error or notification.)^ This is why the limit is 4638 -** called a "soft" limit. It is advisory only. 4639 -** 4640 -** Prior to SQLite version 3.5.0, this routine only constrained the memory 4641 -** allocated by a single thread - the same thread in which this routine 4642 -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is 4643 -** applied to all threads. The value specified for the soft heap limit 4644 -** is an upper bound on the total memory allocation for all threads. In 4645 -** version 3.5.0 there is no mechanism for limiting the heap usage for 4646 -** individual threads. 4647 -*/ 4648 -SQLITE_API void sqlite3_soft_heap_limit(int); 4739 +** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the 4740 +** soft limit on the amount of heap memory that may be allocated by SQLite. 4741 +** ^SQLite strives to keep heap memory utilization below the soft heap 4742 +** limit by reducing the number of pages held in the page cache 4743 +** as heap memory usages approaches the limit. 4744 +** ^The soft heap limit is "soft" because even though SQLite strives to stay 4745 +** below the limit, it will exceed the limit rather than generate 4746 +** an [SQLITE_NOMEM] error. In other words, the soft heap limit 4747 +** is advisory only. 4748 +** 4749 +** ^The return value from sqlite3_soft_heap_limit64() is the size of 4750 +** the soft heap limit prior to the call. ^If the argument N is negative 4751 +** then no change is made to the soft heap limit. Hence, the current 4752 +** size of the soft heap limit can be determined by invoking 4753 +** sqlite3_soft_heap_limit64() with a negative argument. 4754 +** 4755 +** ^If the argument N is zero then the soft heap limit is disabled. 4756 +** 4757 +** ^(The soft heap limit is not enforced in the current implementation 4758 +** if one or more of following conditions are true: 4759 +** 4760 +** <ul> 4761 +** <li> The soft heap limit is set to zero. 4762 +** <li> Memory accounting is disabled using a combination of the 4763 +** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and 4764 +** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. 4765 +** <li> An alternative page cache implementation is specifed using 4766 +** [sqlite3_config]([SQLITE_CONFIG_PCACHE],...). 4767 +** <li> The page cache allocates from its own memory pool supplied 4768 +** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than 4769 +** from the heap. 4770 +** </ul>)^ 4771 +** 4772 +** Beginning with SQLite version 3.7.3, the soft heap limit is enforced 4773 +** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] 4774 +** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], 4775 +** the soft heap limit is enforced on every memory allocation. Without 4776 +** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced 4777 +** when memory is allocated by the page cache. Testing suggests that because 4778 +** the page cache is the predominate memory user in SQLite, most 4779 +** applications will achieve adequate soft heap limit enforcement without 4780 +** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. 4781 +** 4782 +** The circumstances under which SQLite will enforce the soft heap limit may 4783 +** changes in future releases of SQLite. 4784 +*/ 4785 +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); 4786 + 4787 +/* 4788 +** CAPI3REF: Deprecated Soft Heap Limit Interface 4789 +** DEPRECATED 4790 +** 4791 +** This is a deprecated version of the [sqlite3_soft_heap_limit64()] 4792 +** interface. This routine is provided for historical compatibility 4793 +** only. All new applications should use the 4794 +** [sqlite3_soft_heap_limit64()] interface rather than this one. 4795 +*/ 4796 +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); 4797 + 4649 4798 4650 4799 /* 4651 4800 ** CAPI3REF: Extract Metadata About A Column Of A Table 4652 4801 ** 4653 4802 ** ^This routine returns metadata about a specific column of a specific 4654 4803 ** database table accessible using the [database connection] handle 4655 4804 ** passed as the first function argument. ................................................................................ 4765 4914 ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 4766 4915 ** to turn extension loading on and call it with onoff==0 to turn 4767 4916 ** it back off again. 4768 4917 */ 4769 4918 SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); 4770 4919 4771 4920 /* 4772 -** CAPI3REF: Automatically Load An Extensions 4773 -** 4774 -** ^This API can be invoked at program startup in order to register 4775 -** one or more statically linked extensions that will be available 4776 -** to all new [database connections]. 4777 -** 4778 -** ^(This routine stores a pointer to the extension entry point 4779 -** in an array that is obtained from [sqlite3_malloc()]. That memory 4780 -** is deallocated by [sqlite3_reset_auto_extension()].)^ 4781 -** 4782 -** ^This function registers an extension entry point that is 4783 -** automatically invoked whenever a new [database connection] 4784 -** is opened using [sqlite3_open()], [sqlite3_open16()], 4785 -** or [sqlite3_open_v2()]. 4786 -** ^Duplicate extensions are detected so calling this routine 4787 -** multiple times with the same extension is harmless. 4788 -** ^Automatic extensions apply across all threads. 4921 +** CAPI3REF: Automatically Load Statically Linked Extensions 4922 +** 4923 +** ^This interface causes the xEntryPoint() function to be invoked for 4924 +** each new [database connection] that is created. The idea here is that 4925 +** xEntryPoint() is the entry point for a statically linked SQLite extension 4926 +** that is to be automatically loaded into all new database connections. 4927 +** 4928 +** ^(Even though the function prototype shows that xEntryPoint() takes 4929 +** no arguments and returns void, SQLite invokes xEntryPoint() with three 4930 +** arguments and expects and integer result as if the signature of the 4931 +** entry point where as follows: 4932 +** 4933 +** <blockquote><pre> 4934 +** int xEntryPoint( 4935 +** sqlite3 *db, 4936 +** const char **pzErrMsg, 4937 +** const struct sqlite3_api_routines *pThunk 4938 +** ); 4939 +** </pre></blockquote>)^ 4940 +** 4941 +** If the xEntryPoint routine encounters an error, it should make *pzErrMsg 4942 +** point to an appropriate error message (obtained from [sqlite3_mprintf()]) 4943 +** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg 4944 +** is NULL before calling the xEntryPoint(). ^SQLite will invoke 4945 +** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any 4946 +** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], 4947 +** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. 4948 +** 4949 +** ^Calling sqlite3_auto_extension(X) with an entry point X that is already 4950 +** on the list of automatic extensions is a harmless no-op. ^No entry point 4951 +** will be called more than once for each database connection that is opened. 4952 +** 4953 +** See also: [sqlite3_reset_auto_extension()]. 4789 4954 */ 4790 4955 SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); 4791 4956 4792 4957 /* 4793 4958 ** CAPI3REF: Reset Automatic Extension Loading 4794 4959 ** 4795 -** ^(This function disables all previously registered automatic 4796 -** extensions. It undoes the effect of all prior 4797 -** [sqlite3_auto_extension()] calls.)^ 4798 -** 4799 -** ^This function disables automatic extensions in all threads. 4960 +** ^This interface disables all automatic extensions previously 4961 +** registered using [sqlite3_auto_extension()]. 4800 4962 */ 4801 4963 SQLITE_API void sqlite3_reset_auto_extension(void); 4802 4964 4803 4965 /* 4804 4966 ** The interface to the virtual-table mechanism is currently considered 4805 4967 ** to be experimental. The interface might change in incompatible ways. 4806 4968 ** If this is a problem for you, do not use the interface at this time. ................................................................................ 5431 5593 ** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. 5432 5594 ** Additionally, an instance of this structure can be used as an 5433 5595 ** output variable when querying the system for the current mutex 5434 5596 ** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. 5435 5597 ** 5436 5598 ** ^The xMutexInit method defined by this structure is invoked as 5437 5599 ** part of system initialization by the sqlite3_initialize() function. 5438 -** ^The xMutexInit routine is calle by SQLite exactly once for each 5600 +** ^The xMutexInit routine is called by SQLite exactly once for each 5439 5601 ** effective call to [sqlite3_initialize()]. 5440 5602 ** 5441 5603 ** ^The xMutexEnd method defined by this structure is invoked as 5442 5604 ** part of system shutdown by the sqlite3_shutdown() function. The 5443 5605 ** implementation of this method is expected to release all outstanding 5444 5606 ** resources obtained by the mutex methods implementation, especially 5445 5607 ** those obtained by the xMutexInit method. ^The xMutexEnd() ................................................................................ 5464 5626 ** of a valid mutex handle. The implementations of the methods defined 5465 5627 ** by this structure are not required to handle this case, the results 5466 5628 ** of passing a NULL pointer instead of a valid mutex handle are undefined 5467 5629 ** (i.e. it is acceptable to provide an implementation that segfaults if 5468 5630 ** it is passed a NULL pointer). 5469 5631 ** 5470 5632 ** The xMutexInit() method must be threadsafe. ^It must be harmless to 5471 -** invoke xMutexInit() mutiple times within the same process and without 5633 +** invoke xMutexInit() multiple times within the same process and without 5472 5634 ** intervening calls to xMutexEnd(). Second and subsequent calls to 5473 5635 ** xMutexInit() must be no-ops. 5474 5636 ** 5475 5637 ** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] 5476 5638 ** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory 5477 5639 ** allocation for a static mutex. ^However xMutexAlloc() may use SQLite 5478 5640 ** memory allocation for a fast or recursive mutex. ................................................................................ 5628 5790 #define SQLITE_TESTCTRL_PENDING_BYTE 11 5629 5791 #define SQLITE_TESTCTRL_ASSERT 12 5630 5792 #define SQLITE_TESTCTRL_ALWAYS 13 5631 5793 #define SQLITE_TESTCTRL_RESERVE 14 5632 5794 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 5633 5795 #define SQLITE_TESTCTRL_ISKEYWORD 16 5634 5796 #define SQLITE_TESTCTRL_PGHDRSZ 17 5635 -#define SQLITE_TESTCTRL_LAST 17 5797 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 18 5798 +#define SQLITE_TESTCTRL_LAST 18 5636 5799 5637 5800 /* 5638 5801 ** CAPI3REF: SQLite Runtime Status 5639 5802 ** 5640 5803 ** ^This interface is used to retrieve runtime status information 5641 -** about the preformance of SQLite, and optionally to reset various 5804 +** about the performance of SQLite, and optionally to reset various 5642 5805 ** highwater marks. ^The first argument is an integer code for 5643 5806 ** the specific parameter to measure. ^(Recognized integer codes 5644 5807 ** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^ 5645 5808 ** ^The current value of the parameter is returned into *pCurrent. 5646 5809 ** ^The highest recorded value is returned in *pHighwater. ^If the 5647 5810 ** resetFlag is true, then the highest record value is reset after 5648 5811 ** *pHighwater is written. ^(Some parameters do not record the highest 5649 5812 ** value. For those parameters 5650 5813 ** nothing is written into *pHighwater and the resetFlag is ignored.)^ 5651 5814 ** ^(Other parameters record only the highwater mark and not the current 5652 5815 ** value. For these latter parameters nothing is written into *pCurrent.)^ 5653 5816 ** 5654 -** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a 5817 +** ^The sqlite3_status() routine returns SQLITE_OK on success and a 5655 5818 ** non-zero [error code] on failure. 5656 5819 ** 5657 5820 ** This routine is threadsafe but is not atomic. This routine can be 5658 5821 ** called while other threads are running the same or different SQLite 5659 5822 ** interfaces. However the values returned in *pCurrent and 5660 5823 ** *pHighwater reflect the status of SQLite at different points in time 5661 5824 ** and it is possible that another thread might change the parameter ................................................................................ 5697 5860 ** <dd>This parameter returns the number of pages used out of the 5698 5861 ** [pagecache memory allocator] that was configured using 5699 5862 ** [SQLITE_CONFIG_PAGECACHE]. The 5700 5863 ** value returned is in pages, not in bytes.</dd>)^ 5701 5864 ** 5702 5865 ** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt> 5703 5866 ** <dd>This parameter returns the number of bytes of page cache 5704 -** allocation which could not be statisfied by the [SQLITE_CONFIG_PAGECACHE] 5867 +** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] 5705 5868 ** buffer and where forced to overflow to [sqlite3_malloc()]. The 5706 5869 ** returned value includes allocations that overflowed because they 5707 5870 ** where too large (they were larger than the "sz" parameter to 5708 5871 ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because 5709 5872 ** no space was left in the page cache.</dd>)^ 5710 5873 ** 5711 5874 ** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt> ................................................................................ 5720 5883 ** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not 5721 5884 ** in bytes. Since a single thread may only have one scratch allocation 5722 5885 ** outstanding at time, this parameter also reports the number of threads 5723 5886 ** using scratch memory at the same time.</dd>)^ 5724 5887 ** 5725 5888 ** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt> 5726 5889 ** <dd>This parameter returns the number of bytes of scratch memory 5727 -** allocation which could not be statisfied by the [SQLITE_CONFIG_SCRATCH] 5890 +** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] 5728 5891 ** buffer and where forced to overflow to [sqlite3_malloc()]. The values 5729 5892 ** returned include overflows because the requested allocation was too 5730 5893 ** larger (that is, because the requested allocation was larger than the 5731 5894 ** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer 5732 5895 ** slots were available. 5733 5896 ** </dd>)^ 5734 5897 ** ................................................................................ 5760 5923 ** CAPI3REF: Database Connection Status 5761 5924 ** 5762 5925 ** ^This interface is used to retrieve runtime status information 5763 5926 ** about a single [database connection]. ^The first argument is the 5764 5927 ** database connection object to be interrogated. ^The second argument 5765 5928 ** is an integer constant, taken from the set of 5766 5929 ** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that 5767 -** determiness the parameter to interrogate. The set of 5930 +** determines the parameter to interrogate. The set of 5768 5931 ** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely 5769 5932 ** to grow in future releases of SQLite. 5770 5933 ** 5771 5934 ** ^The current value of the requested parameter is written into *pCur 5772 5935 ** and the highest instantaneous value is written into *pHiwtr. ^If 5773 5936 ** the resetFlg is true, then the highest instantaneous value is 5774 5937 ** reset back down to the current value. 5938 +** 5939 +** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a 5940 +** non-zero [error code] on failure. 5775 5941 ** 5776 5942 ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. 5777 5943 */ 5778 5944 SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); 5779 5945 5780 5946 /* 5781 5947 ** CAPI3REF: Status Parameters for database connections ................................................................................ 5895 6061 5896 6062 /* 5897 6063 ** CAPI3REF: Application Defined Page Cache. 5898 6064 ** KEYWORDS: {page cache} 5899 6065 ** 5900 6066 ** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can 5901 6067 ** register an alternative page cache implementation by passing in an 5902 -** instance of the sqlite3_pcache_methods structure.)^ The majority of the 5903 -** heap memory used by SQLite is used by the page cache to cache data read 5904 -** from, or ready to be written to, the database file. By implementing a 5905 -** custom page cache using this API, an application can control more 5906 -** precisely the amount of memory consumed by SQLite, the way in which 6068 +** instance of the sqlite3_pcache_methods structure.)^ 6069 +** In many applications, most of the heap memory allocated by 6070 +** SQLite is used for the page cache. 6071 +** By implementing a 6072 +** custom page cache using this API, an application can better control 6073 +** the amount of memory consumed by SQLite, the way in which 5907 6074 ** that memory is allocated and released, and the policies used to 5908 6075 ** determine exactly which parts of a database file are cached and for 5909 6076 ** how long. 5910 6077 ** 6078 +** The alternative page cache mechanism is an 6079 +** extreme measure that is only needed by the most demanding applications. 6080 +** The built-in page cache is recommended for most uses. 6081 +** 5911 6082 ** ^(The contents of the sqlite3_pcache_methods structure are copied to an 5912 6083 ** internal buffer by SQLite within the call to [sqlite3_config]. Hence 5913 6084 ** the application may discard the parameter after the call to 5914 6085 ** [sqlite3_config()] returns.)^ 5915 6086 ** 5916 -** ^The xInit() method is called once for each call to [sqlite3_initialize()] 6087 +** ^(The xInit() method is called once for each effective 6088 +** call to [sqlite3_initialize()])^ 5917 6089 ** (usually only once during the lifetime of the process). ^(The xInit() 5918 6090 ** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^ 5919 -** ^The xInit() method can set up up global structures and/or any mutexes 6091 +** The intent of the xInit() method is to set up global data structures 5920 6092 ** required by the custom page cache implementation. 6093 +** ^(If the xInit() method is NULL, then the 6094 +** built-in default page cache is used instead of the application defined 6095 +** page cache.)^ 5921 6096 ** 5922 -** ^The xShutdown() method is called from within [sqlite3_shutdown()], 5923 -** if the application invokes this API. It can be used to clean up 6097 +** ^The xShutdown() method is called by [sqlite3_shutdown()]. 6098 +** It can be used to clean up 5924 6099 ** any outstanding resources before process shutdown, if required. 6100 +** ^The xShutdown() method may be NULL. 5925 6101 ** 5926 -** ^SQLite holds a [SQLITE_MUTEX_RECURSIVE] mutex when it invokes 5927 -** the xInit method, so the xInit method need not be threadsafe. ^The 6102 +** ^SQLite automatically serializes calls to the xInit method, 6103 +** so the xInit method need not be threadsafe. ^The 5928 6104 ** xShutdown method is only called from [sqlite3_shutdown()] so it does 5929 6105 ** not need to be threadsafe either. All other methods must be threadsafe 5930 6106 ** in multithreaded applications. 5931 6107 ** 5932 6108 ** ^SQLite will never invoke xInit() more than once without an intervening 5933 6109 ** call to xShutdown(). 5934 6110 ** 5935 -** ^The xCreate() method is used to construct a new cache instance. SQLite 5936 -** will typically create one cache instance for each open database file, 6111 +** ^SQLite invokes the xCreate() method to construct a new cache instance. 6112 +** SQLite will typically create one cache instance for each open database file, 5937 6113 ** though this is not guaranteed. ^The 5938 6114 ** first parameter, szPage, is the size in bytes of the pages that must 5939 6115 ** be allocated by the cache. ^szPage will not be a power of two. ^szPage 5940 6116 ** will the page size of the database file that is to be cached plus an 5941 -** increment (here called "R") of about 100 or 200. ^SQLite will use the 6117 +** increment (here called "R") of about 100 or 200. SQLite will use the 5942 6118 ** extra R bytes on each page to store metadata about the underlying 5943 6119 ** database page on disk. The value of R depends 5944 6120 ** on the SQLite version, the target platform, and how SQLite was compiled. 5945 6121 ** ^R is constant for a particular build of SQLite. ^The second argument to 5946 6122 ** xCreate(), bPurgeable, is true if the cache being created will 5947 6123 ** be used to cache database pages of a file stored on disk, or 5948 -** false if it is used for an in-memory database. ^The cache implementation 6124 +** false if it is used for an in-memory database. The cache implementation 5949 6125 ** does not have to do anything special based with the value of bPurgeable; 5950 6126 ** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will 5951 6127 ** never invoke xUnpin() except to deliberately delete a page. 5952 -** ^In other words, a cache created with bPurgeable set to false will 6128 +** ^In other words, calls to xUnpin() on a cache with bPurgeable set to 6129 +** false will always have the "discard" flag set to true. 6130 +** ^Hence, a cache created with bPurgeable false will 5953 6131 ** never contain any unpinned pages. 5954 6132 ** 5955 6133 ** ^(The xCachesize() method may be called at any time by SQLite to set the 5956 6134 ** suggested maximum cache-size (number of pages stored by) the cache 5957 6135 ** instance passed as the first argument. This is the value configured using 5958 -** the SQLite "[PRAGMA cache_size]" command.)^ ^As with the bPurgeable 6136 +** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable 5959 6137 ** parameter, the implementation is not required to do anything with this 5960 6138 ** value; it is advisory only. 5961 6139 ** 5962 -** ^The xPagecount() method should return the number of pages currently 5963 -** stored in the cache. 6140 +** The xPagecount() method must return the number of pages currently 6141 +** stored in the cache, both pinned and unpinned. 5964 6142 ** 5965 -** ^The xFetch() method is used to fetch a page and return a pointer to it. 5966 -** ^A 'page', in this context, is a buffer of szPage bytes aligned at an 5967 -** 8-byte boundary. ^The page to be fetched is determined by the key. ^The 5968 -** mimimum key value is 1. After it has been retrieved using xFetch, the page 6143 +** The xFetch() method locates a page in the cache and returns a pointer to 6144 +** the page, or a NULL pointer. 6145 +** A "page", in this context, means a buffer of szPage bytes aligned at an 6146 +** 8-byte boundary. The page to be fetched is determined by the key. ^The 6147 +** mimimum key value is 1. After it has been retrieved using xFetch, the page 5969 6148 ** is considered to be "pinned". 5970 6149 ** 5971 -** ^If the requested page is already in the page cache, then the page cache 6150 +** If the requested page is already in the page cache, then the page cache 5972 6151 ** implementation must return a pointer to the page buffer with its content 5973 -** intact. ^(If the requested page is not already in the cache, then the 5974 -** behavior of the cache implementation is determined by the value of the 5975 -** createFlag parameter passed to xFetch, according to the following table: 6152 +** intact. If the requested page is not already in the cache, then the 6153 +** behavior of the cache implementation should use the value of the createFlag 6154 +** parameter to help it determined what action to take: 5976 6155 ** 5977 6156 ** <table border=1 width=85% align=center> 5978 6157 ** <tr><th> createFlag <th> Behaviour when page is not already in cache 5979 6158 ** <tr><td> 0 <td> Do not allocate a new page. Return NULL. 5980 6159 ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so. 5981 6160 ** Otherwise return NULL. 5982 6161 ** <tr><td> 2 <td> Make every effort to allocate a new page. Only return 5983 6162 ** NULL if allocating a new page is effectively impossible. 5984 -** </table>)^ 6163 +** </table> 5985 6164 ** 5986 -** SQLite will normally invoke xFetch() with a createFlag of 0 or 1. If 5987 -** a call to xFetch() with createFlag==1 returns NULL, then SQLite will 6165 +** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite 6166 +** will only use a createFlag of 2 after a prior call with a createFlag of 1 6167 +** failed.)^ In between the to xFetch() calls, SQLite may 5988 6168 ** attempt to unpin one or more cache pages by spilling the content of 5989 -** pinned pages to disk and synching the operating system disk cache. After 5990 -** attempting to unpin pages, the xFetch() method will be invoked again with 5991 -** a createFlag of 2. 6169 +** pinned pages to disk and synching the operating system disk cache. 5992 6170 ** 5993 6171 ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page 5994 -** as its second argument. ^(If the third parameter, discard, is non-zero, 5995 -** then the page should be evicted from the cache. In this case SQLite 5996 -** assumes that the next time the page is retrieved from the cache using 5997 -** the xFetch() method, it will be zeroed.)^ ^If the discard parameter is 5998 -** zero, then the page is considered to be unpinned. ^The cache implementation 6172 +** as its second argument. If the third parameter, discard, is non-zero, 6173 +** then the page must be evicted from the cache. 6174 +** ^If the discard parameter is 6175 +** zero, then the page may be discarded or retained at the discretion of 6176 +** page cache implementation. ^The page cache implementation 5999 6177 ** may choose to evict unpinned pages at any time. 6000 6178 ** 6001 -** ^(The cache is not required to perform any reference counting. A single 6179 +** The cache must not perform any reference counting. A single 6002 6180 ** call to xUnpin() unpins the page regardless of the number of prior calls 6003 -** to xFetch().)^ 6181 +** to xFetch(). 6004 6182 ** 6005 -** ^The xRekey() method is used to change the key value associated with the 6006 -** page passed as the second argument from oldKey to newKey. ^If the cache 6007 -** previously contains an entry associated with newKey, it should be 6183 +** The xRekey() method is used to change the key value associated with the 6184 +** page passed as the second argument. If the cache 6185 +** previously contains an entry associated with newKey, it must be 6008 6186 ** discarded. ^Any prior cache entry associated with newKey is guaranteed not 6009 6187 ** to be pinned. 6010 6188 ** 6011 -** ^When SQLite calls the xTruncate() method, the cache must discard all 6189 +** When SQLite calls the xTruncate() method, the cache must discard all 6012 6190 ** existing cache entries with page numbers (keys) greater than or equal 6013 -** to the value of the iLimit parameter passed to xTruncate(). ^If any 6191 +** to the value of the iLimit parameter passed to xTruncate(). If any 6014 6192 ** of these pages are pinned, they are implicitly unpinned, meaning that 6015 6193 ** they can be safely discarded. 6016 6194 ** 6017 6195 ** ^The xDestroy() method is used to delete a cache allocated by xCreate(). 6018 6196 ** All resources associated with the specified cache should be freed. ^After 6019 6197 ** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] 6020 6198 ** handle invalid, and will not use it with any other sqlite3_pcache_methods ................................................................................ 6182 6360 ** is not a permanent error and does not affect the return value of 6183 6361 ** sqlite3_backup_finish(). 6184 6362 ** 6185 6363 ** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b> 6186 6364 ** 6187 6365 ** ^Each call to sqlite3_backup_step() sets two values inside 6188 6366 ** the [sqlite3_backup] object: the number of pages still to be backed 6189 -** up and the total number of pages in the source databae file. 6367 +** up and the total number of pages in the source database file. 6190 6368 ** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces 6191 6369 ** retrieve these two values, respectively. 6192 6370 ** 6193 6371 ** ^The values returned by these functions are only updated by 6194 6372 ** sqlite3_backup_step(). ^If the source database is modified during a backup 6195 6373 ** operation, then the values are not updated to account for any extra 6196 6374 ** pages that need to be updated or the size of the source database file ................................................................................ 6278 6456 ** the other connections to use as the blocking connection. 6279 6457 ** 6280 6458 ** ^(There may be at most one unlock-notify callback registered by a 6281 6459 ** blocked connection. If sqlite3_unlock_notify() is called when the 6282 6460 ** blocked connection already has a registered unlock-notify callback, 6283 6461 ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is 6284 6462 ** called with a NULL pointer as its second argument, then any existing 6285 -** unlock-notify callback is cancelled. ^The blocked connections 6463 +** unlock-notify callback is canceled. ^The blocked connections 6286 6464 ** unlock-notify callback may also be canceled by closing the blocked 6287 6465 ** connection using [sqlite3_close()]. 6288 6466 ** 6289 6467 ** The unlock-notify callback is not reentrant. If an application invokes 6290 6468 ** any sqlite3_xxx API functions from within an unlock-notify callback, a 6291 6469 ** crash or deadlock may be the result. 6292 6470 ** ................................................................................ 6360 6538 6361 6539 6362 6540 /* 6363 6541 ** CAPI3REF: String Comparison 6364 6542 ** 6365 6543 ** ^The [sqlite3_strnicmp()] API allows applications and extensions to 6366 6544 ** compare the contents of two buffers containing UTF-8 strings in a 6367 -** case-indendent fashion, using the same definition of case independence 6545 +** case-independent fashion, using the same definition of case independence 6368 6546 ** that SQLite uses internally when comparing identifiers. 6369 6547 */ 6370 6548 SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); 6371 6549 6372 6550 /* 6373 6551 ** CAPI3REF: Error Logging Interface 6374 6552 ** ................................................................................ 6484 6662 #endif 6485 6663 6486 6664 #if 0 6487 6665 } /* End of the 'extern "C"' block */ 6488 6666 #endif 6489 6667 #endif 6490 6668 6669 +/* 6670 +** 2010 August 30 6671 +** 6672 +** The author disclaims copyright to this source code. In place of 6673 +** a legal notice, here is a blessing: 6674 +** 6675 +** May you do good and not evil. 6676 +** May you find forgiveness for yourself and forgive others. 6677 +** May you share freely, never taking more than you give. 6678 +** 6679 +************************************************************************* 6680 +*/ 6681 + 6682 +#ifndef _SQLITE3RTREE_H_ 6683 +#define _SQLITE3RTREE_H_ 6684 + 6685 + 6686 +#if 0 6687 +extern "C" { 6688 +#endif 6689 + 6690 +typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; 6691 + 6692 +/* 6693 +** Register a geometry callback named zGeom that can be used as part of an 6694 +** R-Tree geometry query as follows: 6695 +** 6696 +** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...) 6697 +*/ 6698 +SQLITE_API int sqlite3_rtree_geometry_callback( 6699 + sqlite3 *db, 6700 + const char *zGeom, 6701 + int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), 6702 + void *pContext 6703 +); 6704 + 6705 + 6706 +/* 6707 +** A pointer to a structure of the following type is passed as the first 6708 +** argument to callbacks registered using rtree_geometry_callback(). 6709 +*/ 6710 +struct sqlite3_rtree_geometry { 6711 + void *pContext; /* Copy of pContext passed to s_r_g_c() */ 6712 + int nParam; /* Size of array aParam[] */ 6713 + double *aParam; /* Parameters passed to SQL geom function */ 6714 + void *pUser; /* Callback implementation user data */ 6715 + void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ 6716 +}; 6717 + 6718 + 6719 +#if 0 6720 +} /* end of the 'extern "C"' block */ 6721 +#endif 6722 + 6723 +#endif /* ifndef _SQLITE3RTREE_H_ */ 6724 + 6491 6725 6492 6726 /************** End of sqlite3.h *********************************************/ 6493 6727 /************** Continuing where we left off in sqliteInt.h ******************/ 6494 6728 /************** Include hash.h in the middle of sqliteInt.h ******************/ 6495 6729 /************** Begin file hash.h ********************************************/ 6496 6730 /* 6497 6731 ** 2001 September 22 ................................................................................ 7054 7288 typedef struct Column Column; 7055 7289 typedef struct Db Db; 7056 7290 typedef struct Schema Schema; 7057 7291 typedef struct Expr Expr; 7058 7292 typedef struct ExprList ExprList; 7059 7293 typedef struct ExprSpan ExprSpan; 7060 7294 typedef struct FKey FKey; 7295 +typedef struct FuncDestructor FuncDestructor; 7061 7296 typedef struct FuncDef FuncDef; 7062 7297 typedef struct FuncDefHash FuncDefHash; 7063 7298 typedef struct IdList IdList; 7064 7299 typedef struct Index Index; 7065 7300 typedef struct IndexSample IndexSample; 7066 7301 typedef struct KeyClass KeyClass; 7067 7302 typedef struct KeyInfo KeyInfo; ................................................................................ 7160 7395 7161 7396 /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the 7162 7397 ** following values. 7163 7398 ** 7164 7399 ** NOTE: These values must match the corresponding PAGER_ values in 7165 7400 ** pager.h. 7166 7401 */ 7167 -#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */ 7402 +#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ 7168 7403 #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ 7169 -#define BTREE_MEMORY 4 /* In-memory DB. No argument */ 7170 -#define BTREE_READONLY 8 /* Open the database in read-only mode */ 7171 -#define BTREE_READWRITE 16 /* Open for both reading and writing */ 7172 -#define BTREE_CREATE 32 /* Create the database if it does not exist */ 7404 +#define BTREE_MEMORY 4 /* This is an in-memory DB */ 7405 +#define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ 7406 +#define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ 7173 7407 7174 7408 SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); 7175 7409 SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); 7176 7410 SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); 7177 7411 SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); 7178 7412 SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); 7179 7413 SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); ................................................................................ 7201 7435 SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); 7202 7436 SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); 7203 7437 SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); 7204 7438 7205 7439 SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); 7206 7440 7207 7441 /* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR 7208 -** of the following flags: 7442 +** of the flags shown below. 7443 +** 7444 +** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set. 7445 +** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data 7446 +** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With 7447 +** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored 7448 +** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL 7449 +** indices.) 7209 7450 */ 7210 7451 #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ 7211 -#define BTREE_ZERODATA 2 /* Table has keys only - no data */ 7212 -#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */ 7452 +#define BTREE_BLOBKEY 2 /* Table has keys only - no data */ 7213 7453 7214 7454 SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); 7215 7455 SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); 7216 7456 SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); 7217 7457 7218 7458 SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); 7219 7459 SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); ................................................................................ 7826 8066 /* 7827 8067 ** Allowed values for the flags parameter to sqlite3PagerOpen(). 7828 8068 ** 7829 8069 ** NOTE: These values must match the corresponding BTREE_ values in btree.h. 7830 8070 */ 7831 8071 #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ 7832 8072 #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ 8073 +#define PAGER_MEMORY 0x0004 /* In-memory database */ 7833 8074 7834 8075 /* 7835 8076 ** Valid values for the second argument to sqlite3PagerLockingMode(). 7836 8077 */ 7837 8078 #define PAGER_LOCKINGMODE_QUERY -1 7838 8079 #define PAGER_LOCKINGMODE_NORMAL 0 7839 8080 #define PAGER_LOCKINGMODE_EXCLUSIVE 1 ................................................................................ 7866 8107 void(*)(DbPage*) 7867 8108 ); 7868 8109 SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); 7869 8110 SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); 7870 8111 7871 8112 /* Functions used to configure a Pager object. */ 7872 8113 SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); 7873 -SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*, int); 8114 +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); 7874 8115 SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); 7875 8116 SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); 7876 8117 SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int); 7877 8118 SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); 7878 8119 SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); 7879 8120 SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); 7880 8121 SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); ................................................................................ 7893 8134 SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*); 7894 8135 SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); 7895 8136 SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*); 7896 8137 SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); 7897 8138 SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); 7898 8139 7899 8140 /* Functions used to manage pager transactions and savepoints. */ 7900 -SQLITE_PRIVATE int sqlite3PagerPagecount(Pager*, int*); 8141 +SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*); 7901 8142 SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); 7902 8143 SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); 7903 8144 SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*); 7904 8145 SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); 7905 8146 SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); 7906 8147 SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); 7907 8148 SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); ................................................................................ 8460 8701 ** If this is a no-op implementation, implement everything as macros. 8461 8702 */ 8462 8703 #define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) 8463 8704 #define sqlite3_mutex_free(X) 8464 8705 #define sqlite3_mutex_enter(X) 8465 8706 #define sqlite3_mutex_try(X) SQLITE_OK 8466 8707 #define sqlite3_mutex_leave(X) 8467 -#define sqlite3_mutex_held(X) 1 8468 -#define sqlite3_mutex_notheld(X) 1 8708 +#define sqlite3_mutex_held(X) ((void)(X),1) 8709 +#define sqlite3_mutex_notheld(X) ((void)(X),1) 8469 8710 #define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) 8470 8711 #define sqlite3MutexInit() SQLITE_OK 8471 8712 #define sqlite3MutexEnd() 8472 8713 #endif /* defined(SQLITE_MUTEX_OMIT) */ 8473 8714 8474 8715 /************** End of mutex.h ***********************************************/ 8475 8716 /************** Continuing where we left off in sqliteInt.h ******************/ ................................................................................ 8783 9024 void *pUserData; /* User data parameter */ 8784 9025 FuncDef *pNext; /* Next function with same name */ 8785 9026 void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ 8786 9027 void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ 8787 9028 void (*xFinalize)(sqlite3_context*); /* Aggregate finalizer */ 8788 9029 char *zName; /* SQL name of the function. */ 8789 9030 FuncDef *pHash; /* Next with a different name but the same hash */ 9031 + FuncDestructor *pDestructor; /* Reference counted destructor function */ 9032 +}; 9033 + 9034 +/* 9035 +** This structure encapsulates a user-function destructor callback (as 9036 +** configured using create_function_v2()) and a reference counter. When 9037 +** create_function_v2() is called to create a function with a destructor, 9038 +** a single object of this type is allocated. FuncDestructor.nRef is set to 9039 +** the number of FuncDef objects created (either 1 or 3, depending on whether 9040 +** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor 9041 +** member of each of the new FuncDef objects is set to point to the allocated 9042 +** FuncDestructor. 9043 +** 9044 +** Thereafter, when one of the FuncDef objects is deleted, the reference 9045 +** count on this object is decremented. When it reaches 0, the destructor 9046 +** is invoked and the FuncDestructor structure freed. 9047 +*/ 9048 +struct FuncDestructor { 9049 + int nRef; 9050 + void (*xDestroy)(void *); 9051 + void *pUserData; 8790 9052 }; 8791 9053 8792 9054 /* 8793 9055 ** Possible values for FuncDef.flags 8794 9056 */ 8795 9057 #define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ 8796 9058 #define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ ................................................................................ 8823 9085 ** function likeFunc. Argument pArg is cast to a (void *) and made 8824 9086 ** available as the function user-data (sqlite3_user_data()). The 8825 9087 ** FuncDef.flags variable is set to the value passed as the flags 8826 9088 ** parameter. 8827 9089 */ 8828 9090 #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ 8829 9091 {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ 8830 - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0} 9092 + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} 8831 9093 #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ 8832 9094 {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ 8833 - pArg, 0, xFunc, 0, 0, #zName, 0} 9095 + pArg, 0, xFunc, 0, 0, #zName, 0, 0} 8834 9096 #define LIKEFUNC(zName, nArg, arg, flags) \ 8835 - {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0} 9097 + {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} 8836 9098 #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ 8837 9099 {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \ 8838 - SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0} 9100 + SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} 8839 9101 8840 9102 /* 8841 9103 ** All current savepoints are stored in a linked list starting at 8842 9104 ** sqlite3.pSavepoint. The first element in the list is the most recently 8843 9105 ** opened savepoint. Savepoints are added to the list by the vdbe 8844 9106 ** OP_Savepoint instruction. 8845 9107 */ ................................................................................ 9051 9313 struct Table { 9052 9314 char *zName; /* Name of the table or view */ 9053 9315 int iPKey; /* If not negative, use aCol[iPKey] as the primary key */ 9054 9316 int nCol; /* Number of columns in this table */ 9055 9317 Column *aCol; /* Information about each column */ 9056 9318 Index *pIndex; /* List of SQL indexes on this table. */ 9057 9319 int tnum; /* Root BTree node for this table (see note above) */ 9320 + unsigned nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ 9058 9321 Select *pSelect; /* NULL for tables. Points to definition if a view. */ 9059 9322 u16 nRef; /* Number of pointers to this Table */ 9060 9323 u8 tabFlags; /* Mask of TF_* values */ 9061 9324 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ 9062 9325 FKey *pFKey; /* Linked list of all foreign keys in this table */ 9063 9326 char *zColAff; /* String defining the affinity of each column */ 9064 9327 #ifndef SQLITE_OMIT_CHECK ................................................................................ 9181 9444 /* 9182 9445 ** An instance of the following structure is passed as the first 9183 9446 ** argument to sqlite3VdbeKeyCompare and is used to control the 9184 9447 ** comparison of the two index keys. 9185 9448 */ 9186 9449 struct KeyInfo { 9187 9450 sqlite3 *db; /* The database connection */ 9188 - u8 enc; /* Text encoding - one of the TEXT_Utf* values */ 9451 + u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ 9189 9452 u16 nField; /* Number of entries in aColl[] */ 9190 - u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */ 9453 + u8 *aSortOrder; /* Sort order for each column. May be NULL */ 9191 9454 CollSeq *aColl[1]; /* Collating sequence for each term of the key */ 9192 9455 }; 9193 9456 9194 9457 /* 9195 9458 ** An instance of the following structure holds information about a 9196 9459 ** single index record that has already been parsed out into individual 9197 9460 ** values. ................................................................................ 10305 10568 # define sqlite3Tolower(x) tolower((unsigned char)(x)) 10306 10569 #endif 10307 10570 10308 10571 /* 10309 10572 ** Internal function prototypes 10310 10573 */ 10311 10574 SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *); 10312 -SQLITE_PRIVATE int sqlite3IsNumber(const char*, int*, u8); 10313 10575 SQLITE_PRIVATE int sqlite3Strlen30(const char*); 10314 10576 #define sqlite3StrNICmp sqlite3_strnicmp 10315 10577 10316 10578 SQLITE_PRIVATE int sqlite3MallocInit(void); 10317 10579 SQLITE_PRIVATE void sqlite3MallocEnd(void); 10318 10580 SQLITE_PRIVATE void *sqlite3Malloc(int); 10319 10581 SQLITE_PRIVATE void *sqlite3MallocZero(int); ................................................................................ 10329 10591 SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*); 10330 10592 SQLITE_PRIVATE void *sqlite3ScratchMalloc(int); 10331 10593 SQLITE_PRIVATE void sqlite3ScratchFree(void*); 10332 10594 SQLITE_PRIVATE void *sqlite3PageMalloc(int); 10333 10595 SQLITE_PRIVATE void sqlite3PageFree(void*); 10334 10596 SQLITE_PRIVATE void sqlite3MemSetDefault(void); 10335 10597 SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); 10336 -SQLITE_PRIVATE int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64); 10598 +SQLITE_PRIVATE int sqlite3HeapNearlyFull(void); 10337 10599 10338 10600 /* 10339 10601 ** On systems with ample stack space and that support alloca(), make 10340 10602 ** use of alloca() to obtain space for large automatic objects. By default, 10341 10603 ** obtain space from malloc(). 10342 10604 ** 10343 10605 ** The alloca() routine never returns NULL. This will cause code paths ................................................................................ 10500 10762 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int); 10501 10763 SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int); 10502 10764 SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*); 10503 10765 SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int); 10504 10766 SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int); 10505 10767 SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*); 10506 10768 SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); 10507 -SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse*,int,int); 10508 10769 SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int); 10509 10770 SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); 10510 10771 SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); 10511 10772 SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int); 10512 10773 SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse*, Expr*); 10513 10774 SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int); 10514 10775 SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); ................................................................................ 10620 10881 # define sqlite3AuthRead(a,b,c,d) 10621 10882 # define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK 10622 10883 # define sqlite3AuthContextPush(a,b,c) 10623 10884 # define sqlite3AuthContextPop(a) ((void)(a)) 10624 10885 #endif 10625 10886 SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*); 10626 10887 SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*); 10627 -SQLITE_PRIVATE int sqlite3BtreeFactory(sqlite3 *db, const char *zFilename, 10628 - int omitJournal, int nCache, int flags, Btree **ppBtree); 10629 10888 SQLITE_PRIVATE int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); 10630 10889 SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*); 10631 10890 SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*); 10632 10891 SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); 10633 10892 SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*); 10634 10893 SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); 10635 -SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*); 10894 +SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); 10636 10895 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); 10637 -SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *, int); 10638 10896 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); 10639 10897 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); 10640 10898 SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**); 10641 10899 10642 10900 /* 10643 10901 ** Routines to read and write variable-length integers. These used to 10644 10902 ** be defined locally, but now we use the varint routines in the util.c ................................................................................ 10676 10934 10677 10935 10678 10936 SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *); 10679 10937 SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *); 10680 10938 SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); 10681 10939 SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); 10682 10940 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr); 10683 -SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*); 10941 +SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8); 10684 10942 SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...); 10685 10943 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); 10686 10944 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); 10687 10945 SQLITE_PRIVATE const char *sqlite3ErrStr(int); 10688 10946 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); 10689 10947 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); 10690 10948 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); ................................................................................ 10747 11005 SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int); 10748 11006 SQLITE_PRIVATE void sqlite3SchemaFree(void *); 10749 11007 SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *); 10750 11008 SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *); 10751 11009 SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *); 10752 11010 SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, 10753 11011 void (*)(sqlite3_context*,int,sqlite3_value **), 10754 - void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*)); 11012 + void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), 11013 + FuncDestructor *pDestructor 11014 +); 10755 11015 SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); 10756 11016 SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); 10757 11017 10758 11018 SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int); 10759 11019 SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); 10760 11020 SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); 10761 11021 SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*); ................................................................................ 11667 11927 Bool rowidIsValid; /* True if lastRowid is valid */ 11668 11928 Bool atFirst; /* True if pointing to first entry */ 11669 11929 Bool useRandomRowid; /* Generate new record numbers semi-randomly */ 11670 11930 Bool nullRow; /* True if pointing to a row with no data */ 11671 11931 Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ 11672 11932 Bool isTable; /* True if a table requiring integer keys */ 11673 11933 Bool isIndex; /* True if an index containing keys only - no data */ 11934 + Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */ 11674 11935 i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ 11675 11936 Btree *pBt; /* Separate file holding temporary table */ 11676 11937 int pseudoTableReg; /* Register holding pseudotable content. */ 11677 11938 KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ 11678 11939 int nField; /* Number of fields in the header */ 11679 11940 i64 seqCount; /* Sequence counter */ 11680 11941 sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ ................................................................................ 11761 12022 double r; /* Real value */ 11762 12023 sqlite3 *db; /* The associated database connection */ 11763 12024 char *z; /* String or BLOB value */ 11764 12025 int n; /* Number of characters in string value, excluding '\0' */ 11765 12026 u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ 11766 12027 u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */ 11767 12028 u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ 12029 +#ifdef SQLITE_DEBUG 12030 + Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ 12031 + void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */ 12032 +#endif 11768 12033 void (*xDel)(void *); /* If not null, call this function to delete Mem.z */ 11769 12034 char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */ 11770 12035 }; 11771 12036 11772 12037 /* One or more of the following flags are set to indicate the validOK 11773 12038 ** representations of the value stored in the Mem struct. 11774 12039 ** ................................................................................ 11787 12052 #define MEM_Null 0x0001 /* Value is NULL */ 11788 12053 #define MEM_Str 0x0002 /* Value is a string */ 11789 12054 #define MEM_Int 0x0004 /* Value is an integer */ 11790 12055 #define MEM_Real 0x0008 /* Value is a real number */ 11791 12056 #define MEM_Blob 0x0010 /* Value is a BLOB */ 11792 12057 #define MEM_RowSet 0x0020 /* Value is a RowSet object */ 11793 12058 #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ 12059 +#define MEM_Invalid 0x0080 /* Value is undefined */ 11794 12060 #define MEM_TypeMask 0x00ff /* Mask of type bits */ 11795 12061 11796 12062 /* Whenever Mem contains a valid string or blob representation, one of 11797 12063 ** the following flags must be set to determine the memory management 11798 12064 ** policy for Mem.z. The MEM_Term flag tells us whether or not the 11799 12065 ** string is \000 or \u0000 terminated 11800 12066 */ 11801 12067 #define MEM_Term 0x0200 /* String rep is nul terminated */ 11802 12068 #define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */ 11803 12069 #define MEM_Static 0x0800 /* Mem.z points to a static string */ 11804 12070 #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ 11805 12071 #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ 11806 12072 #define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ 11807 - 11808 12073 #ifdef SQLITE_OMIT_INCRBLOB 11809 12074 #undef MEM_Zero 11810 12075 #define MEM_Zero 0x0000 11811 12076 #endif 11812 - 11813 12077 11814 12078 /* 11815 12079 ** Clear any existing type flags from a Mem and replace them with f 11816 12080 */ 11817 12081 #define MemSetTypeFlag(p, f) \ 11818 12082 ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f) 11819 12083 12084 +/* 12085 +** Return true if a memory cell is not marked as invalid. This macro 12086 +** is for use inside assert() statements only. 12087 +*/ 12088 +#ifdef SQLITE_DEBUG 12089 +#define memIsValid(M) ((M)->flags & MEM_Invalid)==0 12090 +#endif 12091 + 11820 12092 11821 12093 /* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains 11822 12094 ** additional information about auxiliary information bound to arguments 11823 12095 ** of the function. This is used to implement the sqlite3_get_auxdata() 11824 12096 ** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data 11825 12097 ** that can be associated with a constant argument to a function. This 11826 12098 ** allows functions such as "regexp" to compile their constant regular ................................................................................ 12000 12272 SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); 12001 12273 SQLITE_PRIVATE const char *sqlite3OpcodeName(int); 12002 12274 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); 12003 12275 SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); 12004 12276 SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); 12005 12277 SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); 12006 12278 SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem); 12279 + 12280 +#ifdef SQLITE_DEBUG 12281 +SQLITE_PRIVATE void sqlite3VdbeMemPrepareToChange(Vdbe*,Mem*); 12282 +#endif 12007 12283 12008 12284 #ifndef SQLITE_OMIT_FOREIGN_KEY 12009 12285 SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int); 12010 12286 #else 12011 12287 # define sqlite3VdbeCheckFk(p,i) 0 12012 12288 #endif 12013 12289 ................................................................................ 12357 12633 cnt++; 12358 12634 }while( nextC ); 12359 12635 end_getDigits: 12360 12636 va_end(ap); 12361 12637 return cnt; 12362 12638 } 12363 12639 12364 -/* 12365 -** Read text from z[] and convert into a floating point number. Return 12366 -** the number of digits converted. 12367 -*/ 12368 -#define getValue sqlite3AtoF 12369 - 12370 12640 /* 12371 12641 ** Parse a timezone extension on the end of a date-time. 12372 12642 ** The extension is of the form: 12373 12643 ** 12374 12644 ** (+/-)HH:MM 12375 12645 ** 12376 12646 ** Or the "zulu" notation: ................................................................................ 12564 12834 ** as there is a year and date. 12565 12835 */ 12566 12836 static int parseDateOrTime( 12567 12837 sqlite3_context *context, 12568 12838 const char *zDate, 12569 12839 DateTime *p 12570 12840 ){ 12571 - int isRealNum; /* Return from sqlite3IsNumber(). Not used */ 12841 + double r; 12572 12842 if( parseYyyyMmDd(zDate,p)==0 ){ 12573 12843 return 0; 12574 12844 }else if( parseHhMmSs(zDate, p)==0 ){ 12575 12845 return 0; 12576 12846 }else if( sqlite3StrICmp(zDate,"now")==0){ 12577 12847 setDateTimeToCurrent(context, p); 12578 12848 return 0; 12579 - }else if( sqlite3IsNumber(zDate, &isRealNum, SQLITE_UTF8) ){ 12580 - double r; 12581 - getValue(zDate, &r); 12849 + }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){ 12582 12850 p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); 12583 12851 p->validJD = 1; 12584 12852 return 0; 12585 12853 } 12586 12854 return 1; 12587 12855 } 12588 12856 ................................................................................ 12795 13063 /* 12796 13064 ** weekday N 12797 13065 ** 12798 13066 ** Move the date to the same time on the next occurrence of 12799 13067 ** weekday N where 0==Sunday, 1==Monday, and so forth. If the 12800 13068 ** date is already on the appropriate weekday, this is a no-op. 12801 13069 */ 12802 - if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0 12803 - && (n=(int)r)==r && n>=0 && r<7 ){ 13070 + if( strncmp(z, "weekday ", 8)==0 13071 + && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8) 13072 + && (n=(int)r)==r && n>=0 && r<7 ){ 12804 13073 sqlite3_int64 Z; 12805 13074 computeYMD_HMS(p); 12806 13075 p->validTZ = 0; 12807 13076 p->validJD = 0; 12808 13077 computeJD(p); 12809 13078 Z = ((p->iJD + 129600000)/86400000) % 7; 12810 13079 if( Z>n ) Z -= 7; ................................................................................ 12851 13120 case '4': 12852 13121 case '5': 12853 13122 case '6': 12854 13123 case '7': 12855 13124 case '8': 12856 13125 case '9': { 12857 13126 double rRounder; 12858 - n = getValue(z, &r); 12859 - assert( n>=1 ); 13127 + for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){} 13128 + if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){ 13129 + rc = 1; 13130 + break; 13131 + } 12860 13132 if( z[n]==':' ){ 12861 13133 /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the 12862 13134 ** specified number of hours, minutes, seconds, and fractional seconds 12863 13135 ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be 12864 13136 ** omitted. 12865 13137 */ 12866 13138 const char *z2 = z; ................................................................................ 13506 13778 return pVfs->xRandomness(pVfs, nByte, zBufOut); 13507 13779 } 13508 13780 SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ 13509 13781 return pVfs->xSleep(pVfs, nMicro); 13510 13782 } 13511 13783 SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ 13512 13784 int rc; 13785 + /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64() 13786 + ** method to get the current date and time if that method is available 13787 + ** (if iVersion is 2 or greater and the function pointer is not NULL) and 13788 + ** will fall back to xCurrentTime() if xCurrentTimeInt64() is 13789 + ** unavailable. 13790 + */ 13513 13791 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ 13514 13792 rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut); 13515 13793 }else{ 13516 13794 double r; 13517 13795 rc = pVfs->xCurrentTime(pVfs, &r); 13518 13796 *pTimeOut = (sqlite3_int64)(r*86400000.0); 13519 13797 } ................................................................................ 13889 14167 ** redirected to xMalloc. Similarly, we know that nByte>0 becauses 13890 14168 ** cases where nByte<=0 will have been intercepted by higher-level 13891 14169 ** routines and redirected to xFree. 13892 14170 */ 13893 14171 static void *sqlite3MemRealloc(void *pPrior, int nByte){ 13894 14172 sqlite3_int64 *p = (sqlite3_int64*)pPrior; 13895 14173 assert( pPrior!=0 && nByte>0 ); 13896 - nByte = ROUND8(nByte); 14174 + assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */ 13897 14175 p--; 13898 14176 p = realloc(p, nByte+8 ); 13899 14177 if( p ){ 13900 14178 p[0] = nByte; 13901 14179 p++; 13902 14180 }else{ 13903 14181 testcase( sqlite3GlobalConfig.xLog!=0 ); ................................................................................ 14295 14573 ** much more likely to break and we are much more liking to find 14296 14574 ** the error. 14297 14575 */ 14298 14576 static void *sqlite3MemRealloc(void *pPrior, int nByte){ 14299 14577 struct MemBlockHdr *pOldHdr; 14300 14578 void *pNew; 14301 14579 assert( mem.disallow==0 ); 14580 + assert( (nByte & 7)==0 ); /* EV: R-46199-30249 */ 14302 14581 pOldHdr = sqlite3MemsysGetHeader(pPrior); 14303 14582 pNew = sqlite3MemMalloc(nByte); 14304 14583 if( pNew ){ 14305 14584 memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize); 14306 14585 if( nByte>pOldHdr->iSize ){ 14307 14586 randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize); 14308 14587 } ................................................................................ 14329 14608 sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); 14330 14609 } 14331 14610 14332 14611 /* 14333 14612 ** Set the "type" of an allocation. 14334 14613 */ 14335 14614 SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){ 14336 - if( p ){ 14615 + if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ 14337 14616 struct MemBlockHdr *pHdr; 14338 14617 pHdr = sqlite3MemsysGetHeader(p); 14339 14618 assert( pHdr->iForeGuard==FOREGUARD ); 14340 14619 pHdr->eType = eType; 14341 14620 } 14342 14621 } 14343 14622 ................................................................................ 14348 14627 ** This routine is designed for use within an assert() statement, to 14349 14628 ** verify the type of an allocation. For example: 14350 14629 ** 14351 14630 ** assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); 14352 14631 */ 14353 14632 SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){ 14354 14633 int rc = 1; 14355 - if( p ){ 14634 + if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ 14356 14635 struct MemBlockHdr *pHdr; 14357 14636 pHdr = sqlite3MemsysGetHeader(p); 14358 14637 assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ 14359 14638 if( (pHdr->eType&eType)==0 ){ 14360 14639 rc = 0; 14361 14640 } 14362 14641 } ................................................................................ 14370 14649 ** This routine is designed for use within an assert() statement, to 14371 14650 ** verify the type of an allocation. For example: 14372 14651 ** 14373 14652 ** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); 14374 14653 */ 14375 14654 SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){ 14376 14655 int rc = 1; 14377 - if( p ){ 14656 + if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ 14378 14657 struct MemBlockHdr *pHdr; 14379 14658 pHdr = sqlite3MemsysGetHeader(p); 14380 14659 assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ 14381 14660 if( (pHdr->eType&eType)!=0 ){ 14382 14661 rc = 0; 14383 14662 } 14384 14663 } ................................................................................ 15564 15843 ** (an allocation larger than 0x40000000) was requested and this 15565 15844 ** routine should return 0 without freeing pPrior. 15566 15845 */ 15567 15846 static void *memsys5Realloc(void *pPrior, int nBytes){ 15568 15847 int nOld; 15569 15848 void *p; 15570 15849 assert( pPrior!=0 ); 15571 - assert( (nBytes&(nBytes-1))==0 ); 15850 + assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */ 15572 15851 assert( nBytes>=0 ); 15573 15852 if( nBytes==0 ){ 15574 15853 return 0; 15575 15854 } 15576 15855 nOld = memsys5Size(pPrior); 15577 15856 if( nBytes<=nOld ){ 15578 15857 return pPrior; ................................................................................ 16622 16901 } 16623 16902 } 16624 16903 #else 16625 16904 /* Use the built-in recursive mutexes if they are available. 16626 16905 */ 16627 16906 pthread_mutex_lock(&p->mutex); 16628 16907 #if SQLITE_MUTEX_NREF 16908 + assert( p->nRef>0 || p->owner==0 ); 16629 16909 p->owner = pthread_self(); 16630 16910 p->nRef++; 16631 16911 #endif 16632 16912 #endif 16633 16913 16634 16914 #ifdef SQLITE_DEBUG 16635 16915 if( p->trace ){ ................................................................................ 16694 16974 ** is undefined if the mutex is not currently entered or 16695 16975 ** is not currently allocated. SQLite will never do either. 16696 16976 */ 16697 16977 static void pthreadMutexLeave(sqlite3_mutex *p){ 16698 16978 assert( pthreadMutexHeld(p) ); 16699 16979 #if SQLITE_MUTEX_NREF 16700 16980 p->nRef--; 16981 + if( p->nRef==0 ) p->owner = 0; 16701 16982 #endif 16702 16983 assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); 16703 16984 16704 16985 #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX 16705 16986 if( p->nRef==0 ){ 16706 16987 pthread_mutex_unlock(&p->mutex); 16707 16988 } ................................................................................ 16958 17239 /* 16959 17240 ** This routine deallocates a previously 16960 17241 ** allocated mutex. SQLite is careful to deallocate every 16961 17242 ** mutex that it allocates. 16962 17243 */ 16963 17244 static void winMutexFree(sqlite3_mutex *p){ 16964 17245 assert( p ); 16965 - assert( p->nRef==0 ); 17246 + assert( p->nRef==0 && p->owner==0 ); 16966 17247 assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); 16967 17248 DeleteCriticalSection(&p->mutex); 16968 17249 sqlite3_free(p); 16969 17250 } 16970 17251 16971 17252 /* 16972 17253 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt ................................................................................ 16982 17263 static void winMutexEnter(sqlite3_mutex *p){ 16983 17264 #ifdef SQLITE_DEBUG 16984 17265 DWORD tid = GetCurrentThreadId(); 16985 17266 assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); 16986 17267 #endif 16987 17268 EnterCriticalSection(&p->mutex); 16988 17269 #ifdef SQLITE_DEBUG 17270 + assert( p->nRef>0 || p->owner==0 ); 16989 17271 p->owner = tid; 16990 17272 p->nRef++; 16991 17273 if( p->trace ){ 16992 17274 printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); 16993 17275 } 16994 17276 #endif 16995 17277 } ................................................................................ 17035 17317 */ 17036 17318 static void winMutexLeave(sqlite3_mutex *p){ 17037 17319 #ifndef NDEBUG 17038 17320 DWORD tid = GetCurrentThreadId(); 17039 17321 assert( p->nRef>0 ); 17040 17322 assert( p->owner==tid ); 17041 17323 p->nRef--; 17324 + if( p->nRef==0 ) p->owner = 0; 17042 17325 assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); 17043 17326 #endif 17044 17327 LeaveCriticalSection(&p->mutex); 17045 17328 #ifdef SQLITE_DEBUG 17046 17329 if( p->trace ){ 17047 17330 printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); 17048 17331 } ................................................................................ 17084 17367 ** May you share freely, never taking more than you give. 17085 17368 ** 17086 17369 ************************************************************************* 17087 17370 ** 17088 17371 ** Memory allocation functions used throughout sqlite. 17089 17372 */ 17090 17373 17374 +/* 17375 +** Attempt to release up to n bytes of non-essential memory currently 17376 +** held by SQLite. An example of non-essential memory is memory used to 17377 +** cache database pages that are not currently in use. 17378 +*/ 17379 +SQLITE_API int sqlite3_release_memory(int n){ 17380 +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT 17381 + return sqlite3PcacheReleaseMemory(n); 17382 +#else 17383 + /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine 17384 + ** is a no-op returning zero if SQLite is not compiled with 17385 + ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */ 17386 + UNUSED_PARAMETER(n); 17387 + return 0; 17388 +#endif 17389 +} 17390 + 17391 +/* 17392 +** An instance of the following object records the location of 17393 +** each unused scratch buffer. 17394 +*/ 17395 +typedef struct ScratchFreeslot { 17396 + struct ScratchFreeslot *pNext; /* Next unused scratch buffer */ 17397 +} ScratchFreeslot; 17398 + 17399 +/* 17400 +** State information local to the memory allocation subsystem. 17401 +*/ 17402 +static SQLITE_WSD struct Mem0Global { 17403 + sqlite3_mutex *mutex; /* Mutex to serialize access */ 17404 + 17405 + /* 17406 + ** The alarm callback and its arguments. The mem0.mutex lock will 17407 + ** be held while the callback is running. Recursive calls into 17408 + ** the memory subsystem are allowed, but no new callbacks will be 17409 + ** issued. 17410 + */ 17411 + sqlite3_int64 alarmThreshold; 17412 + void (*alarmCallback)(void*, sqlite3_int64,int); 17413 + void *alarmArg; 17414 + 17415 + /* 17416 + ** Pointers to the end of sqlite3GlobalConfig.pScratch memory 17417 + ** (so that a range test can be used to determine if an allocation 17418 + ** being freed came from pScratch) and a pointer to the list of 17419 + ** unused scratch allocations. 17420 + */ 17421 + void *pScratchEnd; 17422 + ScratchFreeslot *pScratchFree; 17423 + u32 nScratchFree; 17424 + 17425 + /* 17426 + ** True if heap is nearly "full" where "full" is defined by the 17427 + ** sqlite3_soft_heap_limit() setting. 17428 + */ 17429 + int nearlyFull; 17430 +} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 }; 17431 + 17432 +#define mem0 GLOBAL(struct Mem0Global, mem0) 17433 + 17091 17434 /* 17092 17435 ** This routine runs when the memory allocator sees that the 17093 17436 ** total memory allocation is about to exceed the soft heap 17094 17437 ** limit. 17095 17438 */ 17096 17439 static void softHeapLimitEnforcer( 17097 17440 void *NotUsed, ................................................................................ 17098 17441 sqlite3_int64 NotUsed2, 17099 17442 int allocSize 17100 17443 ){ 17101 17444 UNUSED_PARAMETER2(NotUsed, NotUsed2); 17102 17445 sqlite3_release_memory(allocSize); 17103 17446 } 17104 17447 17448 +/* 17449 +** Change the alarm callback 17450 +*/ 17451 +static int sqlite3MemoryAlarm( 17452 + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), 17453 + void *pArg, 17454 + sqlite3_int64 iThreshold 17455 +){ 17456 + int nUsed; 17457 + sqlite3_mutex_enter(mem0.mutex); 17458 + mem0.alarmCallback = xCallback; 17459 + mem0.alarmArg = pArg; 17460 + mem0.alarmThreshold = iThreshold; 17461 + nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); 17462 + mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed); 17463 + sqlite3_mutex_leave(mem0.mutex); 17464 + return SQLITE_OK; 17465 +} 17466 + 17467 +#ifndef SQLITE_OMIT_DEPRECATED 17468 +/* 17469 +** Deprecated external interface. Internal/core SQLite code 17470 +** should call sqlite3MemoryAlarm. 17471 +*/ 17472 +SQLITE_API int sqlite3_memory_alarm( 17473 + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), 17474 + void *pArg, 17475 + sqlite3_int64 iThreshold 17476 +){ 17477 + return sqlite3MemoryAlarm(xCallback, pArg, iThreshold); 17478 +} 17479 +#endif 17480 + 17105 17481 /* 17106 17482 ** Set the soft heap-size limit for the library. Passing a zero or 17107 17483 ** negative value indicates no limit. 17108 17484 */ 17109 -SQLITE_API void sqlite3_soft_heap_limit(int n){ 17110 - sqlite3_uint64 iLimit; 17111 - int overage; 17112 - if( n<0 ){ 17113 - iLimit = 0; 17114 - }else{ 17115 - iLimit = n; 17116 - } 17485 +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){ 17486 + sqlite3_int64 priorLimit; 17487 + sqlite3_int64 excess; 17117 17488 #ifndef SQLITE_OMIT_AUTOINIT 17118 17489 sqlite3_initialize(); 17119 17490 #endif 17120 - if( iLimit>0 ){ 17121 - sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, iLimit); 17491 + sqlite3_mutex_enter(mem0.mutex); 17492 + priorLimit = mem0.alarmThreshold; 17493 + sqlite3_mutex_leave(mem0.mutex); 17494 + if( n<0 ) return priorLimit; 17495 + if( n>0 ){ 17496 + sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n); 17122 17497 }else{ 17123 17498 sqlite3MemoryAlarm(0, 0, 0); 17124 17499 } 17125 - overage = (int)(sqlite3_memory_used() - (i64)n); 17126 - if( overage>0 ){ 17127 - sqlite3_release_memory(overage); 17128 - } 17129 -} 17130 - 17131 -/* 17132 -** Attempt to release up to n bytes of non-essential memory currently 17133 -** held by SQLite. An example of non-essential memory is memory used to 17134 -** cache database pages that are not currently in use. 17135 -*/ 17136 -SQLITE_API int sqlite3_release_memory(int n){ 17137 -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT 17138 - int nRet = 0; 17139 - nRet += sqlite3PcacheReleaseMemory(n-nRet); 17140 - return nRet; 17141 -#else 17142 - UNUSED_PARAMETER(n); 17143 - return SQLITE_OK; 17144 -#endif 17145 -} 17146 - 17147 -/* 17148 -** State information local to the memory allocation subsystem. 17149 -*/ 17150 -static SQLITE_WSD struct Mem0Global { 17151 - /* Number of free pages for scratch and page-cache memory */ 17152 - u32 nScratchFree; 17153 - u32 nPageFree; 17154 - 17155 - sqlite3_mutex *mutex; /* Mutex to serialize access */ 17156 - 17157 - /* 17158 - ** The alarm callback and its arguments. The mem0.mutex lock will 17159 - ** be held while the callback is running. Recursive calls into 17160 - ** the memory subsystem are allowed, but no new callbacks will be 17161 - ** issued. 17162 - */ 17163 - sqlite3_int64 alarmThreshold; 17164 - void (*alarmCallback)(void*, sqlite3_int64,int); 17165 - void *alarmArg; 17166 - 17167 - /* 17168 - ** Pointers to the end of sqlite3GlobalConfig.pScratch and 17169 - ** sqlite3GlobalConfig.pPage to a block of memory that records 17170 - ** which pages are available. 17171 - */ 17172 - u32 *aScratchFree; 17173 - u32 *aPageFree; 17174 -} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 }; 17175 - 17176 -#define mem0 GLOBAL(struct Mem0Global, mem0) 17500 + excess = sqlite3_memory_used() - n; 17501 + if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff)); 17502 + return priorLimit; 17503 +} 17504 +SQLITE_API void sqlite3_soft_heap_limit(int n){ 17505 + if( n<0 ) n = 0; 17506 + sqlite3_soft_heap_limit64(n); 17507 +} 17177 17508 17178 17509 /* 17179 17510 ** Initialize the memory allocation subsystem. 17180 17511 */ 17181 17512 SQLITE_PRIVATE int sqlite3MallocInit(void){ 17182 17513 if( sqlite3GlobalConfig.m.xMalloc==0 ){ 17183 17514 sqlite3MemSetDefault(); 17184 17515 } 17185 17516 memset(&mem0, 0, sizeof(mem0)); 17186 17517 if( sqlite3GlobalConfig.bCoreMutex ){ 17187 17518 mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); 17188 17519 } 17189 17520 if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100 17190 - && sqlite3GlobalConfig.nScratch>=0 ){ 17191 - int i; 17192 - sqlite3GlobalConfig.szScratch = ROUNDDOWN8(sqlite3GlobalConfig.szScratch-4); 17193 - mem0.aScratchFree = (u32*)&((char*)sqlite3GlobalConfig.pScratch) 17194 - [sqlite3GlobalConfig.szScratch*sqlite3GlobalConfig.nScratch]; 17195 - for(i=0; i<sqlite3GlobalConfig.nScratch; i++){ mem0.aScratchFree[i] = i; } 17196 - mem0.nScratchFree = sqlite3GlobalConfig.nScratch; 17521 + && sqlite3GlobalConfig.nScratch>0 ){ 17522 + int i, n, sz; 17523 + ScratchFreeslot *pSlot; 17524 + sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch); 17525 + sqlite3GlobalConfig.szScratch = sz; 17526 + pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch; 17527 + n = sqlite3GlobalConfig.nScratch; 17528 + mem0.pScratchFree = pSlot; 17529 + mem0.nScratchFree = n; 17530 + for(i=0; i<n-1; i++){ 17531 + pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot); 17532 + pSlot = pSlot->pNext; 17533 + } 17534 + pSlot->pNext = 0; 17535 + mem0.pScratchEnd = (void*)&pSlot[1]; 17197 17536 }else{ 17537 + mem0.pScratchEnd = 0; 17198 17538 sqlite3GlobalConfig.pScratch = 0; 17199 17539 sqlite3GlobalConfig.szScratch = 0; 17540 + sqlite3GlobalConfig.nScratch = 0; 17200 17541 } 17201 - if( sqlite3GlobalConfig.pPage && sqlite3GlobalConfig.szPage>=512 17202 - && sqlite3GlobalConfig.nPage>=1 ){ 17203 - int i; 17204 - int overhead; 17205 - int sz = ROUNDDOWN8(sqlite3GlobalConfig.szPage); 17206 - int n = sqlite3GlobalConfig.nPage; 17207 - overhead = (4*n + sz - 1)/sz; 17208 - sqlite3GlobalConfig.nPage -= overhead; 17209 - mem0.aPageFree = (u32*)&((char*)sqlite3GlobalConfig.pPage) 17210 - [sqlite3GlobalConfig.szPage*sqlite3GlobalConfig.nPage]; 17211 - for(i=0; i<sqlite3GlobalConfig.nPage; i++){ mem0.aPageFree[i] = i; } 17212 - mem0.nPageFree = sqlite3GlobalConfig.nPage; 17213 - }else{ 17542 + if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512 17543 + || sqlite3GlobalConfig.nPage<1 ){ 17214 17544 sqlite3GlobalConfig.pPage = 0; 17215 17545 sqlite3GlobalConfig.szPage = 0; 17546 + sqlite3GlobalConfig.nPage = 0; 17216 17547 } 17217 17548 return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); 17218 17549 } 17550 + 17551 +/* 17552 +** Return true if the heap is currently under memory pressure - in other 17553 +** words if the amount of heap used is close to the limit set by 17554 +** sqlite3_soft_heap_limit(). 17555 +*/ 17556 +SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){ 17557 + return mem0.nearlyFull; 17558 +} 17219 17559 17220 17560 /* 17221 17561 ** Deinitialize the memory allocation subsystem. 17222 17562 */ 17223 17563 SQLITE_PRIVATE void sqlite3MallocEnd(void){ 17224 17564 if( sqlite3GlobalConfig.m.xShutdown ){ 17225 17565 sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData); ................................................................................ 17247 17587 int n, mx; 17248 17588 sqlite3_int64 res; 17249 17589 sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag); 17250 17590 res = (sqlite3_int64)mx; /* Work around bug in Borland C. Ticket #3216 */ 17251 17591 return res; 17252 17592 } 17253 17593 17254 -/* 17255 -** Change the alarm callback 17256 -*/ 17257 -SQLITE_PRIVATE int sqlite3MemoryAlarm( 17258 - void(*xCallback)(void *pArg, sqlite3_int64 used,int N), 17259 - void *pArg, 17260 - sqlite3_int64 iThreshold 17261 -){ 17262 - sqlite3_mutex_enter(mem0.mutex); 17263 - mem0.alarmCallback = xCallback; 17264 - mem0.alarmArg = pArg; 17265 - mem0.alarmThreshold = iThreshold; 17266 - sqlite3_mutex_leave(mem0.mutex); 17267 - return SQLITE_OK; 17268 -} 17269 - 17270 -#ifndef SQLITE_OMIT_DEPRECATED 17271 -/* 17272 -** Deprecated external interface. Internal/core SQLite code 17273 -** should call sqlite3MemoryAlarm. 17274 -*/ 17275 -SQLITE_API int sqlite3_memory_alarm( 17276 - void(*xCallback)(void *pArg, sqlite3_int64 used,int N), 17277 - void *pArg, 17278 - sqlite3_int64 iThreshold 17279 -){ 17280 - return sqlite3MemoryAlarm(xCallback, pArg, iThreshold); 17281 -} 17282 -#endif 17283 - 17284 17594 /* 17285 17595 ** Trigger the alarm 17286 17596 */ 17287 17597 static void sqlite3MallocAlarm(int nByte){ 17288 17598 void (*xCallback)(void*,sqlite3_int64,int); 17289 17599 sqlite3_int64 nowUsed; 17290 17600 void *pArg; ................................................................................ 17309 17619 void *p; 17310 17620 assert( sqlite3_mutex_held(mem0.mutex) ); 17311 17621 nFull = sqlite3GlobalConfig.m.xRoundup(n); 17312 17622 sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n); 17313 17623 if( mem0.alarmCallback!=0 ){ 17314 17624 int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); 17315 17625 if( nUsed+nFull >= mem0.alarmThreshold ){ 17626 + mem0.nearlyFull = 1; 17316 17627 sqlite3MallocAlarm(nFull); 17628 + }else{ 17629 + mem0.nearlyFull = 0; 17317 17630 } 17318 17631 } 17319 17632 p = sqlite3GlobalConfig.m.xMalloc(nFull); 17633 +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT 17320 17634 if( p==0 && mem0.alarmCallback ){ 17321 17635 sqlite3MallocAlarm(nFull); 17322 17636 p = sqlite3GlobalConfig.m.xMalloc(nFull); 17323 17637 } 17638 +#endif 17324 17639 if( p ){ 17325 17640 nFull = sqlite3MallocSize(p); 17326 17641 sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull); 17327 17642 sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1); 17328 17643 } 17329 17644 *pp = p; 17330 17645 return nFull; ................................................................................ 17332 17647 17333 17648 /* 17334 17649 ** Allocate memory. This routine is like sqlite3_malloc() except that it 17335 17650 ** assumes the memory subsystem has already been initialized. 17336 17651 */ 17337 17652 SQLITE_PRIVATE void *sqlite3Malloc(int n){ 17338 17653 void *p; 17339 - if( n<=0 || n>=0x7fffff00 ){ 17654 + if( n<=0 /* IMP: R-65312-04917 */ 17655 + || n>=0x7fffff00 17656 + ){ 17340 17657 /* A memory allocation of a number of bytes which is near the maximum 17341 17658 ** signed integer value might cause an integer overflow inside of the 17342 17659 ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving 17343 17660 ** 255 bytes of overhead. SQLite itself will never use anything near 17344 17661 ** this amount. The only way to reach the limit is with sqlite3_malloc() */ 17345 17662 p = 0; 17346 17663 }else if( sqlite3GlobalConfig.bMemstat ){ 17347 17664 sqlite3_mutex_enter(mem0.mutex); 17348 17665 mallocWithAlarm(n, &p); 17349 17666 sqlite3_mutex_leave(mem0.mutex); 17350 17667 }else{ 17351 17668 p = sqlite3GlobalConfig.m.xMalloc(n); 17352 17669 } 17670 + assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */ 17353 17671 return p; 17354 17672 } 17355 17673 17356 17674 /* 17357 17675 ** This version of the memory allocation is for use by the application. 17358 17676 ** First make sure the memory subsystem is initialized, then do the 17359 17677 ** allocation. ................................................................................ 17383 17701 ** routine is intended to get memory to old large transient data 17384 17702 ** structures that would not normally fit on the stack of an 17385 17703 ** embedded processor. 17386 17704 */ 17387 17705 SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){ 17388 17706 void *p; 17389 17707 assert( n>0 ); 17708 + 17709 + sqlite3_mutex_enter(mem0.mutex); 17710 + if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){ 17711 + p = mem0.pScratchFree; 17712 + mem0.pScratchFree = mem0.pScratchFree->pNext; 17713 + mem0.nScratchFree--; 17714 + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); 17715 + sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); 17716 + sqlite3_mutex_leave(mem0.mutex); 17717 + }else{ 17718 + if( sqlite3GlobalConfig.bMemstat ){ 17719 + sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); 17720 + n = mallocWithAlarm(n, &p); 17721 + if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); 17722 + sqlite3_mutex_leave(mem0.mutex); 17723 + }else{ 17724 + sqlite3_mutex_leave(mem0.mutex); 17725 + p = sqlite3GlobalConfig.m.xMalloc(n); 17726 + } 17727 + sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); 17728 + } 17729 + assert( sqlite3_mutex_notheld(mem0.mutex) ); 17730 + 17390 17731 17391 17732 #if SQLITE_THREADSAFE==0 && !defined(NDEBUG) 17392 - /* Verify that no more than two scratch allocation per thread 17393 - ** is outstanding at one time. (This is only checked in the 17733 + /* Verify that no more than two scratch allocations per thread 17734 + ** are outstanding at one time. (This is only checked in the 17394 17735 ** single-threaded case since checking in the multi-threaded case 17395 17736 ** would be much more complicated.) */ 17396 17737 assert( scratchAllocOut<=1 ); 17397 -#endif 17398 - 17399 - if( sqlite3GlobalConfig.szScratch<n ){ 17400 - goto scratch_overflow; 17401 - }else{ 17402 - sqlite3_mutex_enter(mem0.mutex); 17403 - if( mem0.nScratchFree==0 ){ 17404 - sqlite3_mutex_leave(mem0.mutex); 17405 - goto scratch_overflow; 17406 - }else{ 17407 - int i; 17408 - i = mem0.aScratchFree[--mem0.nScratchFree]; 17409 - i *= sqlite3GlobalConfig.szScratch; 17410 - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); 17411 - sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); 17412 - sqlite3_mutex_leave(mem0.mutex); 17413 - p = (void*)&((char*)sqlite3GlobalConfig.pScratch)[i]; 17414 - assert( (((u8*)p - (u8*)0) & 7)==0 ); 17415 - } 17416 - } 17417 -#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) 17418 - scratchAllocOut = p!=0; 17738 + if( p ) scratchAllocOut++; 17419 17739 #endif 17420 17740 17421 17741 return p; 17422 - 17423 -scratch_overflow: 17424 - if( sqlite3GlobalConfig.bMemstat ){ 17425 - sqlite3_mutex_enter(mem0.mutex); 17426 - sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); 17427 - n = mallocWithAlarm(n, &p); 17428 - if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); 17429 - sqlite3_mutex_leave(mem0.mutex); 17430 - }else{ 17431 - p = sqlite3GlobalConfig.m.xMalloc(n); 17432 - } 17433 - sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); 17434 -#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) 17435 - scratchAllocOut = p!=0; 17436 -#endif 17437 - return p; 17438 17742 } 17439 17743 SQLITE_PRIVATE void sqlite3ScratchFree(void *p){ 17440 17744 if( p ){ 17441 - if( sqlite3GlobalConfig.pScratch==0 17442 - || p<sqlite3GlobalConfig.pScratch 17443 - || p>=(void*)mem0.aScratchFree ){ 17745 + 17746 +#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) 17747 + /* Verify that no more than two scratch allocation per thread 17748 + ** is outstanding at one time. (This is only checked in the 17749 + ** single-threaded case since checking in the multi-threaded case 17750 + ** would be much more complicated.) */ 17751 + assert( scratchAllocOut>=1 && scratchAllocOut<=2 ); 17752 + scratchAllocOut--; 17753 +#endif 17754 + 17755 + if( p>=sqlite3GlobalConfig.pScratch && p<mem0.pScratchEnd ){ 17756 + /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */ 17757 + ScratchFreeslot *pSlot; 17758 + pSlot = (ScratchFreeslot*)p; 17759 + sqlite3_mutex_enter(mem0.mutex); 17760 + pSlot->pNext = mem0.pScratchFree; 17761 + mem0.pScratchFree = pSlot; 17762 + mem0.nScratchFree++; 17763 + assert( mem0.nScratchFree<=sqlite3GlobalConfig.nScratch ); 17764 + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1); 17765 + sqlite3_mutex_leave(mem0.mutex); 17766 + }else{ 17767 + /* Release memory back to the heap */ 17444 17768 assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) ); 17445 17769 assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) ); 17446 17770 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); 17447 17771 if( sqlite3GlobalConfig.bMemstat ){ 17448 17772 int iSize = sqlite3MallocSize(p); 17449 17773 sqlite3_mutex_enter(mem0.mutex); 17450 17774 sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize); ................................................................................ 17451 17775 sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize); 17452 17776 sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1); 17453 17777 sqlite3GlobalConfig.m.xFree(p); 17454 17778 sqlite3_mutex_leave(mem0.mutex); 17455 17779 }else{ 17456 17780 sqlite3GlobalConfig.m.xFree(p); 17457 17781 } 17458 - }else{ 17459 - int i; 17460 - i = (int)((u8*)p - (u8*)sqlite3GlobalConfig.pScratch); 17461 - i /= sqlite3GlobalConfig.szScratch; 17462 - assert( i>=0 && i<sqlite3GlobalConfig.nScratch ); 17463 - sqlite3_mutex_enter(mem0.mutex); 17464 - assert( mem0.nScratchFree<(u32)sqlite3GlobalConfig.nScratch ); 17465 - mem0.aScratchFree[mem0.nScratchFree++] = i; 17466 - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1); 17467 - sqlite3_mutex_leave(mem0.mutex); 17468 - 17469 -#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) 17470 - /* Verify that no more than two scratch allocation per thread 17471 - ** is outstanding at one time. (This is only checked in the 17472 - ** single-threaded case since checking in the multi-threaded case 17473 - ** would be much more complicated.) */ 17474 - assert( scratchAllocOut>=1 && scratchAllocOut<=2 ); 17475 - scratchAllocOut = 0; 17476 -#endif 17477 - 17478 17782 } 17479 17783 } 17480 17784 } 17481 17785 17482 17786 /* 17483 17787 ** TRUE if p is a lookaside memory allocation from db 17484 17788 */ ................................................................................ 17511 17815 } 17512 17816 } 17513 17817 17514 17818 /* 17515 17819 ** Free memory previously obtained from sqlite3Malloc(). 17516 17820 */ 17517 17821 SQLITE_API void sqlite3_free(void *p){ 17518 - if( p==0 ) return; 17822 + if( p==0 ) return; /* IMP: R-49053-54554 */ 17519 17823 assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); 17520 17824 assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); 17521 17825 if( sqlite3GlobalConfig.bMemstat ){ 17522 17826 sqlite3_mutex_enter(mem0.mutex); 17523 17827 sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p)); 17524 17828 sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1); 17525 17829 sqlite3GlobalConfig.m.xFree(p); ................................................................................ 17558 17862 /* 17559 17863 ** Change the size of an existing memory allocation 17560 17864 */ 17561 17865 SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){ 17562 17866 int nOld, nNew; 17563 17867 void *pNew; 17564 17868 if( pOld==0 ){ 17565 - return sqlite3Malloc(nBytes); 17869 + return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */ 17566 17870 } 17567 17871 if( nBytes<=0 ){ 17568 - sqlite3_free(pOld); 17872 + sqlite3_free(pOld); /* IMP: R-31593-10574 */ 17569 17873 return 0; 17570 17874 } 17571 17875 if( nBytes>=0x7fffff00 ){ 17572 17876 /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */ 17573 17877 return 0; 17574 17878 } 17575 17879 nOld = sqlite3MallocSize(pOld); 17880 + /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second 17881 + ** argument to xRealloc is always a value returned by a prior call to 17882 + ** xRoundup. */ 17576 17883 nNew = sqlite3GlobalConfig.m.xRoundup(nBytes); 17577 17884 if( nOld==nNew ){ 17578 17885 pNew = pOld; 17579 17886 }else if( sqlite3GlobalConfig.bMemstat ){ 17580 17887 sqlite3_mutex_enter(mem0.mutex); 17581 17888 sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes); 17582 17889 if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >= ................................................................................ 17594 17901 nNew = sqlite3MallocSize(pNew); 17595 17902 sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld); 17596 17903 } 17597 17904 sqlite3_mutex_leave(mem0.mutex); 17598 17905 }else{ 17599 17906 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); 17600 17907 } 17908 + assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */ 17601 17909 return pNew; 17602 17910 } 17603 17911 17604 17912 /* 17605 17913 ** The public interface to sqlite3Realloc. Make sure that the memory 17606 17914 ** subsystem is initialized prior to invoking sqliteRealloc. 17607 17915 */ ................................................................................ 19757 20065 19758 20066 /* Convenient short-hand */ 19759 20067 #define UpperToLower sqlite3UpperToLower 19760 20068 19761 20069 /* 19762 20070 ** Some systems have stricmp(). Others have strcasecmp(). Because 19763 20071 ** there is no consistency, we will define our own. 20072 +** 20073 +** IMPLEMENTATION-OF: R-20522-24639 The sqlite3_strnicmp() API allows 20074 +** applications and extensions to compare the contents of two buffers 20075 +** containing UTF-8 strings in a case-independent fashion, using the same 20076 +** definition of case independence that SQLite uses internally when 20077 +** comparing identifiers. 19764 20078 */ 19765 20079 SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){ 19766 20080 register unsigned char *a, *b; 19767 20081 a = (unsigned char *)zLeft; 19768 20082 b = (unsigned char *)zRight; 19769 20083 while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } 19770 20084 return UpperToLower[*a] - UpperToLower[*b]; ................................................................................ 19774 20088 a = (unsigned char *)zLeft; 19775 20089 b = (unsigned char *)zRight; 19776 20090 while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } 19777 20091 return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; 19778 20092 } 19779 20093 19780 20094 /* 19781 -** Return TRUE if z is a pure numeric string. Return FALSE and leave 19782 -** *realnum unchanged if the string contains any character which is not 19783 -** part of a number. 20095 +** The string z[] is an text representation of a real number. 20096 +** Convert this string to a double and write it into *pResult. 19784 20097 ** 19785 -** If the string is pure numeric, set *realnum to TRUE if the string 19786 -** contains the '.' character or an "E+000" style exponentiation suffix. 19787 -** Otherwise set *realnum to FALSE. Note that just becaue *realnum is 19788 -** false does not mean that the number can be successfully converted into 19789 -** an integer - it might be too big. 20098 +** The string z[] is length bytes in length (bytes, not characters) and 20099 +** uses the encoding enc. The string is not necessarily zero-terminated. 19790 20100 ** 19791 -** An empty string is considered non-numeric. 20101 +** Return TRUE if the result is a valid real number (or integer) and FALSE 20102 +** if the string is empty or contains extraneous text. Valid numbers 20103 +** are in one of these formats: 20104 +** 20105 +** [+-]digits[E[+-]digits] 20106 +** [+-]digits.[digits][E[+-]digits] 20107 +** [+-].digits[E[+-]digits] 20108 +** 20109 +** Leading and trailing whitespace is ignored for the purpose of determining 20110 +** validity. 20111 +** 20112 +** If some prefix of the input string is a valid number, this routine 20113 +** returns FALSE but it still converts the prefix and writes the result 20114 +** into *pResult. 19792 20115 */ 19793 -SQLITE_PRIVATE int sqlite3IsNumber(const char *z, int *realnum, u8 enc){ 20116 +SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ 20117 +#ifndef SQLITE_OMIT_FLOATING_POINT 19794 20118 int incr = (enc==SQLITE_UTF8?1:2); 19795 - if( enc==SQLITE_UTF16BE ) z++; 19796 - if( *z=='-' || *z=='+' ) z += incr; 19797 - if( !sqlite3Isdigit(*z) ){ 19798 - return 0; 19799 - } 19800 - z += incr; 19801 - *realnum = 0; 19802 - while( sqlite3Isdigit(*z) ){ z += incr; } 19803 -#ifndef SQLITE_OMIT_FLOATING_POINT 19804 - if( *z=='.' ){ 19805 - z += incr; 19806 - if( !sqlite3Isdigit(*z) ) return 0; 19807 - while( sqlite3Isdigit(*z) ){ z += incr; } 19808 - *realnum = 1; 19809 - } 19810 - if( *z=='e' || *z=='E' ){ 19811 - z += incr; 19812 - if( *z=='+' || *z=='-' ) z += incr; 19813 - if( !sqlite3Isdigit(*z) ) return 0; 19814 - while( sqlite3Isdigit(*z) ){ z += incr; } 19815 - *realnum = 1; 19816 - } 19817 -#endif 19818 - return *z==0; 19819 -} 19820 - 19821 -/* 19822 -** The string z[] is an ASCII representation of a real number. 19823 -** Convert this string to a double. 19824 -** 19825 -** This routine assumes that z[] really is a valid number. If it 19826 -** is not, the result is undefined. 19827 -** 19828 -** This routine is used instead of the library atof() function because 19829 -** the library atof() might want to use "," as the decimal point instead 19830 -** of "." depending on how locale is set. But that would cause problems 19831 -** for SQL. So this routine always uses "." regardless of locale. 19832 -*/ 19833 -SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult){ 19834 -#ifndef SQLITE_OMIT_FLOATING_POINT 19835 - const char *zBegin = z; 20119 + const char *zEnd = z + length; 19836 20120 /* sign * significand * (10 ^ (esign * exponent)) */ 19837 - int sign = 1; /* sign of significand */ 19838 - i64 s = 0; /* significand */ 19839 - int d = 0; /* adjust exponent for shifting decimal point */ 19840 - int esign = 1; /* sign of exponent */ 19841 - int e = 0; /* exponent */ 20121 + int sign = 1; /* sign of significand */ 20122 + i64 s = 0; /* significand */ 20123 + int d = 0; /* adjust exponent for shifting decimal point */ 20124 + int esign = 1; /* sign of exponent */ 20125 + int e = 0; /* exponent */ 20126 + int eValid = 1; /* True exponent is either not used or is well-formed */ 19842 20127 double result; 19843 20128 int nDigits = 0; 19844 20129 20130 + *pResult = 0.0; /* Default return value, in case of an error */ 20131 + 20132 + if( enc==SQLITE_UTF16BE ) z++; 20133 + 19845 20134 /* skip leading spaces */ 19846 - while( sqlite3Isspace(*z) ) z++; 20135 + while( z<zEnd && sqlite3Isspace(*z) ) z+=incr; 20136 + if( z>=zEnd ) return 0; 20137 + 19847 20138 /* get sign of significand */ 19848 20139 if( *z=='-' ){ 19849 20140 sign = -1; 19850 - z++; 20141 + z+=incr; 19851 20142 }else if( *z=='+' ){ 19852 - z++; 20143 + z+=incr; 19853 20144 } 20145 + 19854 20146 /* skip leading zeroes */ 19855 - while( z[0]=='0' ) z++, nDigits++; 20147 + while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++; 19856 20148 19857 20149 /* copy max significant digits to significand */ 19858 - while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){ 20150 + while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){ 19859 20151 s = s*10 + (*z - '0'); 19860 - z++, nDigits++; 20152 + z+=incr, nDigits++; 19861 20153 } 20154 + 19862 20155 /* skip non-significant significand digits 19863 20156 ** (increase exponent by d to shift decimal left) */ 19864 - while( sqlite3Isdigit(*z) ) z++, nDigits++, d++; 20157 + while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++; 20158 + if( z>=zEnd ) goto do_atof_calc; 19865 20159 19866 20160 /* if decimal point is present */ 19867 20161 if( *z=='.' ){ 19868 - z++; 20162 + z+=incr; 19869 20163 /* copy digits from after decimal to significand 19870 20164 ** (decrease exponent by d to shift decimal right) */ 19871 - while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){ 20165 + while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){ 19872 20166 s = s*10 + (*z - '0'); 19873 - z++, nDigits++, d--; 20167 + z+=incr, nDigits++, d--; 19874 20168 } 19875 20169 /* skip non-significant digits */ 19876 - while( sqlite3Isdigit(*z) ) z++, nDigits++; 20170 + while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++; 19877 20171 } 20172 + if( z>=zEnd ) goto do_atof_calc; 19878 20173 19879 20174 /* if exponent is present */ 19880 20175 if( *z=='e' || *z=='E' ){ 19881 - z++; 20176 + z+=incr; 20177 + eValid = 0; 20178 + if( z>=zEnd ) goto do_atof_calc; 19882 20179 /* get sign of exponent */ 19883 20180 if( *z=='-' ){ 19884 20181 esign = -1; 19885 - z++; 20182 + z+=incr; 19886 20183 }else if( *z=='+' ){ 19887 - z++; 20184 + z+=incr; 19888 20185 } 19889 20186 /* copy digits to exponent */ 19890 - while( sqlite3Isdigit(*z) ){ 20187 + while( z<zEnd && sqlite3Isdigit(*z) ){ 19891 20188 e = e*10 + (*z - '0'); 19892 - z++; 20189 + z+=incr; 20190 + eValid = 1; 19893 20191 } 19894 20192 } 19895 20193 20194 + /* skip trailing spaces */ 20195 + if( nDigits && eValid ){ 20196 + while( z<zEnd && sqlite3Isspace(*z) ) z+=incr; 20197 + } 20198 + 20199 +do_atof_calc: 19896 20200 /* adjust exponent by d, and update sign */ 19897 20201 e = (e*esign) + d; 19898 20202 if( e<0 ) { 19899 20203 esign = -1; 19900 20204 e *= -1; 19901 20205 } else { 19902 20206 esign = 1; ................................................................................ 19947 20251 result = (double)s; 19948 20252 } 19949 20253 } 19950 20254 19951 20255 /* store the result */ 19952 20256 *pResult = result; 19953 20257 19954 - /* return number of characters used */ 19955 - return (int)(z - zBegin); 20258 + /* return true if number and no extra non-whitespace chracters after */ 20259 + return z>=zEnd && nDigits>0 && eValid; 19956 20260 #else 19957 - return sqlite3Atoi64(z, pResult); 20261 + return !sqlite3Atoi64(z, pResult, length, enc); 19958 20262 #endif /* SQLITE_OMIT_FLOATING_POINT */ 19959 20263 } 19960 20264 19961 20265 /* 19962 20266 ** Compare the 19-character string zNum against the text representation 19963 20267 ** value 2^63: 9223372036854775808. Return negative, zero, or positive 19964 20268 ** if zNum is less than, equal to, or greater than the string. 20269 +** Note that zNum must contain exactly 19 characters. 19965 20270 ** 19966 20271 ** Unlike memcmp() this routine is guaranteed to return the difference 19967 20272 ** in the values of the last digit if the only difference is in the 19968 20273 ** last digit. So, for example, 19969 20274 ** 19970 -** compare2pow63("9223372036854775800") 20275 +** compare2pow63("9223372036854775800", 1) 19971 20276 ** 19972 20277 ** will return -8. 19973 20278 */ 19974 -static int compare2pow63(const char *zNum){ 19975 - int c; 19976 - c = memcmp(zNum,"922337203685477580",18)*10; 20279 +static int compare2pow63(const char *zNum, int incr){ 20280 + int c = 0; 20281 + int i; 20282 + /* 012345678901234567 */ 20283 + const char *pow63 = "922337203685477580"; 20284 + for(i=0; c==0 && i<18; i++){ 20285 + c = (zNum[i*incr]-pow63[i])*10; 20286 + } 19977 20287 if( c==0 ){ 19978 - c = zNum[18] - '8'; 20288 + c = zNum[18*incr] - '8'; 19979 20289 testcase( c==(-1) ); 19980 20290 testcase( c==0 ); 19981 20291 testcase( c==(+1) ); 19982 20292 } 19983 20293 return c; 19984 20294 } 19985 20295 19986 20296 19987 20297 /* 19988 -** Return TRUE if zNum is a 64-bit signed integer and write 19989 -** the value of the integer into *pNum. If zNum is not an integer 19990 -** or is an integer that is too large to be expressed with 64 bits, 19991 -** then return false. 20298 +** Convert zNum to a 64-bit signed integer and write 20299 +** the value of the integer into *pNum. 20300 +** If zNum is exactly 9223372036854665808, return 2. 20301 +** This is a special case as the context will determine 20302 +** if it is too big (used as a negative). 20303 +** If zNum is not an integer or is an integer that 20304 +** is too large to be expressed with 64 bits, 20305 +** then return 1. Otherwise return 0. 19992 20306 ** 19993 -** When this routine was originally written it dealt with only 19994 -** 32-bit numbers. At that time, it was much faster than the 19995 -** atoi() library routine in RedHat 7.2. 20307 +** length is the number of bytes in the string (bytes, not characters). 20308 +** The string is not necessarily zero-terminated. The encoding is 20309 +** given by enc. 19996 20310 */ 19997 -SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum){ 20311 +SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){ 20312 + int incr = (enc==SQLITE_UTF8?1:2); 19998 20313 i64 v = 0; 19999 - int neg; 20000 - int i, c; 20314 + int neg = 0; /* assume positive */ 20315 + int i; 20316 + int c = 0; 20001 20317 const char *zStart; 20002 - while( sqlite3Isspace(*zNum) ) zNum++; 20318 + const char *zEnd = zNum + length; 20319 + if( enc==SQLITE_UTF16BE ) zNum++; 20320 + while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr; 20321 + if( zNum>=zEnd ) goto do_atoi_calc; 20003 20322 if( *zNum=='-' ){ 20004 20323 neg = 1; 20005 - zNum++; 20324 + zNum+=incr; 20006 20325 }else if( *zNum=='+' ){ 20007 - neg = 0; 20008 - zNum++; 20009 - }else{ 20010 - neg = 0; 20326 + zNum+=incr; 20011 20327 } 20328 +do_atoi_calc: 20012 20329 zStart = zNum; 20013 - while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */ 20014 - for(i=0; (c=zNum[i])>='0' && c<='9'; i++){ 20330 + while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */ 20331 + for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){ 20015 20332 v = v*10 + c - '0'; 20016 20333 } 20017 20334 *pNum = neg ? -v : v; 20018 20335 testcase( i==18 ); 20019 20336 testcase( i==19 ); 20020 20337 testcase( i==20 ); 20021 - if( c!=0 || (i==0 && zStart==zNum) || i>19 ){ 20338 + if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr ){ 20022 20339 /* zNum is empty or contains non-numeric text or is longer 20023 - ** than 19 digits (thus guaranting that it is too large) */ 20024 - return 0; 20025 - }else if( i<19 ){ 20340 + ** than 19 digits (thus guaranteeing that it is too large) */ 20341 + return 1; 20342 + }else if( i<19*incr ){ 20026 20343 /* Less than 19 digits, so we know that it fits in 64 bits */ 20027 - return 1; 20344 + return 0; 20028 20345 }else{ 20029 20346 /* 19-digit numbers must be no larger than 9223372036854775807 if positive 20030 20347 ** or 9223372036854775808 if negative. Note that 9223372036854665808 20031 - ** is 2^63. */ 20032 - return compare2pow63(zNum)<neg; 20033 - } 20034 -} 20035 - 20036 -/* 20037 -** The string zNum represents an unsigned integer. The zNum string 20038 -** consists of one or more digit characters and is terminated by 20039 -** a zero character. Any stray characters in zNum result in undefined 20040 -** behavior. 20041 -** 20042 -** If the unsigned integer that zNum represents will fit in a 20043 -** 64-bit signed integer, return TRUE. Otherwise return FALSE. 20044 -** 20045 -** If the negFlag parameter is true, that means that zNum really represents 20046 -** a negative number. (The leading "-" is omitted from zNum.) This 20047 -** parameter is needed to determine a boundary case. A string 20048 -** of "9223373036854775808" returns false if negFlag is false or true 20049 -** if negFlag is true. 20050 -** 20051 -** Leading zeros are ignored. 20052 -*/ 20053 -SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *zNum, int negFlag){ 20054 - int i; 20055 - int neg = 0; 20056 - 20057 - assert( zNum[0]>='0' && zNum[0]<='9' ); /* zNum is an unsigned number */ 20058 - 20059 - if( negFlag ) neg = 1-neg; 20060 - while( *zNum=='0' ){ 20061 - zNum++; /* Skip leading zeros. Ticket #2454 */ 20062 - } 20063 - for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); } 20064 - testcase( i==18 ); 20065 - testcase( i==19 ); 20066 - testcase( i==20 ); 20067 - if( i<19 ){ 20068 - /* Guaranteed to fit if less than 19 digits */ 20069 - return 1; 20070 - }else if( i>19 ){ 20071 - /* Guaranteed to be too big if greater than 19 digits */ 20072 - return 0; 20073 - }else{ 20074 - /* Compare against 2^63. */ 20075 - return compare2pow63(zNum)<neg; 20348 + ** is 2^63. Return 1 if to large */ 20349 + c=compare2pow63(zNum, incr); 20350 + if( c==0 && neg==0 ) return 2; /* too big, exactly 9223372036854665808 */ 20351 + return c<neg ? 0 : 1; 20076 20352 } 20077 20353 } 20078 20354 20079 20355 /* 20080 20356 ** If zNum represents an integer that will fit in 32-bits, then set 20081 20357 ** *pValue to that integer and return true. Otherwise return false. 20082 20358 ** ................................................................................ 22607 22883 unsigned char eFileLock; /* The type of lock held on this fd */ 22608 22884 int lastErrno; /* The unix errno from last I/O error */ 22609 22885 void *lockingContext; /* Locking style specific state */ 22610 22886 UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ 22611 22887 int fileFlags; /* Miscellanous flags */ 22612 22888 const char *zPath; /* Name of the file */ 22613 22889 unixShm *pShm; /* Shared memory segment information */ 22890 + int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ 22614 22891 #if SQLITE_ENABLE_LOCKING_STYLE 22615 22892 int openFlags; /* The flags specified at open() */ 22616 22893 #endif 22617 22894 #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) 22618 22895 unsigned fsFlags; /* cached details from statfs() */ 22619 22896 #endif 22620 22897 #if OS_VXWORKS ................................................................................ 25365 25642 while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){ 25366 25643 amt -= wrote; 25367 25644 offset += wrote; 25368 25645 pBuf = &((char*)pBuf)[wrote]; 25369 25646 } 25370 25647 SimulateIOError(( wrote=(-1), amt=1 )); 25371 25648 SimulateDiskfullError(( wrote=0, amt=1 )); 25649 + 25372 25650 if( amt>0 ){ 25373 25651 if( wrote<0 ){ 25374 25652 /* lastErrno set by seekAndWrite */ 25375 25653 return SQLITE_IOERR_WRITE; 25376 25654 }else{ 25377 25655 pFile->lastErrno = 0; /* not a system error */ 25378 25656 return SQLITE_FULL; 25379 25657 } 25380 25658 } 25659 + 25381 25660 return SQLITE_OK; 25382 25661 } 25383 25662 25384 25663 #ifdef SQLITE_TEST 25385 25664 /* 25386 25665 ** Count the number of fullsyncs and normal syncs. This is used to test 25387 25666 ** that syncs and fullsyncs are occurring at the right times. ................................................................................ 25575 25854 return rc; 25576 25855 } 25577 25856 25578 25857 /* 25579 25858 ** Truncate an open file to a specified size 25580 25859 */ 25581 25860 static int unixTruncate(sqlite3_file *id, i64 nByte){ 25861 + unixFile *pFile = (unixFile *)id; 25582 25862 int rc; 25583 - assert( id ); 25863 + assert( pFile ); 25584 25864 SimulateIOError( return SQLITE_IOERR_TRUNCATE ); 25585 - rc = ftruncate(((unixFile*)id)->h, (off_t)nByte); 25865 + 25866 + /* If the user has configured a chunk-size for this file, truncate the 25867 + ** file so that it consists of an integer number of chunks (i.e. the 25868 + ** actual file size after the operation may be larger than the requested 25869 + ** size). 25870 + */ 25871 + if( pFile->szChunk ){ 25872 + nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; 25873 + } 25874 + 25875 + rc = ftruncate(pFile->h, (off_t)nByte); 25586 25876 if( rc ){ 25587 - ((unixFile*)id)->lastErrno = errno; 25877 + pFile->lastErrno = errno; 25588 25878 return SQLITE_IOERR_TRUNCATE; 25589 25879 }else{ 25590 25880 #ifndef NDEBUG 25591 25881 /* If we are doing a normal write to a database file (as opposed to 25592 25882 ** doing a hot-journal rollback or a write to some file other than a 25593 25883 ** normal database file) and we truncate the file to zero length, 25594 25884 ** that effectively updates the change counter. This might happen 25595 25885 ** when restoring a database using the backup API from a zero-length 25596 25886 ** source. 25597 25887 */ 25598 - if( ((unixFile*)id)->inNormalWrite && nByte==0 ){ 25599 - ((unixFile*)id)->transCntrChng = 1; 25888 + if( pFile->inNormalWrite && nByte==0 ){ 25889 + pFile->transCntrChng = 1; 25600 25890 } 25601 25891 #endif 25602 25892 25603 25893 return SQLITE_OK; 25604 25894 } 25605 25895 } 25606 25896 ................................................................................ 25635 25925 /* 25636 25926 ** Handler for proxy-locking file-control verbs. Defined below in the 25637 25927 ** proxying locking division. 25638 25928 */ 25639 25929 static int proxyFileControl(sqlite3_file*,int,void*); 25640 25930 #endif 25641 25931 25932 +/* 25933 +** This function is called to handle the SQLITE_FCNTL_SIZE_HINT 25934 +** file-control operation. 25935 +** 25936 +** If the user has configured a chunk-size for this file, it could be 25937 +** that the file needs to be extended at this point. Otherwise, the 25938 +** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix. 25939 +*/ 25940 +static int fcntlSizeHint(unixFile *pFile, i64 nByte){ 25941 + if( pFile->szChunk ){ 25942 + i64 nSize; /* Required file size */ 25943 + struct stat buf; /* Used to hold return values of fstat() */ 25944 + 25945 + if( fstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT; 25946 + 25947 + nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; 25948 + if( nSize>(i64)buf.st_size ){ 25949 +#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE 25950 + if( posix_fallocate(pFile->h, buf.st_size, nSize-buf.st_size) ){ 25951 + return SQLITE_IOERR_WRITE; 25952 + } 25953 +#else 25954 + /* If the OS does not have posix_fallocate(), fake it. First use 25955 + ** ftruncate() to set the file size, then write a single byte to 25956 + ** the last byte in each block within the extended region. This 25957 + ** is the same technique used by glibc to implement posix_fallocate() 25958 + ** on systems that do not have a real fallocate() system call. 25959 + */ 25960 + int nBlk = buf.st_blksize; /* File-system block size */ 25961 + i64 iWrite; /* Next offset to write to */ 25962 + int nWrite; /* Return value from seekAndWrite() */ 25963 + 25964 + if( ftruncate(pFile->h, nSize) ){ 25965 + pFile->lastErrno = errno; 25966 + return SQLITE_IOERR_TRUNCATE; 25967 + } 25968 + iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; 25969 + do { 25970 + nWrite = seekAndWrite(pFile, iWrite, "", 1); 25971 + iWrite += nBlk; 25972 + } while( nWrite==1 && iWrite<nSize ); 25973 + if( nWrite!=1 ) return SQLITE_IOERR_WRITE; 25974 +#endif 25975 + } 25976 + } 25977 + 25978 + return SQLITE_OK; 25979 +} 25642 25980 25643 25981 /* 25644 25982 ** Information and control of an open file handle. 25645 25983 */ 25646 25984 static int unixFileControl(sqlite3_file *id, int op, void *pArg){ 25647 25985 switch( op ){ 25648 25986 case SQLITE_FCNTL_LOCKSTATE: { 25649 25987 *(int*)pArg = ((unixFile*)id)->eFileLock; 25650 25988 return SQLITE_OK; 25651 25989 } 25652 25990 case SQLITE_LAST_ERRNO: { 25653 25991 *(int*)pArg = ((unixFile*)id)->lastErrno; 25654 25992 return SQLITE_OK; 25993 + } 25994 + case SQLITE_FCNTL_CHUNK_SIZE: { 25995 + ((unixFile*)id)->szChunk = *(int *)pArg; 25996 + return SQLITE_OK; 25655 25997 } 25656 25998 case SQLITE_FCNTL_SIZE_HINT: { 25657 -#if 0 /* No performance advantage seen on Linux */ 25658 - sqlite3_int64 szFile = *(sqlite3_int64*)pArg; 25659 - unixFile *pFile = (unixFile*)id; 25660 - ftruncate(pFile->h, szFile); 25661 -#endif 25662 - return SQLITE_OK; 25999 + return fcntlSizeHint((unixFile *)id, *(i64 *)pArg); 25663 26000 } 25664 26001 #ifndef NDEBUG 25665 26002 /* The pager calls this method to signal that it has done 25666 26003 ** a rollback and that the database is therefore unchanged and 25667 26004 ** it hence it is OK for the transaction change counter to be 25668 26005 ** unchanged. 25669 26006 */ ................................................................................ 26100 26437 if( !apNew ){ 26101 26438 rc = SQLITE_IOERR_NOMEM; 26102 26439 goto shmpage_out; 26103 26440 } 26104 26441 pShmNode->apRegion = apNew; 26105 26442 while(pShmNode->nRegion<=iRegion){ 26106 26443 void *pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE, 26107 - MAP_SHARED, pShmNode->h, iRegion*szRegion 26444 + MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion 26108 26445 ); 26109 26446 if( pMem==MAP_FAILED ){ 26110 26447 rc = SQLITE_IOERR; 26111 26448 goto shmpage_out; 26112 26449 } 26113 26450 pShmNode->apRegion[pShmNode->nRegion] = pMem; 26114 26451 pShmNode->nRegion++; ................................................................................ 26617 26954 26618 26955 assert( pNew->pInode==NULL ); 26619 26956 26620 26957 /* Parameter isDelete is only used on vxworks. Express this explicitly 26621 26958 ** here to prevent compiler warnings about unused parameters. 26622 26959 */ 26623 26960 UNUSED_PARAMETER(isDelete); 26961 + 26962 + /* Usually the path zFilename should not be a relative pathname. The 26963 + ** exception is when opening the proxy "conch" file in builds that 26964 + ** include the special Apple locking styles. 26965 + */ 26966 +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE 26967 + assert( zFilename==0 || zFilename[0]=='/' 26968 + || pVfs->pAppData==(void*)&autolockIoFinder ); 26969 +#else 26970 + assert( zFilename==0 || zFilename[0]=='/' ); 26971 +#endif 26624 26972 26625 26973 OSTRACE(("OPEN %-3d %s\n", h, zFilename)); 26626 26974 pNew->h = h; 26627 26975 pNew->dirfd = dirfd; 26628 26976 pNew->fileFlags = 0; 26629 - assert( zFilename==0 || zFilename[0]=='/' ); /* Never a relative pathname */ 26630 26977 pNew->zPath = zFilename; 26631 26978 26632 26979 #if OS_VXWORKS 26633 26980 pNew->pId = vxworksFindFileId(zFilename); 26634 26981 if( pNew->pId==0 ){ 26635 26982 noLock = 1; 26636 26983 rc = SQLITE_NOMEM; ................................................................................ 27923 28270 ** bytes of writable memory. 27924 28271 */ 27925 28272 static int proxyGetHostID(unsigned char *pHostID, int *pError){ 27926 28273 struct timespec timeout = {1, 0}; /* 1 sec timeout */ 27927 28274 27928 28275 assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); 27929 28276 memset(pHostID, 0, PROXY_HOSTIDLEN); 28277 +#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\ 28278 + && __MAC_OS_X_VERSION_MIN_REQUIRED<1050 27930 28279 if( gethostuuid(pHostID, &timeout) ){ 27931 28280 int err = errno; 27932 28281 if( pError ){ 27933 28282 *pError = err; 27934 28283 } 27935 28284 return SQLITE_IOERR; 27936 28285 } 28286 +#endif 27937 28287 #ifdef SQLITE_TEST 27938 28288 /* simulate multiple hosts by creating unique hostid file paths */ 27939 28289 if( sqlite3_hostid_num != 0){ 27940 28290 pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF)); 27941 28291 } 27942 28292 #endif 27943 28293 ................................................................................ 28520 28870 pCtx->pOldMethod = pFile->pMethod; 28521 28871 pFile->pMethod = &proxyIoMethods; 28522 28872 }else{ 28523 28873 if( pCtx->conchFile ){ 28524 28874 pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); 28525 28875 sqlite3_free(pCtx->conchFile); 28526 28876 } 28527 - sqlite3_free(pCtx->lockProxyPath); 28877 + sqlite3DbFree(0, pCtx->lockProxyPath); 28528 28878 sqlite3_free(pCtx->conchFilePath); 28529 28879 sqlite3_free(pCtx); 28530 28880 } 28531 28881 OSTRACE(("TRANSPROXY %d %s\n", pFile->h, 28532 28882 (rc==SQLITE_OK ? "ok" : "failed"))); 28533 28883 return rc; 28534 28884 } ................................................................................ 28711 29061 rc = proxyReleaseConch(pFile); 28712 29062 if( rc ) return rc; 28713 29063 } 28714 29064 rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile); 28715 29065 if( rc ) return rc; 28716 29066 sqlite3_free(conchFile); 28717 29067 } 28718 - sqlite3_free(pCtx->lockProxyPath); 29068 + sqlite3DbFree(0, pCtx->lockProxyPath); 28719 29069 sqlite3_free(pCtx->conchFilePath); 28720 - sqlite3_free(pCtx->dbPath); 29070 + sqlite3DbFree(0, pCtx->dbPath); 28721 29071 /* restore the original locking context and pMethod then close it */ 28722 29072 pFile->lockingContext = pCtx->oldLockingContext; 28723 29073 pFile->pMethod = pCtx->pOldMethod; 28724 29074 sqlite3_free(pCtx); 28725 29075 return pFile->pMethod->xClose(id); 28726 29076 } 28727 29077 return SQLITE_OK; ................................................................................ 29159 29509 HANDLE h; /* Handle for accessing the file */ 29160 29510 unsigned char locktype; /* Type of lock currently held on this file */ 29161 29511 short sharedLockByte; /* Randomly chosen byte used as a shared lock */ 29162 29512 DWORD lastErrno; /* The Windows errno from the last I/O error */ 29163 29513 DWORD sectorSize; /* Sector size of the device file is on */ 29164 29514 winShm *pShm; /* Instance of shared memory on this file */ 29165 29515 const char *zPath; /* Full pathname of this file */ 29516 + int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */ 29166 29517 #if SQLITE_OS_WINCE 29167 29518 WCHAR *zDeleteOnClose; /* Name of file to delete when closing */ 29168 29519 HANDLE hMutex; /* Mutex used to control access to shared lock */ 29169 29520 HANDLE hShared; /* Shared memory segment used for locking */ 29170 29521 winceLock local; /* Locks obtained by this instance of winFile */ 29171 29522 winceLock *shared; /* Global shared lock memory for the file */ 29172 29523 #endif ................................................................................ 29669 30020 *****************************************************************************/ 29670 30021 #endif /* SQLITE_OS_WINCE */ 29671 30022 29672 30023 /***************************************************************************** 29673 30024 ** The next group of routines implement the I/O methods specified 29674 30025 ** by the sqlite3_io_methods object. 29675 30026 ******************************************************************************/ 30027 + 30028 +/* 30029 +** Some microsoft compilers lack this definition. 30030 +*/ 30031 +#ifndef INVALID_SET_FILE_POINTER 30032 +# define INVALID_SET_FILE_POINTER ((DWORD)-1) 30033 +#endif 30034 + 30035 +/* 30036 +** Move the current position of the file handle passed as the first 30037 +** argument to offset iOffset within the file. If successful, return 0. 30038 +** Otherwise, set pFile->lastErrno and return non-zero. 30039 +*/ 30040 +static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){ 30041 + LONG upperBits; /* Most sig. 32 bits of new offset */ 30042 + LONG lowerBits; /* Least sig. 32 bits of new offset */ 30043 + DWORD dwRet; /* Value returned by SetFilePointer() */ 30044 + 30045 + upperBits = (LONG)((iOffset>>32) & 0x7fffffff); 30046 + lowerBits = (LONG)(iOffset & 0xffffffff); 30047 + 30048 + /* API oddity: If successful, SetFilePointer() returns a dword 30049 + ** containing the lower 32-bits of the new file-offset. Or, if it fails, 30050 + ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, 30051 + ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine 30052 + ** whether an error has actually occured, it is also necessary to call 30053 + ** GetLastError(). 30054 + */ 30055 + dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); 30056 + if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){ 30057 + pFile->lastErrno = GetLastError(); 30058 + return 1; 30059 + } 30060 + 30061 + return 0; 30062 +} 29676 30063 29677 30064 /* 29678 30065 ** Close a file. 29679 30066 ** 29680 30067 ** It is reported that an attempt to close a handle might sometimes 29681 30068 ** fail. This is a very unreasonable result, but windows is notorious 29682 30069 ** for being unreasonable so I do not doubt that it might happen. If ................................................................................ 29712 30099 } 29713 30100 #endif 29714 30101 OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed")); 29715 30102 OpenCounter(-1); 29716 30103 return rc ? SQLITE_OK : SQLITE_IOERR; 29717 30104 } 29718 30105 29719 -/* 29720 -** Some microsoft compilers lack this definition. 29721 -*/ 29722 -#ifndef INVALID_SET_FILE_POINTER 29723 -# define INVALID_SET_FILE_POINTER ((DWORD)-1) 29724 -#endif 29725 - 29726 30106 /* 29727 30107 ** Read data from a file into a buffer. Return SQLITE_OK if all 29728 30108 ** bytes were read successfully and SQLITE_IOERR if anything goes 29729 30109 ** wrong. 29730 30110 */ 29731 30111 static int winRead( 29732 30112 sqlite3_file *id, /* File to read from */ 29733 30113 void *pBuf, /* Write content into this buffer */ 29734 30114 int amt, /* Number of bytes to read */ 29735 30115 sqlite3_int64 offset /* Begin reading at this offset */ 29736 30116 ){ 29737 - LONG upperBits = (LONG)((offset>>32) & 0x7fffffff); 29738 - LONG lowerBits = (LONG)(offset & 0xffffffff); 29739 - DWORD rc; 29740 - winFile *pFile = (winFile*)id; 29741 - DWORD error; 29742 - DWORD got; 30117 + winFile *pFile = (winFile*)id; /* file handle */ 30118 + DWORD nRead; /* Number of bytes actually read from file */ 29743 30119 29744 30120 assert( id!=0 ); 29745 30121 SimulateIOError(return SQLITE_IOERR_READ); 29746 30122 OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype)); 29747 - rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); 29748 - if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){ 29749 - pFile->lastErrno = error; 30123 + 30124 + if( seekWinFile(pFile, offset) ){ 29750 30125 return SQLITE_FULL; 29751 30126 } 29752 - if( !ReadFile(pFile->h, pBuf, amt, &got, 0) ){ 30127 + if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ 29753 30128 pFile->lastErrno = GetLastError(); 29754 30129 return SQLITE_IOERR_READ; 29755 30130 } 29756 - if( got==(DWORD)amt ){ 29757 - return SQLITE_OK; 29758 - }else{ 30131 + if( nRead<(DWORD)amt ){ 29759 30132 /* Unread parts of the buffer must be zero-filled */ 29760 - memset(&((char*)pBuf)[got], 0, amt-got); 30133 + memset(&((char*)pBuf)[nRead], 0, amt-nRead); 29761 30134 return SQLITE_IOERR_SHORT_READ; 29762 30135 } 30136 + 30137 + return SQLITE_OK; 29763 30138 } 29764 30139 29765 30140 /* 29766 30141 ** Write data from a buffer into a file. Return SQLITE_OK on success 29767 30142 ** or some other error code on failure. 29768 30143 */ 29769 30144 static int winWrite( 29770 - sqlite3_file *id, /* File to write into */ 29771 - const void *pBuf, /* The bytes to be written */ 29772 - int amt, /* Number of bytes to write */ 29773 - sqlite3_int64 offset /* Offset into the file to begin writing at */ 30145 + sqlite3_file *id, /* File to write into */ 30146 + const void *pBuf, /* The bytes to be written */ 30147 + int amt, /* Number of bytes to write */ 30148 + sqlite3_int64 offset /* Offset into the file to begin writing at */ 29774 30149 ){ 29775 - LONG upperBits = (LONG)((offset>>32) & 0x7fffffff); 29776 - LONG lowerBits = (LONG)(offset & 0xffffffff); 29777 - DWORD rc; 29778 - winFile *pFile = (winFile*)id; 29779 - DWORD error; 29780 - DWORD wrote = 0; 30150 + int rc; /* True if error has occured, else false */ 30151 + winFile *pFile = (winFile*)id; /* File handle */ 29781 30152 29782 - assert( id!=0 ); 30153 + assert( amt>0 ); 30154 + assert( pFile ); 29783 30155 SimulateIOError(return SQLITE_IOERR_WRITE); 29784 30156 SimulateDiskfullError(return SQLITE_FULL); 30157 + 29785 30158 OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype)); 29786 - rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); 29787 - if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){ 29788 - pFile->lastErrno = error; 29789 - if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){ 29790 - return SQLITE_FULL; 29791 - }else{ 29792 - return SQLITE_IOERR_WRITE; 30159 + 30160 + rc = seekWinFile(pFile, offset); 30161 + if( rc==0 ){ 30162 + u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ 30163 + int nRem = amt; /* Number of bytes yet to be written */ 30164 + DWORD nWrite; /* Bytes written by each WriteFile() call */ 30165 + 30166 + while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){ 30167 + aRem += nWrite; 30168 + nRem -= nWrite; 30169 + } 30170 + if( nRem>0 ){ 30171 + pFile->lastErrno = GetLastError(); 30172 + rc = 1; 29793 30173 } 29794 30174 } 29795 - assert( amt>0 ); 29796 - while( 29797 - amt>0 29798 - && (rc = WriteFile(pFile->h, pBuf, amt, &wrote, 0))!=0 29799 - && wrote>0 29800 - ){ 29801 - amt -= wrote; 29802 - pBuf = &((char*)pBuf)[wrote]; 29803 - } 29804 - if( !rc || amt>(int)wrote ){ 29805 - pFile->lastErrno = GetLastError(); 30175 + 30176 + if( rc ){ 29806 30177 if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){ 29807 30178 return SQLITE_FULL; 29808 - }else{ 29809 - return SQLITE_IOERR_WRITE; 29810 30179 } 30180 + return SQLITE_IOERR_WRITE; 29811 30181 } 29812 30182 return SQLITE_OK; 29813 30183 } 29814 30184 29815 30185 /* 29816 30186 ** Truncate an open file to a specified size 29817 30187 */ 29818 30188 static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ 29819 - LONG upperBits = (LONG)((nByte>>32) & 0x7fffffff); 29820 - LONG lowerBits = (LONG)(nByte & 0xffffffff); 29821 - DWORD dwRet; 29822 - winFile *pFile = (winFile*)id; 29823 - DWORD error; 29824 - int rc = SQLITE_OK; 30189 + winFile *pFile = (winFile*)id; /* File handle object */ 30190 + int rc = SQLITE_OK; /* Return code for this function */ 29825 30191 29826 - assert( id!=0 ); 30192 + assert( pFile ); 30193 + 29827 30194 OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte)); 29828 30195 SimulateIOError(return SQLITE_IOERR_TRUNCATE); 29829 - dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); 29830 - if( dwRet==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){ 29831 - pFile->lastErrno = error; 30196 + 30197 + /* If the user has configured a chunk-size for this file, truncate the 30198 + ** file so that it consists of an integer number of chunks (i.e. the 30199 + ** actual file size after the operation may be larger than the requested 30200 + ** size). 30201 + */ 30202 + if( pFile->szChunk ){ 30203 + nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; 30204 + } 30205 + 30206 + /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ 30207 + if( seekWinFile(pFile, nByte) ){ 29832 30208 rc = SQLITE_IOERR_TRUNCATE; 29833 - /* SetEndOfFile will fail if nByte is negative */ 29834 - }else if( !SetEndOfFile(pFile->h) ){ 30209 + }else if( 0==SetEndOfFile(pFile->h) ){ 29835 30210 pFile->lastErrno = GetLastError(); 29836 30211 rc = SQLITE_IOERR_TRUNCATE; 29837 30212 } 29838 - OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc==SQLITE_OK ? "ok" : "failed")); 30213 + 30214 + OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok")); 29839 30215 return rc; 29840 30216 } 29841 30217 29842 30218 #ifdef SQLITE_TEST 29843 30219 /* 29844 30220 ** Count the number of fullsyncs and normal syncs. This is used to test 29845 30221 ** that syncs and fullsyncs are occuring at the right times. ................................................................................ 30195 30571 case SQLITE_FCNTL_LOCKSTATE: { 30196 30572 *(int*)pArg = ((winFile*)id)->locktype; 30197 30573 return SQLITE_OK; 30198 30574 } 30199 30575 case SQLITE_LAST_ERRNO: { 30200 30576 *(int*)pArg = (int)((winFile*)id)->lastErrno; 30201 30577 return SQLITE_OK; 30578 + } 30579 + case SQLITE_FCNTL_CHUNK_SIZE: { 30580 + ((winFile*)id)->szChunk = *(int *)pArg; 30581 + return SQLITE_OK; 30202 30582 } 30203 30583 case SQLITE_FCNTL_SIZE_HINT: { 30204 30584 sqlite3_int64 sz = *(sqlite3_int64*)pArg; 30205 30585 SimulateIOErrorBenign(1); 30206 30586 winTruncate(id, sz); 30207 30587 SimulateIOErrorBenign(0); 30208 30588 return SQLITE_OK; ................................................................................ 30232 30612 static int winDeviceCharacteristics(sqlite3_file *id){ 30233 30613 UNUSED_PARAMETER(id); 30234 30614 return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN; 30235 30615 } 30236 30616 30237 30617 #ifndef SQLITE_OMIT_WAL 30238 30618 30619 +/* 30620 +** Windows will only let you create file view mappings 30621 +** on allocation size granularity boundaries. 30622 +** During sqlite3_os_init() we do a GetSystemInfo() 30623 +** to get the granularity size. 30624 +*/ 30625 +SYSTEM_INFO winSysInfo; 30626 + 30239 30627 /* 30240 30628 ** Helper functions to obtain and relinquish the global mutex. The 30241 30629 ** global mutex is used to protect the winLockInfo objects used by 30242 30630 ** this file, all of which may be shared by multiple threads. 30243 30631 ** 30244 30632 ** Function winShmMutexHeld() is used to assert() that the global mutex 30245 30633 ** is held when required. This function is only used as part of assert() ................................................................................ 30400 30788 ** 30401 30789 ** This is not a VFS shared-memory method; it is a utility function called 30402 30790 ** by VFS shared-memory methods. 30403 30791 */ 30404 30792 static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ 30405 30793 winShmNode **pp; 30406 30794 winShmNode *p; 30795 + BOOL bRc; 30407 30796 assert( winShmMutexHeld() ); 30408 30797 pp = &winShmNodeList; 30409 30798 while( (p = *pp)!=0 ){ 30410 30799 if( p->nRef==0 ){ 30411 30800 int i; 30412 30801 if( p->mutex ) sqlite3_mutex_free(p->mutex); 30413 30802 for(i=0; i<p->nRegion; i++){ 30414 - UnmapViewOfFile(p->aRegion[i].pMap); 30415 - CloseHandle(p->aRegion[i].hMap); 30803 + bRc = UnmapViewOfFile(p->aRegion[i].pMap); 30804 + OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n", 30805 + (int)GetCurrentProcessId(), i, 30806 + bRc ? "ok" : "failed")); 30807 + bRc = CloseHandle(p->aRegion[i].hMap); 30808 + OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n", 30809 + (int)GetCurrentProcessId(), i, 30810 + bRc ? "ok" : "failed")); 30416 30811 } 30417 30812 if( p->hFile.h != INVALID_HANDLE_VALUE ){ 30418 30813 SimulateIOErrorBenign(1); 30419 30814 winClose((sqlite3_file *)&p->hFile); 30420 30815 SimulateIOErrorBenign(0); 30421 30816 } 30422 30817 if( deleteFlag ){ ................................................................................ 30485 30880 winShmNodeList = pShmNode; 30486 30881 30487 30882 pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); 30488 30883 if( pShmNode->mutex==0 ){ 30489 30884 rc = SQLITE_NOMEM; 30490 30885 goto shm_open_err; 30491 30886 } 30887 + 30492 30888 rc = winOpen(pDbFd->pVfs, 30493 30889 pShmNode->zFilename, /* Name of the file (UTF-8) */ 30494 30890 (sqlite3_file*)&pShmNode->hFile, /* File handle here */ 30495 - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */ 30891 + SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */ 30496 30892 0); 30497 30893 if( SQLITE_OK!=rc ){ 30498 30894 rc = SQLITE_CANTOPEN_BKPT; 30499 30895 goto shm_open_err; 30500 30896 } 30501 30897 30502 30898 /* Check to see if another process is holding the dead-man switch. ................................................................................ 30796 31192 while( pShmNode->nRegion<=iRegion ){ 30797 31193 HANDLE hMap; /* file-mapping handle */ 30798 31194 void *pMap = 0; /* Mapped memory region */ 30799 31195 30800 31196 hMap = CreateFileMapping(pShmNode->hFile.h, 30801 31197 NULL, PAGE_READWRITE, 0, nByte, NULL 30802 31198 ); 31199 + OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n", 31200 + (int)GetCurrentProcessId(), pShmNode->nRegion, nByte, 31201 + hMap ? "ok" : "failed")); 30803 31202 if( hMap ){ 31203 + int iOffset = pShmNode->nRegion*szRegion; 31204 + int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; 30804 31205 pMap = MapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, 30805 - 0, 0, nByte 31206 + 0, iOffset - iOffsetShift, szRegion + iOffsetShift 30806 31207 ); 31208 + OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n", 31209 + (int)GetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion, 31210 + pMap ? "ok" : "failed")); 30807 31211 } 30808 31212 if( !pMap ){ 30809 31213 pShmNode->lastErrno = GetLastError(); 30810 31214 rc = SQLITE_IOERR; 30811 31215 if( hMap ) CloseHandle(hMap); 30812 31216 goto shmpage_out; 30813 31217 } ................................................................................ 30816 31220 pShmNode->aRegion[pShmNode->nRegion].hMap = hMap; 30817 31221 pShmNode->nRegion++; 30818 31222 } 30819 31223 } 30820 31224 30821 31225 shmpage_out: 30822 31226 if( pShmNode->nRegion>iRegion ){ 31227 + int iOffset = iRegion*szRegion; 31228 + int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; 30823 31229 char *p = (char *)pShmNode->aRegion[iRegion].pMap; 30824 - *pp = (void *)&p[iRegion*szRegion]; 31230 + *pp = (void *)&p[iOffsetShift]; 30825 31231 }else{ 30826 31232 *pp = 0; 30827 31233 } 30828 31234 sqlite3_mutex_leave(pShmNode->mutex); 30829 31235 return rc; 30830 31236 } 30831 31237 ................................................................................ 31044 31450 DWORD dwShareMode; 31045 31451 DWORD dwCreationDisposition; 31046 31452 DWORD dwFlagsAndAttributes = 0; 31047 31453 #if SQLITE_OS_WINCE 31048 31454 int isTemp = 0; 31049 31455 #endif 31050 31456 winFile *pFile = (winFile*)id; 31051 - void *zConverted; /* Filename in OS encoding */ 31052 - const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ 31053 - char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */ 31457 + void *zConverted; /* Filename in OS encoding */ 31458 + const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ 31459 + 31460 + /* If argument zPath is a NULL pointer, this function is required to open 31461 + ** a temporary file. Use this buffer to store the file name in. 31462 + */ 31463 + char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */ 31464 + 31465 + int rc = SQLITE_OK; /* Function Return Code */ 31466 +#if !defined(NDEBUG) || SQLITE_OS_WINCE 31467 + int eType = flags&0xFFFFFF00; /* Type of file to open */ 31468 +#endif 31469 + 31470 + int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); 31471 + int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); 31472 + int isCreate = (flags & SQLITE_OPEN_CREATE); 31473 +#ifndef NDEBUG 31474 + int isReadonly = (flags & SQLITE_OPEN_READONLY); 31475 +#endif 31476 + int isReadWrite = (flags & SQLITE_OPEN_READWRITE); 31477 + 31478 +#ifndef NDEBUG 31479 + int isOpenJournal = (isCreate && ( 31480 + eType==SQLITE_OPEN_MASTER_JOURNAL 31481 + || eType==SQLITE_OPEN_MAIN_JOURNAL 31482 + || eType==SQLITE_OPEN_WAL 31483 + )); 31484 +#endif 31485 + 31486 + /* Check the following statements are true: 31487 + ** 31488 + ** (a) Exactly one of the READWRITE and READONLY flags must be set, and 31489 + ** (b) if CREATE is set, then READWRITE must also be set, and 31490 + ** (c) if EXCLUSIVE is set, then CREATE must also be set. 31491 + ** (d) if DELETEONCLOSE is set, then CREATE must also be set. 31492 + */ 31493 + assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); 31494 + assert(isCreate==0 || isReadWrite); 31495 + assert(isExclusive==0 || isCreate); 31496 + assert(isDelete==0 || isCreate); 31497 + 31498 + /* The main DB, main journal, WAL file and master journal are never 31499 + ** automatically deleted. Nor are they ever temporary files. */ 31500 + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); 31501 + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); 31502 + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); 31503 + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); 31504 + 31505 + /* Assert that the upper layer has set one of the "file-type" flags. */ 31506 + assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB 31507 + || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 31508 + || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL 31509 + || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL 31510 + ); 31054 31511 31055 31512 assert( id!=0 ); 31056 31513 UNUSED_PARAMETER(pVfs); 31057 31514 31058 31515 pFile->h = INVALID_HANDLE_VALUE; 31059 31516 31060 31517 /* If the second argument to this function is NULL, generate a 31061 31518 ** temporary file name to use 31062 31519 */ 31063 31520 if( !zUtf8Name ){ 31064 - int rc = getTempname(MAX_PATH+1, zTmpname); 31521 + assert(isDelete && !isOpenJournal); 31522 + rc = getTempname(MAX_PATH+1, zTmpname); 31065 31523 if( rc!=SQLITE_OK ){ 31066 31524 return rc; 31067 31525 } 31068 31526 zUtf8Name = zTmpname; 31069 31527 } 31070 31528 31071 31529 /* Convert the filename to the system encoding. */ 31072 31530 zConverted = convertUtf8Filename(zUtf8Name); 31073 31531 if( zConverted==0 ){ 31074 31532 return SQLITE_NOMEM; 31075 31533 } 31076 31534 31077 - if( flags & SQLITE_OPEN_READWRITE ){ 31535 + if( isReadWrite ){ 31078 31536 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; 31079 31537 }else{ 31080 31538 dwDesiredAccess = GENERIC_READ; 31081 31539 } 31540 + 31082 31541 /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is 31083 31542 ** created. SQLite doesn't use it to indicate "exclusive access" 31084 31543 ** as it is usually understood. 31085 31544 */ 31086 - assert(!(flags & SQLITE_OPEN_EXCLUSIVE) || (flags & SQLITE_OPEN_CREATE)); 31087 - if( flags & SQLITE_OPEN_EXCLUSIVE ){ 31545 + if( isExclusive ){ 31088 31546 /* Creates a new file, only if it does not already exist. */ 31089 31547 /* If the file exists, it fails. */ 31090 31548 dwCreationDisposition = CREATE_NEW; 31091 - }else if( flags & SQLITE_OPEN_CREATE ){ 31549 + }else if( isCreate ){ 31092 31550 /* Open existing file, or create if it doesn't exist */ 31093 31551 dwCreationDisposition = OPEN_ALWAYS; 31094 31552 }else{ 31095 31553 /* Opens a file, only if it exists. */ 31096 31554 dwCreationDisposition = OPEN_EXISTING; 31097 31555 } 31556 + 31098 31557 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; 31099 - if( flags & SQLITE_OPEN_DELETEONCLOSE ){ 31558 + 31559 + if( isDelete ){ 31100 31560 #if SQLITE_OS_WINCE 31101 31561 dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; 31102 31562 isTemp = 1; 31103 31563 #else 31104 31564 dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY 31105 31565 | FILE_ATTRIBUTE_HIDDEN 31106 31566 | FILE_FLAG_DELETE_ON_CLOSE; ................................................................................ 31109 31569 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; 31110 31570 } 31111 31571 /* Reports from the internet are that performance is always 31112 31572 ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ 31113 31573 #if SQLITE_OS_WINCE 31114 31574 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; 31115 31575 #endif 31576 + 31116 31577 if( isNT() ){ 31117 31578 h = CreateFileW((WCHAR*)zConverted, 31118 31579 dwDesiredAccess, 31119 31580 dwShareMode, 31120 31581 NULL, 31121 31582 dwCreationDisposition, 31122 31583 dwFlagsAndAttributes, ................................................................................ 31134 31595 NULL, 31135 31596 dwCreationDisposition, 31136 31597 dwFlagsAndAttributes, 31137 31598 NULL 31138 31599 ); 31139 31600 #endif 31140 31601 } 31602 + 31141 31603 OSTRACE(("OPEN %d %s 0x%lx %s\n", 31142 31604 h, zName, dwDesiredAccess, 31143 31605 h==INVALID_HANDLE_VALUE ? "failed" : "ok")); 31606 + 31144 31607 if( h==INVALID_HANDLE_VALUE ){ 31145 31608 pFile->lastErrno = GetLastError(); 31146 31609 free(zConverted); 31147 - if( flags & SQLITE_OPEN_READWRITE ){ 31610 + if( isReadWrite ){ 31148 31611 return winOpen(pVfs, zName, id, 31149 - ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); 31612 + ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags); 31150 31613 }else{ 31151 31614 return SQLITE_CANTOPEN_BKPT; 31152 31615 } 31153 31616 } 31617 + 31154 31618 if( pOutFlags ){ 31155 - if( flags & SQLITE_OPEN_READWRITE ){ 31619 + if( isReadWrite ){ 31156 31620 *pOutFlags = SQLITE_OPEN_READWRITE; 31157 31621 }else{ 31158 31622 *pOutFlags = SQLITE_OPEN_READONLY; 31159 31623 } 31160 31624 } 31625 + 31161 31626 memset(pFile, 0, sizeof(*pFile)); 31162 31627 pFile->pMethod = &winIoMethod; 31163 31628 pFile->h = h; 31164 31629 pFile->lastErrno = NO_ERROR; 31165 31630 pFile->pVfs = pVfs; 31166 31631 pFile->pShm = 0; 31167 31632 pFile->zPath = zName; 31168 31633 pFile->sectorSize = getSectorSize(pVfs, zUtf8Name); 31634 + 31169 31635 #if SQLITE_OS_WINCE 31170 - if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) == 31171 - (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) 31636 + if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB 31172 31637 && !winceCreateLock(zName, pFile) 31173 31638 ){ 31174 31639 CloseHandle(h); 31175 31640 free(zConverted); 31176 31641 return SQLITE_CANTOPEN_BKPT; 31177 31642 } 31178 31643 if( isTemp ){ 31179 31644 pFile->zDeleteOnClose = zConverted; 31180 31645 }else 31181 31646 #endif 31182 31647 { 31183 31648 free(zConverted); 31184 31649 } 31650 + 31185 31651 OpenCounter(+1); 31186 - return SQLITE_OK; 31652 + return rc; 31187 31653 } 31188 31654 31189 31655 /* 31190 31656 ** Delete the named file. 31191 31657 ** 31192 31658 ** Note that windows does not allow a file to be deleted if some other 31193 31659 ** process has it open. Sometimes a virus scanner or indexing program ................................................................................ 31697 32163 winDlClose, /* xDlClose */ 31698 32164 winRandomness, /* xRandomness */ 31699 32165 winSleep, /* xSleep */ 31700 32166 winCurrentTime, /* xCurrentTime */ 31701 32167 winGetLastError, /* xGetLastError */ 31702 32168 winCurrentTimeInt64, /* xCurrentTimeInt64 */ 31703 32169 }; 32170 + 32171 +#ifndef SQLITE_OMIT_WAL 32172 + /* get memory map allocation granularity */ 32173 + memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); 32174 + GetSystemInfo(&winSysInfo); 32175 + assert(winSysInfo.dwAllocationGranularity > 0); 32176 +#endif 31704 32177 31705 32178 sqlite3_vfs_register(&winVfs, 1); 31706 32179 return SQLITE_OK; 31707 32180 } 31708 32181 SQLITE_API int sqlite3_os_end(void){ 31709 32182 return SQLITE_OK; 31710 32183 } ................................................................................ 31747 32220 ** sometimes grow into tens of thousands or larger. The size of the 31748 32221 ** Bitvec object is the number of pages in the database file at the 31749 32222 ** start of a transaction, and is thus usually less than a few thousand, 31750 32223 ** but can be as large as 2 billion for a really big database. 31751 32224 */ 31752 32225 31753 32226 /* Size of the Bitvec structure in bytes. */ 31754 -#define BITVEC_SZ (sizeof(void*)*128) /* 512 on 32bit. 1024 on 64bit */ 32227 +#define BITVEC_SZ 512 31755 32228 31756 32229 /* Round the union size down to the nearest pointer boundary, since that's how 31757 32230 ** it will be aligned within the Bitvec struct. */ 31758 32231 #define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*)) 31759 32232 31760 32233 /* Type of the array "element" for the bitmap representation. 31761 32234 ** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE. ................................................................................ 32262 32735 /*************************************************** General Interfaces ****** 32263 32736 ** 32264 32737 ** Initialize and shutdown the page cache subsystem. Neither of these 32265 32738 ** functions are threadsafe. 32266 32739 */ 32267 32740 SQLITE_PRIVATE int sqlite3PcacheInitialize(void){ 32268 32741 if( sqlite3GlobalConfig.pcache.xInit==0 ){ 32742 + /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the 32743 + ** built-in default page cache is used instead of the application defined 32744 + ** page cache. */ 32269 32745 sqlite3PCacheSetDefault(); 32270 32746 } 32271 32747 return sqlite3GlobalConfig.pcache.xInit(sqlite3GlobalConfig.pcache.pArg); 32272 32748 } 32273 32749 SQLITE_PRIVATE void sqlite3PcacheShutdown(void){ 32274 32750 if( sqlite3GlobalConfig.pcache.xShutdown ){ 32751 + /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */ 32275 32752 sqlite3GlobalConfig.pcache.xShutdown(sqlite3GlobalConfig.pcache.pArg); 32276 32753 } 32277 32754 } 32278 32755 32279 32756 /* 32280 32757 ** Return the size in bytes of a PCache object. 32281 32758 */ ................................................................................ 32728 33205 */ 32729 33206 32730 33207 32731 33208 typedef struct PCache1 PCache1; 32732 33209 typedef struct PgHdr1 PgHdr1; 32733 33210 typedef struct PgFreeslot PgFreeslot; 32734 33211 32735 -/* Pointers to structures of this type are cast and returned as 32736 -** opaque sqlite3_pcache* handles 33212 +/* Each page cache is an instance of the following object. Every 33213 +** open database file (including each in-memory database and each 33214 +** temporary or transient database) has a single page cache which 33215 +** is an instance of this object. 33216 +** 33217 +** Pointers to structures of this type are cast and returned as 33218 +** opaque sqlite3_pcache* handles. 32737 33219 */ 32738 33220 struct PCache1 { 32739 33221 /* Cache configuration parameters. Page size (szPage) and the purgeable 32740 33222 ** flag (bPurgeable) are set when the cache is created. nMax may be 32741 33223 ** modified at any time by a call to the pcache1CacheSize() method. 32742 33224 ** The global mutex must be held when accessing nMax. 32743 33225 */ ................................................................................ 32789 33271 int nMaxPage; /* Sum of nMaxPage for purgeable caches */ 32790 33272 int nMinPage; /* Sum of nMinPage for purgeable caches */ 32791 33273 int nCurrentPage; /* Number of purgeable pages allocated */ 32792 33274 PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */ 32793 33275 32794 33276 /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */ 32795 33277 int szSlot; /* Size of each free slot */ 33278 + int nSlot; /* The number of pcache slots */ 33279 + int nFreeSlot; /* Number of unused pcache slots */ 33280 + int nReserve; /* Try to keep nFreeSlot above this */ 32796 33281 void *pStart, *pEnd; /* Bounds of pagecache malloc range */ 32797 33282 PgFreeslot *pFree; /* Free page blocks */ 32798 33283 int isInit; /* True if initialized */ 32799 33284 } pcache1_g; 32800 33285 32801 33286 /* 32802 33287 ** All code in this file should access the global structure above via the ................................................................................ 32836 33321 ** enough to contain 'n' buffers of 'sz' bytes each. 32837 33322 */ 32838 33323 SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ 32839 33324 if( pcache1.isInit ){ 32840 33325 PgFreeslot *p; 32841 33326 sz = ROUNDDOWN8(sz); 32842 33327 pcache1.szSlot = sz; 33328 + pcache1.nSlot = pcache1.nFreeSlot = n; 33329 + pcache1.nReserve = n>90 ? 10 : (n/10 + 1); 32843 33330 pcache1.pStart = pBuf; 32844 33331 pcache1.pFree = 0; 32845 33332 while( n-- ){ 32846 33333 p = (PgFreeslot*)pBuf; 32847 33334 p->pNext = pcache1.pFree; 32848 33335 pcache1.pFree = p; 32849 33336 pBuf = (void*)&((char*)pBuf)[sz]; ................................................................................ 32862 33349 void *p; 32863 33350 assert( sqlite3_mutex_held(pcache1.mutex) ); 32864 33351 sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); 32865 33352 if( nByte<=pcache1.szSlot && pcache1.pFree ){ 32866 33353 assert( pcache1.isInit ); 32867 33354 p = (PgHdr1 *)pcache1.pFree; 32868 33355 pcache1.pFree = pcache1.pFree->pNext; 33356 + pcache1.nFreeSlot--; 33357 + assert( pcache1.nFreeSlot>=0 ); 32869 33358 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); 32870 33359 }else{ 32871 33360 32872 33361 /* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the 32873 33362 ** global pcache mutex and unlock the pager-cache object pCache. This is 32874 33363 ** so that if the attempt to allocate a new buffer causes the the 32875 33364 ** configured soft-heap-limit to be breached, it will be possible to ................................................................................ 32895 33384 if( p==0 ) return; 32896 33385 if( p>=pcache1.pStart && p<pcache1.pEnd ){ 32897 33386 PgFreeslot *pSlot; 32898 33387 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1); 32899 33388 pSlot = (PgFreeslot*)p; 32900 33389 pSlot->pNext = pcache1.pFree; 32901 33390 pcache1.pFree = pSlot; 33391 + pcache1.nFreeSlot++; 33392 + assert( pcache1.nFreeSlot<=pcache1.nSlot ); 32902 33393 }else{ 32903 33394 int iSize; 32904 33395 assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); 32905 33396 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); 32906 33397 iSize = sqlite3MallocSize(p); 32907 33398 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize); 32908 33399 sqlite3_free(p); 32909 33400 } 32910 33401 } 32911 33402 33403 +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT 33404 +/* 33405 +** Return the size of a pcache allocation 33406 +*/ 33407 +static int pcache1MemSize(void *p){ 33408 + assert( sqlite3_mutex_held(pcache1.mutex) ); 33409 + if( p>=pcache1.pStart && p<pcache1.pEnd ){ 33410 + return pcache1.szSlot; 33411 + }else{ 33412 + int iSize; 33413 + assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); 33414 + sqlite3MemdebugSetType(p, MEMTYPE_HEAP); 33415 + iSize = sqlite3MallocSize(p); 33416 + sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); 33417 + return iSize; 33418 + } 33419 +} 33420 +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ 33421 + 32912 33422 /* 32913 33423 ** Allocate a new page object initially associated with cache pCache. 32914 33424 */ 32915 33425 static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ 32916 33426 int nByte = sizeof(PgHdr1) + pCache->szPage; 32917 33427 void *pPg = pcache1Alloc(nByte); 32918 33428 PgHdr1 *p; ................................................................................ 32961 33471 */ 32962 33472 SQLITE_PRIVATE void sqlite3PageFree(void *p){ 32963 33473 pcache1EnterMutex(); 32964 33474 pcache1Free(p); 32965 33475 pcache1LeaveMutex(); 32966 33476 } 32967 33477 33478 + 33479 +/* 33480 +** Return true if it desirable to avoid allocating a new page cache 33481 +** entry. 33482 +** 33483 +** If memory was allocated specifically to the page cache using 33484 +** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then 33485 +** it is desirable to avoid allocating a new page cache entry because 33486 +** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient 33487 +** for all page cache needs and we should not need to spill the 33488 +** allocation onto the heap. 33489 +** 33490 +** Or, the heap is used for all page cache memory put the heap is 33491 +** under memory pressure, then again it is desirable to avoid 33492 +** allocating a new page cache entry in order to avoid stressing 33493 +** the heap even further. 33494 +*/ 33495 +static int pcache1UnderMemoryPressure(PCache1 *pCache){ 33496 + assert( sqlite3_mutex_held(pcache1.mutex) ); 33497 + if( pcache1.nSlot && pCache->szPage<=pcache1.szSlot ){ 33498 + return pcache1.nFreeSlot<pcache1.nReserve; 33499 + }else{ 33500 + return sqlite3HeapNearlyFull(); 33501 + } 33502 +} 33503 + 32968 33504 /******************************************************************************/ 32969 33505 /******** General Implementation Functions ************************************/ 32970 33506 32971 33507 /* 32972 33508 ** This function is used to resize the hash table used by the cache passed 32973 33509 ** as the first argument. 32974 33510 ** ................................................................................ 33202 33738 ** 33203 33739 ** 1. Regardless of the value of createFlag, the cache is searched for a 33204 33740 ** copy of the requested page. If one is found, it is returned. 33205 33741 ** 33206 33742 ** 2. If createFlag==0 and the page is not already in the cache, NULL is 33207 33743 ** returned. 33208 33744 ** 33209 -** 3. If createFlag is 1, and the page is not already in the cache, 33210 -** and if either of the following are true, return NULL: 33745 +** 3. If createFlag is 1, and the page is not already in the cache, then 33746 +** return NULL (do not allocate a new page) if any of the following 33747 +** conditions are true: 33211 33748 ** 33212 33749 ** (a) the number of pages pinned by the cache is greater than 33213 33750 ** PCache1.nMax, or 33751 +** 33214 33752 ** (b) the number of pages pinned by the cache is greater than 33215 33753 ** the sum of nMax for all purgeable caches, less the sum of 33216 -** nMin for all other purgeable caches. 33754 +** nMin for all other purgeable caches, or 33217 33755 ** 33218 33756 ** 4. If none of the first three conditions apply and the cache is marked 33219 33757 ** as purgeable, and if one of the following is true: 33220 33758 ** 33221 33759 ** (a) The number of pages allocated for the cache is already 33222 33760 ** PCache1.nMax, or 33223 33761 ** 33224 33762 ** (b) The number of pages allocated for all purgeable caches is 33225 33763 ** already equal to or greater than the sum of nMax for all 33226 33764 ** purgeable caches, 33765 +** 33766 +** (c) The system is under memory pressure and wants to avoid 33767 +** unnecessary pages cache entry allocations 33227 33768 ** 33228 33769 ** then attempt to recycle a page from the LRU list. If it is the right 33229 33770 ** size, return the recycled buffer. Otherwise, free the buffer and 33230 33771 ** proceed to step 5. 33231 33772 ** 33232 33773 ** 5. Otherwise, allocate and return a new page buffer. 33233 33774 */ ................................................................................ 33252 33793 } 33253 33794 33254 33795 /* Step 3 of header comment. */ 33255 33796 nPinned = pCache->nPage - pCache->nRecyclable; 33256 33797 if( createFlag==1 && ( 33257 33798 nPinned>=(pcache1.nMaxPage+pCache->nMin-pcache1.nMinPage) 33258 33799 || nPinned>=(pCache->nMax * 9 / 10) 33800 + || pcache1UnderMemoryPressure(pCache) 33259 33801 )){ 33260 33802 goto fetch_out; 33261 33803 } 33262 33804 33263 33805 if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){ 33264 33806 goto fetch_out; 33265 33807 } 33266 33808 33267 33809 /* Step 4. Try to recycle a page buffer if appropriate. */ 33268 33810 if( pCache->bPurgeable && pcache1.pLruTail && ( 33269 - (pCache->nPage+1>=pCache->nMax) || pcache1.nCurrentPage>=pcache1.nMaxPage 33811 + (pCache->nPage+1>=pCache->nMax) 33812 + || pcache1.nCurrentPage>=pcache1.nMaxPage 33813 + || pcache1UnderMemoryPressure(pCache) 33270 33814 )){ 33271 33815 pPage = pcache1.pLruTail; 33272 33816 pcache1RemoveFromHash(pPage); 33273 33817 pcache1PinPage(pPage); 33274 33818 if( pPage->pCache->szPage!=pCache->szPage ){ 33275 33819 pcache1FreePage(pPage); 33276 33820 pPage = 0; ................................................................................ 33405 33949 /* 33406 33950 ** Implementation of the sqlite3_pcache.xDestroy method. 33407 33951 ** 33408 33952 ** Destroy a cache allocated using pcache1Create(). 33409 33953 */ 33410 33954 static void pcache1Destroy(sqlite3_pcache *p){ 33411 33955 PCache1 *pCache = (PCache1 *)p; 33956 + assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); 33412 33957 pcache1EnterMutex(); 33413 33958 pcache1TruncateUnsafe(pCache, 0); 33414 33959 pcache1.nMaxPage -= pCache->nMax; 33415 33960 pcache1.nMinPage -= pCache->nMin; 33416 33961 pcache1EnforceMaxPage(); 33417 33962 pcache1LeaveMutex(); 33418 33963 sqlite3_free(pCache->apHash); ................................................................................ 33452 33997 ** of bytes of memory released. 33453 33998 */ 33454 33999 SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ 33455 34000 int nFree = 0; 33456 34001 if( pcache1.pStart==0 ){ 33457 34002 PgHdr1 *p; 33458 34003 pcache1EnterMutex(); 33459 - while( (nReq<0 || nFree<nReq) && (p=pcache1.pLruTail) ){ 33460 - nFree += sqlite3MallocSize(PGHDR1_TO_PAGE(p)); 34004 + while( (nReq<0 || nFree<nReq) && ((p=pcache1.pLruTail)!=0) ){ 34005 + nFree += pcache1MemSize(PGHDR1_TO_PAGE(p)); 33461 34006 pcache1PinPage(p); 33462 34007 pcache1RemoveFromHash(p); 33463 34008 pcache1FreePage(p); 33464 34009 } 33465 34010 pcache1LeaveMutex(); 33466 34011 } 33467 34012 return nFree; ................................................................................ 33962 34507 33963 34508 #ifdef SQLITE_OMIT_WAL 33964 34509 # define sqlite3WalOpen(x,y,z) 0 33965 34510 # define sqlite3WalClose(w,x,y,z) 0 33966 34511 # define sqlite3WalBeginReadTransaction(y,z) 0 33967 34512 # define sqlite3WalEndReadTransaction(z) 33968 34513 # define sqlite3WalRead(v,w,x,y,z) 0 33969 -# define sqlite3WalDbsize(y,z) 34514 +# define sqlite3WalDbsize(y) 0 33970 34515 # define sqlite3WalBeginWriteTransaction(y) 0 33971 34516 # define sqlite3WalEndWriteTransaction(x) 0 33972 34517 # define sqlite3WalUndo(x,y,z) 0 33973 34518 # define sqlite3WalSavepoint(y,z) 33974 34519 # define sqlite3WalSavepointUndo(y,z) 0 33975 34520 # define sqlite3WalFrames(u,v,w,x,y,z) 0 33976 34521 # define sqlite3WalCheckpoint(u,v,w,x) 0 ................................................................................ 33998 34543 */ 33999 34544 SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *); 34000 34545 SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal); 34001 34546 34002 34547 /* Read a page from the write-ahead log, if it is present. */ 34003 34548 SQLITE_PRIVATE int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut); 34004 34549 34005 -/* Return the size of the database as it existed at the beginning 34006 -** of the snapshot */ 34007 -SQLITE_PRIVATE void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno); 34550 +/* If the WAL is not empty, return the size of the database. */ 34551 +SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal); 34008 34552 34009 34553 /* Obtain or release the WRITER lock. */ 34010 34554 SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal); 34011 34555 SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal); 34012 34556 34013 34557 /* Undo any frames written (but not committed) to the log */ 34014 34558 SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx); ................................................................................ 34046 34590 34047 34591 #endif /* ifndef SQLITE_OMIT_WAL */ 34048 34592 #endif /* _WAL_H_ */ 34049 34593 34050 34594 /************** End of wal.h *************************************************/ 34051 34595 /************** Continuing where we left off in pager.c **********************/ 34052 34596 34053 -/* 34054 -******************** NOTES ON THE DESIGN OF THE PAGER ************************ 34597 + 34598 +/******************* NOTES ON THE DESIGN OF THE PAGER ************************ 34599 +** 34600 +** This comment block describes invariants that hold when using a rollback 34601 +** journal. These invariants do not apply for journal_mode=WAL, 34602 +** journal_mode=MEMORY, or journal_mode=OFF. 34055 34603 ** 34056 34604 ** Within this comment block, a page is deemed to have been synced 34057 34605 ** automatically as soon as it is written when PRAGMA synchronous=OFF. 34058 34606 ** Otherwise, the page is not synced until the xSync method of the VFS 34059 34607 ** is called successfully on the file containing the page. 34060 34608 ** 34061 34609 ** Definition: A page of the database file is said to be "overwriteable" if ................................................................................ 34081 34629 ** 34082 34630 ** (2) The content of a page written into the rollback journal exactly matches 34083 34631 ** both the content in the database when the rollback journal was written 34084 34632 ** and the content in the database at the beginning of the current 34085 34633 ** transaction. 34086 34634 ** 34087 34635 ** (3) Writes to the database file are an integer multiple of the page size 34088 -** in length and are aligned to a page boundary. 34636 +** in length and are aligned on a page boundary. 34089 34637 ** 34090 34638 ** (4) Reads from the database file are either aligned on a page boundary and 34091 34639 ** an integer multiple of the page size in length or are taken from the 34092 34640 ** first 100 bytes of the database file. 34093 34641 ** 34094 34642 ** (5) All writes to the database file are synced prior to the rollback journal 34095 34643 ** being deleted, truncated, or zeroed. ................................................................................ 34112 34660 ** is called to restore the database file to the same size it was at 34113 34661 ** the beginning of the transaction. (In some VFSes, the xTruncate 34114 34662 ** method is a no-op, but that does not change the fact the SQLite will 34115 34663 ** invoke it.) 34116 34664 ** 34117 34665 ** (9) Whenever the database file is modified, at least one bit in the range 34118 34666 ** of bytes from 24 through 39 inclusive will be changed prior to releasing 34119 -** the EXCLUSIVE lock. 34667 +** the EXCLUSIVE lock, thus signaling other connections on the same 34668 +** database to flush their caches. 34120 34669 ** 34121 34670 ** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less 34122 34671 ** than one billion transactions. 34123 34672 ** 34124 34673 ** (11) A database file is well-formed at the beginning and at the conclusion 34125 34674 ** of every transaction. 34126 34675 ** 34127 34676 ** (12) An EXCLUSIVE lock is held on the database file when writing to 34128 34677 ** the database file. 34129 34678 ** 34130 34679 ** (13) A SHARED lock is held on the database file while reading any 34131 34680 ** content out of the database file. 34132 -*/ 34681 +** 34682 +******************************************************************************/ 34133 34683 34134 34684 /* 34135 34685 ** Macros for troubleshooting. Normally turned off 34136 34686 */ 34137 34687 #if 0 34138 34688 int sqlite3PagerTrace=1; /* True to enable tracing */ 34139 34689 #define sqlite3DebugPrintf printf ................................................................................ 34150 34700 ** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file 34151 34701 ** struct as its argument. 34152 34702 */ 34153 34703 #define PAGERID(p) ((int)(p->fd)) 34154 34704 #define FILEHANDLEID(fd) ((int)fd) 34155 34705 34156 34706 /* 34157 -** The page cache as a whole is always in one of the following 34158 -** states: 34159 -** 34160 -** PAGER_UNLOCK The page cache is not currently reading or 34161 -** writing the database file. There is no 34162 -** data held in memory. This is the initial 34163 -** state. 34164 -** 34165 -** PAGER_SHARED The page cache is reading the database. 34166 -** Writing is not permitted. There can be 34167 -** multiple readers accessing the same database 34168 -** file at the same time. 34169 -** 34170 -** PAGER_RESERVED This process has reserved the database for writing 34171 -** but has not yet made any changes. Only one process 34172 -** at a time can reserve the database. The original 34173 -** database file has not been modified so other 34174 -** processes may still be reading the on-disk 34175 -** database file. 34176 -** 34177 -** PAGER_EXCLUSIVE The page cache is writing the database. 34178 -** Access is exclusive. No other processes or 34179 -** threads can be reading or writing while one 34180 -** process is writing. 34181 -** 34182 -** PAGER_SYNCED The pager moves to this state from PAGER_EXCLUSIVE 34183 -** after all dirty pages have been written to the 34184 -** database file and the file has been synced to 34185 -** disk. All that remains to do is to remove or 34186 -** truncate the journal file and the transaction 34187 -** will be committed. 34188 -** 34189 -** The page cache comes up in PAGER_UNLOCK. The first time a 34190 -** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED. 34191 -** After all pages have been released using sqlite_page_unref(), 34192 -** the state transitions back to PAGER_UNLOCK. The first time 34193 -** that sqlite3PagerWrite() is called, the state transitions to 34194 -** PAGER_RESERVED. (Note that sqlite3PagerWrite() can only be 34195 -** called on an outstanding page which means that the pager must 34196 -** be in PAGER_SHARED before it transitions to PAGER_RESERVED.) 34197 -** PAGER_RESERVED means that there is an open rollback journal. 34198 -** The transition to PAGER_EXCLUSIVE occurs before any changes 34199 -** are made to the database file, though writes to the rollback 34200 -** journal occurs with just PAGER_RESERVED. After an sqlite3PagerRollback() 34201 -** or sqlite3PagerCommitPhaseTwo(), the state can go back to PAGER_SHARED, 34202 -** or it can stay at PAGER_EXCLUSIVE if we are in exclusive access mode. 34203 -*/ 34204 -#define PAGER_UNLOCK 0 34205 -#define PAGER_SHARED 1 /* same as SHARED_LOCK */ 34206 -#define PAGER_RESERVED 2 /* same as RESERVED_LOCK */ 34207 -#define PAGER_EXCLUSIVE 4 /* same as EXCLUSIVE_LOCK */ 34208 -#define PAGER_SYNCED 5 34707 +** The Pager.eState variable stores the current 'state' of a pager. A 34708 +** pager may be in any one of the seven states shown in the following 34709 +** state diagram. 34710 +** 34711 +** OPEN <------+------+ 34712 +** | | | 34713 +** V | | 34714 +** +---------> READER-------+ | 34715 +** | | | 34716 +** | V | 34717 +** |<-------WRITER_LOCKED------> ERROR 34718 +** | | ^ 34719 +** | V | 34720 +** |<------WRITER_CACHEMOD-------->| 34721 +** | | | 34722 +** | V | 34723 +** |<-------WRITER_DBMOD---------->| 34724 +** | | | 34725 +** | V | 34726 +** +<------WRITER_FINISHED-------->+ 34727 +** 34728 +** 34729 +** List of state transitions and the C [function] that performs each: 34730 +** 34731 +** OPEN -> READER [sqlite3PagerSharedLock] 34732 +** READER -> OPEN [pager_unlock] 34733 +** 34734 +** READER -> WRITER_LOCKED [sqlite3PagerBegin] 34735 +** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal] 34736 +** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal] 34737 +** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne] 34738 +** WRITER_*** -> READER [pager_end_transaction] 34739 +** 34740 +** WRITER_*** -> ERROR [pager_error] 34741 +** ERROR -> OPEN [pager_unlock] 34742 +** 34743 +** 34744 +** OPEN: 34745 +** 34746 +** The pager starts up in this state. Nothing is guaranteed in this 34747 +** state - the file may or may not be locked and the database size is 34748 +** unknown. The database may not be read or written. 34749 +** 34750 +** * No read or write transaction is active. 34751 +** * Any lock, or no lock at all, may be held on the database file. 34752 +** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted. 34753 +** 34754 +** READER: 34755 +** 34756 +** In this state all the requirements for reading the database in 34757 +** rollback (non-WAL) mode are met. Unless the pager is (or recently 34758 +** was) in exclusive-locking mode, a user-level read transaction is 34759 +** open. The database size is known in this state. 34760 +** 34761 +** A connection running with locking_mode=normal enters this state when 34762 +** it opens a read-transaction on the database and returns to state 34763 +** OPEN after the read-transaction is completed. However a connection 34764 +** running in locking_mode=exclusive (including temp databases) remains in 34765 +** this state even after the read-transaction is closed. The only way 34766 +** a locking_mode=exclusive connection can transition from READER to OPEN 34767 +** is via the ERROR state (see below). 34768 +** 34769 +** * A read transaction may be active (but a write-transaction cannot). 34770 +** * A SHARED or greater lock is held on the database file. 34771 +** * The dbSize variable may be trusted (even if a user-level read 34772 +** transaction is not active). The dbOrigSize and dbFileSize variables 34773 +** may not be trusted at this point. 34774 +** * If the database is a WAL database, then the WAL connection is open. 34775 +** * Even if a read-transaction is not open, it is guaranteed that 34776 +** there is no hot-journal in the file-system. 34777 +** 34778 +** WRITER_LOCKED: 34779 +** 34780 +** The pager moves to this state from READER when a write-transaction 34781 +** is first opened on the database. In WRITER_LOCKED state, all locks 34782 +** required to start a write-transaction are held, but no actual 34783 +** modifications to the cache or database have taken place. 34784 +** 34785 +** In rollback mode, a RESERVED or (if the transaction was opened with 34786 +** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when 34787 +** moving to this state, but the journal file is not written to or opened 34788 +** to in this state. If the transaction is committed or rolled back while 34789 +** in WRITER_LOCKED state, all that is required is to unlock the database 34790 +** file. 34791 +** 34792 +** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file. 34793 +** If the connection is running with locking_mode=exclusive, an attempt 34794 +** is made to obtain an EXCLUSIVE lock on the database file. 34795 +** 34796 +** * A write transaction is active. 34797 +** * If the connection is open in rollback-mode, a RESERVED or greater 34798 +** lock is held on the database file. 34799 +** * If the connection is open in WAL-mode, a WAL write transaction 34800 +** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully 34801 +** called). 34802 +** * The dbSize, dbOrigSize and dbFileSize variables are all valid. 34803 +** * The contents of the pager cache have not been modified. 34804 +** * The journal file may or may not be open. 34805 +** * Nothing (not even the first header) has been written to the journal. 34806 +** 34807 +** WRITER_CACHEMOD: 34808 +** 34809 +** A pager moves from WRITER_LOCKED state to this state when a page is 34810 +** first modified by the upper layer. In rollback mode the journal file 34811 +** is opened (if it is not already open) and a header written to the 34812 +** start of it. The database file on disk has not been modified. 34813 +** 34814 +** * A write transaction is active. 34815 +** * A RESERVED or greater lock is held on the database file. 34816 +** * The journal file is open and the first header has been written 34817 +** to it, but the header has not been synced to disk. 34818 +** * The contents of the page cache have been modified. 34819 +** 34820 +** WRITER_DBMOD: 34821 +** 34822 +** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state 34823 +** when it modifies the contents of the database file. WAL connections 34824 +** never enter this state (since they do not modify the database file, 34825 +** just the log file). 34826 +** 34827 +** * A write transaction is active. 34828 +** * An EXCLUSIVE or greater lock is held on the database file. 34829 +** * The journal file is open and the first header has been written 34830 +** and synced to disk. 34831 +** * The contents of the page cache have been modified (and possibly 34832 +** written to disk). 34833 +** 34834 +** WRITER_FINISHED: 34835 +** 34836 +** It is not possible for a WAL connection to enter this state. 34837 +** 34838 +** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD 34839 +** state after the entire transaction has been successfully written into the 34840 +** database file. In this state the transaction may be committed simply 34841 +** by finalizing the journal file. Once in WRITER_FINISHED state, it is 34842 +** not possible to modify the database further. At this point, the upper 34843 +** layer must either commit or rollback the transaction. 34844 +** 34845 +** * A write transaction is active. 34846 +** * An EXCLUSIVE or greater lock is held on the database file. 34847 +** * All writing and syncing of journal and database data has finished. 34848 +** If no error occured, all that remains is to finalize the journal to 34849 +** commit the transaction. If an error did occur, the caller will need 34850 +** to rollback the transaction. 34851 +** 34852 +** ERROR: 34853 +** 34854 +** The ERROR state is entered when an IO or disk-full error (including 34855 +** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it 34856 +** difficult to be sure that the in-memory pager state (cache contents, 34857 +** db size etc.) are consistent with the contents of the file-system. 34858 +** 34859 +** Temporary pager files may enter the ERROR state, but in-memory pagers 34860 +** cannot. 34861 +** 34862 +** For example, if an IO error occurs while performing a rollback, 34863 +** the contents of the page-cache may be left in an inconsistent state. 34864 +** At this point it would be dangerous to change back to READER state 34865 +** (as usually happens after a rollback). Any subsequent readers might 34866 +** report database corruption (due to the inconsistent cache), and if 34867 +** they upgrade to writers, they may inadvertently corrupt the database 34868 +** file. To avoid this hazard, the pager switches into the ERROR state 34869 +** instead of READER following such an error. 34870 +** 34871 +** Once it has entered the ERROR state, any attempt to use the pager 34872 +** to read or write data returns an error. Eventually, once all 34873 +** outstanding transactions have been abandoned, the pager is able to 34874 +** transition back to OPEN state, discarding the contents of the 34875 +** page-cache and any other in-memory state at the same time. Everything 34876 +** is reloaded from disk (and, if necessary, hot-journal rollback peformed) 34877 +** when a read-transaction is next opened on the pager (transitioning 34878 +** the pager into READER state). At that point the system has recovered 34879 +** from the error. 34880 +** 34881 +** Specifically, the pager jumps into the ERROR state if: 34882 +** 34883 +** 1. An error occurs while attempting a rollback. This happens in 34884 +** function sqlite3PagerRollback(). 34885 +** 34886 +** 2. An error occurs while attempting to finalize a journal file 34887 +** following a commit in function sqlite3PagerCommitPhaseTwo(). 34888 +** 34889 +** 3. An error occurs while attempting to write to the journal or 34890 +** database file in function pagerStress() in order to free up 34891 +** memory. 34892 +** 34893 +** In other cases, the error is returned to the b-tree layer. The b-tree 34894 +** layer then attempts a rollback operation. If the error condition 34895 +** persists, the pager enters the ERROR state via condition (1) above. 34896 +** 34897 +** Condition (3) is necessary because it can be triggered by a read-only 34898 +** statement executed within a transaction. In this case, if the error 34899 +** code were simply returned to the user, the b-tree layer would not 34900 +** automatically attempt a rollback, as it assumes that an error in a 34901 +** read-only statement cannot leave the pager in an internally inconsistent 34902 +** state. 34903 +** 34904 +** * The Pager.errCode variable is set to something other than SQLITE_OK. 34905 +** * There are one or more outstanding references to pages (after the 34906 +** last reference is dropped the pager should move back to OPEN state). 34907 +** * The pager is not an in-memory pager. 34908 +** 34909 +** 34910 +** Notes: 34911 +** 34912 +** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the 34913 +** connection is open in WAL mode. A WAL connection is always in one 34914 +** of the first four states. 34915 +** 34916 +** * Normally, a connection open in exclusive mode is never in PAGER_OPEN 34917 +** state. There are two exceptions: immediately after exclusive-mode has 34918 +** been turned on (and before any read or write transactions are 34919 +** executed), and when the pager is leaving the "error state". 34920 +** 34921 +** * See also: assert_pager_state(). 34922 +*/ 34923 +#define PAGER_OPEN 0 34924 +#define PAGER_READER 1 34925 +#define PAGER_WRITER_LOCKED 2 34926 +#define PAGER_WRITER_CACHEMOD 3 34927 +#define PAGER_WRITER_DBMOD 4 34928 +#define PAGER_WRITER_FINISHED 5 34929 +#define PAGER_ERROR 6 34930 + 34931 +/* 34932 +** The Pager.eLock variable is almost always set to one of the 34933 +** following locking-states, according to the lock currently held on 34934 +** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. 34935 +** This variable is kept up to date as locks are taken and released by 34936 +** the pagerLockDb() and pagerUnlockDb() wrappers. 34937 +** 34938 +** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY 34939 +** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not 34940 +** the operation was successful. In these circumstances pagerLockDb() and 34941 +** pagerUnlockDb() take a conservative approach - eLock is always updated 34942 +** when unlocking the file, and only updated when locking the file if the 34943 +** VFS call is successful. This way, the Pager.eLock variable may be set 34944 +** to a less exclusive (lower) value than the lock that is actually held 34945 +** at the system level, but it is never set to a more exclusive value. 34946 +** 34947 +** This is usually safe. If an xUnlock fails or appears to fail, there may 34948 +** be a few redundant xLock() calls or a lock may be held for longer than 34949 +** required, but nothing really goes wrong. 34950 +** 34951 +** The exception is when the database file is unlocked as the pager moves 34952 +** from ERROR to OPEN state. At this point there may be a hot-journal file 34953 +** in the file-system that needs to be rolled back (as part of a OPEN->SHARED 34954 +** transition, by the same pager or any other). If the call to xUnlock() 34955 +** fails at this point and the pager is left holding an EXCLUSIVE lock, this 34956 +** can confuse the call to xCheckReservedLock() call made later as part 34957 +** of hot-journal detection. 34958 +** 34959 +** xCheckReservedLock() is defined as returning true "if there is a RESERVED 34960 +** lock held by this process or any others". So xCheckReservedLock may 34961 +** return true because the caller itself is holding an EXCLUSIVE lock (but 34962 +** doesn't know it because of a previous error in xUnlock). If this happens 34963 +** a hot-journal may be mistaken for a journal being created by an active 34964 +** transaction in another process, causing SQLite to read from the database 34965 +** without rolling it back. 34966 +** 34967 +** To work around this, if a call to xUnlock() fails when unlocking the 34968 +** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It 34969 +** is only changed back to a real locking state after a successful call 34970 +** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition 34971 +** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK 34972 +** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE 34973 +** lock on the database file before attempting to roll it back. See function 34974 +** PagerSharedLock() for more detail. 34975 +** 34976 +** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in 34977 +** PAGER_OPEN state. 34978 +*/ 34979 +#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1) 34209 34980 34210 34981 /* 34211 34982 ** A macro used for invoking the codec if there is one 34212 34983 */ 34213 34984 #ifdef SQLITE_HAS_CODEC 34214 34985 # define CODEC1(P,D,N,X,E) \ 34215 34986 if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; } ................................................................................ 34251 35022 Pgno iSubRec; /* Index of first record in sub-journal */ 34252 35023 #ifndef SQLITE_OMIT_WAL 34253 35024 u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */ 34254 35025 #endif 34255 35026 }; 34256 35027 34257 35028 /* 34258 -** A open page cache is an instance of the following structure. 34259 -** 34260 -** errCode 34261 -** 34262 -** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or 34263 -** or SQLITE_FULL. Once one of the first three errors occurs, it persists 34264 -** and is returned as the result of every major pager API call. The 34265 -** SQLITE_FULL return code is slightly different. It persists only until the 34266 -** next successful rollback is performed on the pager cache. Also, 34267 -** SQLITE_FULL does not affect the sqlite3PagerGet() and sqlite3PagerLookup() 34268 -** APIs, they may still be used successfully. 34269 -** 34270 -** dbSizeValid, dbSize, dbOrigSize, dbFileSize 34271 -** 34272 -** Managing the size of the database file in pages is a little complicated. 34273 -** The variable Pager.dbSize contains the number of pages that the database 34274 -** image currently contains. As the database image grows or shrinks this 34275 -** variable is updated. The variable Pager.dbFileSize contains the number 34276 -** of pages in the database file. This may be different from Pager.dbSize 34277 -** if some pages have been appended to the database image but not yet written 34278 -** out from the cache to the actual file on disk. Or if the image has been 34279 -** truncated by an incremental-vacuum operation. The Pager.dbOrigSize variable 34280 -** contains the number of pages in the database image when the current 34281 -** transaction was opened. The contents of all three of these variables is 34282 -** only guaranteed to be correct if the boolean Pager.dbSizeValid is true. 34283 -** 34284 -** TODO: Under what conditions is dbSizeValid set? Cleared? 35029 +** A open page cache is an instance of struct Pager. A description of 35030 +** some of the more important member variables follows: 35031 +** 35032 +** eState 35033 +** 35034 +** The current 'state' of the pager object. See the comment and state 35035 +** diagram above for a description of the pager state. 35036 +** 35037 +** eLock 35038 +** 35039 +** For a real on-disk database, the current lock held on the database file - 35040 +** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. 35041 +** 35042 +** For a temporary or in-memory database (neither of which require any 35043 +** locks), this variable is always set to EXCLUSIVE_LOCK. Since such 35044 +** databases always have Pager.exclusiveMode==1, this tricks the pager 35045 +** logic into thinking that it already has all the locks it will ever 35046 +** need (and no reason to release them). 35047 +** 35048 +** In some (obscure) circumstances, this variable may also be set to 35049 +** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for 35050 +** details. 34285 35051 ** 34286 35052 ** changeCountDone 34287 35053 ** 34288 35054 ** This boolean variable is used to make sure that the change-counter 34289 35055 ** (the 4-byte header field at byte offset 24 of the database file) is 34290 35056 ** not updated more often than necessary. 34291 35057 ** ................................................................................ 34296 35062 ** The changeCountDone flag is inspected. If it is true, the work of 34297 35063 ** updating the change-counter is omitted for the current transaction. 34298 35064 ** 34299 35065 ** This mechanism means that when running in exclusive mode, a connection 34300 35066 ** need only update the change-counter once, for the first transaction 34301 35067 ** committed. 34302 35068 ** 34303 -** dbModified 34304 -** 34305 -** The dbModified flag is set whenever a database page is dirtied. 34306 -** It is cleared at the end of each transaction. 34307 -** 34308 -** It is used when committing or otherwise ending a transaction. If 34309 -** the dbModified flag is clear then less work has to be done. 34310 -** 34311 -** journalStarted 34312 -** 34313 -** This flag is set during a write-transaction after the first 34314 -** journal-header is written and synced to disk. 34315 -** 34316 -** After this has happened, new pages appended to the database 34317 -** do not need the PGHDR_NEED_SYNC flag set, as they do not need 34318 -** to wait for a journal sync before they can be written out to 34319 -** the database file (see function pager_write()). 34320 -** 34321 35069 ** setMaster 34322 35070 ** 34323 35071 ** When PagerCommitPhaseOne() is called to commit a transaction, it may 34324 35072 ** (or may not) specify a master-journal name to be written into the 34325 35073 ** journal file before it is synced to disk. 34326 35074 ** 34327 35075 ** Whether or not a journal file contains a master-journal pointer affects 34328 35076 ** the way in which the journal file is finalized after the transaction is 34329 35077 ** committed or rolled back when running in "journal_mode=PERSIST" mode. 34330 35078 ** If a journal file does not contain a master-journal pointer, it is 34331 -** finalized by overwriting the first journal header with zeroes. If, 34332 -** on the other hand, it does contain a master-journal pointer, the 34333 -** journal file is finalized by truncating it to zero bytes, just as if 34334 -** the connection were running in "journal_mode=truncate" mode. 35079 +** finalized by overwriting the first journal header with zeroes. If 35080 +** it does contain a master-journal pointer the journal file is finalized 35081 +** by truncating it to zero bytes, just as if the connection were 35082 +** running in "journal_mode=truncate" mode. 34335 35083 ** 34336 35084 ** Journal files that contain master journal pointers cannot be finalized 34337 35085 ** simply by overwriting the first journal-header with zeroes, as the 34338 35086 ** master journal pointer could interfere with hot-journal rollback of any 34339 35087 ** subsequently interrupted transaction that reuses the journal file. 34340 35088 ** 34341 35089 ** The flag is cleared as soon as the journal file is finalized (either 34342 35090 ** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the 34343 35091 ** journal file from being successfully finalized, the setMaster flag 34344 -** is cleared anyway. 35092 +** is cleared anyway (and the pager will move to ERROR state). 34345 35093 ** 34346 35094 ** doNotSpill, doNotSyncSpill 34347 35095 ** 34348 -** When enabled, cache spills are prohibited. The doNotSpill variable 34349 -** inhibits all cache spill and doNotSyncSpill inhibits those spills that 34350 -** would require a journal sync. The doNotSyncSpill is set and cleared 34351 -** by sqlite3PagerWrite() in order to prevent a journal sync from happening 34352 -** in between the journalling of two pages on the same sector. The 34353 -** doNotSpill value set to prevent pagerStress() from trying to use 34354 -** the journal during a rollback. 35096 +** These two boolean variables control the behaviour of cache-spills 35097 +** (calls made by the pcache module to the pagerStress() routine to 35098 +** write cached data to the file-system in order to free up memory). 34355 35099 ** 34356 -** needSync 34357 -** 34358 -** TODO: It might be easier to set this variable in writeJournalHdr() 34359 -** and writeMasterJournal() only. Change its meaning to "unsynced data 34360 -** has been written to the journal". 35100 +** When doNotSpill is non-zero, writing to the database from pagerStress() 35101 +** is disabled altogether. This is done in a very obscure case that 35102 +** comes up during savepoint rollback that requires the pcache module 35103 +** to allocate a new page to prevent the journal file from being written 35104 +** while it is being traversed by code in pager_playback(). 35105 +** 35106 +** If doNotSyncSpill is non-zero, writing to the database from pagerStress() 35107 +** is permitted, but syncing the journal file is not. This flag is set 35108 +** by sqlite3PagerWrite() when the file-system sector-size is larger than 35109 +** the database page-size in order to prevent a journal sync from happening 35110 +** in between the journalling of two pages on the same sector. 34361 35111 ** 34362 35112 ** subjInMemory 34363 35113 ** 34364 35114 ** This is a boolean variable. If true, then any required sub-journal 34365 35115 ** is opened as an in-memory journal file. If false, then in-memory 34366 35116 ** sub-journals are only used for in-memory pager files. 35117 +** 35118 +** This variable is updated by the upper layer each time a new 35119 +** write-transaction is opened. 35120 +** 35121 +** dbSize, dbOrigSize, dbFileSize 35122 +** 35123 +** Variable dbSize is set to the number of pages in the database file. 35124 +** It is valid in PAGER_READER and higher states (all states except for 35125 +** OPEN and ERROR). 35126 +** 35127 +** dbSize is set based on the size of the database file, which may be 35128 +** larger than the size of the database (the value stored at offset 35129 +** 28 of the database header by the btree). If the size of the file 35130 +** is not an integer multiple of the page-size, the value stored in 35131 +** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2). 35132 +** Except, any file that is greater than 0 bytes in size is considered 35133 +** to have at least one page. (i.e. a 1KB file with 2K page-size leads 35134 +** to dbSize==1). 35135 +** 35136 +** During a write-transaction, if pages with page-numbers greater than 35137 +** dbSize are modified in the cache, dbSize is updated accordingly. 35138 +** Similarly, if the database is truncated using PagerTruncateImage(), 35139 +** dbSize is updated. 35140 +** 35141 +** Variables dbOrigSize and dbFileSize are valid in states 35142 +** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize 35143 +** variable at the start of the transaction. It is used during rollback, 35144 +** and to determine whether or not pages need to be journalled before 35145 +** being modified. 35146 +** 35147 +** Throughout a write-transaction, dbFileSize contains the size of 35148 +** the file on disk in pages. It is set to a copy of dbSize when the 35149 +** write-transaction is first opened, and updated when VFS calls are made 35150 +** to write or truncate the database file on disk. 35151 +** 35152 +** The only reason the dbFileSize variable is required is to suppress 35153 +** unnecessary calls to xTruncate() after committing a transaction. If, 35154 +** when a transaction is committed, the dbFileSize variable indicates 35155 +** that the database file is larger than the database image (Pager.dbSize), 35156 +** pager_truncate() is called. The pager_truncate() call uses xFilesize() 35157 +** to measure the database file on disk, and then truncates it if required. 35158 +** dbFileSize is not used when rolling back a transaction. In this case 35159 +** pager_truncate() is called unconditionally (which means there may be 35160 +** a call to xFilesize() that is not strictly required). In either case, 35161 +** pager_truncate() may cause the file to become smaller or larger. 35162 +** 35163 +** dbHintSize 35164 +** 35165 +** The dbHintSize variable is used to limit the number of calls made to 35166 +** the VFS xFileControl(FCNTL_SIZE_HINT) method. 35167 +** 35168 +** dbHintSize is set to a copy of the dbSize variable when a 35169 +** write-transaction is opened (at the same time as dbFileSize and 35170 +** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called, 35171 +** dbHintSize is increased to the number of pages that correspond to the 35172 +** size-hint passed to the method call. See pager_write_pagelist() for 35173 +** details. 35174 +** 35175 +** errCode 35176 +** 35177 +** The Pager.errCode variable is only ever used in PAGER_ERROR state. It 35178 +** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode 35179 +** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX 35180 +** sub-codes. 34367 35181 */ 34368 35182 struct Pager { 34369 35183 sqlite3_vfs *pVfs; /* OS functions to use for IO */ 34370 35184 u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ 34371 - u8 journalMode; /* On of the PAGER_JOURNALMODE_* values */ 35185 + u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ 34372 35186 u8 useJournal; /* Use a rollback journal on this file */ 34373 35187 u8 noReadlock; /* Do not bother to obtain readlocks */ 34374 35188 u8 noSync; /* Do not sync the journal if true */ 34375 35189 u8 fullSync; /* Do extra syncs of the journal for robustness */ 34376 35190 u8 sync_flags; /* One of SYNC_NORMAL or SYNC_FULL */ 34377 35191 u8 tempFile; /* zFilename is a temporary file */ 34378 35192 u8 readOnly; /* True for a read-only database */ 34379 35193 u8 memDb; /* True to inhibit all file I/O */ 34380 35194 34381 - /* The following block contains those class members that are dynamically 34382 - ** modified during normal operations. The other variables in this structure 34383 - ** are either constant throughout the lifetime of the pager, or else 34384 - ** used to store configuration parameters that affect the way the pager 34385 - ** operates. 34386 - ** 34387 - ** The 'state' variable is described in more detail along with the 34388 - ** descriptions of the values it may take - PAGER_UNLOCK etc. Many of the 34389 - ** other variables in this block are described in the comment directly 34390 - ** above this class definition. 35195 + /************************************************************************** 35196 + ** The following block contains those class members that change during 35197 + ** routine opertion. Class members not in this block are either fixed 35198 + ** when the pager is first created or else only change when there is a 35199 + ** significant mode change (such as changing the page_size, locking_mode, 35200 + ** or the journal_mode). From another view, these class members describe 35201 + ** the "state" of the pager, while other class members describe the 35202 + ** "configuration" of the pager. 34391 35203 */ 34392 - u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ 34393 - u8 dbModified; /* True if there are any changes to the Db */ 34394 - u8 needSync; /* True if an fsync() is needed on the journal */ 34395 - u8 journalStarted; /* True if header of journal is synced */ 35204 + u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */ 35205 + u8 eLock; /* Current lock held on database file */ 34396 35206 u8 changeCountDone; /* Set after incrementing the change-counter */ 34397 35207 u8 setMaster; /* True if a m-j name has been written to jrnl */ 34398 35208 u8 doNotSpill; /* Do not spill the cache when non-zero */ 34399 35209 u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */ 34400 - u8 dbSizeValid; /* Set when dbSize is correct */ 34401 35210 u8 subjInMemory; /* True to use in-memory sub-journals */ 34402 35211 Pgno dbSize; /* Number of pages in the database */ 34403 35212 Pgno dbOrigSize; /* dbSize before the current transaction */ 34404 35213 Pgno dbFileSize; /* Number of pages in the database file */ 35214 + Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ 34405 35215 int errCode; /* One of several kinds of errors */ 34406 35216 int nRec; /* Pages journalled since last j-header written */ 34407 35217 u32 cksumInit; /* Quasi-random value added to every checksum */ 34408 35218 u32 nSubRec; /* Number of records written to sub-journal */ 34409 35219 Bitvec *pInJournal; /* One bit for each page in the database file */ 34410 35220 sqlite3_file *fd; /* File descriptor for database */ 34411 35221 sqlite3_file *jfd; /* File descriptor for main journal */ 34412 35222 sqlite3_file *sjfd; /* File descriptor for sub-journal */ 34413 35223 i64 journalOff; /* Current write offset in the journal file */ 34414 35224 i64 journalHdr; /* Byte offset to previous journal header */ 34415 - i64 journalSizeLimit; /* Size limit for persistent journal files */ 35225 + sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ 34416 35226 PagerSavepoint *aSavepoint; /* Array of active savepoints */ 34417 35227 int nSavepoint; /* Number of elements in aSavepoint[] */ 34418 35228 char dbFileVers[16]; /* Changes whenever database file changes */ 34419 - u32 sectorSize; /* Assumed sector size during rollback */ 35229 + /* 35230 + ** End of the routinely-changing class members 35231 + ***************************************************************************/ 34420 35232 34421 35233 u16 nExtra; /* Add this many bytes to each in-memory page */ 34422 35234 i16 nReserve; /* Number of unused bytes at end of each page */ 34423 35235 u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ 35236 + u32 sectorSize; /* Assumed sector size during rollback */ 34424 35237 int pageSize; /* Number of bytes in a page */ 34425 35238 Pgno mxPgno; /* Maximum allowed size of the database */ 35239 + i64 journalSizeLimit; /* Size limit for persistent journal files */ 34426 35240 char *zFilename; /* Name of the database file */ 34427 35241 char *zJournal; /* Name of the journal file */ 34428 35242 int (*xBusyHandler)(void*); /* Function to call when busy */ 34429 35243 void *pBusyHandlerArg; /* Context argument for xBusyHandler */ 34430 35244 #ifdef SQLITE_TEST 34431 35245 int nHit, nMiss; /* Cache hits and missing */ 34432 35246 int nRead, nWrite; /* Database pages read/written */ ................................................................................ 34436 35250 void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ 34437 35251 void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */ 34438 35252 void (*xCodecFree)(void*); /* Destructor for the codec */ 34439 35253 void *pCodec; /* First argument to xCodec... methods */ 34440 35254 #endif 34441 35255 char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ 34442 35256 PCache *pPCache; /* Pointer to page cache object */ 34443 - sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ 34444 35257 #ifndef SQLITE_OMIT_WAL 34445 35258 Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ 34446 35259 char *zWal; /* File name for write-ahead log */ 34447 35260 #endif 34448 35261 }; 34449 35262 34450 35263 /* ................................................................................ 34515 35328 #endif 34516 35329 34517 35330 /* 34518 35331 ** The maximum legal page number is (2^31 - 1). 34519 35332 */ 34520 35333 #define PAGER_MAX_PGNO 2147483647 34521 35334 35335 +/* 35336 +** The argument to this macro is a file descriptor (type sqlite3_file*). 35337 +** Return 0 if it is not open, or non-zero (but not 1) if it is. 35338 +** 35339 +** This is so that expressions can be written as: 35340 +** 35341 +** if( isOpen(pPager->jfd) ){ ... 35342 +** 35343 +** instead of 35344 +** 35345 +** if( pPager->jfd->pMethods ){ ... 35346 +*/ 35347 +#define isOpen(pFd) ((pFd)->pMethods) 35348 + 35349 +/* 35350 +** Return true if this pager uses a write-ahead log instead of the usual 35351 +** rollback journal. Otherwise false. 35352 +*/ 35353 +#ifndef SQLITE_OMIT_WAL 35354 +static int pagerUseWal(Pager *pPager){ 35355 + return (pPager->pWal!=0); 35356 +} 35357 +#else 35358 +# define pagerUseWal(x) 0 35359 +# define pagerRollbackWal(x) 0 35360 +# define pagerWalFrames(v,w,x,y,z) 0 35361 +# define pagerOpenWalIfPresent(z) SQLITE_OK 35362 +# define pagerBeginReadTransaction(z) SQLITE_OK 35363 +#endif 35364 + 34522 35365 #ifndef NDEBUG 34523 35366 /* 34524 35367 ** Usage: 34525 35368 ** 34526 35369 ** assert( assert_pager_state(pPager) ); 34527 -*/ 34528 -static int assert_pager_state(Pager *pPager){ 34529 - 34530 - /* A temp-file is always in PAGER_EXCLUSIVE or PAGER_SYNCED state. */ 34531 - assert( pPager->tempFile==0 || pPager->state>=PAGER_EXCLUSIVE ); 34532 - 34533 - /* The changeCountDone flag is always set for temp-files */ 34534 - assert( pPager->tempFile==0 || pPager->changeCountDone ); 34535 - 34536 - return 1; 35370 +** 35371 +** This function runs many asserts to try to find inconsistencies in 35372 +** the internal state of the Pager object. 35373 +*/ 35374 +static int assert_pager_state(Pager *p){ 35375 + Pager *pPager = p; 35376 + 35377 + /* State must be valid. */ 35378 + assert( p->eState==PAGER_OPEN 35379 + || p->eState==PAGER_READER 35380 + || p->eState==PAGER_WRITER_LOCKED 35381 + || p->eState==PAGER_WRITER_CACHEMOD 35382 + || p->eState==PAGER_WRITER_DBMOD 35383 + || p->eState==PAGER_WRITER_FINISHED 35384 + || p->eState==PAGER_ERROR 35385 + ); 35386 + 35387 + /* Regardless of the current state, a temp-file connection always behaves 35388 + ** as if it has an exclusive lock on the database file. It never updates 35389 + ** the change-counter field, so the changeCountDone flag is always set. 35390 + */ 35391 + assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK ); 35392 + assert( p->tempFile==0 || pPager->changeCountDone ); 35393 + 35394 + /* If the useJournal flag is clear, the journal-mode must be "OFF". 35395 + ** And if the journal-mode is "OFF", the journal file must not be open. 35396 + */ 35397 + assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal ); 35398 + assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) ); 35399 + 35400 + /* Check that MEMDB implies noSync. And an in-memory journal. Since 35401 + ** this means an in-memory pager performs no IO at all, it cannot encounter 35402 + ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing 35403 + ** a journal file. (although the in-memory journal implementation may 35404 + ** return SQLITE_IOERR_NOMEM while the journal file is being written). It 35405 + ** is therefore not possible for an in-memory pager to enter the ERROR 35406 + ** state. 35407 + */ 35408 + if( MEMDB ){ 35409 + assert( p->noSync ); 35410 + assert( p->journalMode==PAGER_JOURNALMODE_OFF 35411 + || p->journalMode==PAGER_JOURNALMODE_MEMORY 35412 + ); 35413 + assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN ); 35414 + assert( pagerUseWal(p)==0 ); 35415 + } 35416 + 35417 + /* If changeCountDone is set, a RESERVED lock or greater must be held 35418 + ** on the file. 35419 + */ 35420 + assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK ); 35421 + assert( p->eLock!=PENDING_LOCK ); 35422 + 35423 + switch( p->eState ){ 35424 + case PAGER_OPEN: 35425 + assert( !MEMDB ); 35426 + assert( pPager->errCode==SQLITE_OK ); 35427 + assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile ); 35428 + break; 35429 + 35430 + case PAGER_READER: 35431 + assert( pPager->errCode==SQLITE_OK ); 35432 + assert( p->eLock!=UNKNOWN_LOCK ); 35433 + assert( p->eLock>=SHARED_LOCK || p->noReadlock ); 35434 + break; 35435 + 35436 + case PAGER_WRITER_LOCKED: 35437 + assert( p->eLock!=UNKNOWN_LOCK ); 35438 + assert( pPager->errCode==SQLITE_OK ); 35439 + if( !pagerUseWal(pPager) ){ 35440 + assert( p->eLock>=RESERVED_LOCK ); 35441 + } 35442 + assert( pPager->dbSize==pPager->dbOrigSize ); 35443 + assert( pPager->dbOrigSize==pPager->dbFileSize ); 35444 + assert( pPager->dbOrigSize==pPager->dbHintSize ); 35445 + assert( pPager->setMaster==0 ); 35446 + break; 35447 + 35448 + case PAGER_WRITER_CACHEMOD: 35449 + assert( p->eLock!=UNKNOWN_LOCK ); 35450 + assert( pPager->errCode==SQLITE_OK ); 35451 + if( !pagerUseWal(pPager) ){ 35452 + /* It is possible that if journal_mode=wal here that neither the 35453 + ** journal file nor the WAL file are open. This happens during 35454 + ** a rollback transaction that switches from journal_mode=off 35455 + ** to journal_mode=wal. 35456 + */ 35457 + assert( p->eLock>=RESERVED_LOCK ); 35458 + assert( isOpen(p->jfd) 35459 + || p->journalMode==PAGER_JOURNALMODE_OFF 35460 + || p->journalMode==PAGER_JOURNALMODE_WAL 35461 + ); 35462 + } 35463 + assert( pPager->dbOrigSize==pPager->dbFileSize ); 35464 + assert( pPager->dbOrigSize==pPager->dbHintSize ); 35465 + break; 35466 + 35467 + case PAGER_WRITER_DBMOD: 35468 + assert( p->eLock==EXCLUSIVE_LOCK ); 35469 + assert( pPager->errCode==SQLITE_OK ); 35470 + assert( !pagerUseWal(pPager) ); 35471 + assert( p->eLock>=EXCLUSIVE_LOCK ); 35472 + assert( isOpen(p->jfd) 35473 + || p->journalMode==PAGER_JOURNALMODE_OFF 35474 + || p->journalMode==PAGER_JOURNALMODE_WAL 35475 + ); 35476 + assert( pPager->dbOrigSize<=pPager->dbHintSize ); 35477 + break; 35478 + 35479 + case PAGER_WRITER_FINISHED: 35480 + assert( p->eLock==EXCLUSIVE_LOCK ); 35481 + assert( pPager->errCode==SQLITE_OK ); 35482 + assert( !pagerUseWal(pPager) ); 35483 + assert( isOpen(p->jfd) 35484 + || p->journalMode==PAGER_JOURNALMODE_OFF 35485 + || p->journalMode==PAGER_JOURNALMODE_WAL 35486 + ); 35487 + break; 35488 + 35489 + case PAGER_ERROR: 35490 + /* There must be at least one outstanding reference to the pager if 35491 + ** in ERROR state. Otherwise the pager should have already dropped 35492 + ** back to OPEN state. 35493 + */ 35494 + assert( pPager->errCode!=SQLITE_OK ); 35495 + assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); 35496 + break; 35497 + } 35498 + 35499 + return 1; 35500 +} 35501 + 35502 +/* 35503 +** Return a pointer to a human readable string in a static buffer 35504 +** containing the state of the Pager object passed as an argument. This 35505 +** is intended to be used within debuggers. For example, as an alternative 35506 +** to "print *pPager" in gdb: 35507 +** 35508 +** (gdb) printf "%s", print_pager_state(pPager) 35509 +*/ 35510 +static char *print_pager_state(Pager *p){ 35511 + static char zRet[1024]; 35512 + 35513 + sqlite3_snprintf(1024, zRet, 35514 + "Filename: %s\n" 35515 + "State: %s errCode=%d\n" 35516 + "Lock: %s\n" 35517 + "Locking mode: locking_mode=%s\n" 35518 + "Journal mode: journal_mode=%s\n" 35519 + "Backing store: tempFile=%d memDb=%d useJournal=%d\n" 35520 + "Journal: journalOff=%lld journalHdr=%lld\n" 35521 + "Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n" 35522 + , p->zFilename 35523 + , p->eState==PAGER_OPEN ? "OPEN" : 35524 + p->eState==PAGER_READER ? "READER" : 35525 + p->eState==PAGER_WRITER_LOCKED ? "WRITER_LOCKED" : 35526 + p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" : 35527 + p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" : 35528 + p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" : 35529 + p->eState==PAGER_ERROR ? "ERROR" : "?error?" 35530 + , (int)p->errCode 35531 + , p->eLock==NO_LOCK ? "NO_LOCK" : 35532 + p->eLock==RESERVED_LOCK ? "RESERVED" : 35533 + p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" : 35534 + p->eLock==SHARED_LOCK ? "SHARED" : 35535 + p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?" 35536 + , p->exclusiveMode ? "exclusive" : "normal" 35537 + , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" : 35538 + p->journalMode==PAGER_JOURNALMODE_OFF ? "off" : 35539 + p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" : 35540 + p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" : 35541 + p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" : 35542 + p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?" 35543 + , (int)p->tempFile, (int)p->memDb, (int)p->useJournal 35544 + , p->journalOff, p->journalHdr 35545 + , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize 35546 + ); 35547 + 35548 + return zRet; 34537 35549 } 34538 35550 #endif 34539 35551 34540 35552 /* 34541 35553 ** Return true if it is necessary to write page *pPg into the sub-journal. 34542 35554 ** A page needs to be written into the sub-journal if there exists one 34543 35555 ** or more open savepoints for which: ................................................................................ 34582 35594 return rc; 34583 35595 } 34584 35596 34585 35597 /* 34586 35598 ** Write a 32-bit integer into a string buffer in big-endian byte order. 34587 35599 */ 34588 35600 #define put32bits(A,B) sqlite3Put4byte((u8*)A,B) 35601 + 34589 35602 34590 35603 /* 34591 35604 ** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK 34592 35605 ** on success or an error code is something goes wrong. 34593 35606 */ 34594 35607 static int write32bits(sqlite3_file *fd, i64 offset, u32 val){ 34595 35608 char ac[4]; 34596 35609 put32bits(ac, val); 34597 35610 return sqlite3OsWrite(fd, ac, 4, offset); 34598 35611 } 34599 35612 34600 35613 /* 34601 -** The argument to this macro is a file descriptor (type sqlite3_file*). 34602 -** Return 0 if it is not open, or non-zero (but not 1) if it is. 34603 -** 34604 -** This is so that expressions can be written as: 34605 -** 34606 -** if( isOpen(pPager->jfd) ){ ... 34607 -** 34608 -** instead of 34609 -** 34610 -** if( pPager->jfd->pMethods ){ ... 34611 -*/ 34612 -#define isOpen(pFd) ((pFd)->pMethods) 34613 - 34614 -/* 34615 -** If file pFd is open, call sqlite3OsUnlock() on it. 34616 -*/ 34617 -static int osUnlock(sqlite3_file *pFd, int eLock){ 34618 - if( !isOpen(pFd) ){ 34619 - return SQLITE_OK; 34620 - } 34621 - return sqlite3OsUnlock(pFd, eLock); 35614 +** Unlock the database file to level eLock, which must be either NO_LOCK 35615 +** or SHARED_LOCK. Regardless of whether or not the call to xUnlock() 35616 +** succeeds, set the Pager.eLock variable to match the (attempted) new lock. 35617 +** 35618 +** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is 35619 +** called, do not modify it. See the comment above the #define of 35620 +** UNKNOWN_LOCK for an explanation of this. 35621 +*/ 35622 +static int pagerUnlockDb(Pager *pPager, int eLock){ 35623 + int rc = SQLITE_OK; 35624 + 35625 + assert( !pPager->exclusiveMode ); 35626 + assert( eLock==NO_LOCK || eLock==SHARED_LOCK ); 35627 + assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 ); 35628 + if( isOpen(pPager->fd) ){ 35629 + assert( pPager->eLock>=eLock ); 35630 + rc = sqlite3OsUnlock(pPager->fd, eLock); 35631 + if( pPager->eLock!=UNKNOWN_LOCK ){ 35632 + pPager->eLock = (u8)eLock; 35633 + } 35634 + IOTRACE(("UNLOCK %p %d\n", pPager, eLock)) 35635 + } 35636 + return rc; 35637 +} 35638 + 35639 +/* 35640 +** Lock the database file to level eLock, which must be either SHARED_LOCK, 35641 +** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the 35642 +** Pager.eLock variable to the new locking state. 35643 +** 35644 +** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is 35645 +** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. 35646 +** See the comment above the #define of UNKNOWN_LOCK for an explanation 35647 +** of this. 35648 +*/ 35649 +static int pagerLockDb(Pager *pPager, int eLock){ 35650 + int rc = SQLITE_OK; 35651 + 35652 + assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK ); 35653 + if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){ 35654 + rc = sqlite3OsLock(pPager->fd, eLock); 35655 + if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){ 35656 + pPager->eLock = (u8)eLock; 35657 + IOTRACE(("LOCK %p %d\n", pPager, eLock)) 35658 + } 35659 + } 35660 + return rc; 34622 35661 } 34623 35662 34624 35663 /* 34625 35664 ** This function determines whether or not the atomic-write optimization 34626 35665 ** can be used with this pager. The optimization can be used if: 34627 35666 ** 34628 35667 ** (a) the value returned by OsDeviceCharacteristics() indicates that ................................................................................ 34690 35729 ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES 34691 35730 ** is defined, and NDEBUG is not defined, an assert() statement checks 34692 35731 ** that the page is either dirty or still matches the calculated page-hash. 34693 35732 */ 34694 35733 #define CHECK_PAGE(x) checkPage(x) 34695 35734 static void checkPage(PgHdr *pPg){ 34696 35735 Pager *pPager = pPg->pPager; 34697 - assert( !pPg->pageHash || pPager->errCode 34698 - || (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) ); 35736 + assert( pPager->eState!=PAGER_ERROR ); 35737 + assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) ); 34699 35738 } 34700 35739 34701 35740 #else 34702 35741 #define pager_datahash(X,Y) 0 34703 35742 #define pager_pagehash(X) 0 35743 +#define pager_set_pagehash(X) 34704 35744 #define CHECK_PAGE(x) 34705 35745 #endif /* SQLITE_CHECK_PAGES */ 34706 35746 34707 35747 /* 34708 35748 ** When this is called the journal file for pager pPager must be open. 34709 35749 ** This function attempts to read a master journal file name from the 34710 35750 ** end of the file and, if successful, copies it into memory supplied ................................................................................ 34863 35903 ** - 4 bytes: Database page size. 34864 35904 ** 34865 35905 ** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space. 34866 35906 */ 34867 35907 static int writeJournalHdr(Pager *pPager){ 34868 35908 int rc = SQLITE_OK; /* Return code */ 34869 35909 char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */ 34870 - u32 nHeader = pPager->pageSize; /* Size of buffer pointed to by zHeader */ 35910 + u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */ 34871 35911 u32 nWrite; /* Bytes of header sector written */ 34872 35912 int ii; /* Loop counter */ 34873 35913 34874 35914 assert( isOpen(pPager->jfd) ); /* Journal file must be open. */ 34875 35915 34876 35916 if( nHeader>JOURNAL_HDR_SZ(pPager) ){ 34877 35917 nHeader = JOURNAL_HDR_SZ(pPager); ................................................................................ 34906 35946 ** * When the pager is in no-sync mode. Corruption can follow a 34907 35947 ** power failure in this case anyway. 34908 35948 ** 34909 35949 ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees 34910 35950 ** that garbage data is never appended to the journal file. 34911 35951 */ 34912 35952 assert( isOpen(pPager->fd) || pPager->noSync ); 34913 - if( (pPager->noSync) || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY) 35953 + if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY) 34914 35954 || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) 34915 35955 ){ 34916 35956 memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); 34917 35957 put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); 34918 35958 }else{ 34919 35959 memset(zHeader, 0, sizeof(aJournalMagic)+4); 34920 35960 } ................................................................................ 35030 36070 ){ 35031 36071 return rc; 35032 36072 } 35033 36073 35034 36074 if( pPager->journalOff==0 ){ 35035 36075 u32 iPageSize; /* Page-size field of journal header */ 35036 36076 u32 iSectorSize; /* Sector-size field of journal header */ 35037 - u16 iPageSize16; /* Copy of iPageSize in 16-bit variable */ 35038 36077 35039 36078 /* Read the page-size and sector-size journal header fields. */ 35040 36079 if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize)) 35041 36080 || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize)) 35042 36081 ){ 35043 36082 return rc; 35044 36083 } 36084 + 36085 + /* Versions of SQLite prior to 3.5.8 set the page-size field of the 36086 + ** journal header to zero. In this case, assume that the Pager.pageSize 36087 + ** variable is already set to the correct page size. 36088 + */ 36089 + if( iPageSize==0 ){ 36090 + iPageSize = pPager->pageSize; 36091 + } 35045 36092 35046 36093 /* Check that the values read from the page-size and sector-size fields 35047 36094 ** are within range. To be 'in range', both values need to be a power 35048 36095 ** of two greater than or equal to 512 or 32, and not greater than their 35049 36096 ** respective compile time maximum limits. 35050 36097 */ 35051 36098 if( iPageSize<512 || iSectorSize<32 ................................................................................ 35060 36107 return SQLITE_DONE; 35061 36108 } 35062 36109 35063 36110 /* Update the page-size to match the value read from the journal. 35064 36111 ** Use a testcase() macro to make sure that malloc failure within 35065 36112 ** PagerSetPagesize() is tested. 35066 36113 */ 35067 - iPageSize16 = (u16)iPageSize; 35068 - rc = sqlite3PagerSetPagesize(pPager, &iPageSize16, -1); 36114 + rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1); 35069 36115 testcase( rc!=SQLITE_OK ); 35070 - assert( rc!=SQLITE_OK || iPageSize16==(u16)iPageSize ); 35071 36116 35072 36117 /* Update the assumed sector-size to match the value used by 35073 36118 ** the process that created this journal. If this journal was 35074 36119 ** created by a process other than this one, then this routine 35075 36120 ** is being called from within pager_playback(). The local value 35076 36121 ** of Pager.sectorSize is restored at the end of that routine. 35077 36122 */ ................................................................................ 35106 36151 int rc; /* Return code */ 35107 36152 int nMaster; /* Length of string zMaster */ 35108 36153 i64 iHdrOff; /* Offset of header in journal file */ 35109 36154 i64 jrnlSize; /* Size of journal file on disk */ 35110 36155 u32 cksum = 0; /* Checksum of string zMaster */ 35111 36156 35112 36157 assert( pPager->setMaster==0 ); 36158 + assert( !pagerUseWal(pPager) ); 36159 + 35113 36160 if( !zMaster 35114 36161 || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 35115 36162 || pPager->journalMode==PAGER_JOURNALMODE_OFF 35116 36163 ){ 35117 36164 return SQLITE_OK; 35118 36165 } 35119 36166 pPager->setMaster = 1; ................................................................................ 35142 36189 || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster))) 35143 36190 || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum))) 35144 36191 || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, iHdrOff+4+nMaster+8))) 35145 36192 ){ 35146 36193 return rc; 35147 36194 } 35148 36195 pPager->journalOff += (nMaster+20); 35149 - pPager->needSync = !pPager->noSync; 35150 36196 35151 36197 /* If the pager is in peristent-journal mode, then the physical 35152 36198 ** journal-file may extend past the end of the master-journal name 35153 36199 ** and 8 bytes of magic data just written to the file. This is 35154 36200 ** dangerous because the code to rollback a hot-journal file 35155 36201 ** will not be able to find the master-journal name to determine 35156 36202 ** whether or not the journal is hot. ................................................................................ 35178 36224 ** fail, since no attempt to allocate dynamic memory will be made. 35179 36225 */ 35180 36226 (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p); 35181 36227 return p; 35182 36228 } 35183 36229 35184 36230 /* 35185 -** Unless the pager is in error-state, discard all in-memory pages. If 35186 -** the pager is in error-state, then this call is a no-op. 35187 -** 35188 -** TODO: Why can we not reset the pager while in error state? 36231 +** Discard the entire contents of the in-memory page-cache. 35189 36232 */ 35190 36233 static void pager_reset(Pager *pPager){ 35191 - if( SQLITE_OK==pPager->errCode ){ 35192 - sqlite3BackupRestart(pPager->pBackup); 35193 - sqlite3PcacheClear(pPager->pPCache); 35194 - pPager->dbSizeValid = 0; 35195 - } 36234 + sqlite3BackupRestart(pPager->pBackup); 36235 + sqlite3PcacheClear(pPager->pPCache); 35196 36236 } 35197 36237 35198 36238 /* 35199 36239 ** Free all structures in the Pager.aSavepoint[] array and set both 35200 36240 ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal 35201 36241 ** if it is open and the pager is not in exclusive mode. 35202 36242 */ ................................................................................ 35231 36271 assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); 35232 36272 } 35233 36273 } 35234 36274 return rc; 35235 36275 } 35236 36276 35237 36277 /* 35238 -** Return true if this pager uses a write-ahead log instead of the usual 35239 -** rollback journal. Otherwise false. 35240 -*/ 35241 -#ifndef SQLITE_OMIT_WAL 35242 -static int pagerUseWal(Pager *pPager){ 35243 - return (pPager->pWal!=0); 35244 -} 35245 -#else 35246 -# define pagerUseWal(x) 0 35247 -# define pagerRollbackWal(x) 0 35248 -# define pagerWalFrames(v,w,x,y,z) 0 35249 -# define pagerOpenWalIfPresent(z) SQLITE_OK 35250 -# define pagerBeginReadTransaction(z) SQLITE_OK 35251 -#endif 35252 - 35253 -/* 35254 -** Unlock the database file. This function is a no-op if the pager 35255 -** is in exclusive mode. 36278 +** This function is a no-op if the pager is in exclusive mode and not 36279 +** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN 36280 +** state. 35256 36281 ** 35257 -** If the pager is currently in error state, discard the contents of 35258 -** the cache and reset the Pager structure internal state. If there is 35259 -** an open journal-file, then the next time a shared-lock is obtained 35260 -** on the pager file (by this or any other process), it will be 35261 -** treated as a hot-journal and rolled back. 36282 +** If the pager is not in exclusive-access mode, the database file is 36283 +** completely unlocked. If the file is unlocked and the file-system does 36284 +** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is 36285 +** closed (if it is open). 36286 +** 36287 +** If the pager is in ERROR state when this function is called, the 36288 +** contents of the pager cache are discarded before switching back to 36289 +** the OPEN state. Regardless of whether the pager is in exclusive-mode 36290 +** or not, any journal file left in the file-system will be treated 36291 +** as a hot-journal and rolled back the next time a read-transaction 36292 +** is opened (by this or by any other connection). 35262 36293 */ 35263 36294 static void pager_unlock(Pager *pPager){ 35264 - if( !pPager->exclusiveMode ){ 35265 - int rc = SQLITE_OK; /* Return code */ 36295 + 36296 + assert( pPager->eState==PAGER_READER 36297 + || pPager->eState==PAGER_OPEN 36298 + || pPager->eState==PAGER_ERROR 36299 + ); 36300 + 36301 + sqlite3BitvecDestroy(pPager->pInJournal); 36302 + pPager->pInJournal = 0; 36303 + releaseAllSavepoints(pPager); 36304 + 36305 + if( pagerUseWal(pPager) ){ 36306 + assert( !isOpen(pPager->jfd) ); 36307 + sqlite3WalEndReadTransaction(pPager->pWal); 36308 + pPager->eState = PAGER_OPEN; 36309 + }else if( !pPager->exclusiveMode ){ 36310 + int rc; /* Error code returned by pagerUnlockDb() */ 35266 36311 int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0; 35267 36312 35268 36313 /* If the operating system support deletion of open files, then 35269 36314 ** close the journal file when dropping the database lock. Otherwise 35270 36315 ** another connection with journal_mode=delete might delete the file 35271 36316 ** out from under us. 35272 36317 */ ................................................................................ 35278 36323 assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); 35279 36324 if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN) 35280 36325 || 1!=(pPager->journalMode & 5) 35281 36326 ){ 35282 36327 sqlite3OsClose(pPager->jfd); 35283 36328 } 35284 36329 35285 - sqlite3BitvecDestroy(pPager->pInJournal); 35286 - pPager->pInJournal = 0; 35287 - releaseAllSavepoints(pPager); 35288 - 35289 - /* If the file is unlocked, somebody else might change it. The 35290 - ** values stored in Pager.dbSize etc. might become invalid if 35291 - ** this happens. One can argue that this doesn't need to be cleared 35292 - ** until the change-counter check fails in PagerSharedLock(). 35293 - ** Clearing the page size cache here is being conservative. 35294 - */ 35295 - pPager->dbSizeValid = 0; 35296 - 35297 - if( pagerUseWal(pPager) ){ 35298 - sqlite3WalEndReadTransaction(pPager->pWal); 35299 - }else{ 35300 - rc = osUnlock(pPager->fd, NO_LOCK); 35301 - } 35302 - if( rc ){ 35303 - pPager->errCode = rc; 35304 - } 35305 - IOTRACE(("UNLOCK %p\n", pPager)) 35306 - 35307 - /* If Pager.errCode is set, the contents of the pager cache cannot be 35308 - ** trusted. Now that the pager file is unlocked, the contents of the 35309 - ** cache can be discarded and the error code safely cleared. 35310 - */ 35311 - if( pPager->errCode ){ 35312 - if( rc==SQLITE_OK ){ 35313 - pPager->errCode = SQLITE_OK; 35314 - } 35315 - pager_reset(pPager); 35316 - } 35317 - 36330 + /* If the pager is in the ERROR state and the call to unlock the database 36331 + ** file fails, set the current lock to UNKNOWN_LOCK. See the comment 36332 + ** above the #define for UNKNOWN_LOCK for an explanation of why this 36333 + ** is necessary. 36334 + */ 36335 + rc = pagerUnlockDb(pPager, NO_LOCK); 36336 + if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){ 36337 + pPager->eLock = UNKNOWN_LOCK; 36338 + } 36339 + 36340 + /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here 36341 + ** without clearing the error code. This is intentional - the error 36342 + ** code is cleared and the cache reset in the block below. 36343 + */ 36344 + assert( pPager->errCode || pPager->eState!=PAGER_ERROR ); 35318 36345 pPager->changeCountDone = 0; 35319 - pPager->state = PAGER_UNLOCK; 35320 - pPager->dbModified = 0; 35321 - } 35322 -} 35323 - 35324 -/* 35325 -** This function should be called when an IOERR, CORRUPT or FULL error 35326 -** may have occurred. The first argument is a pointer to the pager 35327 -** structure, the second the error-code about to be returned by a pager 35328 -** API function. The value returned is a copy of the second argument 35329 -** to this function. 35330 -** 35331 -** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL 35332 -** the error becomes persistent. Until the persistent error is cleared, 35333 -** subsequent API calls on this Pager will immediately return the same 35334 -** error code. 35335 -** 35336 -** A persistent error indicates that the contents of the pager-cache 36346 + pPager->eState = PAGER_OPEN; 36347 + } 36348 + 36349 + /* If Pager.errCode is set, the contents of the pager cache cannot be 36350 + ** trusted. Now that there are no outstanding references to the pager, 36351 + ** it can safely move back to PAGER_OPEN state. This happens in both 36352 + ** normal and exclusive-locking mode. 36353 + */ 36354 + if( pPager->errCode ){ 36355 + assert( !MEMDB ); 36356 + pager_reset(pPager); 36357 + pPager->changeCountDone = pPager->tempFile; 36358 + pPager->eState = PAGER_OPEN; 36359 + pPager->errCode = SQLITE_OK; 36360 + } 36361 + 36362 + pPager->journalOff = 0; 36363 + pPager->journalHdr = 0; 36364 + pPager->setMaster = 0; 36365 +} 36366 + 36367 +/* 36368 +** This function is called whenever an IOERR or FULL error that requires 36369 +** the pager to transition into the ERROR state may ahve occurred. 36370 +** The first argument is a pointer to the pager structure, the second 36371 +** the error-code about to be returned by a pager API function. The 36372 +** value returned is a copy of the second argument to this function. 36373 +** 36374 +** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the 36375 +** IOERR sub-codes, the pager enters the ERROR state and the error code 36376 +** is stored in Pager.errCode. While the pager remains in the ERROR state, 36377 +** all major API calls on the Pager will immediately return Pager.errCode. 36378 +** 36379 +** The ERROR state indicates that the contents of the pager-cache 35337 36380 ** cannot be trusted. This state can be cleared by completely discarding 35338 36381 ** the contents of the pager-cache. If a transaction was active when 35339 36382 ** the persistent error occurred, then the rollback journal may need 35340 36383 ** to be replayed to restore the contents of the database file (as if 35341 36384 ** it were a hot-journal). 35342 36385 */ 35343 36386 static int pager_error(Pager *pPager, int rc){ ................................................................................ 35346 36389 assert( 35347 36390 pPager->errCode==SQLITE_FULL || 35348 36391 pPager->errCode==SQLITE_OK || 35349 36392 (pPager->errCode & 0xff)==SQLITE_IOERR 35350 36393 ); 35351 36394 if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ 35352 36395 pPager->errCode = rc; 36396 + pPager->eState = PAGER_ERROR; 35353 36397 } 35354 36398 return rc; 35355 36399 } 35356 36400 35357 -/* 35358 -** Execute a rollback if a transaction is active and unlock the 35359 -** database file. 35360 -** 35361 -** If the pager has already entered the error state, do not attempt 35362 -** the rollback at this time. Instead, pager_unlock() is called. The 35363 -** call to pager_unlock() will discard all in-memory pages, unlock 35364 -** the database file and clear the error state. If this means that 35365 -** there is a hot-journal left in the file-system, the next connection 35366 -** to obtain a shared lock on the pager (which may be this one) will 35367 -** roll it back. 35368 -** 35369 -** If the pager has not already entered the error state, but an IO or 35370 -** malloc error occurs during a rollback, then this will itself cause 35371 -** the pager to enter the error state. Which will be cleared by the 35372 -** call to pager_unlock(), as described above. 35373 -*/ 35374 -static void pagerUnlockAndRollback(Pager *pPager){ 35375 - if( pPager->errCode==SQLITE_OK && pPager->state>=PAGER_RESERVED ){ 35376 - sqlite3BeginBenignMalloc(); 35377 - sqlite3PagerRollback(pPager); 35378 - sqlite3EndBenignMalloc(); 35379 - } 35380 - pager_unlock(pPager); 35381 -} 35382 - 35383 36401 /* 35384 36402 ** This routine ends a transaction. A transaction is usually ended by 35385 36403 ** either a COMMIT or a ROLLBACK operation. This routine may be called 35386 36404 ** after rollback of a hot-journal, or if an error occurs while opening 35387 36405 ** the journal file or writing the very first journal-header of a 35388 36406 ** database transaction. 35389 36407 ** 35390 -** If the pager is in PAGER_SHARED or PAGER_UNLOCK state when this 35391 -** routine is called, it is a no-op (returns SQLITE_OK). 36408 +** This routine is never called in PAGER_ERROR state. If it is called 36409 +** in PAGER_NONE or PAGER_SHARED state and the lock held is less 36410 +** exclusive than a RESERVED lock, it is a no-op. 35392 36411 ** 35393 36412 ** Otherwise, any active savepoints are released. 35394 36413 ** 35395 36414 ** If the journal file is open, then it is "finalized". Once a journal 35396 36415 ** file has been finalized it is not possible to use it to roll back a 35397 36416 ** transaction. Nor will it be considered to be a hot-journal by this 35398 36417 ** or any other database connection. Exactly how a journal is finalized ................................................................................ 35415 36434 ** The journal file is closed and deleted using sqlite3OsDelete(). 35416 36435 ** 35417 36436 ** If the pager is running in exclusive mode, this method of finalizing 35418 36437 ** the journal file is never used. Instead, if the journalMode is 35419 36438 ** DELETE and the pager is in exclusive mode, the method described under 35420 36439 ** journalMode==PERSIST is used instead. 35421 36440 ** 35422 -** After the journal is finalized, if running in non-exclusive mode, the 35423 -** pager moves to PAGER_SHARED state (and downgrades the lock on the 35424 -** database file accordingly). 35425 -** 35426 -** If the pager is running in exclusive mode and is in PAGER_SYNCED state, 35427 -** it moves to PAGER_EXCLUSIVE. No locks are downgraded when running in 35428 -** exclusive mode. 36441 +** After the journal is finalized, the pager moves to PAGER_READER state. 36442 +** If running in non-exclusive rollback mode, the lock on the file is 36443 +** downgraded to a SHARED_LOCK. 35429 36444 ** 35430 36445 ** SQLITE_OK is returned if no error occurs. If an error occurs during 35431 36446 ** any of the IO operations to finalize the journal file or unlock the 35432 36447 ** database then the IO error code is returned to the user. If the 35433 36448 ** operation to finalize the journal file fails, then the code still 35434 36449 ** tries to unlock the database file if not in exclusive mode. If the 35435 36450 ** unlock operation fails as well, then the first error code related ................................................................................ 35436 36451 ** to the first error encountered (the journal finalization one) is 35437 36452 ** returned. 35438 36453 */ 35439 36454 static int pager_end_transaction(Pager *pPager, int hasMaster){ 35440 36455 int rc = SQLITE_OK; /* Error code from journal finalization operation */ 35441 36456 int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ 35442 36457 35443 - if( pPager->state<PAGER_RESERVED ){ 36458 + /* Do nothing if the pager does not have an open write transaction 36459 + ** or at least a RESERVED lock. This function may be called when there 36460 + ** is no write-transaction active but a RESERVED or greater lock is 36461 + ** held under two circumstances: 36462 + ** 36463 + ** 1. After a successful hot-journal rollback, it is called with 36464 + ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK. 36465 + ** 36466 + ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE 36467 + ** lock switches back to locking_mode=normal and then executes a 36468 + ** read-transaction, this function is called with eState==PAGER_READER 36469 + ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed. 36470 + */ 36471 + assert( assert_pager_state(pPager) ); 36472 + assert( pPager->eState!=PAGER_ERROR ); 36473 + if( pPager->eState<PAGER_WRITER_LOCKED && pPager->eLock<RESERVED_LOCK ){ 35444 36474 return SQLITE_OK; 35445 36475 } 36476 + 35446 36477 releaseAllSavepoints(pPager); 35447 - 35448 36478 assert( isOpen(pPager->jfd) || pPager->pInJournal==0 ); 35449 36479 if( isOpen(pPager->jfd) ){ 35450 36480 assert( !pagerUseWal(pPager) ); 35451 36481 35452 36482 /* Finalize the journal file. */ 35453 36483 if( sqlite3IsMemJournal(pPager->jfd) ){ 35454 36484 assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); ................................................................................ 35456 36486 }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){ 35457 36487 if( pPager->journalOff==0 ){ 35458 36488 rc = SQLITE_OK; 35459 36489 }else{ 35460 36490 rc = sqlite3OsTruncate(pPager->jfd, 0); 35461 36491 } 35462 36492 pPager->journalOff = 0; 35463 - pPager->journalStarted = 0; 35464 36493 }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST 35465 36494 || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL) 35466 36495 ){ 35467 36496 rc = zeroJournalHdr(pPager, hasMaster); 35468 - pager_error(pPager, rc); 35469 36497 pPager->journalOff = 0; 35470 - pPager->journalStarted = 0; 35471 36498 }else{ 35472 36499 /* This branch may be executed with Pager.journalMode==MEMORY if 35473 36500 ** a hot-journal was just rolled back. In this case the journal 35474 36501 ** file should be closed and deleted. If this connection writes to 35475 36502 ** the database file, it will do so using an in-memory journal. 35476 36503 */ 35477 36504 assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE ................................................................................ 35479 36506 || pPager->journalMode==PAGER_JOURNALMODE_WAL 35480 36507 ); 35481 36508 sqlite3OsClose(pPager->jfd); 35482 36509 if( !pPager->tempFile ){ 35483 36510 rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); 35484 36511 } 35485 36512 } 36513 + } 35486 36514 35487 36515 #ifdef SQLITE_CHECK_PAGES 35488 - sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); 36516 + sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); 36517 + if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){ 36518 + PgHdr *p = pager_lookup(pPager, 1); 36519 + if( p ){ 36520 + p->pageHash = 0; 36521 + sqlite3PagerUnref(p); 36522 + } 36523 + } 35489 36524 #endif 35490 - } 36525 + 35491 36526 sqlite3BitvecDestroy(pPager->pInJournal); 35492 36527 pPager->pInJournal = 0; 35493 36528 pPager->nRec = 0; 35494 36529 sqlite3PcacheCleanAll(pPager->pPCache); 36530 + sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); 35495 36531 35496 36532 if( pagerUseWal(pPager) ){ 36533 + /* Drop the WAL write-lock, if any. Also, if the connection was in 36534 + ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE 36535 + ** lock held on the database file. 36536 + */ 35497 36537 rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); 35498 36538 assert( rc2==SQLITE_OK ); 35499 - pPager->state = PAGER_SHARED; 35500 - 35501 - /* If the connection was in locking_mode=exclusive mode but is no longer, 35502 - ** drop the EXCLUSIVE lock held on the database file. 35503 - */ 35504 - if( !pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, 0) ){ 35505 - rc2 = osUnlock(pPager->fd, SHARED_LOCK); 35506 - } 35507 - }else if( !pPager->exclusiveMode ){ 35508 - rc2 = osUnlock(pPager->fd, SHARED_LOCK); 35509 - pPager->state = PAGER_SHARED; 36539 + } 36540 + if( !pPager->exclusiveMode 36541 + && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) 36542 + ){ 36543 + rc2 = pagerUnlockDb(pPager, SHARED_LOCK); 35510 36544 pPager->changeCountDone = 0; 35511 - }else if( pPager->state==PAGER_SYNCED ){ 35512 - pPager->state = PAGER_EXCLUSIVE; 35513 36545 } 36546 + pPager->eState = PAGER_READER; 35514 36547 pPager->setMaster = 0; 35515 - pPager->needSync = 0; 35516 - pPager->dbModified = 0; 35517 - 35518 - /* TODO: Is this optimal? Why is the db size invalidated here 35519 - ** when the database file is not unlocked? */ 35520 - pPager->dbOrigSize = 0; 35521 - sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); 35522 - if( !MEMDB ){ 35523 - pPager->dbSizeValid = 0; 35524 - } 35525 36548 35526 36549 return (rc==SQLITE_OK?rc2:rc); 35527 36550 } 36551 + 36552 +/* 36553 +** Execute a rollback if a transaction is active and unlock the 36554 +** database file. 36555 +** 36556 +** If the pager has already entered the ERROR state, do not attempt 36557 +** the rollback at this time. Instead, pager_unlock() is called. The 36558 +** call to pager_unlock() will discard all in-memory pages, unlock 36559 +** the database file and move the pager back to OPEN state. If this 36560 +** means that there is a hot-journal left in the file-system, the next 36561 +** connection to obtain a shared lock on the pager (which may be this one) 36562 +** will roll it back. 36563 +** 36564 +** If the pager has not already entered the ERROR state, but an IO or 36565 +** malloc error occurs during a rollback, then this will itself cause 36566 +** the pager to enter the ERROR state. Which will be cleared by the 36567 +** call to pager_unlock(), as described above. 36568 +*/ 36569 +static void pagerUnlockAndRollback(Pager *pPager){ 36570 + if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){ 36571 + assert( assert_pager_state(pPager) ); 36572 + if( pPager->eState>=PAGER_WRITER_LOCKED ){ 36573 + sqlite3BeginBenignMalloc(); 36574 + sqlite3PagerRollback(pPager); 36575 + sqlite3EndBenignMalloc(); 36576 + }else if( !pPager->exclusiveMode ){ 36577 + assert( pPager->eState==PAGER_READER ); 36578 + pager_end_transaction(pPager, 0); 36579 + } 36580 + } 36581 + pager_unlock(pPager); 36582 +} 35528 36583 35529 36584 /* 35530 36585 ** Parameter aData must point to a buffer of pPager->pageSize bytes 35531 36586 ** of data. Compute and return a checksum based ont the contents of the 35532 36587 ** page of data and the current value of pPager->cksumInit. 35533 36588 ** 35534 36589 ** This is not a real checksum. It is really just the sum of the ................................................................................ 35572 36627 35573 36628 /* 35574 36629 ** Read a single page from either the journal file (if isMainJrnl==1) or 35575 36630 ** from the sub-journal (if isMainJrnl==0) and playback that page. 35576 36631 ** The page begins at offset *pOffset into the file. The *pOffset 35577 36632 ** value is increased to the start of the next page in the journal. 35578 36633 ** 35579 -** The isMainJrnl flag is true if this is the main rollback journal and 35580 -** false for the statement journal. The main rollback journal uses 35581 -** checksums - the statement journal does not. 36634 +** The main rollback journal uses checksums - the statement journal does 36635 +** not. 35582 36636 ** 35583 36637 ** If the page number of the page record read from the (sub-)journal file 35584 36638 ** is greater than the current value of Pager.dbSize, then playback is 35585 36639 ** skipped and SQLITE_OK is returned. 35586 36640 ** 35587 36641 ** If pDone is not NULL, then it is a record of pages that have already 35588 36642 ** been played back. If the page at *pOffset has already been played back ................................................................................ 35627 36681 assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */ 35628 36682 assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */ 35629 36683 assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */ 35630 36684 35631 36685 aData = pPager->pTmpSpace; 35632 36686 assert( aData ); /* Temp storage must have already been allocated */ 35633 36687 assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) ); 36688 + 36689 + /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction 36690 + ** or savepoint rollback done at the request of the caller) or this is 36691 + ** a hot-journal rollback. If it is a hot-journal rollback, the pager 36692 + ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback 36693 + ** only reads from the main journal, not the sub-journal. 36694 + */ 36695 + assert( pPager->eState>=PAGER_WRITER_CACHEMOD 36696 + || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK) 36697 + ); 36698 + assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl ); 35634 36699 35635 36700 /* Read the page number and page data from the journal or sub-journal 35636 36701 ** file. Return an error code to the caller if an IO error occurs. 35637 36702 */ 35638 36703 jfd = isMainJrnl ? pPager->jfd : pPager->sjfd; 35639 36704 rc = read32bits(jfd, *pOffset, &pgno); 35640 36705 if( rc!=SQLITE_OK ) return rc; ................................................................................ 35664 36729 35665 36730 /* If this page has already been played by before during the current 35666 36731 ** rollback, then don't bother to play it back again. 35667 36732 */ 35668 36733 if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){ 35669 36734 return rc; 35670 36735 } 35671 - assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE ); 35672 36736 35673 36737 /* When playing back page 1, restore the nReserve setting 35674 36738 */ 35675 36739 if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){ 35676 36740 pPager->nReserve = ((u8*)aData)[20]; 35677 36741 pagerReportSize(pPager); 35678 36742 } 35679 36743 35680 - /* If the pager is in RESERVED state, then there must be a copy of this 36744 + /* If the pager is in CACHEMOD state, then there must be a copy of this 35681 36745 ** page in the pager cache. In this case just update the pager cache, 35682 36746 ** not the database file. The page is left marked dirty in this case. 35683 36747 ** 35684 36748 ** An exception to the above rule: If the database is in no-sync mode 35685 36749 ** and a page is moved during an incremental vacuum then the page may 35686 36750 ** not be in the pager cache. Later: if a malloc() or IO error occurs 35687 36751 ** during a Movepage() call, then the page may not be in the cache 35688 36752 ** either. So the condition described in the above paragraph is not 35689 36753 ** assert()able. 35690 36754 ** 35691 - ** If in EXCLUSIVE state, then we update the pager cache if it exists 35692 - ** and the main file. The page is then marked not dirty. 36755 + ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the 36756 + ** pager cache if it exists and the main file. The page is then marked 36757 + ** not dirty. Since this code is only executed in PAGER_OPEN state for 36758 + ** a hot-journal rollback, it is guaranteed that the page-cache is empty 36759 + ** if the pager is in OPEN state. 35693 36760 ** 35694 36761 ** Ticket #1171: The statement journal might contain page content that is 35695 36762 ** different from the page content at the start of the transaction. 35696 36763 ** This occurs when a page is changed prior to the start of a statement 35697 36764 ** then changed again within the statement. When rolling back such a 35698 36765 ** statement we must not write to the original database unless we know 35699 36766 ** for certain that original page contents are synced into the main rollback ................................................................................ 35711 36778 */ 35712 36779 if( pagerUseWal(pPager) ){ 35713 36780 pPg = 0; 35714 36781 }else{ 35715 36782 pPg = pager_lookup(pPager, pgno); 35716 36783 } 35717 36784 assert( pPg || !MEMDB ); 36785 + assert( pPager->eState!=PAGER_OPEN || pPg==0 ); 35718 36786 PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n", 35719 36787 PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData), 35720 36788 (isMainJrnl?"main-journal":"sub-journal") 35721 36789 )); 35722 36790 if( isMainJrnl ){ 35723 36791 isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr); 35724 36792 }else{ 35725 36793 isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC)); 35726 36794 } 35727 - if( (pPager->state>=PAGER_EXCLUSIVE) 35728 - && isOpen(pPager->fd) 36795 + if( isOpen(pPager->fd) 36796 + && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) 35729 36797 && isSynced 35730 36798 ){ 35731 36799 i64 ofst = (pgno-1)*(i64)pPager->pageSize; 35732 36800 testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 ); 35733 36801 assert( !pagerUseWal(pPager) ); 35734 36802 rc = sqlite3OsWrite(pPager->fd, (u8*)aData, pPager->pageSize, ofst); 35735 36803 if( pgno>pPager->dbFileSize ){ ................................................................................ 35797 36865 ** be written out into the database file before its journal file 35798 36866 ** segment is synced. If a crash occurs during or following this, 35799 36867 ** database corruption may ensue. 35800 36868 */ 35801 36869 assert( !pagerUseWal(pPager) ); 35802 36870 sqlite3PcacheMakeClean(pPg); 35803 36871 } 35804 -#ifdef SQLITE_CHECK_PAGES 35805 - pPg->pageHash = pager_pagehash(pPg); 35806 -#endif 36872 + pager_set_pagehash(pPg); 36873 + 35807 36874 /* If this was page 1, then restore the value of Pager.dbFileVers. 35808 36875 ** Do this before any decoding. */ 35809 36876 if( pgno==1 ){ 35810 36877 memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); 35811 36878 } 35812 36879 35813 36880 /* Decode the page just read from disk */ ................................................................................ 35951 37018 35952 37019 35953 37020 /* 35954 37021 ** This function is used to change the actual size of the database 35955 37022 ** file in the file-system. This only happens when committing a transaction, 35956 37023 ** or rolling back a transaction (including rolling back a hot-journal). 35957 37024 ** 35958 -** If the main database file is not open, or an exclusive lock is not 35959 -** held, this function is a no-op. Otherwise, the size of the file is 35960 -** changed to nPage pages (nPage*pPager->pageSize bytes). If the file 35961 -** on disk is currently larger than nPage pages, then use the VFS 37025 +** If the main database file is not open, or the pager is not in either 37026 +** DBMOD or OPEN state, this function is a no-op. Otherwise, the size 37027 +** of the file is changed to nPage pages (nPage*pPager->pageSize bytes). 37028 +** If the file on disk is currently larger than nPage pages, then use the VFS 35962 37029 ** xTruncate() method to truncate it. 35963 37030 ** 35964 37031 ** Or, it might might be the case that the file on disk is smaller than 35965 37032 ** nPage pages. Some operating system implementations can get confused if 35966 37033 ** you try to truncate a file to some size that is larger than it 35967 37034 ** currently is, so detect this case and write a single zero byte to 35968 37035 ** the end of the new file instead. 35969 37036 ** 35970 37037 ** If successful, return SQLITE_OK. If an IO error occurs while modifying 35971 37038 ** the database file, return the error code to the caller. 35972 37039 */ 35973 37040 static int pager_truncate(Pager *pPager, Pgno nPage){ 35974 37041 int rc = SQLITE_OK; 35975 - if( pPager->state>=PAGER_EXCLUSIVE && isOpen(pPager->fd) ){ 37042 + assert( pPager->eState!=PAGER_ERROR ); 37043 + assert( pPager->eState!=PAGER_READER ); 37044 + 37045 + if( isOpen(pPager->fd) 37046 + && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) 37047 + ){ 35976 37048 i64 currentSize, newSize; 37049 + assert( pPager->eLock==EXCLUSIVE_LOCK ); 35977 37050 /* TODO: Is it safe to use Pager.dbFileSize here? */ 35978 37051 rc = sqlite3OsFileSize(pPager->fd, ¤tSize); 35979 37052 newSize = pPager->pageSize*(i64)nPage; 35980 37053 if( rc==SQLITE_OK && currentSize!=newSize ){ 35981 37054 if( currentSize>newSize ){ 35982 37055 rc = sqlite3OsTruncate(pPager->fd, newSize); 35983 37056 }else{ ................................................................................ 36093 37166 int needPagerReset; /* True to reset page prior to first page rollback */ 36094 37167 36095 37168 /* Figure out how many records are in the journal. Abort early if 36096 37169 ** the journal is empty. 36097 37170 */ 36098 37171 assert( isOpen(pPager->jfd) ); 36099 37172 rc = sqlite3OsFileSize(pPager->jfd, &szJ); 36100 - if( rc!=SQLITE_OK || szJ==0 ){ 37173 + if( rc!=SQLITE_OK ){ 36101 37174 goto end_playback; 36102 37175 } 36103 37176 36104 37177 /* Read the master journal name from the journal, if it is present. 36105 37178 ** If a master journal file name is specified, but the file is not 36106 37179 ** present on disk, then the journal is not hot and does not need to be 36107 37180 ** played back. ................................................................................ 36127 37200 /* This loop terminates either when a readJournalHdr() or 36128 37201 ** pager_playback_one_page() call returns SQLITE_DONE or an IO error 36129 37202 ** occurs. 36130 37203 */ 36131 37204 while( 1 ){ 36132 37205 /* Read the next journal header from the journal file. If there are 36133 37206 ** not enough bytes left in the journal file for a complete header, or 36134 - ** it is corrupted, then a process must of failed while writing it. 37207 + ** it is corrupted, then a process must have failed while writing it. 36135 37208 ** This indicates nothing more needs to be rolled back. 36136 37209 */ 36137 37210 rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg); 36138 37211 if( rc!=SQLITE_OK ){ 36139 37212 if( rc==SQLITE_DONE ){ 36140 37213 rc = SQLITE_OK; 36141 37214 } ................................................................................ 36241 37314 pPager->changeCountDone = pPager->tempFile; 36242 37315 36243 37316 if( rc==SQLITE_OK ){ 36244 37317 zMaster = pPager->pTmpSpace; 36245 37318 rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); 36246 37319 testcase( rc!=SQLITE_OK ); 36247 37320 } 36248 - if( rc==SQLITE_OK && pPager->noSync==0 && pPager->state>=PAGER_EXCLUSIVE ){ 36249 - rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); 36250 - } 36251 - if( rc==SQLITE_OK && pPager->noSync==0 && pPager->state>=PAGER_EXCLUSIVE ){ 37321 + if( rc==SQLITE_OK && !pPager->noSync 37322 + && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) 37323 + ){ 36252 37324 rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); 36253 37325 } 36254 37326 if( rc==SQLITE_OK ){ 36255 37327 rc = pager_end_transaction(pPager, zMaster[0]!='\0'); 36256 37328 testcase( rc!=SQLITE_OK ); 36257 37329 } 36258 37330 if( rc==SQLITE_OK && zMaster[0] && res ){ ................................................................................ 36286 37358 static int readDbPage(PgHdr *pPg){ 36287 37359 Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */ 36288 37360 Pgno pgno = pPg->pgno; /* Page number to read */ 36289 37361 int rc = SQLITE_OK; /* Return code */ 36290 37362 int isInWal = 0; /* True if page is in log file */ 36291 37363 int pgsz = pPager->pageSize; /* Number of bytes to read */ 36292 37364 36293 - assert( pPager->state>=PAGER_SHARED && !MEMDB ); 37365 + assert( pPager->eState>=PAGER_READER && !MEMDB ); 36294 37366 assert( isOpen(pPager->fd) ); 36295 37367 36296 37368 if( NEVER(!isOpen(pPager->fd)) ){ 36297 37369 assert( pPager->tempFile ); 36298 37370 memset(pPg->pData, 0, pPager->pageSize); 36299 37371 return SQLITE_OK; 36300 37372 } ................................................................................ 36433 37505 ); 36434 37506 if( rc==SQLITE_OK && pPager->pBackup ){ 36435 37507 PgHdr *p; 36436 37508 for(p=pList; p; p=p->pDirty){ 36437 37509 sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); 36438 37510 } 36439 37511 } 37512 + 37513 +#ifdef SQLITE_CHECK_PAGES 37514 + { 37515 + PgHdr *p; 37516 + for(p=pList; p; p=p->pDirty) pager_set_pagehash(p); 37517 + } 37518 +#endif 37519 + 36440 37520 return rc; 36441 37521 } 36442 37522 36443 37523 /* 36444 37524 ** Begin a read transaction on the WAL. 36445 37525 ** 36446 37526 ** This routine used to be called "pagerOpenSnapshot()" because it essentially ................................................................................ 36449 37529 ** other writers or checkpointers. 36450 37530 */ 36451 37531 static int pagerBeginReadTransaction(Pager *pPager){ 36452 37532 int rc; /* Return code */ 36453 37533 int changed = 0; /* True if cache must be reset */ 36454 37534 36455 37535 assert( pagerUseWal(pPager) ); 37536 + assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); 36456 37537 36457 37538 /* sqlite3WalEndReadTransaction() was not called for the previous 36458 37539 ** transaction in locking_mode=EXCLUSIVE. So call it now. If we 36459 37540 ** are in locking_mode=NORMAL and EndRead() was previously called, 36460 37541 ** the duplicate call is harmless. 36461 37542 */ 36462 37543 sqlite3WalEndReadTransaction(pPager->pWal); 36463 37544 36464 37545 rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed); 36465 - if( rc==SQLITE_OK ){ 36466 - int dummy; 36467 - if( changed ){ 36468 - pager_reset(pPager); 36469 - assert( pPager->errCode || pPager->dbSizeValid==0 ); 36470 - } 36471 - rc = sqlite3PagerPagecount(pPager, &dummy); 36472 - } 36473 - pPager->state = PAGER_SHARED; 36474 - 36475 - return rc; 36476 -} 36477 - 37546 + if( rc!=SQLITE_OK || changed ){ 37547 + pager_reset(pPager); 37548 + } 37549 + 37550 + return rc; 37551 +} 37552 +#endif 37553 + 37554 +/* 37555 +** This function is called as part of the transition from PAGER_OPEN 37556 +** to PAGER_READER state to determine the size of the database file 37557 +** in pages (assuming the page size currently stored in Pager.pageSize). 37558 +** 37559 +** If no error occurs, SQLITE_OK is returned and the size of the database 37560 +** in pages is stored in *pnPage. Otherwise, an error code (perhaps 37561 +** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified. 37562 +*/ 37563 +static int pagerPagecount(Pager *pPager, Pgno *pnPage){ 37564 + Pgno nPage; /* Value to return via *pnPage */ 37565 + 37566 + /* Query the WAL sub-system for the database size. The WalDbsize() 37567 + ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or 37568 + ** if the database size is not available. The database size is not 37569 + ** available from the WAL sub-system if the log file is empty or 37570 + ** contains no valid committed transactions. 37571 + */ 37572 + assert( pPager->eState==PAGER_OPEN ); 37573 + assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock ); 37574 + nPage = sqlite3WalDbsize(pPager->pWal); 37575 + 37576 + /* If the database size was not available from the WAL sub-system, 37577 + ** determine it based on the size of the database file. If the size 37578 + ** of the database file is not an integer multiple of the page-size, 37579 + ** round down to the nearest page. Except, any file larger than 0 37580 + ** bytes in size is considered to contain at least one page. 37581 + */ 37582 + if( nPage==0 ){ 37583 + i64 n = 0; /* Size of db file in bytes */ 37584 + assert( isOpen(pPager->fd) || pPager->tempFile ); 37585 + if( isOpen(pPager->fd) ){ 37586 + int rc = sqlite3OsFileSize(pPager->fd, &n); 37587 + if( rc!=SQLITE_OK ){ 37588 + return rc; 37589 + } 37590 + } 37591 + nPage = (Pgno)(n / pPager->pageSize); 37592 + if( nPage==0 && n>0 ){ 37593 + nPage = 1; 37594 + } 37595 + } 37596 + 37597 + /* If the current number of pages in the file is greater than the 37598 + ** configured maximum pager number, increase the allowed limit so 37599 + ** that the file can be read. 37600 + */ 37601 + if( nPage>pPager->mxPgno ){ 37602 + pPager->mxPgno = (Pgno)nPage; 37603 + } 37604 + 37605 + *pnPage = nPage; 37606 + return SQLITE_OK; 37607 +} 37608 + 37609 +#ifndef SQLITE_OMIT_WAL 36478 37610 /* 36479 37611 ** Check if the *-wal file that corresponds to the database opened by pPager 36480 37612 ** exists if the database is not empy, or verify that the *-wal file does 36481 37613 ** not exist (by deleting it) if the database file is empty. 36482 37614 ** 36483 37615 ** If the database is not empty and the *-wal file exists, open the pager 36484 37616 ** in WAL mode. If the database is empty or if no *-wal file exists and 36485 37617 ** if no error occurs, make sure Pager.journalMode is not set to 36486 37618 ** PAGER_JOURNALMODE_WAL. 36487 37619 ** 36488 37620 ** Return SQLITE_OK or an error code. 36489 37621 ** 36490 -** If the WAL file is opened, also open a snapshot (read transaction). 36491 -** 36492 37622 ** The caller must hold a SHARED lock on the database file to call this 36493 37623 ** function. Because an EXCLUSIVE lock on the db file is required to delete 36494 37624 ** a WAL on a none-empty database, this ensures there is no race condition 36495 37625 ** between the xAccess() below and an xDelete() being executed by some 36496 37626 ** other connection. 36497 37627 */ 36498 37628 static int pagerOpenWalIfPresent(Pager *pPager){ 36499 37629 int rc = SQLITE_OK; 37630 + assert( pPager->eState==PAGER_OPEN ); 37631 + assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock ); 37632 + 36500 37633 if( !pPager->tempFile ){ 36501 37634 int isWal; /* True if WAL file exists */ 36502 - int nPage; /* Size of the database file */ 36503 - assert( pPager->state>=SHARED_LOCK ); 36504 - rc = sqlite3PagerPagecount(pPager, &nPage); 37635 + Pgno nPage; /* Size of the database file */ 37636 + 37637 + rc = pagerPagecount(pPager, &nPage); 36505 37638 if( rc ) return rc; 36506 37639 if( nPage==0 ){ 36507 37640 rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); 36508 37641 isWal = 0; 36509 37642 }else{ 36510 37643 rc = sqlite3OsAccess( 36511 37644 pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal 36512 37645 ); 36513 37646 } 36514 37647 if( rc==SQLITE_OK ){ 36515 37648 if( isWal ){ 36516 - pager_reset(pPager); 37649 + testcase( sqlite3PcachePagecount(pPager->pPCache)==0 ); 36517 37650 rc = sqlite3PagerOpenWal(pPager, 0); 36518 - if( rc==SQLITE_OK ){ 36519 - rc = pagerBeginReadTransaction(pPager); 36520 - } 36521 37651 }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){ 36522 37652 pPager->journalMode = PAGER_JOURNALMODE_DELETE; 36523 37653 } 36524 37654 } 36525 37655 } 36526 37656 return rc; 36527 37657 } ................................................................................ 36565 37695 */ 36566 37696 static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ 36567 37697 i64 szJ; /* Effective size of the main journal */ 36568 37698 i64 iHdrOff; /* End of first segment of main-journal records */ 36569 37699 int rc = SQLITE_OK; /* Return code */ 36570 37700 Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */ 36571 37701 36572 - assert( pPager->state>=PAGER_SHARED ); 37702 + assert( pPager->eState!=PAGER_ERROR ); 37703 + assert( pPager->eState>=PAGER_WRITER_LOCKED ); 36573 37704 36574 37705 /* Allocate a bitvec to use to store the set of pages rolled back */ 36575 37706 if( pSavepoint ){ 36576 37707 pDone = sqlite3BitvecCreate(pSavepoint->nOrig); 36577 37708 if( !pDone ){ 36578 37709 return SQLITE_NOMEM; 36579 37710 } ................................................................................ 36704 37835 ** and FULL=3. 36705 37836 */ 36706 37837 #ifndef SQLITE_OMIT_PAGER_PRAGMAS 36707 37838 SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){ 36708 37839 pPager->noSync = (level==1 || pPager->tempFile) ?1:0; 36709 37840 pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0; 36710 37841 pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL); 36711 - if( pPager->noSync ) pPager->needSync = 0; 36712 37842 } 36713 37843 #endif 36714 37844 36715 37845 /* 36716 37846 ** The following global variable is incremented whenever the library 36717 37847 ** attempts to open a temporary file. This information is used for 36718 37848 ** testing and analysis only. ................................................................................ 36786 37916 36787 37917 /* 36788 37918 ** Change the page size used by the Pager object. The new page size 36789 37919 ** is passed in *pPageSize. 36790 37920 ** 36791 37921 ** If the pager is in the error state when this function is called, it 36792 37922 ** is a no-op. The value returned is the error state error code (i.e. 36793 -** one of SQLITE_IOERR, SQLITE_CORRUPT or SQLITE_FULL). 37923 +** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL). 36794 37924 ** 36795 37925 ** Otherwise, if all of the following are true: 36796 37926 ** 36797 37927 ** * the new page size (value of *pPageSize) is valid (a power 36798 37928 ** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and 36799 37929 ** 36800 37930 ** * there are no outstanding page references, and ................................................................................ 36810 37940 ** In all other cases, SQLITE_OK is returned. 36811 37941 ** 36812 37942 ** If the page size is not changed, either because one of the enumerated 36813 37943 ** conditions above is not true, the pager was in error state when this 36814 37944 ** function was called, or because the memory allocation attempt failed, 36815 37945 ** then *pPageSize is set to the old, retained page size before returning. 36816 37946 */ 36817 -SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize, int nReserve){ 36818 - int rc = pPager->errCode; 36819 - 36820 - if( rc==SQLITE_OK ){ 36821 - u16 pageSize = *pPageSize; 36822 - assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); 36823 - if( (pPager->memDb==0 || pPager->dbSize==0) 36824 - && sqlite3PcacheRefCount(pPager->pPCache)==0 36825 - && pageSize && pageSize!=pPager->pageSize 36826 - ){ 36827 - char *pNew = (char *)sqlite3PageMalloc(pageSize); 36828 - if( !pNew ){ 36829 - rc = SQLITE_NOMEM; 36830 - }else{ 36831 - pager_reset(pPager); 36832 - pPager->pageSize = pageSize; 36833 - sqlite3PageFree(pPager->pTmpSpace); 36834 - pPager->pTmpSpace = pNew; 36835 - sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); 36836 - } 36837 - } 36838 - *pPageSize = (u16)pPager->pageSize; 37947 +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){ 37948 + int rc = SQLITE_OK; 37949 + 37950 + /* It is not possible to do a full assert_pager_state() here, as this 37951 + ** function may be called from within PagerOpen(), before the state 37952 + ** of the Pager object is internally consistent. 37953 + ** 37954 + ** At one point this function returned an error if the pager was in 37955 + ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that 37956 + ** there is at least one outstanding page reference, this function 37957 + ** is a no-op for that case anyhow. 37958 + */ 37959 + 37960 + u32 pageSize = *pPageSize; 37961 + assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); 37962 + if( (pPager->memDb==0 || pPager->dbSize==0) 37963 + && sqlite3PcacheRefCount(pPager->pPCache)==0 37964 + && pageSize && pageSize!=(u32)pPager->pageSize 37965 + ){ 37966 + char *pNew = NULL; /* New temp space */ 37967 + i64 nByte = 0; 37968 + 37969 + if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){ 37970 + rc = sqlite3OsFileSize(pPager->fd, &nByte); 37971 + } 37972 + if( rc==SQLITE_OK ){ 37973 + pNew = (char *)sqlite3PageMalloc(pageSize); 37974 + if( !pNew ) rc = SQLITE_NOMEM; 37975 + } 37976 + 37977 + if( rc==SQLITE_OK ){ 37978 + pager_reset(pPager); 37979 + pPager->dbSize = (Pgno)(nByte/pageSize); 37980 + pPager->pageSize = pageSize; 37981 + sqlite3PageFree(pPager->pTmpSpace); 37982 + pPager->pTmpSpace = pNew; 37983 + sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); 37984 + } 37985 + } 37986 + 37987 + *pPageSize = pPager->pageSize; 37988 + if( rc==SQLITE_OK ){ 36839 37989 if( nReserve<0 ) nReserve = pPager->nReserve; 36840 37990 assert( nReserve>=0 && nReserve<1000 ); 36841 37991 pPager->nReserve = (i16)nReserve; 36842 37992 pagerReportSize(pPager); 36843 37993 } 36844 37994 return rc; 36845 37995 } ................................................................................ 36860 38010 ** Attempt to set the maximum database page count if mxPage is positive. 36861 38011 ** Make no changes if mxPage is zero or negative. And never reduce the 36862 38012 ** maximum page count below the current size of the database. 36863 38013 ** 36864 38014 ** Regardless of mxPage, return the current maximum page count. 36865 38015 */ 36866 38016 SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ 36867 - int nPage; 36868 38017 if( mxPage>0 ){ 36869 38018 pPager->mxPgno = mxPage; 36870 38019 } 36871 - if( pPager->state!=PAGER_UNLOCK ){ 36872 - sqlite3PagerPagecount(pPager, &nPage); 36873 - assert( (int)pPager->mxPgno>=nPage ); 38020 + if( pPager->eState!=PAGER_OPEN && pPager->mxPgno<pPager->dbSize ){ 38021 + pPager->mxPgno = pPager->dbSize; 36874 38022 } 36875 38023 return pPager->mxPgno; 36876 38024 } 36877 38025 36878 38026 /* 36879 38027 ** The following set of routines are used to disable the simulated 36880 38028 ** I/O error mechanism. These routines are used to avoid simulated ................................................................................ 36931 38079 rc = SQLITE_OK; 36932 38080 } 36933 38081 } 36934 38082 return rc; 36935 38083 } 36936 38084 36937 38085 /* 36938 -** Return the total number of pages in the database file associated 36939 -** with pPager. Normally, this is calculated as (<db file size>/<page-size>). 38086 +** This function may only be called when a read-transaction is open on 38087 +** the pager. It returns the total number of pages in the database. 38088 +** 36940 38089 ** However, if the file is between 1 and <page-size> bytes in size, then 36941 38090 ** this is considered a 1 page file. 36942 -** 36943 -** If the pager is in error state when this function is called, then the 36944 -** error state error code is returned and *pnPage left unchanged. Or, 36945 -** if the file system has to be queried for the size of the file and 36946 -** the query attempt returns an IO error, the IO error code is returned 36947 -** and *pnPage is left unchanged. 36948 -** 36949 -** Otherwise, if everything is successful, then SQLITE_OK is returned 36950 -** and *pnPage is set to the number of pages in the database. 36951 38091 */ 36952 -SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){ 36953 - Pgno nPage = 0; /* Value to return via *pnPage */ 36954 - 36955 - /* Determine the number of pages in the file. Store this in nPage. */ 36956 - if( pPager->dbSizeValid ){ 36957 - nPage = pPager->dbSize; 36958 - }else{ 36959 - int rc; /* Error returned by OsFileSize() */ 36960 - i64 n = 0; /* File size in bytes returned by OsFileSize() */ 36961 - 36962 - if( pagerUseWal(pPager) && pPager->state!=PAGER_UNLOCK ){ 36963 - sqlite3WalDbsize(pPager->pWal, &nPage); 36964 - } 36965 - 36966 - if( nPage==0 ){ 36967 - assert( isOpen(pPager->fd) || pPager->tempFile ); 36968 - if( isOpen(pPager->fd) ){ 36969 - if( SQLITE_OK!=(rc = sqlite3OsFileSize(pPager->fd, &n)) ){ 36970 - pager_error(pPager, rc); 36971 - return rc; 36972 - } 36973 - } 36974 - if( n>0 && n<pPager->pageSize ){ 36975 - nPage = 1; 36976 - }else{ 36977 - nPage = (Pgno)(n / pPager->pageSize); 36978 - } 36979 - } 36980 - if( pPager->state!=PAGER_UNLOCK ){ 36981 - pPager->dbSize = nPage; 36982 - pPager->dbFileSize = nPage; 36983 - pPager->dbSizeValid = 1; 36984 - } 36985 - } 36986 - 36987 - /* If the current number of pages in the file is greater than the 36988 - ** configured maximum pager number, increase the allowed limit so 36989 - ** that the file can be read. 36990 - */ 36991 - if( nPage>pPager->mxPgno ){ 36992 - pPager->mxPgno = (Pgno)nPage; 36993 - } 36994 - 36995 - /* Set the output variable and return SQLITE_OK */ 36996 - *pnPage = nPage; 36997 - return SQLITE_OK; 38092 +SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){ 38093 + assert( pPager->eState>=PAGER_READER ); 38094 + assert( pPager->eState!=PAGER_WRITER_FINISHED ); 38095 + *pnPage = (int)pPager->dbSize; 36998 38096 } 36999 38097 37000 38098 37001 38099 /* 37002 38100 ** Try to obtain a lock of type locktype on the database file. If 37003 38101 ** a similar or greater lock is already held, this function is a no-op 37004 38102 ** (returning SQLITE_OK immediately). ................................................................................ 37011 38109 ** Return SQLITE_OK on success and an error code if we cannot obtain 37012 38110 ** the lock. If the lock is obtained successfully, set the Pager.state 37013 38111 ** variable to locktype before returning. 37014 38112 */ 37015 38113 static int pager_wait_on_lock(Pager *pPager, int locktype){ 37016 38114 int rc; /* Return code */ 37017 38115 37018 - /* The OS lock values must be the same as the Pager lock values */ 37019 - assert( PAGER_SHARED==SHARED_LOCK ); 37020 - assert( PAGER_RESERVED==RESERVED_LOCK ); 37021 - assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK ); 37022 - 37023 - /* If the file is currently unlocked then the size must be unknown. It 37024 - ** must not have been modified at this point. 37025 - */ 37026 - assert( pPager->state>=PAGER_SHARED || pPager->dbSizeValid==0 ); 37027 - assert( pPager->state>=PAGER_SHARED || pPager->dbModified==0 ); 37028 - 37029 38116 /* Check that this is either a no-op (because the requested lock is 37030 38117 ** already held, or one of the transistions that the busy-handler 37031 38118 ** may be invoked during, according to the comment above 37032 38119 ** sqlite3PagerSetBusyhandler(). 37033 38120 */ 37034 - assert( (pPager->state>=locktype) 37035 - || (pPager->state==PAGER_UNLOCK && locktype==PAGER_SHARED) 37036 - || (pPager->state==PAGER_RESERVED && locktype==PAGER_EXCLUSIVE) 38121 + assert( (pPager->eLock>=locktype) 38122 + || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK) 38123 + || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK) 37037 38124 ); 37038 38125 37039 - if( pPager->state>=locktype ){ 37040 - rc = SQLITE_OK; 37041 - }else{ 37042 - do { 37043 - rc = sqlite3OsLock(pPager->fd, locktype); 37044 - }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) ); 37045 - if( rc==SQLITE_OK ){ 37046 - pPager->state = (u8)locktype; 37047 - IOTRACE(("LOCK %p %d\n", pPager, locktype)) 37048 - } 37049 - } 38126 + do { 38127 + rc = pagerLockDb(pPager, locktype); 38128 + }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) ); 37050 38129 return rc; 37051 38130 } 37052 38131 37053 38132 /* 37054 38133 ** Function assertTruncateConstraint(pPager) checks that one of the 37055 38134 ** following is true for all dirty pages currently in the page-cache: 37056 38135 ** ................................................................................ 37087 38166 /* 37088 38167 ** Truncate the in-memory database file image to nPage pages. This 37089 38168 ** function does not actually modify the database file on disk. It 37090 38169 ** just sets the internal state of the pager object so that the 37091 38170 ** truncation will be done when the current transaction is committed. 37092 38171 */ 37093 38172 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ 37094 - assert( pPager->dbSizeValid ); 37095 38173 assert( pPager->dbSize>=nPage ); 37096 - assert( pPager->state>=PAGER_RESERVED ); 38174 + assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); 37097 38175 pPager->dbSize = nPage; 37098 38176 assertTruncateConstraint(pPager); 37099 38177 } 37100 38178 37101 38179 37102 38180 /* 37103 38181 ** This function is called before attempting a hot-journal rollback. It ................................................................................ 37139 38217 ** to the caller. 37140 38218 */ 37141 38219 SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ 37142 38220 u8 *pTmp = (u8 *)pPager->pTmpSpace; 37143 38221 37144 38222 disable_simulated_io_errors(); 37145 38223 sqlite3BeginBenignMalloc(); 37146 - pPager->errCode = 0; 38224 + /* pPager->errCode = 0; */ 37147 38225 pPager->exclusiveMode = 0; 37148 38226 #ifndef SQLITE_OMIT_WAL 37149 38227 sqlite3WalClose(pPager->pWal, 37150 38228 (pPager->noSync ? 0 : pPager->sync_flags), 37151 38229 pPager->pageSize, pTmp 37152 38230 ); 37153 38231 pPager->pWal = 0; 37154 38232 #endif 37155 38233 pager_reset(pPager); 37156 38234 if( MEMDB ){ 37157 38235 pager_unlock(pPager); 37158 38236 }else{ 37159 - /* Set Pager.journalHdr to -1 for the benefit of the pager_playback() 37160 - ** call which may be made from within pagerUnlockAndRollback(). If it 37161 - ** is not -1, then the unsynced portion of an open journal file may 37162 - ** be played back into the database. If a power failure occurs while 37163 - ** this is happening, the database may become corrupt. 38237 + /* If it is open, sync the journal file before calling UnlockAndRollback. 38238 + ** If this is not done, then an unsynced portion of the open journal 38239 + ** file may be played back into the database. If a power failure occurs 38240 + ** while this is happening, the database could become corrupt. 38241 + ** 38242 + ** If an error occurs while trying to sync the journal, shift the pager 38243 + ** into the ERROR state. This causes UnlockAndRollback to unlock the 38244 + ** database and close the journal file without attempting to roll it 38245 + ** back or finalize it. The next database user will have to do hot-journal 38246 + ** rollback before accessing the database file. 37164 38247 */ 37165 38248 if( isOpen(pPager->jfd) ){ 37166 - pPager->errCode = pagerSyncHotJournal(pPager); 38249 + pager_error(pPager, pagerSyncHotJournal(pPager)); 37167 38250 } 37168 38251 pagerUnlockAndRollback(pPager); 37169 38252 } 37170 38253 sqlite3EndBenignMalloc(); 37171 38254 enable_simulated_io_errors(); 37172 38255 PAGERTRACE(("CLOSE %d\n", PAGERID(pPager))); 37173 38256 IOTRACE(("CLOSE %p\n", pPager)) ................................................................................ 37204 38287 } 37205 38288 37206 38289 /* 37207 38290 ** Sync the journal. In other words, make sure all the pages that have 37208 38291 ** been written to the journal have actually reached the surface of the 37209 38292 ** disk and can be restored in the event of a hot-journal rollback. 37210 38293 ** 37211 -** If the Pager.needSync flag is not set, then this function is a 37212 -** no-op. Otherwise, the actions required depend on the journal-mode 37213 -** and the device characteristics of the the file-system, as follows: 38294 +** If the Pager.noSync flag is set, then this function is a no-op. 38295 +** Otherwise, the actions required depend on the journal-mode and the 38296 +** device characteristics of the the file-system, as follows: 37214 38297 ** 37215 38298 ** * If the journal file is an in-memory journal file, no action need 37216 38299 ** be taken. 37217 38300 ** 37218 38301 ** * Otherwise, if the device does not support the SAFE_APPEND property, 37219 38302 ** then the nRec field of the most recently written journal header 37220 38303 ** is updated to contain the number of journal records that have ................................................................................ 37230 38313 ** if( NOT SAFE_APPEND ){ 37231 38314 ** if( <full-sync mode> ) xSync(<journal file>); 37232 38315 ** <update nRec field> 37233 38316 ** } 37234 38317 ** if( NOT SEQUENTIAL ) xSync(<journal file>); 37235 38318 ** } 37236 38319 ** 37237 -** The Pager.needSync flag is never be set for temporary files, or any 37238 -** file operating in no-sync mode (Pager.noSync set to non-zero). 37239 -** 37240 38320 ** If successful, this routine clears the PGHDR_NEED_SYNC flag of every 37241 38321 ** page currently held in memory before returning SQLITE_OK. If an IO 37242 38322 ** error is encountered, then the IO error code is returned to the caller. 37243 38323 */ 37244 -static int syncJournal(Pager *pPager){ 37245 - if( pPager->needSync ){ 38324 +static int syncJournal(Pager *pPager, int newHdr){ 38325 + int rc; /* Return code */ 38326 + 38327 + assert( pPager->eState==PAGER_WRITER_CACHEMOD 38328 + || pPager->eState==PAGER_WRITER_DBMOD 38329 + ); 38330 + assert( assert_pager_state(pPager) ); 38331 + assert( !pagerUseWal(pPager) ); 38332 + 38333 + rc = sqlite3PagerExclusiveLock(pPager); 38334 + if( rc!=SQLITE_OK ) return rc; 38335 + 38336 + if( !pPager->noSync ){ 37246 38337 assert( !pPager->tempFile ); 37247 - if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ 37248 - int rc; /* Return code */ 38338 + if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ 37249 38339 const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); 37250 38340 assert( isOpen(pPager->jfd) ); 37251 38341 37252 38342 if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ 37253 38343 /* This block deals with an obscure problem. If the last connection 37254 38344 ** that wrote to this database was operating in persistent-journal 37255 38345 ** mode, then the journal file may at this point actually be larger ................................................................................ 37316 38406 PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); 37317 38407 IOTRACE(("JSYNC %p\n", pPager)) 37318 38408 rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| 37319 38409 (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) 37320 38410 ); 37321 38411 if( rc!=SQLITE_OK ) return rc; 37322 38412 } 38413 + 38414 + pPager->journalHdr = pPager->journalOff; 38415 + if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ 38416 + pPager->nRec = 0; 38417 + rc = writeJournalHdr(pPager); 38418 + if( rc!=SQLITE_OK ) return rc; 38419 + } 38420 + }else{ 38421 + pPager->journalHdr = pPager->journalOff; 37323 38422 } 37324 - 37325 - /* The journal file was just successfully synced. Set Pager.needSync 37326 - ** to zero and clear the PGHDR_NEED_SYNC flag on all pagess. 37327 - */ 37328 - pPager->needSync = 0; 37329 - pPager->journalStarted = 1; 37330 - pPager->journalHdr = pPager->journalOff; 37331 - sqlite3PcacheClearSyncFlags(pPager->pPCache); 37332 38423 } 37333 38424 38425 + /* Unless the pager is in noSync mode, the journal file was just 38426 + ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on 38427 + ** all pages. 38428 + */ 38429 + sqlite3PcacheClearSyncFlags(pPager->pPCache); 38430 + pPager->eState = PAGER_WRITER_DBMOD; 38431 + assert( assert_pager_state(pPager) ); 37334 38432 return SQLITE_OK; 37335 38433 } 37336 38434 37337 38435 /* 37338 38436 ** The argument is the first in a linked list of dirty pages connected 37339 38437 ** by the PgHdr.pDirty pointer. This function writes each one of the 37340 38438 ** in-memory pages in the list to the database file. The argument may ................................................................................ 37363 38461 ** the database file. 37364 38462 ** 37365 38463 ** If everything is successful, SQLITE_OK is returned. If an IO error 37366 38464 ** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot 37367 38465 ** be obtained, SQLITE_BUSY is returned. 37368 38466 */ 37369 38467 static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ 37370 - int rc; /* Return code */ 38468 + int rc = SQLITE_OK; /* Return code */ 37371 38469 37372 - /* At this point there may be either a RESERVED or EXCLUSIVE lock on the 37373 - ** database file. If there is already an EXCLUSIVE lock, the following 37374 - ** call is a no-op. 37375 - ** 37376 - ** Moving the lock from RESERVED to EXCLUSIVE actually involves going 37377 - ** through an intermediate state PENDING. A PENDING lock prevents new 37378 - ** readers from attaching to the database but is unsufficient for us to 37379 - ** write. The idea of a PENDING lock is to prevent new readers from 37380 - ** coming in while we wait for existing readers to clear. 37381 - ** 37382 - ** While the pager is in the RESERVED state, the original database file 37383 - ** is unchanged and we can rollback without having to playback the 37384 - ** journal into the original database file. Once we transition to 37385 - ** EXCLUSIVE, it means the database file has been changed and any rollback 37386 - ** will require a journal playback. 37387 - */ 38470 + /* This function is only called for rollback pagers in WRITER_DBMOD state. */ 37388 38471 assert( !pagerUseWal(pPager) ); 37389 - assert( pPager->state>=PAGER_RESERVED ); 37390 - rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); 38472 + assert( pPager->eState==PAGER_WRITER_DBMOD ); 38473 + assert( pPager->eLock==EXCLUSIVE_LOCK ); 37391 38474 37392 38475 /* If the file is a temp-file has not yet been opened, open it now. It 37393 38476 ** is not possible for rc to be other than SQLITE_OK if this branch 37394 38477 ** is taken, as pager_wait_on_lock() is a no-op for temp-files. 37395 38478 */ 37396 38479 if( !isOpen(pPager->fd) ){ 37397 38480 assert( pPager->tempFile && rc==SQLITE_OK ); ................................................................................ 37398 38481 rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags); 37399 38482 } 37400 38483 37401 38484 /* Before the first write, give the VFS a hint of what the final 37402 38485 ** file size will be. 37403 38486 */ 37404 38487 assert( rc!=SQLITE_OK || isOpen(pPager->fd) ); 37405 - if( rc==SQLITE_OK && pPager->dbSize>(pPager->dbOrigSize+1) ){ 38488 + if( rc==SQLITE_OK && pPager->dbSize>pPager->dbHintSize ){ 37406 38489 sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize; 37407 38490 sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile); 38491 + pPager->dbHintSize = pPager->dbSize; 37408 38492 } 37409 38493 37410 38494 while( rc==SQLITE_OK && pList ){ 37411 38495 Pgno pgno = pList->pgno; 37412 38496 37413 38497 /* If there are dirty pages in the page cache with page numbers greater 37414 38498 ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to ................................................................................ 37417 38501 ** 37418 38502 ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag 37419 38503 ** set (set by sqlite3PagerDontWrite()). 37420 38504 */ 37421 38505 if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ 37422 38506 i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ 37423 38507 char *pData; /* Data to write */ 38508 + 38509 + assert( (pList->flags&PGHDR_NEED_SYNC)==0 ); 37424 38510 37425 38511 /* Encode the database */ 37426 38512 CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData); 37427 38513 37428 38514 /* Write out the page data. */ 37429 38515 rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset); 37430 38516 ................................................................................ 37446 38532 PAGERID(pPager), pgno, pager_pagehash(pList))); 37447 38533 IOTRACE(("PGOUT %p %d\n", pPager, pgno)); 37448 38534 PAGER_INCR(sqlite3_pager_writedb_count); 37449 38535 PAGER_INCR(pPager->nWrite); 37450 38536 }else{ 37451 38537 PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno)); 37452 38538 } 37453 -#ifdef SQLITE_CHECK_PAGES 37454 - pList->pageHash = pager_pagehash(pList); 37455 -#endif 38539 + pager_set_pagehash(pList); 37456 38540 pList = pList->pDirty; 37457 38541 } 37458 38542 37459 38543 return rc; 37460 38544 } 37461 38545 37462 38546 /* ................................................................................ 37560 38644 ** journal (and adding a new header) is not allowed. This occurs 37561 38645 ** during calls to sqlite3PagerWrite() while trying to journal multiple 37562 38646 ** pages belonging to the same sector. 37563 38647 ** 37564 38648 ** The doNotSpill flag inhibits all cache spilling regardless of whether 37565 38649 ** or not a sync is required. This is set during a rollback. 37566 38650 ** 37567 - ** Spilling is also inhibited when in an error state. 38651 + ** Spilling is also prohibited when in an error state since that could 38652 + ** lead to database corruption. In the current implementaton it 38653 + ** is impossible for sqlite3PCacheFetch() to be called with createFlag==1 38654 + ** while in the error state, hence it is impossible for this routine to 38655 + ** be called in the error state. Nevertheless, we include a NEVER() 38656 + ** test for the error state as a safeguard against future changes. 37568 38657 */ 37569 - if( pPager->errCode ) return SQLITE_OK; 38658 + if( NEVER(pPager->errCode) ) return SQLITE_OK; 37570 38659 if( pPager->doNotSpill ) return SQLITE_OK; 37571 38660 if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){ 37572 38661 return SQLITE_OK; 37573 38662 } 37574 38663 37575 38664 pPg->pDirty = 0; 37576 38665 if( pagerUseWal(pPager) ){ ................................................................................ 37580 38669 } 37581 38670 if( rc==SQLITE_OK ){ 37582 38671 rc = pagerWalFrames(pPager, pPg, 0, 0, 0); 37583 38672 } 37584 38673 }else{ 37585 38674 37586 38675 /* Sync the journal file if required. */ 37587 - if( pPg->flags&PGHDR_NEED_SYNC ){ 37588 - assert( !pPager->noSync ); 37589 - rc = syncJournal(pPager); 37590 - if( rc==SQLITE_OK && 37591 - !(pPager->journalMode==PAGER_JOURNALMODE_MEMORY) && 37592 - !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) 37593 - ){ 37594 - pPager->nRec = 0; 37595 - rc = writeJournalHdr(pPager); 37596 - } 38676 + if( pPg->flags&PGHDR_NEED_SYNC 38677 + || pPager->eState==PAGER_WRITER_CACHEMOD 38678 + ){ 38679 + rc = syncJournal(pPager, 1); 37597 38680 } 37598 38681 37599 38682 /* If the page number of this page is larger than the current size of 37600 38683 ** the database image, it may need to be written to the sub-journal. 37601 38684 ** This is because the call to pager_write_pagelist() below will not 37602 38685 ** actually write data to the file in this case. 37603 38686 ** ................................................................................ 37627 38710 rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg) 37628 38711 ) ){ 37629 38712 rc = subjournalPage(pPg); 37630 38713 } 37631 38714 37632 38715 /* Write the contents of the page out to the database file. */ 37633 38716 if( rc==SQLITE_OK ){ 38717 + assert( (pPg->flags&PGHDR_NEED_SYNC)==0 ); 37634 38718 rc = pager_write_pagelist(pPager, pPg); 37635 38719 } 37636 38720 } 37637 38721 37638 38722 /* Mark the page as clean. */ 37639 38723 if( rc==SQLITE_OK ){ 37640 38724 PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); 37641 38725 sqlite3PcacheMakeClean(pPg); 37642 38726 } 37643 38727 37644 - return pager_error(pPager, rc); 38728 + return pager_error(pPager, rc); 37645 38729 } 37646 38730 37647 38731 37648 38732 /* 37649 38733 ** Allocate and initialize a new Pager object and put a pointer to it 37650 38734 ** in *ppPager. The pager should eventually be freed by passing it 37651 38735 ** to sqlite3PagerClose(). ................................................................................ 37692 38776 int readOnly = 0; /* True if this is a read-only file */ 37693 38777 int journalFileSize; /* Bytes to allocate for each journal fd */ 37694 38778 char *zPathname = 0; /* Full path to database file */ 37695 38779 int nPathname = 0; /* Number of bytes in zPathname */ 37696 38780 int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */ 37697 38781 int noReadlock = (flags & PAGER_NO_READLOCK)!=0; /* True to omit read-lock */ 37698 38782 int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */ 37699 - u16 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */ 38783 + u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */ 37700 38784 37701 38785 /* Figure out how much space is required for each journal file-handle 37702 38786 ** (there are two of them, the main journal and the sub-journal). This 37703 38787 ** is the maximum space required for an in-memory journal file handle 37704 38788 ** and a regular journal file-handle. Note that a "regular journal-handle" 37705 38789 ** may be a wrapper capable of caching the first portion of the journal 37706 38790 ** file in memory to implement the atomic-write optimization (see ................................................................................ 37710 38794 journalFileSize = ROUND8(sqlite3JournalSize(pVfs)); 37711 38795 }else{ 37712 38796 journalFileSize = ROUND8(sqlite3MemJournalSize()); 37713 38797 } 37714 38798 37715 38799 /* Set the output variable to NULL in case an error occurs. */ 37716 38800 *ppPager = 0; 38801 + 38802 +#ifndef SQLITE_OMIT_MEMORYDB 38803 + if( flags & PAGER_MEMORY ){ 38804 + memDb = 1; 38805 + zFilename = 0; 38806 + } 38807 +#endif 37717 38808 37718 38809 /* Compute and store the full pathname in an allocated buffer pointed 37719 38810 ** to by zPathname, length nPathname. Or, if this is a temporary file, 37720 38811 ** leave both nPathname and zPathname set to 0. 37721 38812 */ 37722 38813 if( zFilename && zFilename[0] ){ 37723 38814 nPathname = pVfs->mxPathname+1; 37724 38815 zPathname = sqlite3Malloc(nPathname*2); 37725 38816 if( zPathname==0 ){ 37726 38817 return SQLITE_NOMEM; 37727 38818 } 37728 -#ifndef SQLITE_OMIT_MEMORYDB 37729 - if( strcmp(zFilename,":memory:")==0 ){ 37730 - memDb = 1; 37731 - zPathname[0] = 0; 37732 - }else 37733 -#endif 37734 - { 37735 - zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ 37736 - rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); 37737 - } 37738 - 38819 + zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ 38820 + rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); 37739 38821 nPathname = sqlite3Strlen30(zPathname); 37740 38822 if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){ 37741 38823 /* This branch is taken when the journal path required by 37742 38824 ** the database being opened will be more than pVfs->mxPathname 37743 38825 ** bytes in length. This means the database cannot be opened, 37744 38826 ** as it will not be possible to open the journal file or even 37745 38827 ** check for a hot-journal before reading. ................................................................................ 37786 38868 pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile)); 37787 38869 pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize); 37788 38870 pPager->zFilename = (char*)(pPtr += journalFileSize); 37789 38871 assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); 37790 38872 37791 38873 /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */ 37792 38874 if( zPathname ){ 38875 + assert( nPathname>0 ); 37793 38876 pPager->zJournal = (char*)(pPtr += nPathname + 1); 37794 38877 memcpy(pPager->zFilename, zPathname, nPathname); 37795 38878 memcpy(pPager->zJournal, zPathname, nPathname); 37796 38879 memcpy(&pPager->zJournal[nPathname], "-journal", 8); 37797 - if( pPager->zFilename[0]==0 ){ 37798 - pPager->zJournal[0] = 0; 37799 - } 37800 38880 #ifndef SQLITE_OMIT_WAL 37801 - else{ 37802 - pPager->zWal = &pPager->zJournal[nPathname+8+1]; 37803 - memcpy(pPager->zWal, zPathname, nPathname); 37804 - memcpy(&pPager->zWal[nPathname], "-wal", 4); 37805 - } 38881 + pPager->zWal = &pPager->zJournal[nPathname+8+1]; 38882 + memcpy(pPager->zWal, zPathname, nPathname); 38883 + memcpy(&pPager->zWal[nPathname], "-wal", 4); 37806 38884 #endif 37807 38885 sqlite3_free(zPathname); 37808 38886 } 37809 38887 pPager->pVfs = pVfs; 37810 38888 pPager->vfsFlags = vfsFlags; 37811 38889 37812 38890 /* Open the pager file. 37813 38891 */ 37814 - if( zFilename && zFilename[0] && !memDb ){ 38892 + if( zFilename && zFilename[0] ){ 37815 38893 int fout = 0; /* VFS flags returned by xOpen() */ 37816 38894 rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); 38895 + assert( !memDb ); 37817 38896 readOnly = (fout&SQLITE_OPEN_READONLY); 37818 38897 37819 38898 /* If the file was successfully opened for read/write access, 37820 38899 ** choose a default page size in case we have to create the 37821 38900 ** database file. The default page size is the maximum of: 37822 38901 ** 37823 38902 ** + SQLITE_DEFAULT_PAGE_SIZE, ................................................................................ 37827 38906 if( rc==SQLITE_OK && !readOnly ){ 37828 38907 setSectorSize(pPager); 37829 38908 assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE); 37830 38909 if( szPageDflt<pPager->sectorSize ){ 37831 38910 if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){ 37832 38911 szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE; 37833 38912 }else{ 37834 - szPageDflt = (u16)pPager->sectorSize; 38913 + szPageDflt = (u32)pPager->sectorSize; 37835 38914 } 37836 38915 } 37837 38916 #ifdef SQLITE_ENABLE_ATOMIC_WRITE 37838 38917 { 37839 38918 int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); 37840 38919 int ii; 37841 38920 assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); ................................................................................ 37855 38934 ** opening the file until the first call to OsWrite(). 37856 38935 ** 37857 38936 ** This branch is also run for an in-memory database. An in-memory 37858 38937 ** database is the same as a temp-file that is never written out to 37859 38938 ** disk and uses an in-memory rollback journal. 37860 38939 */ 37861 38940 tempFile = 1; 37862 - pPager->state = PAGER_EXCLUSIVE; 38941 + pPager->eState = PAGER_READER; 38942 + pPager->eLock = EXCLUSIVE_LOCK; 37863 38943 readOnly = (vfsFlags&SQLITE_OPEN_READONLY); 37864 38944 } 37865 38945 37866 38946 /* The following call to PagerSetPagesize() serves to set the value of 37867 38947 ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer. 37868 38948 */ 37869 38949 if( rc==SQLITE_OK ){ ................................................................................ 37892 38972 IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename)) 37893 38973 37894 38974 pPager->useJournal = (u8)useJournal; 37895 38975 pPager->noReadlock = (noReadlock && readOnly) ?1:0; 37896 38976 /* pPager->stmtOpen = 0; */ 37897 38977 /* pPager->stmtInUse = 0; */ 37898 38978 /* pPager->nRef = 0; */ 37899 - pPager->dbSizeValid = (u8)memDb; 37900 38979 /* pPager->stmtSize = 0; */ 37901 38980 /* pPager->stmtJSize = 0; */ 37902 38981 /* pPager->nPage = 0; */ 37903 38982 pPager->mxPgno = SQLITE_MAX_PAGE_COUNT; 37904 38983 /* pPager->state = PAGER_UNLOCK; */ 38984 +#if 0 37905 38985 assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) ); 38986 +#endif 37906 38987 /* pPager->errMask = 0; */ 37907 38988 pPager->tempFile = (u8)tempFile; 37908 38989 assert( tempFile==PAGER_LOCKINGMODE_NORMAL 37909 38990 || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); 37910 38991 assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); 37911 38992 pPager->exclusiveMode = (u8)tempFile; 37912 38993 pPager->changeCountDone = pPager->tempFile; 37913 38994 pPager->memDb = (u8)memDb; 37914 38995 pPager->readOnly = (u8)readOnly; 37915 - /* pPager->needSync = 0; */ 37916 38996 assert( useJournal || pPager->tempFile ); 37917 38997 pPager->noSync = pPager->tempFile; 37918 38998 pPager->fullSync = pPager->noSync ?0:1; 37919 38999 pPager->sync_flags = SQLITE_SYNC_NORMAL; 37920 39000 /* pPager->pFirst = 0; */ 37921 39001 /* pPager->pFirstSynced = 0; */ 37922 39002 /* pPager->pLast = 0; */ ................................................................................ 37973 39053 */ 37974 39054 static int hasHotJournal(Pager *pPager, int *pExists){ 37975 39055 sqlite3_vfs * const pVfs = pPager->pVfs; 37976 39056 int rc = SQLITE_OK; /* Return code */ 37977 39057 int exists = 1; /* True if a journal file is present */ 37978 39058 int jrnlOpen = !!isOpen(pPager->jfd); 37979 39059 37980 - assert( pPager!=0 ); 37981 39060 assert( pPager->useJournal ); 37982 39061 assert( isOpen(pPager->fd) ); 37983 - assert( pPager->state <= PAGER_SHARED ); 39062 + assert( pPager->eState==PAGER_OPEN ); 39063 + 37984 39064 assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) & 37985 39065 SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 37986 39066 )); 37987 39067 37988 39068 *pExists = 0; 37989 39069 if( !jrnlOpen ){ 37990 39070 rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists); 37991 39071 } 37992 39072 if( rc==SQLITE_OK && exists ){ 37993 - int locked; /* True if some process holds a RESERVED lock */ 39073 + int locked = 0; /* True if some process holds a RESERVED lock */ 37994 39074 37995 39075 /* Race condition here: Another process might have been holding the 37996 39076 ** the RESERVED lock and have a journal open at the sqlite3OsAccess() 37997 39077 ** call above, but then delete the journal and drop the lock before 37998 39078 ** we get to the following sqlite3OsCheckReservedLock() call. If that 37999 39079 ** is the case, this routine might think there is a hot journal when 38000 39080 ** in fact there is none. This results in a false-positive which will 38001 39081 ** be dealt with by the playback routine. Ticket #3883. 38002 39082 */ 38003 39083 rc = sqlite3OsCheckReservedLock(pPager->fd, &locked); 38004 39084 if( rc==SQLITE_OK && !locked ){ 38005 - int nPage; 39085 + Pgno nPage; /* Number of pages in database file */ 38006 39086 38007 39087 /* Check the size of the database file. If it consists of 0 pages, 38008 39088 ** then delete the journal file. See the header comment above for 38009 39089 ** the reasoning here. Delete the obsolete journal file under 38010 39090 ** a RESERVED lock to avoid race conditions and to avoid violating 38011 39091 ** [H33020]. 38012 39092 */ 38013 - rc = sqlite3PagerPagecount(pPager, &nPage); 39093 + rc = pagerPagecount(pPager, &nPage); 38014 39094 if( rc==SQLITE_OK ){ 38015 39095 if( nPage==0 ){ 38016 39096 sqlite3BeginBenignMalloc(); 38017 - if( sqlite3OsLock(pPager->fd, RESERVED_LOCK)==SQLITE_OK ){ 39097 + if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){ 38018 39098 sqlite3OsDelete(pVfs, pPager->zJournal, 0); 38019 - sqlite3OsUnlock(pPager->fd, SHARED_LOCK); 39099 + pagerUnlockDb(pPager, SHARED_LOCK); 38020 39100 } 38021 39101 sqlite3EndBenignMalloc(); 38022 39102 }else{ 38023 39103 /* The journal file exists and no other connection has a reserved 38024 39104 ** or greater lock on the database file. Now check that there is 38025 39105 ** at least one non-zero bytes at the start of the journal file. 38026 39106 ** If there is, then we consider this journal to be hot. If not, ................................................................................ 38065 39145 ** This function is called to obtain a shared lock on the database file. 38066 39146 ** It is illegal to call sqlite3PagerAcquire() until after this function 38067 39147 ** has been successfully called. If a shared-lock is already held when 38068 39148 ** this function is called, it is a no-op. 38069 39149 ** 38070 39150 ** The following operations are also performed by this function. 38071 39151 ** 38072 -** 1) If the pager is currently in PAGER_UNLOCK state (no lock held 39152 +** 1) If the pager is currently in PAGER_OPEN state (no lock held 38073 39153 ** on the database file), then an attempt is made to obtain a 38074 39154 ** SHARED lock on the database file. Immediately after obtaining 38075 39155 ** the SHARED lock, the file-system is checked for a hot-journal, 38076 39156 ** which is played back if present. Following any hot-journal 38077 39157 ** rollback, the contents of the cache are validated by checking 38078 39158 ** the 'change-counter' field of the database file header and 38079 39159 ** discarded if they are found to be invalid. ................................................................................ 38080 39160 ** 38081 39161 ** 2) If the pager is running in exclusive-mode, and there are currently 38082 39162 ** no outstanding references to any pages, and is in the error state, 38083 39163 ** then an attempt is made to clear the error state by discarding 38084 39164 ** the contents of the page cache and rolling back any open journal 38085 39165 ** file. 38086 39166 ** 38087 -** If the operation described by (2) above is not attempted, and if the 38088 -** pager is in an error state other than SQLITE_FULL when this is called, 38089 -** the error state error code is returned. It is permitted to read the 38090 -** database when in SQLITE_FULL error state. 38091 -** 38092 -** Otherwise, if everything is successful, SQLITE_OK is returned. If an 38093 -** IO error occurs while locking the database, checking for a hot-journal 38094 -** file or rolling back a journal file, the IO error code is returned. 39167 +** If everything is successful, SQLITE_OK is returned. If an IO error 39168 +** occurs while locking the database, checking for a hot-journal file or 39169 +** rolling back a journal file, the IO error code is returned. 38095 39170 */ 38096 39171 SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ 38097 39172 int rc = SQLITE_OK; /* Return code */ 38098 - int isErrorReset = 0; /* True if recovering from error state */ 38099 39173 38100 39174 /* This routine is only called from b-tree and only when there are no 38101 - ** outstanding pages */ 39175 + ** outstanding pages. This implies that the pager state should either 39176 + ** be OPEN or READER. READER is only possible if the pager is or was in 39177 + ** exclusive access mode. 39178 + */ 38102 39179 assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); 39180 + assert( assert_pager_state(pPager) ); 39181 + assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); 38103 39182 if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; } 38104 39183 38105 - /* If this database is in an error-state, now is a chance to clear 38106 - ** the error. Discard the contents of the pager-cache and rollback 38107 - ** any hot journal in the file-system. 38108 - */ 38109 - if( pPager->errCode ){ 38110 - if( isOpen(pPager->jfd) || pPager->zJournal ){ 38111 - isErrorReset = 1; 38112 - } 38113 - pPager->errCode = SQLITE_OK; 38114 - pager_reset(pPager); 38115 - } 39184 + if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){ 39185 + int bHotJournal = 1; /* True if there exists a hot journal-file */ 38116 39186 38117 - if( pagerUseWal(pPager) ){ 38118 - rc = pagerBeginReadTransaction(pPager); 38119 - }else if( pPager->state==PAGER_UNLOCK || isErrorReset ){ 38120 - sqlite3_vfs * const pVfs = pPager->pVfs; 38121 - int isHotJournal = 0; 38122 39187 assert( !MEMDB ); 38123 - assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); 38124 - if( pPager->noReadlock ){ 38125 - assert( pPager->readOnly ); 38126 - pPager->state = PAGER_SHARED; 38127 - }else{ 39188 + assert( pPager->noReadlock==0 || pPager->readOnly ); 39189 + 39190 + if( pPager->noReadlock==0 ){ 38128 39191 rc = pager_wait_on_lock(pPager, SHARED_LOCK); 38129 39192 if( rc!=SQLITE_OK ){ 38130 - assert( pPager->state==PAGER_UNLOCK ); 38131 - return pager_error(pPager, rc); 39193 + assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK ); 39194 + goto failed; 38132 39195 } 38133 39196 } 38134 - assert( pPager->state>=SHARED_LOCK ); 38135 39197 38136 39198 /* If a journal file exists, and there is no RESERVED lock on the 38137 39199 ** database file, then it either needs to be played back or deleted. 38138 39200 */ 38139 - if( !isErrorReset ){ 38140 - assert( pPager->state <= PAGER_SHARED ); 38141 - rc = hasHotJournal(pPager, &isHotJournal); 38142 - if( rc!=SQLITE_OK ){ 38143 - goto failed; 38144 - } 39201 + if( pPager->eLock<=SHARED_LOCK ){ 39202 + rc = hasHotJournal(pPager, &bHotJournal); 38145 39203 } 38146 - if( isErrorReset || isHotJournal ){ 39204 + if( rc!=SQLITE_OK ){ 39205 + goto failed; 39206 + } 39207 + if( bHotJournal ){ 38147 39208 /* Get an EXCLUSIVE lock on the database file. At this point it is 38148 39209 ** important that a RESERVED lock is not obtained on the way to the 38149 39210 ** EXCLUSIVE lock. If it were, another process might open the 38150 39211 ** database file, detect the RESERVED lock, and conclude that the 38151 39212 ** database is safe to read while this process is still rolling the 38152 39213 ** hot-journal back. 38153 39214 ** 38154 39215 ** Because the intermediate RESERVED lock is not requested, any 38155 39216 ** other process attempting to access the database file will get to 38156 39217 ** this point in the code and fail to obtain its own EXCLUSIVE lock 38157 39218 ** on the database file. 39219 + ** 39220 + ** Unless the pager is in locking_mode=exclusive mode, the lock is 39221 + ** downgraded to SHARED_LOCK before this function returns. 38158 39222 */ 38159 - if( pPager->state<EXCLUSIVE_LOCK ){ 38160 - rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); 38161 - if( rc!=SQLITE_OK ){ 38162 - rc = pager_error(pPager, rc); 38163 - goto failed; 38164 - } 38165 - pPager->state = PAGER_EXCLUSIVE; 38166 - } 38167 - 38168 - /* Open the journal for read/write access. This is because in 38169 - ** exclusive-access mode the file descriptor will be kept open and 38170 - ** possibly used for a transaction later on. On some systems, the 38171 - ** OsTruncate() call used in exclusive-access mode also requires 38172 - ** a read/write file handle. 38173 - */ 38174 - if( !isOpen(pPager->jfd) ){ 38175 - int res; 38176 - rc = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS,&res); 38177 - if( rc==SQLITE_OK ){ 38178 - if( res ){ 38179 - int fout = 0; 38180 - int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; 38181 - assert( !pPager->tempFile ); 38182 - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); 38183 - assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); 38184 - if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ 38185 - rc = SQLITE_CANTOPEN_BKPT; 38186 - sqlite3OsClose(pPager->jfd); 38187 - } 38188 - }else{ 38189 - /* If the journal does not exist, it usually means that some 38190 - ** other connection managed to get in and roll it back before 38191 - ** this connection obtained the exclusive lock above. Or, it 38192 - ** may mean that the pager was in the error-state when this 38193 - ** function was called and the journal file does not exist. */ 38194 - rc = pager_end_transaction(pPager, 0); 38195 - } 38196 - } 38197 - } 39223 + rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); 38198 39224 if( rc!=SQLITE_OK ){ 38199 39225 goto failed; 38200 39226 } 38201 - 38202 - /* Reset the journal status fields to indicates that we have no 38203 - ** rollback journal at this time. */ 38204 - pPager->journalStarted = 0; 38205 - pPager->journalOff = 0; 38206 - pPager->setMaster = 0; 38207 - pPager->journalHdr = 0; 38208 39227 38209 - /* Make sure the journal file has been synced to disk. */ 39228 + /* If it is not already open and the file exists on disk, open the 39229 + ** journal for read/write access. Write access is required because 39230 + ** in exclusive-access mode the file descriptor will be kept open 39231 + ** and possibly used for a transaction later on. Also, write-access 39232 + ** is usually required to finalize the journal in journal_mode=persist 39233 + ** mode (and also for journal_mode=truncate on some systems). 39234 + ** 39235 + ** If the journal does not exist, it usually means that some 39236 + ** other connection managed to get in and roll it back before 39237 + ** this connection obtained the exclusive lock above. Or, it 39238 + ** may mean that the pager was in the error-state when this 39239 + ** function was called and the journal file does not exist. 39240 + */ 39241 + if( !isOpen(pPager->jfd) ){ 39242 + sqlite3_vfs * const pVfs = pPager->pVfs; 39243 + int bExists; /* True if journal file exists */ 39244 + rc = sqlite3OsAccess( 39245 + pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists); 39246 + if( rc==SQLITE_OK && bExists ){ 39247 + int fout = 0; 39248 + int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; 39249 + assert( !pPager->tempFile ); 39250 + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); 39251 + assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); 39252 + if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ 39253 + rc = SQLITE_CANTOPEN_BKPT; 39254 + sqlite3OsClose(pPager->jfd); 39255 + } 39256 + } 39257 + } 38210 39258 38211 39259 /* Playback and delete the journal. Drop the database write 38212 39260 ** lock and reacquire the read lock. Purge the cache before 38213 39261 ** playing back the hot-journal so that we don't end up with 38214 39262 ** an inconsistent cache. Sync the hot journal before playing 38215 39263 ** it back since the process that crashed and left the hot journal 38216 39264 ** probably did not sync it and we are required to always sync 38217 39265 ** the journal before playing it back. 38218 39266 */ 38219 39267 if( isOpen(pPager->jfd) ){ 39268 + assert( rc==SQLITE_OK ); 38220 39269 rc = pagerSyncHotJournal(pPager); 38221 39270 if( rc==SQLITE_OK ){ 38222 39271 rc = pager_playback(pPager, 1); 38223 - } 38224 - if( rc!=SQLITE_OK ){ 38225 - rc = pager_error(pPager, rc); 38226 - goto failed; 38227 - } 38228 - } 38229 - assert( (pPager->state==PAGER_SHARED) 38230 - || (pPager->exclusiveMode && pPager->state>PAGER_SHARED) 38231 - ); 38232 - } 38233 - 38234 - if( pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0 ){ 39272 + pPager->eState = PAGER_OPEN; 39273 + } 39274 + }else if( !pPager->exclusiveMode ){ 39275 + pagerUnlockDb(pPager, SHARED_LOCK); 39276 + } 39277 + 39278 + if( rc!=SQLITE_OK ){ 39279 + /* This branch is taken if an error occurs while trying to open 39280 + ** or roll back a hot-journal while holding an EXCLUSIVE lock. The 39281 + ** pager_unlock() routine will be called before returning to unlock 39282 + ** the file. If the unlock attempt fails, then Pager.eLock must be 39283 + ** set to UNKNOWN_LOCK (see the comment above the #define for 39284 + ** UNKNOWN_LOCK above for an explanation). 39285 + ** 39286 + ** In order to get pager_unlock() to do this, set Pager.eState to 39287 + ** PAGER_ERROR now. This is not actually counted as a transition 39288 + ** to ERROR state in the state diagram at the top of this file, 39289 + ** since we know that the same call to pager_unlock() will very 39290 + ** shortly transition the pager object to the OPEN state. Calling 39291 + ** assert_pager_state() would fail now, as it should not be possible 39292 + ** to be in ERROR state when there are zero outstanding page 39293 + ** references. 39294 + */ 39295 + pager_error(pPager, rc); 39296 + goto failed; 39297 + } 39298 + 39299 + assert( pPager->eState==PAGER_OPEN ); 39300 + assert( (pPager->eLock==SHARED_LOCK) 39301 + || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) 39302 + ); 39303 + } 39304 + 39305 + if( !pPager->tempFile 39306 + && (pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0) 39307 + ){ 38235 39308 /* The shared-lock has just been acquired on the database file 38236 39309 ** and there are already pages in the cache (from a previous 38237 39310 ** read or write transaction). Check to see if the database 38238 39311 ** has been modified. If the database has changed, flush the 38239 39312 ** cache. 38240 39313 ** 38241 39314 ** Database changes is detected by looking at 15 bytes beginning ................................................................................ 38244 39317 ** other bytes change randomly with each file change when 38245 39318 ** a codec is in use. 38246 39319 ** 38247 39320 ** There is a vanishingly small chance that a change will not be 38248 39321 ** detected. The chance of an undetected change is so small that 38249 39322 ** it can be neglected. 38250 39323 */ 38251 - int nPage = 0; 39324 + Pgno nPage = 0; 38252 39325 char dbFileVers[sizeof(pPager->dbFileVers)]; 38253 - sqlite3PagerPagecount(pPager, &nPage); 38254 39326 38255 - if( pPager->errCode ){ 38256 - rc = pPager->errCode; 38257 - goto failed; 38258 - } 39327 + rc = pagerPagecount(pPager, &nPage); 39328 + if( rc ) goto failed; 38259 39329 38260 39330 if( nPage>0 ){ 38261 39331 IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); 38262 39332 rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); 38263 39333 if( rc!=SQLITE_OK ){ 38264 39334 goto failed; 38265 39335 } ................................................................................ 38267 39337 memset(dbFileVers, 0, sizeof(dbFileVers)); 38268 39338 } 38269 39339 38270 39340 if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ 38271 39341 pager_reset(pPager); 38272 39342 } 38273 39343 } 38274 - assert( pPager->exclusiveMode || pPager->state==PAGER_SHARED ); 38275 39344 38276 39345 /* If there is a WAL file in the file-system, open this database in WAL 38277 39346 ** mode. Otherwise, the following function call is a no-op. 38278 39347 */ 38279 39348 rc = pagerOpenWalIfPresent(pPager); 39349 +#ifndef SQLITE_OMIT_WAL 39350 + assert( pPager->pWal==0 || rc==SQLITE_OK ); 39351 +#endif 39352 + } 39353 + 39354 + if( pagerUseWal(pPager) ){ 39355 + assert( rc==SQLITE_OK ); 39356 + rc = pagerBeginReadTransaction(pPager); 39357 + } 39358 + 39359 + if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){ 39360 + rc = pagerPagecount(pPager, &pPager->dbSize); 38280 39361 } 38281 39362 38282 39363 failed: 38283 39364 if( rc!=SQLITE_OK ){ 38284 - /* pager_unlock() is a no-op for exclusive mode and in-memory databases. */ 39365 + assert( !MEMDB ); 38285 39366 pager_unlock(pPager); 39367 + assert( pPager->eState==PAGER_OPEN ); 39368 + }else{ 39369 + pPager->eState = PAGER_READER; 38286 39370 } 38287 39371 return rc; 38288 39372 } 38289 39373 38290 39374 /* 38291 39375 ** If the reference count has reached zero, rollback any active 38292 39376 ** transaction and unlock the pager. 38293 39377 ** 38294 39378 ** Except, in locking_mode=EXCLUSIVE when there is nothing to in 38295 39379 ** the rollback journal, the unlock is not performed and there is 38296 39380 ** nothing to rollback, so this routine is a no-op. 38297 39381 */ 38298 39382 static void pagerUnlockIfUnused(Pager *pPager){ 38299 - if( (sqlite3PcacheRefCount(pPager->pPCache)==0) 38300 - && (!pPager->exclusiveMode || pPager->journalOff>0) 38301 - ){ 39383 + if( (sqlite3PcacheRefCount(pPager->pPCache)==0) ){ 38302 39384 pagerUnlockAndRollback(pPager); 38303 39385 } 38304 39386 } 38305 39387 38306 39388 /* 38307 39389 ** Acquire a reference to page number pgno in pager pPager (a page 38308 39390 ** reference has type DbPage*). If the requested reference is ................................................................................ 38358 39440 Pgno pgno, /* Page number to fetch */ 38359 39441 DbPage **ppPage, /* Write a pointer to the page here */ 38360 39442 int noContent /* Do not bother reading content from disk if true */ 38361 39443 ){ 38362 39444 int rc; 38363 39445 PgHdr *pPg; 38364 39446 39447 + assert( pPager->eState>=PAGER_READER ); 38365 39448 assert( assert_pager_state(pPager) ); 38366 - assert( pPager->state>PAGER_UNLOCK ); 38367 39449 38368 39450 if( pgno==0 ){ 38369 39451 return SQLITE_CORRUPT_BKPT; 38370 39452 } 38371 39453 38372 39454 /* If the pager is in the error state, return an error immediately. 38373 39455 ** Otherwise, request the page from the PCache layer. */ 38374 - if( pPager->errCode!=SQLITE_OK && pPager->errCode!=SQLITE_FULL ){ 39456 + if( pPager->errCode!=SQLITE_OK ){ 38375 39457 rc = pPager->errCode; 38376 39458 }else{ 38377 39459 rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage); 38378 39460 } 38379 39461 38380 39462 if( rc!=SQLITE_OK ){ 38381 39463 /* Either the call to sqlite3PcacheFetch() returned an error or the ................................................................................ 38393 39475 assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); 38394 39476 PAGER_INCR(pPager->nHit); 38395 39477 return SQLITE_OK; 38396 39478 38397 39479 }else{ 38398 39480 /* The pager cache has created a new page. Its content needs to 38399 39481 ** be initialized. */ 38400 - int nMax; 38401 39482 38402 39483 PAGER_INCR(pPager->nMiss); 38403 39484 pPg = *ppPage; 38404 39485 pPg->pPager = pPager; 38405 39486 38406 39487 /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page 38407 39488 ** number greater than this, or the unused locking-page, is requested. */ 38408 39489 if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ 38409 39490 rc = SQLITE_CORRUPT_BKPT; 38410 39491 goto pager_acquire_err; 38411 39492 } 38412 39493 38413 - rc = sqlite3PagerPagecount(pPager, &nMax); 38414 - if( rc!=SQLITE_OK ){ 38415 - goto pager_acquire_err; 38416 - } 38417 - 38418 - if( MEMDB || nMax<(int)pgno || noContent || !isOpen(pPager->fd) ){ 39494 + if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){ 38419 39495 if( pgno>pPager->mxPgno ){ 38420 39496 rc = SQLITE_FULL; 38421 39497 goto pager_acquire_err; 38422 39498 } 38423 39499 if( noContent ){ 38424 39500 /* Failure to set the bits in the InJournal bit-vectors is benign. 38425 39501 ** It merely means that we might do some extra work to journal a ................................................................................ 38441 39517 }else{ 38442 39518 assert( pPg->pPager==pPager ); 38443 39519 rc = readDbPage(pPg); 38444 39520 if( rc!=SQLITE_OK ){ 38445 39521 goto pager_acquire_err; 38446 39522 } 38447 39523 } 38448 -#ifdef SQLITE_CHECK_PAGES 38449 - pPg->pageHash = pager_pagehash(pPg); 38450 -#endif 39524 + pager_set_pagehash(pPg); 38451 39525 } 38452 39526 38453 39527 return SQLITE_OK; 38454 39528 38455 39529 pager_acquire_err: 38456 39530 assert( rc!=SQLITE_OK ); 38457 39531 if( pPg ){ ................................................................................ 38462 39536 *ppPage = 0; 38463 39537 return rc; 38464 39538 } 38465 39539 38466 39540 /* 38467 39541 ** Acquire a page if it is already in the in-memory cache. Do 38468 39542 ** not read the page from disk. Return a pointer to the page, 38469 -** or 0 if the page is not in cache. Also, return 0 if the 38470 -** pager is in PAGER_UNLOCK state when this function is called, 38471 -** or if the pager is in an error state other than SQLITE_FULL. 39543 +** or 0 if the page is not in cache. 38472 39544 ** 38473 39545 ** See also sqlite3PagerGet(). The difference between this routine 38474 39546 ** and sqlite3PagerGet() is that _get() will go to the disk and read 38475 39547 ** in the page if the page is not already in cache. This routine 38476 39548 ** returns NULL if the page is not in cache or if a disk I/O error 38477 39549 ** has ever happened. 38478 39550 */ 38479 39551 SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ 38480 39552 PgHdr *pPg = 0; 38481 39553 assert( pPager!=0 ); 38482 39554 assert( pgno!=0 ); 38483 39555 assert( pPager->pPCache!=0 ); 38484 - assert( pPager->state > PAGER_UNLOCK ); 39556 + assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR ); 38485 39557 sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg); 38486 39558 return pPg; 38487 39559 } 38488 39560 38489 39561 /* 38490 39562 ** Release a page reference. 38491 39563 ** ................................................................................ 38522 39594 ** 38523 39595 ** Return SQLITE_OK if everything is successful. Otherwise, return 38524 39596 ** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or 38525 39597 ** an IO error code if opening or writing the journal file fails. 38526 39598 */ 38527 39599 static int pager_open_journal(Pager *pPager){ 38528 39600 int rc = SQLITE_OK; /* Return code */ 38529 - int nPage; /* Size of database file */ 38530 39601 sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */ 38531 39602 38532 - assert( pPager->state>=PAGER_RESERVED ); 38533 - assert( pPager->useJournal ); 38534 - assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF ); 39603 + assert( pPager->eState==PAGER_WRITER_LOCKED ); 39604 + assert( assert_pager_state(pPager) ); 38535 39605 assert( pPager->pInJournal==0 ); 38536 39606 38537 39607 /* If already in the error state, this function is a no-op. But on 38538 39608 ** the other hand, this routine is never called if we are already in 38539 39609 ** an error state. */ 38540 39610 if( NEVER(pPager->errCode) ) return pPager->errCode; 38541 39611 38542 - testcase( pPager->dbSizeValid==0 ); 38543 - rc = sqlite3PagerPagecount(pPager, &nPage); 38544 - if( rc ) return rc; 38545 - pPager->pInJournal = sqlite3BitvecCreate(nPage); 38546 - if( pPager->pInJournal==0 ){ 38547 - return SQLITE_NOMEM; 38548 - } 38549 - 38550 - /* Open the journal file if it is not already open. */ 38551 - if( !isOpen(pPager->jfd) ){ 38552 - if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ 38553 - sqlite3MemJournalOpen(pPager->jfd); 38554 - }else{ 38555 - const int flags = /* VFS flags to open journal file */ 38556 - SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| 38557 - (pPager->tempFile ? 38558 - (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL): 38559 - (SQLITE_OPEN_MAIN_JOURNAL) 38560 - ); 38561 -#ifdef SQLITE_ENABLE_ATOMIC_WRITE 38562 - rc = sqlite3JournalOpen( 38563 - pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) 38564 - ); 38565 -#else 38566 - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); 38567 -#endif 38568 - } 38569 - assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); 38570 - } 38571 - 38572 - 38573 - /* Write the first journal header to the journal file and open 38574 - ** the sub-journal if necessary. 38575 - */ 38576 - if( rc==SQLITE_OK ){ 38577 - /* TODO: Check if all of these are really required. */ 38578 - pPager->dbOrigSize = pPager->dbSize; 38579 - pPager->journalStarted = 0; 38580 - pPager->needSync = 0; 38581 - pPager->nRec = 0; 38582 - pPager->journalOff = 0; 38583 - pPager->setMaster = 0; 38584 - pPager->journalHdr = 0; 38585 - rc = writeJournalHdr(pPager); 39612 + if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ 39613 + pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize); 39614 + if( pPager->pInJournal==0 ){ 39615 + return SQLITE_NOMEM; 39616 + } 39617 + 39618 + /* Open the journal file if it is not already open. */ 39619 + if( !isOpen(pPager->jfd) ){ 39620 + if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ 39621 + sqlite3MemJournalOpen(pPager->jfd); 39622 + }else{ 39623 + const int flags = /* VFS flags to open journal file */ 39624 + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| 39625 + (pPager->tempFile ? 39626 + (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL): 39627 + (SQLITE_OPEN_MAIN_JOURNAL) 39628 + ); 39629 + #ifdef SQLITE_ENABLE_ATOMIC_WRITE 39630 + rc = sqlite3JournalOpen( 39631 + pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) 39632 + ); 39633 + #else 39634 + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); 39635 + #endif 39636 + } 39637 + assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); 39638 + } 39639 + 39640 + 39641 + /* Write the first journal header to the journal file and open 39642 + ** the sub-journal if necessary. 39643 + */ 39644 + if( rc==SQLITE_OK ){ 39645 + /* TODO: Check if all of these are really required. */ 39646 + pPager->nRec = 0; 39647 + pPager->journalOff = 0; 39648 + pPager->setMaster = 0; 39649 + pPager->journalHdr = 0; 39650 + rc = writeJournalHdr(pPager); 39651 + } 38586 39652 } 38587 39653 38588 39654 if( rc!=SQLITE_OK ){ 38589 39655 sqlite3BitvecDestroy(pPager->pInJournal); 38590 39656 pPager->pInJournal = 0; 39657 + }else{ 39658 + assert( pPager->eState==PAGER_WRITER_LOCKED ); 39659 + pPager->eState = PAGER_WRITER_CACHEMOD; 38591 39660 } 39661 + 38592 39662 return rc; 38593 39663 } 38594 39664 38595 39665 /* 38596 39666 ** Begin a write-transaction on the specified pager object. If a 38597 39667 ** write-transaction has already been opened, this function is a no-op. 38598 39668 ** 38599 39669 ** If the exFlag argument is false, then acquire at least a RESERVED 38600 39670 ** lock on the database file. If exFlag is true, then acquire at least 38601 39671 ** an EXCLUSIVE lock. If such a lock is already held, no locking 38602 39672 ** functions need be called. 38603 39673 ** 38604 -** If this is not a temporary or in-memory file and, the journal file is 38605 -** opened if it has not been already. For a temporary file, the opening 38606 -** of the journal file is deferred until there is an actual need to 38607 -** write to the journal. TODO: Why handle temporary files differently? 38608 -** 38609 -** If the journal file is opened (or if it is already open), then a 38610 -** journal-header is written to the start of it. 38611 -** 38612 39674 ** If the subjInMemory argument is non-zero, then any sub-journal opened 38613 39675 ** within this transaction will be opened as an in-memory file. This 38614 39676 ** has no effect if the sub-journal is already opened (as it may be when 38615 39677 ** running in exclusive mode) or if the transaction does not require a 38616 39678 ** sub-journal. If the subjInMemory argument is zero, then any required 38617 39679 ** sub-journal is implemented in-memory if pPager is an in-memory database, 38618 39680 ** or using a temporary file otherwise. 38619 39681 */ 38620 39682 SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ 38621 39683 int rc = SQLITE_OK; 38622 - assert( pPager->state!=PAGER_UNLOCK ); 39684 + 39685 + if( pPager->errCode ) return pPager->errCode; 39686 + assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR ); 38623 39687 pPager->subjInMemory = (u8)subjInMemory; 38624 39688 38625 - if( pPager->state==PAGER_SHARED ){ 39689 + if( ALWAYS(pPager->eState==PAGER_READER) ){ 38626 39690 assert( pPager->pInJournal==0 ); 38627 - assert( !MEMDB && !pPager->tempFile ); 38628 39691 38629 39692 if( pagerUseWal(pPager) ){ 38630 39693 /* If the pager is configured to use locking_mode=exclusive, and an 38631 39694 ** exclusive lock on the database is not already held, obtain it now. 38632 39695 */ 38633 39696 if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){ 38634 - rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); 38635 - pPager->state = PAGER_SHARED; 39697 + rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); 38636 39698 if( rc!=SQLITE_OK ){ 38637 39699 return rc; 38638 39700 } 38639 39701 sqlite3WalExclusiveMode(pPager->pWal, 1); 38640 39702 } 38641 39703 38642 39704 /* Grab the write lock on the log file. If successful, upgrade to 38643 39705 ** PAGER_RESERVED state. Otherwise, return an error code to the caller. 38644 39706 ** The busy-handler is not invoked if another connection already 38645 39707 ** holds the write-lock. If possible, the upper layer will call it. 38646 - ** 38647 - ** WAL mode sets Pager.state to PAGER_RESERVED when it has an open 38648 - ** transaction, but never to PAGER_EXCLUSIVE. This is because in 38649 - ** PAGER_EXCLUSIVE state the code to roll back savepoint transactions 38650 - ** may copy data from the sub-journal into the database file as well 38651 - ** as into the page cache. Which would be incorrect in WAL mode. 38652 39708 */ 38653 39709 rc = sqlite3WalBeginWriteTransaction(pPager->pWal); 38654 - if( rc==SQLITE_OK ){ 38655 - pPager->dbOrigSize = pPager->dbSize; 38656 - pPager->state = PAGER_RESERVED; 38657 - pPager->journalOff = 0; 38658 - } 38659 - 38660 - assert( rc!=SQLITE_OK || pPager->state==PAGER_RESERVED ); 38661 - assert( rc==SQLITE_OK || pPager->state==PAGER_SHARED ); 38662 39710 }else{ 38663 39711 /* Obtain a RESERVED lock on the database file. If the exFlag parameter 38664 39712 ** is true, then immediately upgrade this to an EXCLUSIVE lock. The 38665 39713 ** busy-handler callback can be used when upgrading to the EXCLUSIVE 38666 39714 ** lock, but not when obtaining the RESERVED lock. 38667 39715 */ 38668 - rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); 38669 - if( rc==SQLITE_OK ){ 38670 - pPager->state = PAGER_RESERVED; 38671 - if( exFlag ){ 38672 - rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); 38673 - } 38674 - } 38675 - } 38676 - 38677 - /* No need to open the journal file at this time. It will be 38678 - ** opened before it is written to. If we defer opening the journal, 38679 - ** we might save the work of creating a file if the transaction 38680 - ** ends up being a no-op. 38681 - */ 38682 - 38683 - if( rc!=SQLITE_OK ){ 38684 - assert( !pPager->dbModified ); 38685 - /* Ignore any IO error that occurs within pager_end_transaction(). The 38686 - ** purpose of this call is to reset the internal state of the pager 38687 - ** sub-system. It doesn't matter if the journal-file is not properly 38688 - ** finalized at this point (since it is not a valid journal file anyway). 38689 - */ 38690 - pager_end_transaction(pPager, 0); 38691 - } 39716 + rc = pagerLockDb(pPager, RESERVED_LOCK); 39717 + if( rc==SQLITE_OK && exFlag ){ 39718 + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); 39719 + } 39720 + } 39721 + 39722 + if( rc==SQLITE_OK ){ 39723 + /* Change to WRITER_LOCKED state. 39724 + ** 39725 + ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD 39726 + ** when it has an open transaction, but never to DBMOD or FINISHED. 39727 + ** This is because in those states the code to roll back savepoint 39728 + ** transactions may copy data from the sub-journal into the database 39729 + ** file as well as into the page cache. Which would be incorrect in 39730 + ** WAL mode. 39731 + */ 39732 + pPager->eState = PAGER_WRITER_LOCKED; 39733 + pPager->dbHintSize = pPager->dbSize; 39734 + pPager->dbFileSize = pPager->dbSize; 39735 + pPager->dbOrigSize = pPager->dbSize; 39736 + pPager->journalOff = 0; 39737 + } 39738 + 39739 + assert( rc==SQLITE_OK || pPager->eState==PAGER_READER ); 39740 + assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED ); 39741 + assert( assert_pager_state(pPager) ); 38692 39742 } 38693 39743 38694 39744 PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager))); 38695 39745 return rc; 38696 39746 } 38697 39747 38698 39748 /* ................................................................................ 38703 39753 ** of any open savepoints as appropriate. 38704 39754 */ 38705 39755 static int pager_write(PgHdr *pPg){ 38706 39756 void *pData = pPg->pData; 38707 39757 Pager *pPager = pPg->pPager; 38708 39758 int rc = SQLITE_OK; 38709 39759 38710 - /* This routine is not called unless a transaction has already been 38711 - ** started. 39760 + /* This routine is not called unless a write-transaction has already 39761 + ** been started. The journal file may or may not be open at this point. 39762 + ** It is never called in the ERROR state. 38712 39763 */ 38713 - assert( pPager->state>=PAGER_RESERVED ); 39764 + assert( pPager->eState==PAGER_WRITER_LOCKED 39765 + || pPager->eState==PAGER_WRITER_CACHEMOD 39766 + || pPager->eState==PAGER_WRITER_DBMOD 39767 + ); 39768 + assert( assert_pager_state(pPager) ); 38714 39769 38715 39770 /* If an error has been previously detected, report the same error 38716 - ** again. 38717 - */ 39771 + ** again. This should not happen, but the check provides robustness. */ 38718 39772 if( NEVER(pPager->errCode) ) return pPager->errCode; 38719 39773 38720 39774 /* Higher-level routines never call this function if database is not 38721 39775 ** writable. But check anyway, just for robustness. */ 38722 39776 if( NEVER(pPager->readOnly) ) return SQLITE_PERM; 38723 39777 38724 - assert( !pPager->setMaster ); 38725 - 38726 39778 CHECK_PAGE(pPg); 39779 + 39780 + /* The journal file needs to be opened. Higher level routines have already 39781 + ** obtained the necessary locks to begin the write-transaction, but the 39782 + ** rollback journal might not yet be open. Open it now if this is the case. 39783 + ** 39784 + ** This is done before calling sqlite3PcacheMakeDirty() on the page. 39785 + ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then 39786 + ** an error might occur and the pager would end up in WRITER_LOCKED state 39787 + ** with pages marked as dirty in the cache. 39788 + */ 39789 + if( pPager->eState==PAGER_WRITER_LOCKED ){ 39790 + rc = pager_open_journal(pPager); 39791 + if( rc!=SQLITE_OK ) return rc; 39792 + } 39793 + assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); 39794 + assert( assert_pager_state(pPager) ); 38727 39795 38728 39796 /* Mark the page as dirty. If the page has already been written 38729 39797 ** to the journal then we can return right away. 38730 39798 */ 38731 39799 sqlite3PcacheMakeDirty(pPg); 38732 39800 if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){ 38733 39801 assert( !pagerUseWal(pPager) ); 38734 - pPager->dbModified = 1; 38735 39802 }else{ 38736 - 38737 - /* If we get this far, it means that the page needs to be 38738 - ** written to the transaction journal or the ckeckpoint journal 38739 - ** or both. 38740 - ** 38741 - ** Higher level routines should have already started a transaction, 38742 - ** which means they have acquired the necessary locks but the rollback 38743 - ** journal might not yet be open. 38744 - */ 38745 - assert( pPager->state>=RESERVED_LOCK ); 38746 - if( pPager->pInJournal==0 38747 - && pPager->journalMode!=PAGER_JOURNALMODE_OFF 38748 - && !pagerUseWal(pPager) 38749 - ){ 38750 - assert( pPager->useJournal ); 38751 - rc = pager_open_journal(pPager); 38752 - if( rc!=SQLITE_OK ) return rc; 38753 - } 38754 - pPager->dbModified = 1; 38755 39803 38756 39804 /* The transaction journal now exists and we have a RESERVED or an 38757 39805 ** EXCLUSIVE lock on the main database file. Write the current page to 38758 39806 ** the transaction journal if it is not there already. 38759 39807 */ 38760 - if( !pageInJournal(pPg) && isOpen(pPager->jfd) ){ 38761 - assert( !pagerUseWal(pPager) ); 38762 - if( pPg->pgno<=pPager->dbOrigSize ){ 39808 + if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){ 39809 + assert( pagerUseWal(pPager)==0 ); 39810 + if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){ 38763 39811 u32 cksum; 38764 39812 char *pData2; 39813 + i64 iOff = pPager->journalOff; 38765 39814 38766 39815 /* We should never write to the journal file the page that 38767 39816 ** contains the database locks. The following assert verifies 38768 39817 ** that we do not. */ 38769 39818 assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); 38770 39819 38771 - assert( pPager->journalHdr <= pPager->journalOff ); 39820 + assert( pPager->journalHdr<=pPager->journalOff ); 38772 39821 CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); 38773 39822 cksum = pager_cksum(pPager, (u8*)pData2); 38774 - rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno); 38775 - if( rc==SQLITE_OK ){ 38776 - rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, 38777 - pPager->journalOff + 4); 38778 - pPager->journalOff += pPager->pageSize+4; 38779 - } 38780 - if( rc==SQLITE_OK ){ 38781 - rc = write32bits(pPager->jfd, pPager->journalOff, cksum); 38782 - pPager->journalOff += 4; 38783 - } 39823 + 39824 + /* Even if an IO or diskfull error occurs while journalling the 39825 + ** page in the block above, set the need-sync flag for the page. 39826 + ** Otherwise, when the transaction is rolled back, the logic in 39827 + ** playback_one_page() will think that the page needs to be restored 39828 + ** in the database file. And if an IO error occurs while doing so, 39829 + ** then corruption may follow. 39830 + */ 39831 + pPg->flags |= PGHDR_NEED_SYNC; 39832 + 39833 + rc = write32bits(pPager->jfd, iOff, pPg->pgno); 39834 + if( rc!=SQLITE_OK ) return rc; 39835 + rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4); 39836 + if( rc!=SQLITE_OK ) return rc; 39837 + rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum); 39838 + if( rc!=SQLITE_OK ) return rc; 39839 + 38784 39840 IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, 38785 39841 pPager->journalOff, pPager->pageSize)); 38786 39842 PAGER_INCR(sqlite3_pager_writej_count); 38787 39843 PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n", 38788 39844 PAGERID(pPager), pPg->pgno, 38789 39845 ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg))); 38790 39846 38791 - /* Even if an IO or diskfull error occurred while journalling the 38792 - ** page in the block above, set the need-sync flag for the page. 38793 - ** Otherwise, when the transaction is rolled back, the logic in 38794 - ** playback_one_page() will think that the page needs to be restored 38795 - ** in the database file. And if an IO error occurs while doing so, 38796 - ** then corruption may follow. 38797 - */ 38798 - if( !pPager->noSync ){ 38799 - pPg->flags |= PGHDR_NEED_SYNC; 38800 - pPager->needSync = 1; 38801 - } 38802 - 38803 - /* An error has occurred writing to the journal file. The 38804 - ** transaction will be rolled back by the layer above. 38805 - */ 38806 - if( rc!=SQLITE_OK ){ 38807 - return rc; 38808 - } 38809 - 39847 + pPager->journalOff += 8 + pPager->pageSize; 38810 39848 pPager->nRec++; 38811 39849 assert( pPager->pInJournal!=0 ); 38812 39850 rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); 38813 39851 testcase( rc==SQLITE_NOMEM ); 38814 39852 assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); 38815 39853 rc |= addToSavepointBitvecs(pPager, pPg->pgno); 38816 39854 if( rc!=SQLITE_OK ){ 38817 39855 assert( rc==SQLITE_NOMEM ); 38818 39856 return rc; 38819 39857 } 38820 39858 }else{ 38821 - if( !pPager->journalStarted && !pPager->noSync ){ 39859 + if( pPager->eState!=PAGER_WRITER_DBMOD ){ 38822 39860 pPg->flags |= PGHDR_NEED_SYNC; 38823 - pPager->needSync = 1; 38824 39861 } 38825 39862 PAGERTRACE(("APPEND %d page %d needSync=%d\n", 38826 39863 PAGERID(pPager), pPg->pgno, 38827 39864 ((pPg->flags&PGHDR_NEED_SYNC)?1:0))); 38828 39865 } 38829 39866 } 38830 39867 ................................................................................ 38836 39873 if( subjRequiresPage(pPg) ){ 38837 39874 rc = subjournalPage(pPg); 38838 39875 } 38839 39876 } 38840 39877 38841 39878 /* Update the database size and return. 38842 39879 */ 38843 - assert( pPager->state>=PAGER_SHARED ); 38844 39880 if( pPager->dbSize<pPg->pgno ){ 38845 39881 pPager->dbSize = pPg->pgno; 38846 39882 } 38847 39883 return rc; 38848 39884 } 38849 39885 38850 39886 /* ................................................................................ 38864 39900 SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){ 38865 39901 int rc = SQLITE_OK; 38866 39902 38867 39903 PgHdr *pPg = pDbPage; 38868 39904 Pager *pPager = pPg->pPager; 38869 39905 Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); 38870 39906 39907 + assert( pPager->eState>=PAGER_WRITER_LOCKED ); 39908 + assert( pPager->eState!=PAGER_ERROR ); 39909 + assert( assert_pager_state(pPager) ); 39910 + 38871 39911 if( nPagePerSector>1 ){ 38872 39912 Pgno nPageCount; /* Total number of pages in database file */ 38873 39913 Pgno pg1; /* First page of the sector pPg is located on. */ 38874 39914 int nPage = 0; /* Number of pages starting at pg1 to journal */ 38875 39915 int ii; /* Loop counter */ 38876 39916 int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ 38877 39917 ................................................................................ 38885 39925 38886 39926 /* This trick assumes that both the page-size and sector-size are 38887 39927 ** an integer power of 2. It sets variable pg1 to the identifier 38888 39928 ** of the first page of the sector pPg is located on. 38889 39929 */ 38890 39930 pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; 38891 39931 38892 - rc = sqlite3PagerPagecount(pPager, (int *)&nPageCount); 38893 - if( rc==SQLITE_OK ){ 38894 - if( pPg->pgno>nPageCount ){ 38895 - nPage = (pPg->pgno - pg1)+1; 38896 - }else if( (pg1+nPagePerSector-1)>nPageCount ){ 38897 - nPage = nPageCount+1-pg1; 38898 - }else{ 38899 - nPage = nPagePerSector; 38900 - } 38901 - assert(nPage>0); 38902 - assert(pg1<=pPg->pgno); 38903 - assert((pg1+nPage)>pPg->pgno); 39932 + nPageCount = pPager->dbSize; 39933 + if( pPg->pgno>nPageCount ){ 39934 + nPage = (pPg->pgno - pg1)+1; 39935 + }else if( (pg1+nPagePerSector-1)>nPageCount ){ 39936 + nPage = nPageCount+1-pg1; 39937 + }else{ 39938 + nPage = nPagePerSector; 38904 39939 } 39940 + assert(nPage>0); 39941 + assert(pg1<=pPg->pgno); 39942 + assert((pg1+nPage)>pPg->pgno); 38905 39943 38906 39944 for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){ 38907 39945 Pgno pg = pg1+ii; 38908 39946 PgHdr *pPage; 38909 39947 if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ 38910 39948 if( pg!=PAGER_MJ_PGNO(pPager) ){ 38911 39949 rc = sqlite3PagerGet(pPager, pg, &pPage); 38912 39950 if( rc==SQLITE_OK ){ 38913 39951 rc = pager_write(pPage); 38914 39952 if( pPage->flags&PGHDR_NEED_SYNC ){ 38915 39953 needSync = 1; 38916 - assert(pPager->needSync); 38917 39954 } 38918 39955 sqlite3PagerUnref(pPage); 38919 39956 } 38920 39957 } 38921 39958 }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ 38922 39959 if( pPage->flags&PGHDR_NEED_SYNC ){ 38923 39960 needSync = 1; ................................................................................ 38929 39966 /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages 38930 39967 ** starting at pg1, then it needs to be set for all of them. Because 38931 39968 ** writing to any of these nPage pages may damage the others, the 38932 39969 ** journal file must contain sync()ed copies of all of them 38933 39970 ** before any of them can be written out to the database file. 38934 39971 */ 38935 39972 if( rc==SQLITE_OK && needSync ){ 38936 - assert( !MEMDB && pPager->noSync==0 ); 39973 + assert( !MEMDB ); 38937 39974 for(ii=0; ii<nPage; ii++){ 38938 39975 PgHdr *pPage = pager_lookup(pPager, pg1+ii); 38939 39976 if( pPage ){ 38940 39977 pPage->flags |= PGHDR_NEED_SYNC; 38941 39978 sqlite3PagerUnref(pPage); 38942 39979 } 38943 39980 } 38944 - assert(pPager->needSync); 38945 39981 } 38946 39982 38947 39983 assert( pPager->doNotSyncSpill==1 ); 38948 39984 pPager->doNotSyncSpill--; 38949 39985 }else{ 38950 39986 rc = pager_write(pDbPage); 38951 39987 } ................................................................................ 38979 40015 */ 38980 40016 SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){ 38981 40017 Pager *pPager = pPg->pPager; 38982 40018 if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ 38983 40019 PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); 38984 40020 IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) 38985 40021 pPg->flags |= PGHDR_DONT_WRITE; 38986 -#ifdef SQLITE_CHECK_PAGES 38987 - pPg->pageHash = pager_pagehash(pPg); 38988 -#endif 40022 + pager_set_pagehash(pPg); 38989 40023 } 38990 40024 } 38991 40025 38992 40026 /* 38993 40027 ** This routine is called to increment the value of the database file 38994 40028 ** change-counter, stored as a 4-byte big-endian integer starting at 38995 40029 ** byte offset 24 of the pager file. ................................................................................ 39003 40037 ** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case, 39004 40038 ** if isDirect is non-zero, then the database file is updated directly 39005 40039 ** by writing an updated version of page 1 using a call to the 39006 40040 ** sqlite3OsWrite() function. 39007 40041 */ 39008 40042 static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ 39009 40043 int rc = SQLITE_OK; 40044 + 40045 + assert( pPager->eState==PAGER_WRITER_CACHEMOD 40046 + || pPager->eState==PAGER_WRITER_DBMOD 40047 + ); 40048 + assert( assert_pager_state(pPager) ); 39010 40049 39011 40050 /* Declare and initialize constant integer 'isDirect'. If the 39012 40051 ** atomic-write optimization is enabled in this build, then isDirect 39013 40052 ** is initialized to the value passed as the isDirectMode parameter 39014 40053 ** to this function. Otherwise, it is always set to zero. 39015 40054 ** 39016 40055 ** The idea is that if the atomic-write optimization is not ................................................................................ 39022 40061 # define DIRECT_MODE 0 39023 40062 assert( isDirectMode==0 ); 39024 40063 UNUSED_PARAMETER(isDirectMode); 39025 40064 #else 39026 40065 # define DIRECT_MODE isDirectMode 39027 40066 #endif 39028 40067 39029 - assert( pPager->state>=PAGER_RESERVED ); 39030 40068 if( !pPager->changeCountDone && pPager->dbSize>0 ){ 39031 40069 PgHdr *pPgHdr; /* Reference to page 1 */ 39032 40070 u32 change_counter; /* Initial value of change-counter field */ 39033 40071 39034 40072 assert( !pPager->tempFile && isOpen(pPager->fd) ); 39035 40073 39036 40074 /* Open page 1 of the file for writing. */ ................................................................................ 39107 40145 ** If the EXCLUSIVE lock is already held or the attempt to obtain it is 39108 40146 ** successful, or the connection is in WAL mode, SQLITE_OK is returned. 39109 40147 ** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is 39110 40148 ** returned. 39111 40149 */ 39112 40150 SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){ 39113 40151 int rc = SQLITE_OK; 39114 - assert( pPager->state>=PAGER_RESERVED ); 40152 + assert( pPager->eState==PAGER_WRITER_CACHEMOD 40153 + || pPager->eState==PAGER_WRITER_DBMOD 40154 + || pPager->eState==PAGER_WRITER_LOCKED 40155 + ); 40156 + assert( assert_pager_state(pPager) ); 39115 40157 if( 0==pagerUseWal(pPager) ){ 39116 - rc = pager_wait_on_lock(pPager, PAGER_EXCLUSIVE); 40158 + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); 39117 40159 } 39118 40160 return rc; 39119 40161 } 39120 40162 39121 40163 /* 39122 40164 ** Sync the database file for the pager pPager. zMaster points to the name 39123 40165 ** of a master journal file that should be written into the individual ................................................................................ 39147 40189 SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( 39148 40190 Pager *pPager, /* Pager object */ 39149 40191 const char *zMaster, /* If not NULL, the master journal name */ 39150 40192 int noSync /* True to omit the xSync on the db file */ 39151 40193 ){ 39152 40194 int rc = SQLITE_OK; /* Return code */ 39153 40195 39154 - /* The dbOrigSize is never set if journal_mode=OFF */ 39155 - assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 ); 40196 + assert( pPager->eState==PAGER_WRITER_LOCKED 40197 + || pPager->eState==PAGER_WRITER_CACHEMOD 40198 + || pPager->eState==PAGER_WRITER_DBMOD 40199 + || pPager->eState==PAGER_ERROR 40200 + ); 40201 + assert( assert_pager_state(pPager) ); 39156 40202 39157 40203 /* If a prior error occurred, report that error again. */ 39158 - if( pPager->errCode ) return pPager->errCode; 40204 + if( NEVER(pPager->errCode) ) return pPager->errCode; 39159 40205 39160 40206 PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 39161 40207 pPager->zFilename, zMaster, pPager->dbSize)); 39162 40208 39163 - if( MEMDB && pPager->dbModified ){ 40209 + /* If no database changes have been made, return early. */ 40210 + if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK; 40211 + 40212 + if( MEMDB ){ 39164 40213 /* If this is an in-memory db, or no pages have been written to, or this 39165 40214 ** function has already been called, it is mostly a no-op. However, any 39166 40215 ** backup in progress needs to be restarted. 39167 40216 */ 39168 40217 sqlite3BackupRestart(pPager->pBackup); 39169 - }else if( pPager->dbModified ){ 40218 + }else{ 39170 40219 if( pagerUseWal(pPager) ){ 39171 40220 PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); 39172 40221 if( pList ){ 39173 40222 rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1, 39174 40223 (pPager->fullSync ? pPager->sync_flags : 0) 39175 40224 ); 39176 40225 } ................................................................................ 39205 40254 PgHdr *pPg; 39206 40255 assert( isOpen(pPager->jfd) 39207 40256 || pPager->journalMode==PAGER_JOURNALMODE_OFF 39208 40257 || pPager->journalMode==PAGER_JOURNALMODE_WAL 39209 40258 ); 39210 40259 if( !zMaster && isOpen(pPager->jfd) 39211 40260 && pPager->journalOff==jrnlBufferSize(pPager) 39212 - && pPager->dbSize>=pPager->dbFileSize 40261 + && pPager->dbSize>=pPager->dbOrigSize 39213 40262 && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) 39214 40263 ){ 39215 40264 /* Update the db file change counter via the direct-write method. The 39216 40265 ** following call will modify the in-memory representation of page 1 39217 40266 ** to include the updated change counter and then write page 1 39218 40267 ** directly to the database file. Because of the atomic-write 39219 40268 ** property of the host file-system, this is safe. ................................................................................ 39235 40284 ** file. This can only happen in auto-vacuum mode. 39236 40285 ** 39237 40286 ** Before reading the pages with page numbers larger than the 39238 40287 ** current value of Pager.dbSize, set dbSize back to the value 39239 40288 ** that it took at the start of the transaction. Otherwise, the 39240 40289 ** calls to sqlite3PagerGet() return zeroed pages instead of 39241 40290 ** reading data from the database file. 39242 - ** 39243 - ** When journal_mode==OFF the dbOrigSize is always zero, so this 39244 - ** block never runs if journal_mode=OFF. 39245 40291 */ 39246 40292 #ifndef SQLITE_OMIT_AUTOVACUUM 39247 40293 if( pPager->dbSize<pPager->dbOrigSize 39248 - && ALWAYS(pPager->journalMode!=PAGER_JOURNALMODE_OFF) 40294 + && pPager->journalMode!=PAGER_JOURNALMODE_OFF 39249 40295 ){ 39250 40296 Pgno i; /* Iterator variable */ 39251 40297 const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */ 39252 40298 const Pgno dbSize = pPager->dbSize; /* Database image size */ 39253 40299 pPager->dbSize = pPager->dbOrigSize; 39254 40300 for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){ 39255 40301 if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){ ................................................................................ 39268 40314 /* Write the master journal name into the journal file. If a master 39269 40315 ** journal file name has already been written to the journal file, 39270 40316 ** or if zMaster is NULL (no master journal), then this call is a no-op. 39271 40317 */ 39272 40318 rc = writeMasterJournal(pPager, zMaster); 39273 40319 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; 39274 40320 39275 - /* Sync the journal file. If the atomic-update optimization is being 39276 - ** used, this call will not create the journal file or perform any 39277 - ** real IO. 40321 + /* Sync the journal file and write all dirty pages to the database. 40322 + ** If the atomic-update optimization is being used, this sync will not 40323 + ** create the journal file or perform any real IO. 40324 + ** 40325 + ** Because the change-counter page was just modified, unless the 40326 + ** atomic-update optimization is used it is almost certain that the 40327 + ** journal requires a sync here. However, in locking_mode=exclusive 40328 + ** on a system under memory pressure it is just possible that this is 40329 + ** not the case. In this case it is likely enough that the redundant 40330 + ** xSync() call will be changed to a no-op by the OS anyhow. 39278 40331 */ 39279 - rc = syncJournal(pPager); 40332 + rc = syncJournal(pPager, 0); 39280 40333 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; 39281 40334 39282 - /* Write all dirty pages to the database file. */ 39283 40335 rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); 39284 40336 if( rc!=SQLITE_OK ){ 39285 40337 assert( rc!=SQLITE_IOERR_BLOCKED ); 39286 40338 goto commit_phase_one_exit; 39287 40339 } 39288 40340 sqlite3PcacheCleanAll(pPager->pPCache); 39289 40341 39290 40342 /* If the file on disk is not the same size as the database image, 39291 40343 ** then use pager_truncate to grow or shrink the file here. 39292 40344 */ 39293 40345 if( pPager->dbSize!=pPager->dbFileSize ){ 39294 40346 Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager)); 39295 - assert( pPager->state>=PAGER_EXCLUSIVE ); 40347 + assert( pPager->eState==PAGER_WRITER_DBMOD ); 39296 40348 rc = pager_truncate(pPager, nNew); 39297 40349 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; 39298 40350 } 39299 40351 39300 40352 /* Finally, sync the database file. */ 39301 40353 if( !pPager->noSync && !noSync ){ 39302 40354 rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); 39303 40355 } 39304 40356 IOTRACE(("DBSYNC %p\n", pPager)) 39305 40357 } 39306 - 39307 - assert( pPager->state!=PAGER_SYNCED ); 39308 - pPager->state = PAGER_SYNCED; 39309 40358 } 39310 40359 39311 40360 commit_phase_one_exit: 40361 + if( rc==SQLITE_OK && !pagerUseWal(pPager) ){ 40362 + pPager->eState = PAGER_WRITER_FINISHED; 40363 + } 39312 40364 return rc; 39313 40365 } 39314 40366 39315 40367 39316 40368 /* 39317 40369 ** When this function is called, the database file has been completely 39318 40370 ** updated to reflect the changes made by the current transaction and ................................................................................ 39332 40384 int rc = SQLITE_OK; /* Return code */ 39333 40385 39334 40386 /* This routine should not be called if a prior error has occurred. 39335 40387 ** But if (due to a coding error elsewhere in the system) it does get 39336 40388 ** called, just return the same error code without doing anything. */ 39337 40389 if( NEVER(pPager->errCode) ) return pPager->errCode; 39338 40390 39339 - /* This function should not be called if the pager is not in at least 39340 - ** PAGER_RESERVED state. **FIXME**: Make it so that this test always 39341 - ** fails - make it so that we never reach this point if we do not hold 39342 - ** all necessary locks. 39343 - */ 39344 - if( NEVER(pPager->state<PAGER_RESERVED) ) return SQLITE_ERROR; 40391 + assert( pPager->eState==PAGER_WRITER_LOCKED 40392 + || pPager->eState==PAGER_WRITER_FINISHED 40393 + || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD) 40394 + ); 40395 + assert( assert_pager_state(pPager) ); 39345 40396 39346 40397 /* An optimization. If the database was not actually modified during 39347 40398 ** this transaction, the pager is running in exclusive-mode and is 39348 40399 ** using persistent journals, then this function is a no-op. 39349 40400 ** 39350 40401 ** The start of the journal file currently contains a single journal 39351 40402 ** header with the nRec field set to 0. If such a journal is used as 39352 40403 ** a hot-journal during hot-journal rollback, 0 changes will be made 39353 40404 ** to the database file. So there is no need to zero the journal 39354 40405 ** header. Since the pager is in exclusive mode, there is no need 39355 40406 ** to drop any locks either. 39356 40407 */ 39357 - if( pPager->dbModified==0 && pPager->exclusiveMode 40408 + if( pPager->eState==PAGER_WRITER_LOCKED 40409 + && pPager->exclusiveMode 39358 40410 && pPager->journalMode==PAGER_JOURNALMODE_PERSIST 39359 40411 ){ 39360 40412 assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); 40413 + pPager->eState = PAGER_READER; 39361 40414 return SQLITE_OK; 39362 40415 } 39363 40416 39364 40417 PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); 39365 - assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dbModified ); 39366 40418 rc = pager_end_transaction(pPager, pPager->setMaster); 39367 40419 return pager_error(pPager, rc); 39368 40420 } 39369 40421 39370 40422 /* 39371 -** Rollback all changes. The database falls back to PAGER_SHARED mode. 40423 +** If a write transaction is open, then all changes made within the 40424 +** transaction are reverted and the current write-transaction is closed. 40425 +** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR 40426 +** state if an error occurs. 39372 40427 ** 39373 -** This function performs two tasks: 40428 +** If the pager is already in PAGER_ERROR state when this function is called, 40429 +** it returns Pager.errCode immediately. No work is performed in this case. 40430 +** 40431 +** Otherwise, in rollback mode, this function performs two functions: 39374 40432 ** 39375 40433 ** 1) It rolls back the journal file, restoring all database file and 39376 40434 ** in-memory cache pages to the state they were in when the transaction 39377 40435 ** was opened, and 40436 +** 39378 40437 ** 2) It finalizes the journal file, so that it is not used for hot 39379 40438 ** rollback at any point in the future. 39380 40439 ** 39381 -** subject to the following qualifications: 40440 +** Finalization of the journal file (task 2) is only performed if the 40441 +** rollback is successful. 39382 40442 ** 39383 -** * If the journal file is not yet open when this function is called, 39384 -** then only (2) is performed. In this case there is no journal file 39385 -** to roll back. 39386 -** 39387 -** * If in an error state other than SQLITE_FULL, then task (1) is 39388 -** performed. If successful, task (2). Regardless of the outcome 39389 -** of either, the error state error code is returned to the caller 39390 -** (i.e. either SQLITE_IOERR or SQLITE_CORRUPT). 39391 -** 39392 -** * If the pager is in PAGER_RESERVED state, then attempt (1). Whether 39393 -** or not (1) is successful, also attempt (2). If successful, return 39394 -** SQLITE_OK. Otherwise, enter the error state and return the first 39395 -** error code encountered. 39396 -** 39397 -** In this case there is no chance that the database was written to. 39398 -** So is safe to finalize the journal file even if the playback 39399 -** (operation 1) failed. However the pager must enter the error state 39400 -** as the contents of the in-memory cache are now suspect. 39401 -** 39402 -** * Finally, if in PAGER_EXCLUSIVE state, then attempt (1). Only 39403 -** attempt (2) if (1) is successful. Return SQLITE_OK if successful, 39404 -** otherwise enter the error state and return the error code from the 39405 -** failing operation. 39406 -** 39407 -** In this case the database file may have been written to. So if the 39408 -** playback operation did not succeed it would not be safe to finalize 39409 -** the journal file. It needs to be left in the file-system so that 39410 -** some other process can use it to restore the database state (by 39411 -** hot-journal rollback). 40443 +** In WAL mode, all cache-entries containing data modified within the 40444 +** current transaction are either expelled from the cache or reverted to 40445 +** their pre-transaction state by re-reading data from the database or 40446 +** WAL files. The WAL transaction is then closed. 39412 40447 */ 39413 40448 SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ 39414 40449 int rc = SQLITE_OK; /* Return code */ 39415 40450 PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager))); 40451 + 40452 + /* PagerRollback() is a no-op if called in READER or OPEN state. If 40453 + ** the pager is already in the ERROR state, the rollback is not 40454 + ** attempted here. Instead, the error code is returned to the caller. 40455 + */ 40456 + assert( assert_pager_state(pPager) ); 40457 + if( pPager->eState==PAGER_ERROR ) return pPager->errCode; 40458 + if( pPager->eState<=PAGER_READER ) return SQLITE_OK; 40459 + 39416 40460 if( pagerUseWal(pPager) ){ 39417 40461 int rc2; 39418 - 39419 40462 rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); 39420 40463 rc2 = pager_end_transaction(pPager, pPager->setMaster); 39421 40464 if( rc==SQLITE_OK ) rc = rc2; 39422 - rc = pager_error(pPager, rc); 39423 - }else if( !pPager->dbModified || !isOpen(pPager->jfd) ){ 39424 - rc = pager_end_transaction(pPager, pPager->setMaster); 39425 - }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ 39426 - if( pPager->state>=PAGER_EXCLUSIVE ){ 39427 - pager_playback(pPager, 0); 39428 - } 39429 - rc = pPager->errCode; 39430 - }else{ 39431 - if( pPager->state==PAGER_RESERVED ){ 39432 - int rc2; 39433 - rc = pager_playback(pPager, 0); 39434 - rc2 = pager_end_transaction(pPager, pPager->setMaster); 39435 - if( rc==SQLITE_OK ){ 39436 - rc = rc2; 39437 - } 39438 - }else{ 39439 - rc = pager_playback(pPager, 0); 39440 - } 39441 - 39442 - if( !MEMDB ){ 39443 - pPager->dbSizeValid = 0; 39444 - } 39445 - 39446 - /* If an error occurs during a ROLLBACK, we can no longer trust the pager 39447 - ** cache. So call pager_error() on the way out to make any error 39448 - ** persistent. 39449 - */ 39450 - rc = pager_error(pPager, rc); 39451 - } 39452 - return rc; 40465 + }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){ 40466 + rc = pager_end_transaction(pPager, 0); 40467 + }else{ 40468 + rc = pager_playback(pPager, 0); 40469 + } 40470 + 40471 + assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK ); 40472 + assert( rc==SQLITE_OK || rc==SQLITE_FULL || (rc&0xFF)==SQLITE_IOERR ); 40473 + 40474 + /* If an error occurs during a ROLLBACK, we can no longer trust the pager 40475 + ** cache. So call pager_error() on the way out to make any error persistent. 40476 + */ 40477 + return pager_error(pPager, rc); 39453 40478 } 39454 40479 39455 40480 /* 39456 40481 ** Return TRUE if the database file is opened read-only. Return FALSE 39457 40482 ** if the database is (in theory) writable. 39458 40483 */ 39459 40484 SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){ ................................................................................ 39491 40516 ** This routine is used for testing and analysis only. 39492 40517 */ 39493 40518 SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ 39494 40519 static int a[11]; 39495 40520 a[0] = sqlite3PcacheRefCount(pPager->pPCache); 39496 40521 a[1] = sqlite3PcachePagecount(pPager->pPCache); 39497 40522 a[2] = sqlite3PcacheGetCachesize(pPager->pPCache); 39498 - a[3] = pPager->dbSizeValid ? (int) pPager->dbSize : -1; 39499 - a[4] = pPager->state; 40523 + a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; 40524 + a[4] = pPager->eState; 39500 40525 a[5] = pPager->errCode; 39501 40526 a[6] = pPager->nHit; 39502 40527 a[7] = pPager->nMiss; 39503 40528 a[8] = 0; /* Used to be pPager->nOvfl */ 39504 40529 a[9] = pPager->nRead; 39505 40530 a[10] = pPager->nWrite; 39506 40531 return a; ................................................................................ 39523 40548 ** If a memory allocation fails, SQLITE_NOMEM is returned. If an error 39524 40549 ** occurs while opening the sub-journal file, then an IO error code is 39525 40550 ** returned. Otherwise, SQLITE_OK. 39526 40551 */ 39527 40552 SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ 39528 40553 int rc = SQLITE_OK; /* Return code */ 39529 40554 int nCurrent = pPager->nSavepoint; /* Current number of savepoints */ 40555 + 40556 + assert( pPager->eState>=PAGER_WRITER_LOCKED ); 40557 + assert( assert_pager_state(pPager) ); 39530 40558 39531 40559 if( nSavepoint>nCurrent && pPager->useJournal ){ 39532 40560 int ii; /* Iterator variable */ 39533 40561 PagerSavepoint *aNew; /* New Pager.aSavepoint array */ 39534 - int nPage; /* Size of database file */ 39535 - 39536 - rc = sqlite3PagerPagecount(pPager, &nPage); 39537 - if( rc ) return rc; 39538 40562 39539 40563 /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM 39540 40564 ** if the allocation fails. Otherwise, zero the new portion in case a 39541 40565 ** malloc failure occurs while populating it in the for(...) loop below. 39542 40566 */ 39543 40567 aNew = (PagerSavepoint *)sqlite3Realloc( 39544 40568 pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint ................................................................................ 39547 40571 return SQLITE_NOMEM; 39548 40572 } 39549 40573 memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint)); 39550 40574 pPager->aSavepoint = aNew; 39551 40575 39552 40576 /* Populate the PagerSavepoint structures just allocated. */ 39553 40577 for(ii=nCurrent; ii<nSavepoint; ii++){ 39554 - aNew[ii].nOrig = nPage; 40578 + aNew[ii].nOrig = pPager->dbSize; 39555 40579 if( isOpen(pPager->jfd) && pPager->journalOff>0 ){ 39556 40580 aNew[ii].iOffset = pPager->journalOff; 39557 40581 }else{ 39558 40582 aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); 39559 40583 } 39560 40584 aNew[ii].iSubRec = pPager->nSubRec; 39561 - aNew[ii].pInSavepoint = sqlite3BitvecCreate(nPage); 40585 + aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize); 39562 40586 if( !aNew[ii].pInSavepoint ){ 39563 40587 return SQLITE_NOMEM; 39564 40588 } 39565 40589 if( pagerUseWal(pPager) ){ 39566 40590 sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData); 39567 40591 } 39568 40592 pPager->nSavepoint = ii+1; ................................................................................ 39601 40625 ** then savepoint iSavepoint is also destroyed. 39602 40626 ** 39603 40627 ** This function may return SQLITE_NOMEM if a memory allocation fails, 39604 40628 ** or an IO error code if an IO error occurs while rolling back a 39605 40629 ** savepoint. If no errors occur, SQLITE_OK is returned. 39606 40630 */ 39607 40631 SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ 39608 - int rc = SQLITE_OK; 40632 + int rc = pPager->errCode; /* Return code */ 39609 40633 39610 40634 assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); 39611 40635 assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK ); 39612 40636 39613 - if( iSavepoint<pPager->nSavepoint ){ 40637 + if( rc==SQLITE_OK && iSavepoint<pPager->nSavepoint ){ 39614 40638 int ii; /* Iterator variable */ 39615 40639 int nNew; /* Number of remaining savepoints after this op. */ 39616 40640 39617 40641 /* Figure out how many savepoints will still be active after this 39618 40642 ** operation. Store this value in nNew. Then free resources associated 39619 40643 ** with any savepoints that are destroyed by this operation. 39620 40644 */ ................................................................................ 39642 40666 ** the database file, so the playback operation can be skipped. 39643 40667 */ 39644 40668 else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){ 39645 40669 PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; 39646 40670 rc = pagerPlaybackSavepoint(pPager, pSavepoint); 39647 40671 assert(rc!=SQLITE_DONE); 39648 40672 } 39649 - 39650 40673 } 40674 + 39651 40675 return rc; 39652 40676 } 39653 40677 39654 40678 /* 39655 40679 ** Return the full pathname of the database file. 39656 40680 */ 39657 40681 SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager){ ................................................................................ 39741 40765 SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ 39742 40766 PgHdr *pPgOld; /* The page being overwritten. */ 39743 40767 Pgno needSyncPgno = 0; /* Old value of pPg->pgno, if sync is required */ 39744 40768 int rc; /* Return code */ 39745 40769 Pgno origPgno; /* The original page number */ 39746 40770 39747 40771 assert( pPg->nRef>0 ); 40772 + assert( pPager->eState==PAGER_WRITER_CACHEMOD 40773 + || pPager->eState==PAGER_WRITER_DBMOD 40774 + ); 40775 + assert( assert_pager_state(pPager) ); 39748 40776 39749 40777 /* In order to be able to rollback, an in-memory database must journal 39750 40778 ** the page we are moving from. 39751 40779 */ 39752 40780 if( MEMDB ){ 39753 40781 rc = sqlite3PagerWrite(pPg); 39754 40782 if( rc ) return rc; ................................................................................ 39790 40818 ** the journal needs to be sync()ed before database page pPg->pgno 39791 40819 ** can be written to. The caller has already promised not to write to it. 39792 40820 */ 39793 40821 if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ 39794 40822 needSyncPgno = pPg->pgno; 39795 40823 assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize ); 39796 40824 assert( pPg->flags&PGHDR_DIRTY ); 39797 - assert( pPager->needSync ); 39798 40825 } 39799 40826 39800 40827 /* If the cache contains a page with page-number pgno, remove it 39801 - ** from its hash chain. Also, if the PgHdr.needSync was set for 40828 + ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for 39802 40829 ** page pgno before the 'move' operation, it needs to be retained 39803 40830 ** for the page moved there. 39804 40831 */ 39805 40832 pPg->flags &= ~PGHDR_NEED_SYNC; 39806 40833 pPgOld = pager_lookup(pPager, pgno); 39807 40834 assert( !pPgOld || pPgOld->nRef==1 ); 39808 40835 if( pPgOld ){ 39809 40836 pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); 39810 40837 if( MEMDB ){ 39811 40838 /* Do not discard pages from an in-memory database since we might 39812 40839 ** need to rollback later. Just move the page out of the way. */ 39813 - assert( pPager->dbSizeValid ); 39814 40840 sqlite3PcacheMove(pPgOld, pPager->dbSize+1); 39815 40841 }else{ 39816 40842 sqlite3PcacheDrop(pPgOld); 39817 40843 } 39818 40844 } 39819 40845 39820 40846 origPgno = pPg->pgno; 39821 40847 sqlite3PcacheMove(pPg, pgno); 39822 40848 sqlite3PcacheMakeDirty(pPg); 39823 - pPager->dbModified = 1; 40849 + 40850 + /* For an in-memory database, make sure the original page continues 40851 + ** to exist, in case the transaction needs to roll back. Use pPgOld 40852 + ** as the original page since it has already been allocated. 40853 + */ 40854 + if( MEMDB ){ 40855 + assert( pPgOld ); 40856 + sqlite3PcacheMove(pPgOld, origPgno); 40857 + sqlite3PagerUnref(pPgOld); 40858 + } 39824 40859 39825 40860 if( needSyncPgno ){ 39826 40861 /* If needSyncPgno is non-zero, then the journal file needs to be 39827 40862 ** sync()ed before any data is written to database file page needSyncPgno. 39828 40863 ** Currently, no such page exists in the page-cache and the 39829 40864 ** "is journaled" bitvec flag has been set. This needs to be remedied by 39830 - ** loading the page into the pager-cache and setting the PgHdr.needSync 40865 + ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC 39831 40866 ** flag. 39832 40867 ** 39833 40868 ** If the attempt to load the page into the page-cache fails, (due 39834 40869 ** to a malloc() or IO failure), clear the bit in the pInJournal[] 39835 40870 ** array. Otherwise, if the page is loaded and written again in 39836 40871 ** this transaction, it may be written to the database file before 39837 40872 ** it is synced into the journal file. This way, it may end up in 39838 40873 ** the journal file twice, but that is not a problem. 39839 - ** 39840 - ** The sqlite3PagerGet() call may cause the journal to sync. So make 39841 - ** sure the Pager.needSync flag is set too. 39842 40874 */ 39843 40875 PgHdr *pPgHdr; 39844 - assert( pPager->needSync ); 39845 40876 rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); 39846 40877 if( rc!=SQLITE_OK ){ 39847 40878 if( needSyncPgno<=pPager->dbOrigSize ){ 39848 40879 assert( pPager->pTmpSpace!=0 ); 39849 40880 sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace); 39850 40881 } 39851 40882 return rc; 39852 40883 } 39853 - pPager->needSync = 1; 39854 - assert( pPager->noSync==0 && !MEMDB ); 39855 40884 pPgHdr->flags |= PGHDR_NEED_SYNC; 39856 40885 sqlite3PcacheMakeDirty(pPgHdr); 39857 40886 sqlite3PagerUnref(pPgHdr); 39858 40887 } 39859 40888 39860 - /* 39861 - ** For an in-memory database, make sure the original page continues 39862 - ** to exist, in case the transaction needs to roll back. Use pPgOld 39863 - ** as the original page since it has already been allocated. 39864 - */ 39865 - if( MEMDB ){ 39866 - sqlite3PcacheMove(pPgOld, origPgno); 39867 - sqlite3PagerUnref(pPgOld); 39868 - } 39869 - 39870 40889 return SQLITE_OK; 39871 40890 } 39872 40891 #endif 39873 40892 39874 40893 /* 39875 40894 ** Return a pointer to the data for the specified page. 39876 40895 */ ................................................................................ 39927 40946 ** 39928 40947 ** * Temporary databases cannot have _WAL journalmode. 39929 40948 ** 39930 40949 ** The returned indicate the current (possibly updated) journal-mode. 39931 40950 */ 39932 40951 SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ 39933 40952 u8 eOld = pPager->journalMode; /* Prior journalmode */ 40953 + 40954 +#ifdef SQLITE_DEBUG 40955 + /* The print_pager_state() routine is intended to be used by the debugger 40956 + ** only. We invoke it once here to suppress a compiler warning. */ 40957 + print_pager_state(pPager); 40958 +#endif 40959 + 39934 40960 39935 40961 /* The eMode parameter is always valid */ 39936 40962 assert( eMode==PAGER_JOURNALMODE_DELETE 39937 40963 || eMode==PAGER_JOURNALMODE_TRUNCATE 39938 40964 || eMode==PAGER_JOURNALMODE_PERSIST 39939 40965 || eMode==PAGER_JOURNALMODE_OFF 39940 40966 || eMode==PAGER_JOURNALMODE_WAL ................................................................................ 39953 40979 assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF ); 39954 40980 if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){ 39955 40981 eMode = eOld; 39956 40982 } 39957 40983 } 39958 40984 39959 40985 if( eMode!=eOld ){ 39960 - /* When changing between rollback modes, close the journal file prior 39961 - ** to the change. But when changing from a rollback mode to WAL, keep 39962 - ** the journal open since there is a rollback-style transaction in play 39963 - ** used to convert the version numbers in the btree header. 39964 - */ 39965 - if( isOpen(pPager->jfd) && eMode!=PAGER_JOURNALMODE_WAL ){ 39966 - sqlite3OsClose(pPager->jfd); 39967 - } 39968 40986 39969 40987 /* Change the journal mode. */ 40988 + assert( pPager->eState!=PAGER_ERROR ); 39970 40989 pPager->journalMode = (u8)eMode; 39971 40990 39972 40991 /* When transistioning from TRUNCATE or PERSIST to any other journal 39973 - ** mode except WAL (and we are not in locking_mode=EXCLUSIVE) then 40992 + ** mode except WAL, unless the pager is in locking_mode=exclusive mode, 39974 40993 ** delete the journal file. 39975 40994 */ 39976 40995 assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); 39977 40996 assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); 39978 40997 assert( (PAGER_JOURNALMODE_DELETE & 5)==0 ); 39979 40998 assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 ); 39980 40999 assert( (PAGER_JOURNALMODE_OFF & 5)==0 ); ................................................................................ 39987 41006 ** not possible, then that is not a problem. Deleting the journal file 39988 41007 ** here is an optimization only. 39989 41008 ** 39990 41009 ** Before deleting the journal file, obtain a RESERVED lock on the 39991 41010 ** database file. This ensures that the journal file is not deleted 39992 41011 ** while it is in use by some other client. 39993 41012 */ 39994 - int rc = SQLITE_OK; 39995 - int state = pPager->state; 39996 - if( state<PAGER_SHARED ){ 39997 - rc = sqlite3PagerSharedLock(pPager); 39998 - } 39999 - if( pPager->state==PAGER_SHARED ){ 40000 - assert( rc==SQLITE_OK ); 40001 - rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); 40002 - } 40003 - if( rc==SQLITE_OK ){ 41013 + sqlite3OsClose(pPager->jfd); 41014 + if( pPager->eLock>=RESERVED_LOCK ){ 40004 41015 sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); 41016 + }else{ 41017 + int rc = SQLITE_OK; 41018 + int state = pPager->eState; 41019 + assert( state==PAGER_OPEN || state==PAGER_READER ); 41020 + if( state==PAGER_OPEN ){ 41021 + rc = sqlite3PagerSharedLock(pPager); 41022 + } 41023 + if( pPager->eState==PAGER_READER ){ 41024 + assert( rc==SQLITE_OK ); 41025 + rc = pagerLockDb(pPager, RESERVED_LOCK); 41026 + } 41027 + if( rc==SQLITE_OK ){ 41028 + sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); 41029 + } 41030 + if( rc==SQLITE_OK && state==PAGER_READER ){ 41031 + pagerUnlockDb(pPager, SHARED_LOCK); 41032 + }else if( state==PAGER_OPEN ){ 41033 + pager_unlock(pPager); 41034 + } 41035 + assert( state==pPager->eState ); 40005 41036 } 40006 - if( rc==SQLITE_OK && state==PAGER_SHARED ){ 40007 - sqlite3OsUnlock(pPager->fd, SHARED_LOCK); 40008 - }else if( state==PAGER_UNLOCK ){ 40009 - pager_unlock(pPager); 40010 - } 40011 - assert( state==pPager->state ); 40012 41037 } 40013 41038 } 40014 41039 40015 41040 /* Return the new journal mode */ 40016 41041 return (int)pPager->journalMode; 40017 41042 } 40018 41043 ................................................................................ 40025 41050 40026 41051 /* 40027 41052 ** Return TRUE if the pager is in a state where it is OK to change the 40028 41053 ** journalmode. Journalmode changes can only happen when the database 40029 41054 ** is unmodified. 40030 41055 */ 40031 41056 SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ 40032 - if( pPager->dbModified ) return 0; 41057 + assert( assert_pager_state(pPager) ); 41058 + if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0; 40033 41059 if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; 40034 41060 return 1; 40035 41061 } 40036 41062 40037 41063 /* 40038 41064 ** Get/set the size-limit used for persistent journal files. 40039 41065 ** ................................................................................ 40090 41116 ** The caller must be holding a SHARED lock on the database file to call 40091 41117 ** this function. 40092 41118 ** 40093 41119 ** If the pager passed as the first argument is open on a real database 40094 41120 ** file (not a temp file or an in-memory database), and the WAL file 40095 41121 ** is not already open, make an attempt to open it now. If successful, 40096 41122 ** return SQLITE_OK. If an error occurs or the VFS used by the pager does 40097 -** not support the xShmXXX() methods, return an error code. *pisOpen is 41123 +** not support the xShmXXX() methods, return an error code. *pbOpen is 40098 41124 ** not modified in either case. 40099 41125 ** 40100 41126 ** If the pager is open on a temp-file (or in-memory database), or if 40101 -** the WAL file is already open, set *pisOpen to 1 and return SQLITE_OK 41127 +** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK 40102 41128 ** without doing anything. 40103 41129 */ 40104 41130 SQLITE_PRIVATE int sqlite3PagerOpenWal( 40105 41131 Pager *pPager, /* Pager object */ 40106 - int *pisOpen /* OUT: Set to true if call is a no-op */ 41132 + int *pbOpen /* OUT: Set to true if call is a no-op */ 40107 41133 ){ 40108 41134 int rc = SQLITE_OK; /* Return code */ 40109 41135 40110 - assert( pPager->state>=PAGER_SHARED ); 40111 - assert( (pisOpen==0 && !pPager->tempFile && !pPager->pWal) || *pisOpen==0 ); 41136 + assert( assert_pager_state(pPager) ); 41137 + assert( pPager->eState==PAGER_OPEN || pbOpen ); 41138 + assert( pPager->eState==PAGER_READER || !pbOpen ); 41139 + assert( pbOpen==0 || *pbOpen==0 ); 41140 + assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) ); 40112 41141 40113 41142 if( !pPager->tempFile && !pPager->pWal ){ 40114 41143 if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; 41144 + 41145 + /* Close any rollback journal previously open */ 41146 + sqlite3OsClose(pPager->jfd); 40115 41147 40116 41148 /* Open the connection to the log file. If this operation fails, 40117 41149 ** (e.g. due to malloc() failure), unlock the database file and 40118 41150 ** return an error code. 40119 41151 */ 40120 41152 rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, &pPager->pWal); 40121 41153 if( rc==SQLITE_OK ){ 40122 41154 pPager->journalMode = PAGER_JOURNALMODE_WAL; 41155 + pPager->eState = PAGER_OPEN; 40123 41156 } 40124 41157 }else{ 40125 - *pisOpen = 1; 41158 + *pbOpen = 1; 40126 41159 } 40127 41160 40128 41161 return rc; 40129 41162 } 40130 41163 40131 41164 /* 40132 41165 ** This function is called to close the connection to the log file prior ................................................................................ 40144 41177 40145 41178 /* If the log file is not already open, but does exist in the file-system, 40146 41179 ** it may need to be checkpointed before the connection can switch to 40147 41180 ** rollback mode. Open it now so this can happen. 40148 41181 */ 40149 41182 if( !pPager->pWal ){ 40150 41183 int logexists = 0; 40151 - rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED); 41184 + rc = pagerLockDb(pPager, SHARED_LOCK); 40152 41185 if( rc==SQLITE_OK ){ 40153 41186 rc = sqlite3OsAccess( 40154 41187 pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists 40155 41188 ); 40156 41189 } 40157 41190 if( rc==SQLITE_OK && logexists ){ 40158 41191 rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, ................................................................................ 40160 41193 } 40161 41194 } 40162 41195 40163 41196 /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on 40164 41197 ** the database file, the log and log-summary files will be deleted. 40165 41198 */ 40166 41199 if( rc==SQLITE_OK && pPager->pWal ){ 40167 - rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_EXCLUSIVE); 41200 + rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); 40168 41201 if( rc==SQLITE_OK ){ 40169 41202 rc = sqlite3WalClose(pPager->pWal, 40170 41203 (pPager->noSync ? 0 : pPager->sync_flags), 40171 41204 pPager->pageSize, (u8*)pPager->pTmpSpace 40172 41205 ); 40173 41206 pPager->pWal = 0; 40174 41207 }else{ 40175 41208 /* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock 40176 41209 ** that we did get back to SHARED. */ 40177 - sqlite3OsUnlock(pPager->fd, SQLITE_LOCK_SHARED); 41210 + pagerUnlockDb(pPager, SQLITE_LOCK_SHARED); 40178 41211 } 40179 41212 } 40180 41213 return rc; 40181 41214 } 40182 41215 40183 41216 #ifdef SQLITE_HAS_CODEC 40184 41217 /* ................................................................................ 40490 41523 40491 41524 40492 41525 /* 40493 41526 ** The following object holds a copy of the wal-index header content. 40494 41527 ** 40495 41528 ** The actual header in the wal-index consists of two copies of this 40496 41529 ** object. 41530 +** 41531 +** The szPage value can be any power of 2 between 512 and 32768, inclusive. 41532 +** Or it can be 1 to represent a 65536-byte page. The latter case was 41533 +** added in 3.7.1 when support for 64K pages was added. 40497 41534 */ 40498 41535 struct WalIndexHdr { 40499 41536 u32 iVersion; /* Wal-index version */ 40500 41537 u32 unused; /* Unused (padding) field */ 40501 41538 u32 iChange; /* Counter incremented each transaction */ 40502 41539 u8 isInit; /* 1 when initialized */ 40503 41540 u8 bigEndCksum; /* True if checksums in WAL are big-endian */ 40504 - u16 szPage; /* Database page size in bytes */ 41541 + u16 szPage; /* Database page size in bytes. 1==64K */ 40505 41542 u32 mxFrame; /* Index of last valid frame in the WAL */ 40506 41543 u32 nPage; /* Size of database in pages */ 40507 41544 u32 aFrameCksum[2]; /* Checksum of last frame in log */ 40508 41545 u32 aSalt[2]; /* Two salt values copied from WAL header */ 40509 41546 u32 aCksum[2]; /* Checksum over all prior fields */ 40510 41547 }; 40511 41548 ................................................................................ 40608 41645 struct Wal { 40609 41646 sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */ 40610 41647 sqlite3_file *pDbFd; /* File handle for the database file */ 40611 41648 sqlite3_file *pWalFd; /* File handle for WAL file */ 40612 41649 u32 iCallback; /* Value to pass to log callback (or 0) */ 40613 41650 int nWiData; /* Size of array apWiData */ 40614 41651 volatile u32 **apWiData; /* Pointer to wal-index content in memory */ 40615 - u16 szPage; /* Database page size */ 41652 + u32 szPage; /* Database page size */ 40616 41653 i16 readLock; /* Which read lock is being held. -1 for none */ 40617 41654 u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */ 40618 41655 u8 writeLock; /* True if in a write transaction */ 40619 41656 u8 ckptLock; /* True if holding a checkpoint lock */ 40620 41657 u8 readOnly; /* True if the WAL file is open read-only */ 40621 41658 WalIndexHdr hdr; /* Wal-index header for current transaction */ 40622 41659 const char *zWalName; /* Name of WAL file */ ................................................................................ 41279 42316 || szPage&(szPage-1) 41280 42317 || szPage>SQLITE_MAX_PAGE_SIZE 41281 42318 || szPage<512 41282 42319 ){ 41283 42320 goto finished; 41284 42321 } 41285 42322 pWal->hdr.bigEndCksum = (u8)(magic&0x00000001); 41286 - pWal->szPage = (u16)szPage; 42323 + pWal->szPage = szPage; 41287 42324 pWal->nCkpt = sqlite3Get4byte(&aBuf[12]); 41288 42325 memcpy(&pWal->hdr.aSalt, &aBuf[16], 8); 41289 42326 41290 42327 /* Verify that the WAL header checksum is correct */ 41291 42328 walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, 41292 42329 aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum 41293 42330 ); ................................................................................ 41329 42366 rc = walIndexAppend(pWal, ++iFrame, pgno); 41330 42367 if( rc!=SQLITE_OK ) break; 41331 42368 41332 42369 /* If nTruncate is non-zero, this is a commit record. */ 41333 42370 if( nTruncate ){ 41334 42371 pWal->hdr.mxFrame = iFrame; 41335 42372 pWal->hdr.nPage = nTruncate; 41336 - pWal->hdr.szPage = (u16)szPage; 42373 + pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); 42374 + testcase( szPage<=32768 ); 42375 + testcase( szPage>=65536 ); 41337 42376 aFrameCksum[0] = pWal->hdr.aFrameCksum[0]; 41338 42377 aFrameCksum[1] = pWal->hdr.aFrameCksum[1]; 41339 42378 } 41340 42379 } 41341 42380 41342 42381 sqlite3_free(aFrame); 41343 42382 } ................................................................................ 41354 42393 ** currently holding locks that exclude all other readers, writers and 41355 42394 ** checkpointers. 41356 42395 */ 41357 42396 pInfo = walCkptInfo(pWal); 41358 42397 pInfo->nBackfill = 0; 41359 42398 pInfo->aReadMark[0] = 0; 41360 42399 for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED; 42400 + 42401 + /* If more than one frame was recovered from the log file, report an 42402 + ** event via sqlite3_log(). This is to help with identifying performance 42403 + ** problems caused by applications routinely shutting down without 42404 + ** checkpointing the log file. 42405 + */ 42406 + if( pWal->hdr.nPage ){ 42407 + sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s", 42408 + pWal->hdr.nPage, pWal->zWalName 42409 + ); 42410 + } 41361 42411 } 41362 42412 41363 42413 recovery_error: 41364 42414 WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok")); 41365 42415 walUnlockExclusive(pWal, iLock, nLock); 41366 42416 return rc; 41367 42417 } ................................................................................ 41714 42764 static int walCheckpoint( 41715 42765 Wal *pWal, /* Wal connection */ 41716 42766 int sync_flags, /* Flags for OsSync() (or 0) */ 41717 42767 int nBuf, /* Size of zBuf in bytes */ 41718 42768 u8 *zBuf /* Temporary buffer to use */ 41719 42769 ){ 41720 42770 int rc; /* Return code */ 41721 - int szPage = pWal->hdr.szPage; /* Database page-size */ 42771 + int szPage; /* Database page-size */ 41722 42772 WalIterator *pIter = 0; /* Wal iterator context */ 41723 42773 u32 iDbpage = 0; /* Next database page to write */ 41724 42774 u32 iFrame = 0; /* Wal frame containing data for iDbpage */ 41725 42775 u32 mxSafeFrame; /* Max frame that can be backfilled */ 42776 + u32 mxPage; /* Max database page to write */ 41726 42777 int i; /* Loop counter */ 41727 42778 volatile WalCkptInfo *pInfo; /* The checkpoint status information */ 41728 42779 42780 + szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); 42781 + testcase( szPage<=32768 ); 42782 + testcase( szPage>=65536 ); 41729 42783 if( pWal->hdr.mxFrame==0 ) return SQLITE_OK; 41730 42784 41731 42785 /* Allocate the iterator */ 41732 42786 rc = walIteratorInit(pWal, &pIter); 41733 42787 if( rc!=SQLITE_OK ){ 41734 42788 return rc; 41735 42789 } 41736 42790 assert( pIter ); 41737 42791 41738 42792 /*** TODO: Move this test out to the caller. Make it an assert() here ***/ 41739 - if( pWal->hdr.szPage!=nBuf ){ 42793 + if( szPage!=nBuf ){ 41740 42794 rc = SQLITE_CORRUPT_BKPT; 41741 42795 goto walcheckpoint_out; 41742 42796 } 41743 42797 41744 42798 /* Compute in mxSafeFrame the index of the last frame of the WAL that is 41745 42799 ** safe to write into the database. Frames beyond mxSafeFrame might 41746 42800 ** overwrite database pages that are in use by active readers and thus 41747 42801 ** cannot be backfilled from the WAL. 41748 42802 */ 41749 42803 mxSafeFrame = pWal->hdr.mxFrame; 42804 + mxPage = pWal->hdr.nPage; 41750 42805 pInfo = walCkptInfo(pWal); 41751 42806 for(i=1; i<WAL_NREADER; i++){ 41752 42807 u32 y = pInfo->aReadMark[i]; 41753 42808 if( mxSafeFrame>=y ){ 41754 42809 assert( y<=pWal->hdr.mxFrame ); 41755 42810 rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1); 41756 42811 if( rc==SQLITE_OK ){ ................................................................................ 41763 42818 } 41764 42819 } 41765 42820 } 41766 42821 41767 42822 if( pInfo->nBackfill<mxSafeFrame 41768 42823 && (rc = walLockExclusive(pWal, WAL_READ_LOCK(0), 1))==SQLITE_OK 41769 42824 ){ 42825 + i64 nSize; /* Current size of database file */ 41770 42826 u32 nBackfill = pInfo->nBackfill; 41771 42827 41772 42828 /* Sync the WAL to disk */ 41773 42829 if( sync_flags ){ 41774 42830 rc = sqlite3OsSync(pWal->pWalFd, sync_flags); 41775 42831 } 42832 + 42833 + /* If the database file may grow as a result of this checkpoint, hint 42834 + ** about the eventual size of the db file to the VFS layer. 42835 + */ 42836 + if( rc==SQLITE_OK ){ 42837 + i64 nReq = ((i64)mxPage * szPage); 42838 + rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); 42839 + if( rc==SQLITE_OK && nSize<nReq ){ 42840 + sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); 42841 + } 42842 + } 41776 42843 41777 42844 /* Iterate through the contents of the WAL, copying data to the db file. */ 41778 42845 while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ 41779 42846 i64 iOffset; 41780 42847 assert( walFramePgno(pWal, iFrame)==iDbpage ); 41781 - if( iFrame<=nBackfill || iFrame>mxSafeFrame ) continue; 42848 + if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue; 41782 42849 iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; 41783 42850 /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ 41784 42851 rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); 41785 42852 if( rc!=SQLITE_OK ) break; 41786 42853 iOffset = (iDbpage-1)*(i64)szPage; 41787 42854 testcase( IS_BIG_INT(iOffset) ); 41788 42855 rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); ................................................................................ 41881 42948 u32 aCksum[2]; /* Checksum on the header content */ 41882 42949 WalIndexHdr h1, h2; /* Two copies of the header content */ 41883 42950 WalIndexHdr volatile *aHdr; /* Header in shared memory */ 41884 42951 41885 42952 /* The first page of the wal-index must be mapped at this point. */ 41886 42953 assert( pWal->nWiData>0 && pWal->apWiData[0] ); 41887 42954 41888 - /* Read the header. This might happen currently with a write to the 42955 + /* Read the header. This might happen concurrently with a write to the 41889 42956 ** same area of shared memory on a different CPU in a SMP, 41890 42957 ** meaning it is possible that an inconsistent snapshot is read 41891 42958 ** from the file. If this happens, return non-zero. 41892 42959 ** 41893 42960 ** There are two copies of the header at the beginning of the wal-index. 41894 42961 ** When reading, read [0] first then [1]. Writes are in the reverse order. 41895 42962 ** Memory barriers are used to prevent the compiler or the hardware from ................................................................................ 41910 42977 if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){ 41911 42978 return 1; /* Checksum does not match */ 41912 42979 } 41913 42980 41914 42981 if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){ 41915 42982 *pChanged = 1; 41916 42983 memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr)); 41917 - pWal->szPage = pWal->hdr.szPage; 42984 + pWal->szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); 42985 + testcase( pWal->szPage<=32768 ); 42986 + testcase( pWal->szPage>=65536 ); 41918 42987 } 41919 42988 41920 42989 /* The header was successfully read. Return zero. */ 41921 42990 return 0; 41922 42991 } 41923 42992 41924 42993 /* ................................................................................ 42229 43298 } 42230 43299 42231 43300 /* 42232 43301 ** Finish with a read transaction. All this does is release the 42233 43302 ** read-lock. 42234 43303 */ 42235 43304 SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ 43305 + sqlite3WalEndWriteTransaction(pWal); 42236 43306 if( pWal->readLock>=0 ){ 42237 43307 walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); 42238 43308 pWal->readLock = -1; 42239 43309 } 42240 43310 } 42241 43311 42242 43312 /* ................................................................................ 42339 43409 } 42340 43410 #endif 42341 43411 42342 43412 /* If iRead is non-zero, then it is the log frame number that contains the 42343 43413 ** required page. Read and return data from the log file. 42344 43414 */ 42345 43415 if( iRead ){ 42346 - i64 iOffset = walFrameOffset(iRead, pWal->hdr.szPage) + WAL_FRAME_HDRSIZE; 43416 + int sz; 43417 + i64 iOffset; 43418 + sz = pWal->hdr.szPage; 43419 + sz = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); 43420 + testcase( sz<=32768 ); 43421 + testcase( sz>=65536 ); 43422 + iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; 42347 43423 *pInWal = 1; 42348 43424 /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ 42349 43425 return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset); 42350 43426 } 42351 43427 42352 43428 *pInWal = 0; 42353 43429 return SQLITE_OK; 42354 43430 } 42355 43431 42356 43432 42357 43433 /* 42358 -** Set *pPgno to the size of the database file (or zero, if unknown). 43434 +** Return the size of the database in pages (or zero, if unknown). 42359 43435 */ 42360 -SQLITE_PRIVATE void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno){ 42361 - assert( pWal->readLock>=0 || pWal->lockError ); 42362 - *pPgno = pWal->hdr.nPage; 43436 +SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){ 43437 + if( pWal && ALWAYS(pWal->readLock>=0) ){ 43438 + return pWal->hdr.nPage; 43439 + } 43440 + return 0; 42363 43441 } 42364 43442 42365 43443 42366 43444 /* 42367 43445 ** This function starts a write transaction on the WAL. 42368 43446 ** 42369 43447 ** A read transaction must have already been started by a prior call ................................................................................ 42431 43509 ** returned to the caller. 42432 43510 ** 42433 43511 ** Otherwise, if the callback function does not return an error, this 42434 43512 ** function returns SQLITE_OK. 42435 43513 */ 42436 43514 SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ 42437 43515 int rc = SQLITE_OK; 42438 - if( pWal->writeLock ){ 43516 + if( ALWAYS(pWal->writeLock) ){ 42439 43517 Pgno iMax = pWal->hdr.mxFrame; 42440 43518 Pgno iFrame; 42441 43519 42442 43520 /* Restore the clients cache of the wal-index header to the state it 42443 43521 ** was in before the client began writing to the database. 42444 43522 */ 42445 43523 memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); ................................................................................ 42519 43597 ** to the current log file, it is possible to overwrite the start of the 42520 43598 ** existing log file with the new frames (i.e. "reset" the log). If so, 42521 43599 ** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left 42522 43600 ** unchanged. 42523 43601 ** 42524 43602 ** SQLITE_OK is returned if no error is encountered (regardless of whether 42525 43603 ** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned 42526 -** if some error 43604 +** if an error occurs. 42527 43605 */ 42528 43606 static int walRestartLog(Wal *pWal){ 42529 43607 int rc = SQLITE_OK; 42530 43608 int cnt; 42531 43609 42532 43610 if( pWal->readLock==0 ){ 42533 43611 volatile WalCkptInfo *pInfo = walCkptInfo(pWal); ................................................................................ 42552 43630 sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); 42553 43631 sqlite3_randomness(4, &aSalt[1]); 42554 43632 walIndexWriteHdr(pWal); 42555 43633 pInfo->nBackfill = 0; 42556 43634 for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED; 42557 43635 assert( pInfo->aReadMark[0]==0 ); 42558 43636 walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); 43637 + }else if( rc!=SQLITE_BUSY ){ 43638 + return rc; 42559 43639 } 42560 43640 } 42561 43641 walUnlockShared(pWal, WAL_READ_LOCK(0)); 42562 43642 pWal->readLock = -1; 42563 43643 cnt = 0; 42564 43644 do{ 42565 43645 int notUsed; ................................................................................ 42620 43700 sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt); 42621 43701 sqlite3_randomness(8, pWal->hdr.aSalt); 42622 43702 memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8); 42623 43703 walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum); 42624 43704 sqlite3Put4byte(&aWalHdr[24], aCksum[0]); 42625 43705 sqlite3Put4byte(&aWalHdr[28], aCksum[1]); 42626 43706 42627 - pWal->szPage = (u16)szPage; 43707 + pWal->szPage = szPage; 42628 43708 pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN; 42629 43709 pWal->hdr.aFrameCksum[0] = aCksum[0]; 42630 43710 pWal->hdr.aFrameCksum[1] = aCksum[1]; 42631 43711 42632 43712 rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0); 42633 43713 WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok")); 42634 43714 if( rc!=SQLITE_OK ){ 42635 43715 return rc; 42636 43716 } 42637 43717 } 42638 - assert( pWal->szPage==szPage ); 43718 + assert( (int)pWal->szPage==szPage ); 42639 43719 42640 43720 /* Write the log file. */ 42641 43721 for(p=pList; p; p=p->pDirty){ 42642 43722 u32 nDbsize; /* Db-size field for frame header */ 42643 43723 i64 iOffset; /* Write offset in log file */ 42644 43724 void *pData; 42645 43725 ................................................................................ 42715 43795 iFrame++; 42716 43796 nLast--; 42717 43797 rc = walIndexAppend(pWal, iFrame, pLast->pgno); 42718 43798 } 42719 43799 42720 43800 if( rc==SQLITE_OK ){ 42721 43801 /* Update the private copy of the header. */ 42722 - pWal->hdr.szPage = (u16)szPage; 43802 + pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); 43803 + testcase( szPage<=32768 ); 43804 + testcase( szPage>=65536 ); 42723 43805 pWal->hdr.mxFrame = iFrame; 42724 43806 if( isCommit ){ 42725 43807 pWal->hdr.iChange++; 42726 43808 pWal->hdr.nPage = nTruncate; 42727 43809 } 42728 43810 /* If this is a commit, update the wal-index header too. */ 42729 43811 if( isCommit ){ ................................................................................ 42927 44009 ** page has a small header which contains the Ptr(N) pointer and other 42928 44010 ** information such as the size of key and data. 42929 44011 ** 42930 44012 ** FORMAT DETAILS 42931 44013 ** 42932 44014 ** The file is divided into pages. The first page is called page 1, 42933 44015 ** the second is page 2, and so forth. A page number of zero indicates 42934 -** "no such page". The page size can be any power of 2 between 512 and 32768. 44016 +** "no such page". The page size can be any power of 2 between 512 and 65536. 42935 44017 ** Each page can be either a btree page, a freelist page, an overflow 42936 44018 ** page, or a pointer-map page. 42937 44019 ** 42938 44020 ** The first page is always a btree page. The first 100 bytes of the first 42939 44021 ** page contain a special header (the "file header") that describes the file. 42940 44022 ** The format of the file header is as follows: 42941 44023 ** ................................................................................ 43289 44371 sqlite3 *db; /* Database connection currently using this Btree */ 43290 44372 BtCursor *pCursor; /* A list of all open cursors */ 43291 44373 MemPage *pPage1; /* First page of the database */ 43292 44374 u8 readOnly; /* True if the underlying file is readonly */ 43293 44375 u8 pageSizeFixed; /* True if the page size can no longer be changed */ 43294 44376 u8 secureDelete; /* True if secure_delete is enabled */ 43295 44377 u8 initiallyEmpty; /* Database is empty at start of transaction */ 44378 + u8 openFlags; /* Flags to sqlite3BtreeOpen() */ 43296 44379 #ifndef SQLITE_OMIT_AUTOVACUUM 43297 44380 u8 autoVacuum; /* True if auto-vacuum is enabled */ 43298 44381 u8 incrVacuum; /* True if incr-vacuum is enabled */ 43299 44382 #endif 43300 - u16 pageSize; /* Total number of bytes on a page */ 43301 - u16 usableSize; /* Number of usable bytes on each page */ 43302 44383 u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ 43303 44384 u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ 43304 44385 u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */ 43305 44386 u16 minLeaf; /* Minimum local payload in a LEAFDATA table */ 43306 44387 u8 inTransaction; /* Transaction state */ 43307 44388 u8 doNotUseWAL; /* If true, do not open write-ahead-log file */ 44389 + u32 pageSize; /* Total number of bytes on a page */ 44390 + u32 usableSize; /* Number of usable bytes on each page */ 43308 44391 int nTransaction; /* Number of open transactions (read + write) */ 43309 44392 u32 nPage; /* Number of pages in the database */ 43310 44393 void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ 43311 44394 void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ 43312 44395 sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */ 43313 44396 Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */ 43314 44397 #ifndef SQLITE_OMIT_SHARED_CACHE ................................................................................ 43899 44982 #if 0 43900 44983 int sqlite3BtreeTrace=1; /* True to enable tracing */ 43901 44984 # define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);} 43902 44985 #else 43903 44986 # define TRACE(X) 43904 44987 #endif 43905 44988 43906 - 44989 +/* 44990 +** Extract a 2-byte big-endian integer from an array of unsigned bytes. 44991 +** But if the value is zero, make it 65536. 44992 +** 44993 +** This routine is used to extract the "offset to cell content area" value 44994 +** from the header of a btree page. If the page size is 65536 and the page 44995 +** is empty, the offset should be 65536, but the 2-byte value stores zero. 44996 +** This routine makes the necessary adjustment to 65536. 44997 +*/ 44998 +#define get2byteNotZero(X) (((((int)get2byte(X))-1)&0xffff)+1) 43907 44999 43908 45000 #ifndef SQLITE_OMIT_SHARED_CACHE 43909 45001 /* 43910 45002 ** A list of BtShared objects that are eligible for participation 43911 45003 ** in shared cache. This variable has file scope during normal builds, 43912 45004 ** but the test harness needs to access it so we make it global for 43913 45005 ** test builds. ................................................................................ 44588 45680 } 44589 45681 44590 45682 #ifndef SQLITE_OMIT_AUTOVACUUM 44591 45683 /* 44592 45684 ** Given a page number of a regular database page, return the page 44593 45685 ** number for the pointer-map page that contains the entry for the 44594 45686 ** input page number. 45687 +** 45688 +** Return 0 (not a valid page) for pgno==1 since there is 45689 +** no pointer map associated with page 1. The integrity_check logic 45690 +** requires that ptrmapPageno(*,1)!=1. 44595 45691 */ 44596 45692 static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ 44597 45693 int nPagesPerMapPage; 44598 45694 Pgno iPtrMap, ret; 44599 45695 assert( sqlite3_mutex_held(pBt->mutex) ); 45696 + if( pgno<2 ) return 0; 44600 45697 nPagesPerMapPage = (pBt->usableSize/5)+1; 44601 45698 iPtrMap = (pgno-2)/nPagesPerMapPage; 44602 45699 ret = (iPtrMap*nPagesPerMapPage) + 2; 44603 45700 if( ret==PENDING_BYTE_PAGE(pBt) ){ 44604 45701 ret++; 44605 45702 } 44606 45703 return ret; ................................................................................ 45021 46118 assert( pPage->nOverflow==0 ); 45022 46119 usableSize = pPage->pBt->usableSize; 45023 46120 assert( nByte < usableSize-8 ); 45024 46121 45025 46122 nFrag = data[hdr+7]; 45026 46123 assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); 45027 46124 gap = pPage->cellOffset + 2*pPage->nCell; 45028 - top = get2byte(&data[hdr+5]); 46125 + top = get2byteNotZero(&data[hdr+5]); 45029 46126 if( gap>top ) return SQLITE_CORRUPT_BKPT; 45030 46127 testcase( gap+2==top ); 45031 46128 testcase( gap+1==top ); 45032 46129 testcase( gap==top ); 45033 46130 45034 46131 if( nFrag>=60 ){ 45035 46132 /* Always defragment highly fragmented pages */ 45036 46133 rc = defragmentPage(pPage); 45037 46134 if( rc ) return rc; 45038 - top = get2byte(&data[hdr+5]); 46135 + top = get2byteNotZero(&data[hdr+5]); 45039 46136 }else if( gap+2<=top ){ 45040 46137 /* Search the freelist looking for a free slot big enough to satisfy 45041 46138 ** the request. The allocation is made from the first free slot in 45042 46139 ** the list that is large enough to accomadate it. 45043 46140 */ 45044 46141 int pc, addr; 45045 46142 for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){ ................................................................................ 45073 46170 /* Check to make sure there is enough space in the gap to satisfy 45074 46171 ** the allocation. If not, defragment. 45075 46172 */ 45076 46173 testcase( gap+2+nByte==top ); 45077 46174 if( gap+2+nByte>top ){ 45078 46175 rc = defragmentPage(pPage); 45079 46176 if( rc ) return rc; 45080 - top = get2byte(&data[hdr+5]); 46177 + top = get2byteNotZero(&data[hdr+5]); 45081 46178 assert( gap+nByte<=top ); 45082 46179 } 45083 46180 45084 46181 45085 46182 /* Allocate memory from the gap in between the cell pointer array 45086 46183 ** and the cell content area. The btreeInitPage() call has already 45087 46184 ** validated the freelist. Given that the freelist is valid, there ................................................................................ 45239 46336 assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); 45240 46337 45241 46338 if( !pPage->isInit ){ 45242 46339 u16 pc; /* Address of a freeblock within pPage->aData[] */ 45243 46340 u8 hdr; /* Offset to beginning of page header */ 45244 46341 u8 *data; /* Equal to pPage->aData */ 45245 46342 BtShared *pBt; /* The main btree structure */ 45246 - u16 usableSize; /* Amount of usable space on each page */ 46343 + int usableSize; /* Amount of usable space on each page */ 45247 46344 u16 cellOffset; /* Offset from start of page to first cell pointer */ 45248 - u16 nFree; /* Number of unused bytes on the page */ 45249 - u16 top; /* First byte of the cell content area */ 46345 + int nFree; /* Number of unused bytes on the page */ 46346 + int top; /* First byte of the cell content area */ 45250 46347 int iCellFirst; /* First allowable cell or freeblock offset */ 45251 46348 int iCellLast; /* Last possible cell or freeblock offset */ 45252 46349 45253 46350 pBt = pPage->pBt; 45254 46351 45255 46352 hdr = pPage->hdrOffset; 45256 46353 data = pPage->aData; 45257 46354 if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT; 45258 - assert( pBt->pageSize>=512 && pBt->pageSize<=32768 ); 45259 - pPage->maskPage = pBt->pageSize - 1; 46355 + assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); 46356 + pPage->maskPage = (u16)(pBt->pageSize - 1); 45260 46357 pPage->nOverflow = 0; 45261 46358 usableSize = pBt->usableSize; 45262 46359 pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf; 45263 - top = get2byte(&data[hdr+5]); 46360 + top = get2byteNotZero(&data[hdr+5]); 45264 46361 pPage->nCell = get2byte(&data[hdr+3]); 45265 46362 if( pPage->nCell>MX_CELL(pBt) ){ 45266 46363 /* To many cells for a single page. The page must be corrupt */ 45267 46364 return SQLITE_CORRUPT_BKPT; 45268 46365 } 45269 46366 testcase( pPage->nCell==MX_CELL(pBt) ); 45270 46367 ................................................................................ 45355 46452 memset(&data[hdr], 0, pBt->usableSize - hdr); 45356 46453 } 45357 46454 data[hdr] = (char)flags; 45358 46455 first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); 45359 46456 memset(&data[hdr+1], 0, 4); 45360 46457 data[hdr+7] = 0; 45361 46458 put2byte(&data[hdr+5], pBt->usableSize); 45362 - pPage->nFree = pBt->usableSize - first; 46459 + pPage->nFree = (u16)(pBt->usableSize - first); 45363 46460 decodeFlags(pPage, flags); 45364 46461 pPage->hdrOffset = hdr; 45365 46462 pPage->cellOffset = first; 45366 46463 pPage->nOverflow = 0; 45367 - assert( pBt->pageSize>=512 && pBt->pageSize<=32768 ); 45368 - pPage->maskPage = pBt->pageSize - 1; 46464 + assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); 46465 + pPage->maskPage = (u16)(pBt->pageSize - 1); 45369 46466 pPage->nCell = 0; 45370 46467 pPage->isInit = 1; 45371 46468 } 45372 46469 45373 46470 45374 46471 /* 45375 46472 ** Convert a DbPage obtained from the pager into a MemPage used by ................................................................................ 45525 46622 return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); 45526 46623 } 45527 46624 45528 46625 /* 45529 46626 ** Open a database file. 45530 46627 ** 45531 46628 ** zFilename is the name of the database file. If zFilename is NULL 45532 -** a new database with a random name is created. This randomly named 45533 -** database file will be deleted when sqlite3BtreeClose() is called. 46629 +** then an ephemeral database is created. The ephemeral database might 46630 +** be exclusively in memory, or it might use a disk-based memory cache. 46631 +** Either way, the ephemeral database will be automatically deleted 46632 +** when sqlite3BtreeClose() is called. 46633 +** 45534 46634 ** If zFilename is ":memory:" then an in-memory database is created 45535 46635 ** that is automatically destroyed when it is closed. 45536 46636 ** 46637 +** The "flags" parameter is a bitmask that might contain bits 46638 +** BTREE_OMIT_JOURNAL and/or BTREE_NO_READLOCK. The BTREE_NO_READLOCK 46639 +** bit is also set if the SQLITE_NoReadlock flags is set in db->flags. 46640 +** These flags are passed through into sqlite3PagerOpen() and must 46641 +** be the same values as PAGER_OMIT_JOURNAL and PAGER_NO_READLOCK. 46642 +** 45537 46643 ** If the database is already opened in the same database connection 45538 46644 ** and we are in shared cache mode, then the open will fail with an 45539 46645 ** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared 45540 46646 ** objects in the same database connection since doing so will lead 45541 46647 ** to problems with locking. 45542 46648 */ 45543 46649 SQLITE_PRIVATE int sqlite3BtreeOpen( ................................................................................ 45550 46656 sqlite3_vfs *pVfs; /* The VFS to use for this btree */ 45551 46657 BtShared *pBt = 0; /* Shared part of btree structure */ 45552 46658 Btree *p; /* Handle to return */ 45553 46659 sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */ 45554 46660 int rc = SQLITE_OK; /* Result code from this function */ 45555 46661 u8 nReserve; /* Byte of unused space on each page */ 45556 46662 unsigned char zDbHeader[100]; /* Database header content */ 46663 + 46664 + /* True if opening an ephemeral, temporary database */ 46665 + const int isTempDb = zFilename==0 || zFilename[0]==0; 45557 46666 45558 46667 /* Set the variable isMemdb to true for an in-memory database, or 45559 46668 ** false for a file-based database. This symbol is only required if 45560 46669 ** either of the shared-data or autovacuum features are compiled 45561 46670 ** into the library. 45562 46671 */ 45563 46672 #if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM) 45564 46673 #ifdef SQLITE_OMIT_MEMORYDB 45565 46674 const int isMemdb = 0; 45566 46675 #else 45567 - const int isMemdb = zFilename && !strcmp(zFilename, ":memory:"); 46676 + const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0) 46677 + || (isTempDb && sqlite3TempInMemory(db)); 45568 46678 #endif 45569 46679 #endif 45570 46680 45571 46681 assert( db!=0 ); 45572 46682 assert( sqlite3_mutex_held(db->mutex) ); 46683 + assert( (flags&0xff)==flags ); /* flags fit in 8 bits */ 45573 46684 46685 + /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */ 46686 + assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 ); 46687 + 46688 + /* A BTREE_SINGLE database is always a temporary and/or ephemeral */ 46689 + assert( (flags & BTREE_SINGLE)==0 || isTempDb ); 46690 + 46691 + if( db->flags & SQLITE_NoReadlock ){ 46692 + flags |= BTREE_NO_READLOCK; 46693 + } 46694 + if( isMemdb ){ 46695 + flags |= BTREE_MEMORY; 46696 + } 46697 + if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){ 46698 + vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; 46699 + } 45574 46700 pVfs = db->pVfs; 45575 46701 p = sqlite3MallocZero(sizeof(Btree)); 45576 46702 if( !p ){ 45577 46703 return SQLITE_NOMEM; 45578 46704 } 45579 46705 p->inTrans = TRANS_NONE; 45580 46706 p->db = db; ................................................................................ 45584 46710 #endif 45585 46711 45586 46712 #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) 45587 46713 /* 45588 46714 ** If this Btree is a candidate for shared cache, try to find an 45589 46715 ** existing BtShared object that we can share with 45590 46716 */ 45591 - if( isMemdb==0 && zFilename && zFilename[0] ){ 46717 + if( isMemdb==0 && isTempDb==0 ){ 45592 46718 if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ 45593 46719 int nFullPathname = pVfs->mxPathname+1; 45594 46720 char *zFullPathname = sqlite3Malloc(nFullPathname); 45595 46721 sqlite3_mutex *mutexShared; 45596 46722 p->sharable = 1; 45597 46723 if( !zFullPathname ){ 45598 46724 sqlite3_free(p); ................................................................................ 45659 46785 EXTRA_SIZE, flags, vfsFlags, pageReinit); 45660 46786 if( rc==SQLITE_OK ){ 45661 46787 rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); 45662 46788 } 45663 46789 if( rc!=SQLITE_OK ){ 45664 46790 goto btree_open_out; 45665 46791 } 46792 + pBt->openFlags = (u8)flags; 45666 46793 pBt->db = db; 45667 46794 sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); 45668 46795 p->pBt = pBt; 45669 46796 45670 46797 pBt->pCursor = 0; 45671 46798 pBt->pPage1 = 0; 45672 46799 pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); 45673 46800 #ifdef SQLITE_SECURE_DELETE 45674 46801 pBt->secureDelete = 1; 45675 46802 #endif 45676 - pBt->pageSize = get2byte(&zDbHeader[16]); 46803 + pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16); 45677 46804 if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE 45678 46805 || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ 45679 46806 pBt->pageSize = 0; 45680 46807 #ifndef SQLITE_OMIT_AUTOVACUUM 45681 46808 /* If the magic name ":memory:" will create an in-memory database, then 45682 46809 ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if 45683 46810 ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if ................................................................................ 45763 46890 if( rc!=SQLITE_OK ){ 45764 46891 if( pBt && pBt->pPager ){ 45765 46892 sqlite3PagerClose(pBt->pPager); 45766 46893 } 45767 46894 sqlite3_free(pBt); 45768 46895 sqlite3_free(p); 45769 46896 *ppBtree = 0; 46897 + }else{ 46898 + /* If the B-Tree was successfully opened, set the pager-cache size to the 46899 + ** default value. Except, when opening on an existing shared pager-cache, 46900 + ** do not change the pager-cache size. 46901 + */ 46902 + if( sqlite3BtreeSchema(p, 0, 0)==0 ){ 46903 + sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); 46904 + } 45770 46905 } 45771 46906 if( mutexOpen ){ 45772 46907 assert( sqlite3_mutex_held(mutexOpen) ); 45773 46908 sqlite3_mutex_leave(mutexOpen); 45774 46909 } 45775 46910 return rc; 45776 46911 } ................................................................................ 45983 47118 nReserve = pBt->pageSize - pBt->usableSize; 45984 47119 } 45985 47120 assert( nReserve>=0 && nReserve<=255 ); 45986 47121 if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && 45987 47122 ((pageSize-1)&pageSize)==0 ){ 45988 47123 assert( (pageSize & 7)==0 ); 45989 47124 assert( !pBt->pPage1 && !pBt->pCursor ); 45990 - pBt->pageSize = (u16)pageSize; 47125 + pBt->pageSize = (u32)pageSize; 45991 47126 freeTempSpace(pBt); 45992 47127 } 45993 47128 rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); 45994 47129 pBt->usableSize = pBt->pageSize - (u16)nReserve; 45995 47130 if( iFix ) pBt->pageSizeFixed = 1; 45996 47131 sqlite3BtreeLeave(p); 45997 47132 return rc; ................................................................................ 46118 47253 rc = btreeGetPage(pBt, 1, &pPage1, 0); 46119 47254 if( rc!=SQLITE_OK ) return rc; 46120 47255 46121 47256 /* Do some checking to help insure the file we opened really is 46122 47257 ** a valid database file. 46123 47258 */ 46124 47259 nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData); 46125 - if( (rc = sqlite3PagerPagecount(pBt->pPager, &nPageFile))!=SQLITE_OK ){; 46126 - goto page1_init_failed; 46127 - } 47260 + sqlite3PagerPagecount(pBt->pPager, &nPageFile); 46128 47261 if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){ 46129 47262 nPage = nPageFile; 46130 47263 } 46131 47264 if( nPage>0 ){ 46132 - int pageSize; 46133 - int usableSize; 47265 + u32 pageSize; 47266 + u32 usableSize; 46134 47267 u8 *page1 = pPage1->aData; 46135 47268 rc = SQLITE_NOTADB; 46136 47269 if( memcmp(page1, zMagicHeader, 16)!=0 ){ 46137 47270 goto page1_init_failed; 46138 47271 } 46139 47272 46140 47273 #ifdef SQLITE_OMIT_WAL ................................................................................ 46177 47310 ** embedded fraction must be 12.5% for both leaf-data and non-leaf-data. 46178 47311 ** The original design allowed these amounts to vary, but as of 46179 47312 ** version 3.6.0, we require them to be fixed. 46180 47313 */ 46181 47314 if( memcmp(&page1[21], "\100\040\040",3)!=0 ){ 46182 47315 goto page1_init_failed; 46183 47316 } 46184 - pageSize = get2byte(&page1[16]); 46185 - if( ((pageSize-1)&pageSize)!=0 || pageSize<512 || 46186 - (SQLITE_MAX_PAGE_SIZE<32768 && pageSize>SQLITE_MAX_PAGE_SIZE) 47317 + pageSize = (page1[16]<<8) | (page1[17]<<16); 47318 + if( ((pageSize-1)&pageSize)!=0 47319 + || pageSize>SQLITE_MAX_PAGE_SIZE 47320 + || pageSize<=256 46187 47321 ){ 46188 47322 goto page1_init_failed; 46189 47323 } 46190 47324 assert( (pageSize & 7)==0 ); 46191 47325 usableSize = pageSize - page1[20]; 46192 - if( pageSize!=pBt->pageSize ){ 47326 + if( (u32)pageSize!=pBt->pageSize ){ 46193 47327 /* After reading the first page of the database assuming a page size 46194 47328 ** of BtShared.pageSize, we have discovered that the page-size is 46195 47329 ** actually pageSize. Unlock the database, leave pBt->pPage1 at 46196 47330 ** zero and return SQLITE_OK. The caller will call this function 46197 47331 ** again with the correct page-size. 46198 47332 */ 46199 47333 releasePage(pPage1); 46200 - pBt->usableSize = (u16)usableSize; 46201 - pBt->pageSize = (u16)pageSize; 47334 + pBt->usableSize = usableSize; 47335 + pBt->pageSize = pageSize; 46202 47336 freeTempSpace(pBt); 46203 47337 rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, 46204 47338 pageSize-usableSize); 46205 47339 return rc; 46206 47340 } 46207 47341 if( nPageHeader>nPageFile ){ 46208 47342 rc = SQLITE_CORRUPT_BKPT; 46209 47343 goto page1_init_failed; 46210 47344 } 46211 47345 if( usableSize<480 ){ 46212 47346 goto page1_init_failed; 46213 47347 } 46214 - pBt->pageSize = (u16)pageSize; 46215 - pBt->usableSize = (u16)usableSize; 47348 + pBt->pageSize = pageSize; 47349 + pBt->usableSize = usableSize; 46216 47350 #ifndef SQLITE_OMIT_AUTOVACUUM 46217 47351 pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); 46218 47352 pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0); 46219 47353 #endif 46220 47354 } 46221 47355 46222 47356 /* maxLocal is the maximum amount of payload to store locally for ................................................................................ 46224 47358 ** cells can will fit on one page. We assume a 10-byte page header. 46225 47359 ** Besides the payload, the cell must store: 46226 47360 ** 2-byte pointer to the cell 46227 47361 ** 4-byte child pointer 46228 47362 ** 9-byte nKey value 46229 47363 ** 4-byte nData value 46230 47364 ** 4-byte overflow page pointer 46231 - ** So a cell consists of a 2-byte poiner, a header which is as much as 47365 + ** So a cell consists of a 2-byte pointer, a header which is as much as 46232 47366 ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow 46233 47367 ** page pointer. 46234 47368 */ 46235 - pBt->maxLocal = (pBt->usableSize-12)*64/255 - 23; 46236 - pBt->minLocal = (pBt->usableSize-12)*32/255 - 23; 46237 - pBt->maxLeaf = pBt->usableSize - 35; 46238 - pBt->minLeaf = (pBt->usableSize-12)*32/255 - 23; 47369 + pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23); 47370 + pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23); 47371 + pBt->maxLeaf = (u16)(pBt->usableSize - 35); 47372 + pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23); 46239 47373 assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); 46240 47374 pBt->pPage1 = pPage1; 46241 47375 pBt->nPage = nPage; 46242 47376 return SQLITE_OK; 46243 47377 46244 47378 page1_init_failed: 46245 47379 releasePage(pPage1); ................................................................................ 46284 47418 pP1 = pBt->pPage1; 46285 47419 assert( pP1!=0 ); 46286 47420 data = pP1->aData; 46287 47421 rc = sqlite3PagerWrite(pP1->pDbPage); 46288 47422 if( rc ) return rc; 46289 47423 memcpy(data, zMagicHeader, sizeof(zMagicHeader)); 46290 47424 assert( sizeof(zMagicHeader)==16 ); 46291 - put2byte(&data[16], pBt->pageSize); 47425 + data[16] = (u8)((pBt->pageSize>>8)&0xff); 47426 + data[17] = (u8)((pBt->pageSize>>16)&0xff); 46292 47427 data[18] = 1; 46293 47428 data[19] = 1; 46294 47429 assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize); 46295 47430 data[20] = (u8)(pBt->pageSize - pBt->usableSize); 46296 47431 data[21] = 64; 46297 47432 data[22] = 32; 46298 47433 data[23] = 32; ................................................................................ 48295 49430 }else{ 48296 49431 assert( nCellKey>intKey ); 48297 49432 c = +1; 48298 49433 } 48299 49434 pCur->validNKey = 1; 48300 49435 pCur->info.nKey = nCellKey; 48301 49436 }else{ 48302 - /* The maximum supported page-size is 32768 bytes. This means that 49437 + /* The maximum supported page-size is 65536 bytes. This means that 48303 49438 ** the maximum number of record bytes stored on an index B-Tree 48304 - ** page is at most 8198 bytes, which may be stored as a 2-byte 49439 + ** page is less than 16384 bytes and may be stored as a 2-byte 48305 49440 ** varint. This information is used to attempt to avoid parsing 48306 49441 ** the entire cell by checking for the cases where the record is 48307 49442 ** stored entirely within the b-tree page by inspecting the first 48308 49443 ** 2 bytes of the cell. 48309 49444 */ 48310 49445 int nCell = pCell[0]; 48311 49446 if( !(nCell & 0x80) && nCell<=pPage->maxLocal ){ ................................................................................ 48660 49795 if( rc ){ 48661 49796 goto end_allocate_page; 48662 49797 } 48663 49798 if( k==0 ){ 48664 49799 if( !pPrevTrunk ){ 48665 49800 memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); 48666 49801 }else{ 49802 + rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); 49803 + if( rc!=SQLITE_OK ){ 49804 + goto end_allocate_page; 49805 + } 48667 49806 memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4); 48668 49807 } 48669 49808 }else{ 48670 49809 /* The trunk page is required by the caller but it contains 48671 49810 ** pointers to free-list leaves. The first leaf becomes a trunk 48672 49811 ** page in this case. 48673 49812 */ ................................................................................ 48966 50105 */ 48967 50106 static int clearCell(MemPage *pPage, unsigned char *pCell){ 48968 50107 BtShared *pBt = pPage->pBt; 48969 50108 CellInfo info; 48970 50109 Pgno ovflPgno; 48971 50110 int rc; 48972 50111 int nOvfl; 48973 - u16 ovflPageSize; 50112 + u32 ovflPageSize; 48974 50113 48975 50114 assert( sqlite3_mutex_held(pPage->pBt->mutex) ); 48976 50115 btreeParseCellPtr(pPage, pCell, &info); 48977 50116 if( info.iOverflow==0 ){ 48978 50117 return SQLITE_OK; /* No overflow pages. Return without doing anything */ 48979 50118 } 48980 50119 ovflPgno = get4byte(&pCell[info.iOverflow]); ................................................................................ 49191 50330 ** the cell content has been copied someplace else. This routine just 49192 50331 ** removes the reference to the cell from pPage. 49193 50332 ** 49194 50333 ** "sz" must be the number of bytes in the cell. 49195 50334 */ 49196 50335 static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ 49197 50336 int i; /* Loop counter */ 49198 - int pc; /* Offset to cell content of cell being deleted */ 50337 + u32 pc; /* Offset to cell content of cell being deleted */ 49199 50338 u8 *data; /* pPage->aData */ 49200 50339 u8 *ptr; /* Used to move bytes around within data[] */ 49201 50340 int rc; /* The return code */ 49202 50341 int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ 49203 50342 49204 50343 if( *pRC ) return; 49205 50344 ................................................................................ 49209 50348 assert( sqlite3_mutex_held(pPage->pBt->mutex) ); 49210 50349 data = pPage->aData; 49211 50350 ptr = &data[pPage->cellOffset + 2*idx]; 49212 50351 pc = get2byte(ptr); 49213 50352 hdr = pPage->hdrOffset; 49214 50353 testcase( pc==get2byte(&data[hdr+5]) ); 49215 50354 testcase( pc+sz==pPage->pBt->usableSize ); 49216 - if( pc < get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){ 50355 + if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){ 49217 50356 *pRC = SQLITE_CORRUPT_BKPT; 49218 50357 return; 49219 50358 } 49220 50359 rc = freeSpace(pPage, pc, sz); 49221 50360 if( rc ){ 49222 50361 *pRC = rc; 49223 50362 return; ................................................................................ 49266 50405 u8 *ptr; /* Used for moving information around in data[] */ 49267 50406 49268 50407 int nSkip = (iChild ? 4 : 0); 49269 50408 49270 50409 if( *pRC ) return; 49271 50410 49272 50411 assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); 49273 - assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 ); 50412 + assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921 ); 49274 50413 assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) ); 49275 50414 assert( sqlite3_mutex_held(pPage->pBt->mutex) ); 49276 50415 /* The cell should normally be sized correctly. However, when moving a 49277 50416 ** malformed cell from a leaf page to an interior page, if the cell size 49278 50417 ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size 49279 50418 ** might be less than 8 (leaf-size + pointer) on the interior node. Hence 49280 50419 ** the term after the || in the following assert(). */ ................................................................................ 49346 50485 int cellbody; /* Address of next cell body */ 49347 50486 u8 * const data = pPage->aData; /* Pointer to data for pPage */ 49348 50487 const int hdr = pPage->hdrOffset; /* Offset of header on pPage */ 49349 50488 const int nUsable = pPage->pBt->usableSize; /* Usable size of page */ 49350 50489 49351 50490 assert( pPage->nOverflow==0 ); 49352 50491 assert( sqlite3_mutex_held(pPage->pBt->mutex) ); 49353 - assert( nCell>=0 && nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 ); 50492 + assert( nCell>=0 && nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921); 49354 50493 assert( sqlite3PagerIswriteable(pPage->pDbPage) ); 49355 50494 49356 50495 /* Check that the page has just been zeroed by zeroPage() */ 49357 50496 assert( pPage->nCell==0 ); 49358 - assert( get2byte(&data[hdr+5])==nUsable ); 50497 + assert( get2byteNotZero(&data[hdr+5])==nUsable ); 49359 50498 49360 50499 pCellptr = &data[pPage->cellOffset + nCell*2]; 49361 50500 cellbody = nUsable; 49362 50501 for(i=nCell-1; i>=0; i--){ 49363 50502 pCellptr -= 2; 49364 50503 cellbody -= aSize[i]; 49365 50504 put2byte(pCellptr, cellbody); ................................................................................ 49417 50556 int rc; /* Return Code */ 49418 50557 Pgno pgnoNew; /* Page number of pNew */ 49419 50558 49420 50559 assert( sqlite3_mutex_held(pPage->pBt->mutex) ); 49421 50560 assert( sqlite3PagerIswriteable(pParent->pDbPage) ); 49422 50561 assert( pPage->nOverflow==1 ); 49423 50562 50563 + /* This error condition is now caught prior to reaching this function */ 49424 50564 if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT; 49425 50565 49426 50566 /* Allocate a new page. This page will become the right-sibling of 49427 50567 ** pPage. Make the parent page writable, so that the new divider cell 49428 50568 ** may be inserted. If both these operations are successful, proceed. 49429 50569 */ 49430 50570 rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); ................................................................................ 49746 50886 ** Unless SQLite is compiled in secure-delete mode. In this case, 49747 50887 ** the dropCell() routine will overwrite the entire cell with zeroes. 49748 50888 ** In this case, temporarily copy the cell into the aOvflSpace[] 49749 50889 ** buffer. It will be copied out again as soon as the aSpace[] buffer 49750 50890 ** is allocated. */ 49751 50891 if( pBt->secureDelete ){ 49752 50892 int iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData); 49753 - if( (iOff+szNew[i])>pBt->usableSize ){ 50893 + if( (iOff+szNew[i])>(int)pBt->usableSize ){ 49754 50894 rc = SQLITE_CORRUPT_BKPT; 49755 50895 memset(apOld, 0, (i+1)*sizeof(MemPage*)); 49756 50896 goto balance_cleanup; 49757 50897 }else{ 49758 50898 memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]); 49759 50899 apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; 49760 50900 } ................................................................................ 49825 50965 if( i<nOld-1 && !leafData){ 49826 50966 u16 sz = (u16)szNew[i]; 49827 50967 u8 *pTemp; 49828 50968 assert( nCell<nMaxCells ); 49829 50969 szCell[nCell] = sz; 49830 50970 pTemp = &aSpace1[iSpace1]; 49831 50971 iSpace1 += sz; 49832 - assert( sz<=pBt->pageSize/4 ); 50972 + assert( sz<=pBt->maxLocal+23 ); 49833 50973 assert( iSpace1<=pBt->pageSize ); 49834 50974 memcpy(pTemp, apDiv[i], sz); 49835 50975 apCell[nCell] = pTemp+leafCorrection; 49836 50976 assert( leafCorrection==0 || leafCorrection==4 ); 49837 50977 szCell[nCell] = szCell[nCell] - leafCorrection; 49838 50978 if( !pOld->leaf ){ 49839 50979 assert( leafCorrection==0 ); ................................................................................ 50071 51211 */ 50072 51212 if( szCell[j]==4 ){ 50073 51213 assert(leafCorrection==4); 50074 51214 sz = cellSizePtr(pParent, pCell); 50075 51215 } 50076 51216 } 50077 51217 iOvflSpace += sz; 50078 - assert( sz<=pBt->pageSize/4 ); 51218 + assert( sz<=pBt->maxLocal+23 ); 50079 51219 assert( iOvflSpace<=pBt->pageSize ); 50080 51220 insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno, &rc); 50081 51221 if( rc!=SQLITE_OK ) goto balance_cleanup; 50082 51222 assert( sqlite3PagerIswriteable(pParent->pDbPage) ); 50083 51223 50084 51224 j++; 50085 51225 nxDiv++; ................................................................................ 50708 51848 ** The type of type is determined by the flags parameter. Only the 50709 51849 ** following values of flags are currently in use. Other values for 50710 51850 ** flags might not work: 50711 51851 ** 50712 51852 ** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys 50713 51853 ** BTREE_ZERODATA Used for SQL indices 50714 51854 */ 50715 -static int btreeCreateTable(Btree *p, int *piTable, int flags){ 51855 +static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){ 50716 51856 BtShared *pBt = p->pBt; 50717 51857 MemPage *pRoot; 50718 51858 Pgno pgnoRoot; 50719 51859 int rc; 51860 + int ptfFlags; /* Page-type flage for the root page of new table */ 50720 51861 50721 51862 assert( sqlite3BtreeHoldsMutex(p) ); 50722 51863 assert( pBt->inTransaction==TRANS_WRITE ); 50723 51864 assert( !pBt->readOnly ); 50724 51865 50725 51866 #ifdef SQLITE_OMIT_AUTOVACUUM 50726 51867 rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); ................................................................................ 50831 51972 50832 51973 }else{ 50833 51974 rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); 50834 51975 if( rc ) return rc; 50835 51976 } 50836 51977 #endif 50837 51978 assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); 50838 - zeroPage(pRoot, flags | PTF_LEAF); 51979 + if( createTabFlags & BTREE_INTKEY ){ 51980 + ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF; 51981 + }else{ 51982 + ptfFlags = PTF_ZERODATA | PTF_LEAF; 51983 + } 51984 + zeroPage(pRoot, ptfFlags); 50839 51985 sqlite3PagerUnref(pRoot->pDbPage); 51986 + assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 ); 50840 51987 *piTable = (int)pgnoRoot; 50841 51988 return SQLITE_OK; 50842 51989 } 50843 51990 SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){ 50844 51991 int rc; 50845 51992 sqlite3BtreeEnter(p); 50846 51993 rc = btreeCreateTable(p, piTable, flags); ................................................................................ 51315 52462 if( isFreeList ){ 51316 52463 int n = get4byte(&pOvflData[4]); 51317 52464 #ifndef SQLITE_OMIT_AUTOVACUUM 51318 52465 if( pCheck->pBt->autoVacuum ){ 51319 52466 checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext); 51320 52467 } 51321 52468 #endif 51322 - if( n>pCheck->pBt->usableSize/4-2 ){ 52469 + if( n>(int)pCheck->pBt->usableSize/4-2 ){ 51323 52470 checkAppendMsg(pCheck, zContext, 51324 52471 "freelist leaf count too big on page %d", iPage); 51325 52472 N--; 51326 52473 }else{ 51327 52474 for(i=0; i<n; i++){ 51328 52475 Pgno iFreePage = get4byte(&pOvflData[8+i*4]); 51329 52476 #ifndef SQLITE_OMIT_AUTOVACUUM ................................................................................ 51526 52673 */ 51527 52674 data = pPage->aData; 51528 52675 hdr = pPage->hdrOffset; 51529 52676 hit = sqlite3PageMalloc( pBt->pageSize ); 51530 52677 if( hit==0 ){ 51531 52678 pCheck->mallocFailed = 1; 51532 52679 }else{ 51533 - u16 contentOffset = get2byte(&data[hdr+5]); 52680 + int contentOffset = get2byteNotZero(&data[hdr+5]); 51534 52681 assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ 51535 52682 memset(hit+contentOffset, 0, usableSize-contentOffset); 51536 52683 memset(hit, 1, contentOffset); 51537 52684 nCell = get2byte(&data[hdr+3]); 51538 52685 cellStart = hdr + 12 - 4*pPage->leaf; 51539 52686 for(i=0; i<nCell; i++){ 51540 52687 int pc = get2byte(&data[cellStart+i*2]); 51541 - u16 size = 1024; 52688 + u32 size = 65536; 51542 52689 int j; 51543 52690 if( pc<=usableSize-4 ){ 51544 52691 size = cellSizePtr(pPage, &data[pc]); 51545 52692 } 51546 - if( (pc+size-1)>=usableSize ){ 52693 + if( (int)(pc+size-1)>=usableSize ){ 51547 52694 checkAppendMsg(pCheck, 0, 51548 52695 "Corruption detected in cell %d on page %d",i,iPage); 51549 52696 }else{ 51550 52697 for(j=pc+size-1; j>=pc; j--) hit[j]++; 51551 52698 } 51552 52699 } 51553 52700 i = get2byte(&data[hdr+1]); ................................................................................ 52092 53239 52093 53240 if( pSrcDb==pDestDb ){ 52094 53241 sqlite3Error( 52095 53242 pDestDb, SQLITE_ERROR, "source and destination must be distinct" 52096 53243 ); 52097 53244 p = 0; 52098 53245 }else { 52099 - /* Allocate space for a new sqlite3_backup object */ 53246 + /* Allocate space for a new sqlite3_backup object... 53247 + ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a 53248 + ** call to sqlite3_backup_init() and is destroyed by a call to 53249 + ** sqlite3_backup_finish(). */ 52100 53250 p = (sqlite3_backup *)sqlite3_malloc(sizeof(sqlite3_backup)); 52101 53251 if( !p ){ 52102 53252 sqlite3Error(pDestDb, SQLITE_NOMEM, 0); 52103 53253 } 52104 53254 } 52105 53255 52106 53256 /* If the allocation succeeded, populate the new object. */ ................................................................................ 52162 53312 52163 53313 /* Catch the case where the destination is an in-memory database and the 52164 53314 ** page sizes of the source and destination differ. 52165 53315 */ 52166 53316 if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){ 52167 53317 rc = SQLITE_READONLY; 52168 53318 } 53319 + 53320 +#ifdef SQLITE_HAS_CODEC 53321 + /* Backup is not possible if the page size of the destination is changing 53322 + ** a a codec is in use. 53323 + */ 53324 + if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){ 53325 + rc = SQLITE_READONLY; 53326 + } 53327 +#endif 52169 53328 52170 53329 /* This loop runs once for each destination page spanned by the source 52171 53330 ** page. For each iteration, variable iOff is set to the byte offset 52172 53331 ** of the destination page. 52173 53332 */ 52174 53333 for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){ 52175 53334 DbPage *pDestPg = 0; ................................................................................ 52466 53625 52467 53626 /* Exit the mutexes and free the backup context structure. */ 52468 53627 if( p->pDestDb ){ 52469 53628 sqlite3_mutex_leave(p->pDestDb->mutex); 52470 53629 } 52471 53630 sqlite3BtreeLeave(p->pSrc); 52472 53631 if( p->pDestDb ){ 53632 + /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a 53633 + ** call to sqlite3_backup_init() and is destroyed by a call to 53634 + ** sqlite3_backup_finish(). */ 52473 53635 sqlite3_free(p); 52474 53636 } 52475 53637 sqlite3_mutex_leave(mutex); 52476 53638 return rc; 52477 53639 } 52478 53640 52479 53641 /* ................................................................................ 52717 53879 if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){ 52718 53880 if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ 52719 53881 return SQLITE_NOMEM; 52720 53882 } 52721 53883 pMem->z[pMem->n] = 0; 52722 53884 pMem->z[pMem->n+1] = 0; 52723 53885 pMem->flags |= MEM_Term; 53886 +#ifdef SQLITE_DEBUG 53887 + pMem->pScopyFrom = 0; 53888 +#endif 52724 53889 } 52725 53890 52726 53891 return SQLITE_OK; 52727 53892 } 52728 53893 52729 53894 /* 52730 53895 ** If the given Mem* has a zero-filled tail, turn it into an ordinary ................................................................................ 52837 54002 assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); 52838 54003 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 52839 54004 memset(&ctx, 0, sizeof(ctx)); 52840 54005 ctx.s.flags = MEM_Null; 52841 54006 ctx.s.db = pMem->db; 52842 54007 ctx.pMem = pMem; 52843 54008 ctx.pFunc = pFunc; 52844 - pFunc->xFinalize(&ctx); 54009 + pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ 52845 54010 assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel ); 52846 54011 sqlite3DbFree(pMem->db, pMem->zMalloc); 52847 54012 memcpy(pMem, &ctx.s, sizeof(ctx.s)); 52848 54013 rc = ctx.isError; 52849 54014 } 52850 54015 return rc; 52851 54016 } ................................................................................ 52950 54115 flags = pMem->flags; 52951 54116 if( flags & MEM_Int ){ 52952 54117 return pMem->u.i; 52953 54118 }else if( flags & MEM_Real ){ 52954 54119 return doubleToInt64(pMem->r); 52955 54120 }else if( flags & (MEM_Str|MEM_Blob) ){ 52956 54121 i64 value; 52957 - pMem->flags |= MEM_Str; 52958 - if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) 52959 - || sqlite3VdbeMemNulTerminate(pMem) ){ 52960 - return 0; 52961 - } 52962 - assert( pMem->z ); 52963 - sqlite3Atoi64(pMem->z, &value); 54122 + assert( pMem->z || pMem->n==0 ); 54123 + testcase( pMem->z==0 ); 54124 + sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); 52964 54125 return value; 52965 54126 }else{ 52966 54127 return 0; 52967 54128 } 52968 54129 } 52969 54130 52970 54131 /* ................................................................................ 52979 54140 if( pMem->flags & MEM_Real ){ 52980 54141 return pMem->r; 52981 54142 }else if( pMem->flags & MEM_Int ){ 52982 54143 return (double)pMem->u.i; 52983 54144 }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ 52984 54145 /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ 52985 54146 double val = (double)0; 52986 - pMem->flags |= MEM_Str; 52987 - if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) 52988 - || sqlite3VdbeMemNulTerminate(pMem) ){ 52989 - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ 52990 - return (double)0; 52991 - } 52992 - assert( pMem->z ); 52993 - sqlite3AtoF(pMem->z, &val); 54147 + sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc); 52994 54148 return val; 52995 54149 }else{ 52996 54150 /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ 52997 54151 return (double)0; 52998 54152 } 52999 54153 } 53000 54154 ................................................................................ 53059 54213 ** Invalidate any prior representations. 53060 54214 ** 53061 54215 ** Every effort is made to force the conversion, even if the input 53062 54216 ** is a string that does not look completely like a number. Convert 53063 54217 ** as much of the string as we can and ignore the rest. 53064 54218 */ 53065 54219 SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ 53066 - int rc; 53067 - assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ); 53068 - assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); 53069 - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 53070 - rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8); 53071 - if( rc ) return rc; 53072 - rc = sqlite3VdbeMemNulTerminate(pMem); 53073 - if( rc ) return rc; 53074 - if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){ 53075 - MemSetTypeFlag(pMem, MEM_Int); 53076 - }else{ 53077 - pMem->r = sqlite3VdbeRealValue(pMem); 53078 - MemSetTypeFlag(pMem, MEM_Real); 53079 - sqlite3VdbeIntegerAffinity(pMem); 54220 + if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){ 54221 + assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); 54222 + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 54223 + if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){ 54224 + MemSetTypeFlag(pMem, MEM_Int); 54225 + }else{ 54226 + pMem->r = sqlite3VdbeRealValue(pMem); 54227 + MemSetTypeFlag(pMem, MEM_Real); 54228 + sqlite3VdbeIntegerAffinity(pMem); 54229 + } 53080 54230 } 54231 + assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); 54232 + pMem->flags &= ~(MEM_Str|MEM_Blob); 53081 54233 return SQLITE_OK; 53082 54234 } 53083 54235 53084 54236 /* 53085 54237 ** Delete any previous value and set the value stored in *pMem to NULL. 53086 54238 */ 53087 54239 SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){ ................................................................................ 53178 54330 n += p->u.nZero; 53179 54331 } 53180 54332 return n>p->db->aLimit[SQLITE_LIMIT_LENGTH]; 53181 54333 } 53182 54334 return 0; 53183 54335 } 53184 54336 54337 +#ifdef SQLITE_DEBUG 54338 +/* 54339 +** This routine prepares a memory cell for modication by breaking 54340 +** its link to a shallow copy and by marking any current shallow 54341 +** copies of this cell as invalid. 54342 +** 54343 +** This is used for testing and debugging only - to make sure shallow 54344 +** copies are not misused. 54345 +*/ 54346 +SQLITE_PRIVATE void sqlite3VdbeMemPrepareToChange(Vdbe *pVdbe, Mem *pMem){ 54347 + int i; 54348 + Mem *pX; 54349 + for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){ 54350 + if( pX->pScopyFrom==pMem ){ 54351 + pX->flags |= MEM_Invalid; 54352 + pX->pScopyFrom = 0; 54353 + } 54354 + } 54355 + pMem->pScopyFrom = 0; 54356 +} 54357 +#endif /* SQLITE_DEBUG */ 54358 + 53185 54359 /* 53186 54360 ** Size of struct Mem not including the Mem.zMalloc member. 53187 54361 */ 53188 54362 #define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc)) 53189 54363 53190 54364 /* 53191 54365 ** Make an shallow copy of pFrom into pTo. Prior contents of ................................................................................ 53546 54720 sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); 53547 54721 if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){ 53548 54722 assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); 53549 54723 if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ 53550 54724 return 0; 53551 54725 } 53552 54726 } 53553 - sqlite3VdbeMemNulTerminate(pVal); 54727 + sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-59893-45467 */ 53554 54728 }else{ 53555 54729 assert( (pVal->flags&MEM_Blob)==0 ); 53556 54730 sqlite3VdbeMemStringify(pVal, enc); 53557 54731 assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); 53558 54732 } 53559 54733 assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 53560 54734 || pVal->db->mallocFailed ); ................................................................................ 53594 54768 u8 enc, /* Encoding to use */ 53595 54769 u8 affinity, /* Affinity to use */ 53596 54770 sqlite3_value **ppVal /* Write the new value here */ 53597 54771 ){ 53598 54772 int op; 53599 54773 char *zVal = 0; 53600 54774 sqlite3_value *pVal = 0; 54775 + int negInt = 1; 54776 + const char *zNeg = ""; 53601 54777 53602 54778 if( !pExpr ){ 53603 54779 *ppVal = 0; 53604 54780 return SQLITE_OK; 53605 54781 } 53606 54782 op = pExpr->op; 53607 54783 ................................................................................ 53610 54786 ** when SQLITE_ENABLE_STAT2 is omitted. 53611 54787 */ 53612 54788 #ifdef SQLITE_ENABLE_STAT2 53613 54789 if( op==TK_REGISTER ) op = pExpr->op2; 53614 54790 #else 53615 54791 if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; 53616 54792 #endif 54793 + 54794 + /* Handle negative integers in a single step. This is needed in the 54795 + ** case when the value is -9223372036854775808. 54796 + */ 54797 + if( op==TK_UMINUS 54798 + && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){ 54799 + pExpr = pExpr->pLeft; 54800 + op = pExpr->op; 54801 + negInt = -1; 54802 + zNeg = "-"; 54803 + } 53617 54804 53618 54805 if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ 53619 54806 pVal = sqlite3ValueNew(db); 53620 54807 if( pVal==0 ) goto no_mem; 53621 54808 if( ExprHasProperty(pExpr, EP_IntValue) ){ 53622 - sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue); 54809 + sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt); 53623 54810 }else{ 53624 - zVal = sqlite3DbStrDup(db, pExpr->u.zToken); 54811 + zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken); 53625 54812 if( zVal==0 ) goto no_mem; 53626 54813 sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); 53627 54814 if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT; 53628 54815 } 53629 54816 if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ 53630 54817 sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); 53631 54818 }else{ 53632 54819 sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); 53633 54820 } 54821 + if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str; 53634 54822 if( enc!=SQLITE_UTF8 ){ 53635 54823 sqlite3VdbeChangeEncoding(pVal, enc); 53636 54824 } 53637 54825 }else if( op==TK_UMINUS ) { 54826 + /* This branch happens for multiple negative signs. Ex: -(-5) */ 53638 54827 if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){ 54828 + sqlite3VdbeMemNumerify(pVal); 53639 54829 pVal->u.i = -1 * pVal->u.i; 53640 54830 /* (double)-1 In case of SQLITE_OMIT_FLOATING_POINT... */ 53641 54831 pVal->r = (double)-1 * pVal->r; 54832 + sqlite3ValueApplyAffinity(pVal, affinity, enc); 53642 54833 } 53643 54834 } 53644 54835 #ifndef SQLITE_OMIT_BLOB_LITERAL 53645 54836 else if( op==TK_BLOB ){ 53646 54837 int nVal; 53647 54838 assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); 53648 54839 assert( pExpr->u.zToken[1]=='\'' ); ................................................................................ 55461 56652 ** still have 'null' as the master journal pointer, so they will roll 55462 56653 ** back independently if a failure occurs. 55463 56654 */ 55464 56655 for(i=0; i<db->nDb; i++){ 55465 56656 Btree *pBt = db->aDb[i].pBt; 55466 56657 if( sqlite3BtreeIsInTrans(pBt) ){ 55467 56658 char const *zFile = sqlite3BtreeGetJournalname(pBt); 55468 - if( zFile==0 || zFile[0]==0 ){ 56659 + if( zFile==0 ){ 55469 56660 continue; /* Ignore TEMP and :memory: databases */ 55470 56661 } 56662 + assert( zFile[0]!=0 ); 55471 56663 if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ 55472 56664 needSync = 1; 55473 56665 } 55474 56666 rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset); 55475 56667 offset += sqlite3Strlen30(zFile)+1; 55476 56668 if( rc!=SQLITE_OK ){ 55477 56669 sqlite3OsCloseFree(pMaster); ................................................................................ 55767 56959 55768 56960 /* Check for one of the special errors */ 55769 56961 mrc = p->rc & 0xff; 55770 56962 assert( p->rc!=SQLITE_IOERR_BLOCKED ); /* This error no longer exists */ 55771 56963 isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR 55772 56964 || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL; 55773 56965 if( isSpecialError ){ 55774 - /* If the query was read-only, we need do no rollback at all. Otherwise, 55775 - ** proceed with the special handling. 56966 + /* If the query was read-only and the error code is SQLITE_INTERRUPT, 56967 + ** no rollback is necessary. Otherwise, at least a savepoint 56968 + ** transaction must be rolled back to restore the database to a 56969 + ** consistent state. 56970 + ** 56971 + ** Even if the statement is read-only, it is important to perform 56972 + ** a statement or transaction rollback operation. If the error 56973 + ** occured while writing to the journal, sub-journal or database 56974 + ** file as part of an effort to free up cache space (see function 56975 + ** pagerStress() in pager.c), the rollback is required to restore 56976 + ** the pager to a consistent state. 55776 56977 */ 55777 56978 if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){ 55778 56979 if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){ 55779 56980 eStatementOp = SAVEPOINT_ROLLBACK; 55780 56981 }else{ 55781 56982 /* We are forced to roll back the active transaction. Before doing 55782 56983 ** so, abort any other statements this handle currently has active. ................................................................................ 56918 58119 ** 56919 58120 ** This routine sets the error code and string returned by 56920 58121 ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). 56921 58122 */ 56922 58123 SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ 56923 58124 int rc; 56924 58125 if( pStmt==0 ){ 58126 + /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL 58127 + ** pointer is a harmless no-op. */ 56925 58128 rc = SQLITE_OK; 56926 58129 }else{ 56927 58130 Vdbe *v = (Vdbe*)pStmt; 56928 58131 sqlite3 *db = v->db; 56929 58132 #if SQLITE_THREADSAFE 56930 58133 sqlite3_mutex *mutex; 56931 58134 #endif ................................................................................ 56994 58197 */ 56995 58198 SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){ 56996 58199 Mem *p = (Mem*)pVal; 56997 58200 if( p->flags & (MEM_Blob|MEM_Str) ){ 56998 58201 sqlite3VdbeMemExpandBlob(p); 56999 58202 p->flags &= ~MEM_Str; 57000 58203 p->flags |= MEM_Blob; 57001 - return p->z; 58204 + return p->n ? p->z : 0; 57002 58205 }else{ 57003 58206 return sqlite3_value_text(pVal); 57004 58207 } 57005 58208 } 57006 58209 SQLITE_API int sqlite3_value_bytes(sqlite3_value *pVal){ 57007 58210 return sqlite3ValueBytes(pVal, SQLITE_UTF8); 57008 58211 } ................................................................................ 57348 58551 assert( p && p->pFunc ); 57349 58552 return p->pFunc->pUserData; 57350 58553 } 57351 58554 57352 58555 /* 57353 58556 ** Extract the user data from a sqlite3_context structure and return a 57354 58557 ** pointer to it. 58558 +** 58559 +** IMPLEMENTATION-OF: R-46798-50301 The sqlite3_context_db_handle() interface 58560 +** returns a copy of the pointer to the database connection (the 1st 58561 +** parameter) of the sqlite3_create_function() and 58562 +** sqlite3_create_function16() routines that originally registered the 58563 +** application defined function. 57355 58564 */ 57356 58565 SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ 57357 58566 assert( p && p->pFunc ); 57358 58567 return p->s.db; 57359 58568 } 57360 58569 57361 58570 /* ................................................................................ 57557 58766 ** sqlite3_column_int() 57558 58767 ** sqlite3_column_int64() 57559 58768 ** sqlite3_column_text() 57560 58769 ** sqlite3_column_text16() 57561 58770 ** sqlite3_column_real() 57562 58771 ** sqlite3_column_bytes() 57563 58772 ** sqlite3_column_bytes16() 57564 -** 57565 -** But not for sqlite3_column_blob(), which never calls malloc(). 58773 +** sqiite3_column_blob() 57566 58774 */ 57567 58775 static void columnMallocFailure(sqlite3_stmt *pStmt) 57568 58776 { 57569 58777 /* If malloc() failed during an encoding conversion within an 57570 58778 ** sqlite3_column_XXX API, then set the return code of the statement to 57571 58779 ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR 57572 58780 ** and _finalize() will return NOMEM. ................................................................................ 57826 59034 pVar = &p->aVar[i]; 57827 59035 sqlite3VdbeMemRelease(pVar); 57828 59036 pVar->flags = MEM_Null; 57829 59037 sqlite3Error(p->db, SQLITE_OK, 0); 57830 59038 57831 59039 /* If the bit corresponding to this variable in Vdbe.expmask is set, then 57832 59040 ** binding a new value to this variable invalidates the current query plan. 59041 + ** 59042 + ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host 59043 + ** parameter in the WHERE clause might influence the choice of query plan 59044 + ** for a statement, then the statement will be automatically recompiled, 59045 + ** as if there had been a schema change, on the first sqlite3_step() call 59046 + ** following any change to the bindings of that parameter. 57833 59047 */ 57834 59048 if( p->isPrepareV2 && 57835 59049 ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff) 57836 59050 ){ 57837 59051 p->expired = 1; 57838 59052 } 57839 59053 return SQLITE_OK; ................................................................................ 58323 59537 ** Various scripts scan this source file in order to generate HTML 58324 59538 ** documentation, headers files, or other derived files. The formatting 58325 59539 ** of the code in this file is, therefore, important. See other comments 58326 59540 ** in this file for details. If in doubt, do not deviate from existing 58327 59541 ** commenting and indentation practices when changing or adding code. 58328 59542 */ 58329 59543 59544 +/* 59545 +** Invoke this macro on memory cells just prior to changing the 59546 +** value of the cell. This macro verifies that shallow copies are 59547 +** not misused. 59548 +*/ 59549 +#ifdef SQLITE_DEBUG 59550 +# define memAboutToChange(P,M) sqlite3VdbeMemPrepareToChange(P,M) 59551 +#else 59552 +# define memAboutToChange(P,M) 59553 +#endif 59554 + 58330 59555 /* 58331 59556 ** The following global variable is incremented every time a cursor 58332 59557 ** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test 58333 59558 ** procedures use this information to make sure that indices are 58334 59559 ** working correctly. This variable has no function other than to 58335 59560 ** help verify the correct operation of the library. 58336 59561 */ ................................................................................ 58515 59740 ** Try to convert a value into a numeric representation if we can 58516 59741 ** do so without loss of information. In other words, if the string 58517 59742 ** looks like a number, convert it into a number. If it does not 58518 59743 ** look like a number, leave it alone. 58519 59744 */ 58520 59745 static void applyNumericAffinity(Mem *pRec){ 58521 59746 if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ 58522 - int realnum; 59747 + double rValue; 59748 + i64 iValue; 58523 59749 u8 enc = pRec->enc; 58524 - sqlite3VdbeMemNulTerminate(pRec); 58525 - if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, enc) ){ 58526 - i64 value; 58527 - char *zUtf8 = pRec->z; 58528 -#ifndef SQLITE_OMIT_UTF16 58529 - if( enc!=SQLITE_UTF8 ){ 58530 - assert( pRec->db ); 58531 - zUtf8 = sqlite3Utf16to8(pRec->db, pRec->z, pRec->n, enc); 58532 - if( !zUtf8 ) return; 58533 - } 58534 -#endif 58535 - if( !realnum && sqlite3Atoi64(zUtf8, &value) ){ 58536 - pRec->u.i = value; 58537 - MemSetTypeFlag(pRec, MEM_Int); 58538 - }else{ 58539 - sqlite3AtoF(zUtf8, &pRec->r); 58540 - MemSetTypeFlag(pRec, MEM_Real); 58541 - } 58542 -#ifndef SQLITE_OMIT_UTF16 58543 - if( enc!=SQLITE_UTF8 ){ 58544 - sqlite3DbFree(pRec->db, zUtf8); 58545 - } 58546 -#endif 59750 + if( (pRec->flags&MEM_Str)==0 ) return; 59751 + if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; 59752 + if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ 59753 + pRec->u.i = iValue; 59754 + pRec->flags |= MEM_Int; 59755 + }else{ 59756 + pRec->r = rValue; 59757 + pRec->flags |= MEM_Real; 58547 59758 } 58548 59759 } 58549 59760 } 58550 59761 58551 59762 /* 58552 59763 ** Processing is determine by the affinity parameter: 58553 59764 ** ................................................................................ 59432 60643 ** value or convert mem[p2] to a different type. 59433 60644 */ 59434 60645 assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); 59435 60646 if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){ 59436 60647 assert( pOp->p2>0 ); 59437 60648 assert( pOp->p2<=p->nMem ); 59438 60649 pOut = &aMem[pOp->p2]; 60650 + memAboutToChange(p, pOut); 59439 60651 sqlite3VdbeMemReleaseExternal(pOut); 59440 60652 pOut->flags = MEM_Int; 59441 60653 } 59442 60654 59443 60655 /* Sanity checking on other operands */ 59444 60656 #ifdef SQLITE_DEBUG 59445 60657 if( (pOp->opflags & OPFLG_IN1)!=0 ){ 59446 60658 assert( pOp->p1>0 ); 59447 60659 assert( pOp->p1<=p->nMem ); 60660 + assert( memIsValid(&aMem[pOp->p1]) ); 59448 60661 REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); 59449 60662 } 59450 60663 if( (pOp->opflags & OPFLG_IN2)!=0 ){ 59451 60664 assert( pOp->p2>0 ); 59452 60665 assert( pOp->p2<=p->nMem ); 60666 + assert( memIsValid(&aMem[pOp->p2]) ); 59453 60667 REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); 59454 60668 } 59455 60669 if( (pOp->opflags & OPFLG_IN3)!=0 ){ 59456 60670 assert( pOp->p3>0 ); 59457 60671 assert( pOp->p3<=p->nMem ); 60672 + assert( memIsValid(&aMem[pOp->p3]) ); 59458 60673 REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); 59459 60674 } 59460 60675 if( (pOp->opflags & OPFLG_OUT2)!=0 ){ 59461 60676 assert( pOp->p2>0 ); 59462 60677 assert( pOp->p2<=p->nMem ); 60678 + memAboutToChange(p, &aMem[pOp->p2]); 59463 60679 } 59464 60680 if( (pOp->opflags & OPFLG_OUT3)!=0 ){ 59465 60681 assert( pOp->p3>0 ); 59466 60682 assert( pOp->p3<=p->nMem ); 60683 + memAboutToChange(p, &aMem[pOp->p3]); 59467 60684 } 59468 60685 #endif 59469 60686 59470 60687 switch( pOp->opcode ){ 59471 60688 59472 60689 /***************************************************************************** 59473 60690 ** What follows is a massive switch statement where each case implements a ................................................................................ 59521 60738 ** 59522 60739 ** Write the current address onto register P1 59523 60740 ** and then jump to address P2. 59524 60741 */ 59525 60742 case OP_Gosub: { /* jump, in1 */ 59526 60743 pIn1 = &aMem[pOp->p1]; 59527 60744 assert( (pIn1->flags & MEM_Dyn)==0 ); 60745 + memAboutToChange(p, pIn1); 59528 60746 pIn1->flags = MEM_Int; 59529 60747 pIn1->u.i = pc; 59530 60748 REGISTER_TRACE(pOp->p1, pIn1); 59531 60749 pc = pOp->p2 - 1; 59532 60750 break; 59533 60751 } 59534 60752 ................................................................................ 59728 60946 break; 59729 60947 } 59730 60948 59731 60949 59732 60950 /* Opcode: Blob P1 P2 * P4 59733 60951 ** 59734 60952 ** P4 points to a blob of data P1 bytes long. Store this 59735 -** blob in register P2. This instruction is not coded directly 59736 -** by the compiler. Instead, the compiler layer specifies 59737 -** an OP_HexBlob opcode, with the hex string representation of 59738 -** the blob as P4. This opcode is transformed to an OP_Blob 59739 -** the first time it is executed. 60953 +** blob in register P2. 59740 60954 */ 59741 60955 case OP_Blob: { /* out2-prerelease */ 59742 60956 assert( pOp->p1 <= SQLITE_MAX_LENGTH ); 59743 60957 sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); 59744 60958 pOut->enc = encoding; 59745 60959 UPDATE_MAX_BLOBSIZE(pOut); 59746 60960 break; ................................................................................ 59790 61004 assert( u.ac.p1+u.ac.n<=u.ac.p2 || u.ac.p2+u.ac.n<=u.ac.p1 ); 59791 61005 59792 61006 pIn1 = &aMem[u.ac.p1]; 59793 61007 pOut = &aMem[u.ac.p2]; 59794 61008 while( u.ac.n-- ){ 59795 61009 assert( pOut<=&aMem[p->nMem] ); 59796 61010 assert( pIn1<=&aMem[p->nMem] ); 61011 + assert( memIsValid(pIn1) ); 61012 + memAboutToChange(p, pOut); 59797 61013 u.ac.zMalloc = pOut->zMalloc; 59798 61014 pOut->zMalloc = 0; 59799 61015 sqlite3VdbeMemMove(pOut, pIn1); 59800 61016 pIn1->zMalloc = u.ac.zMalloc; 59801 61017 REGISTER_TRACE(u.ac.p2++, pOut); 59802 61018 pIn1++; 59803 61019 pOut++; ................................................................................ 59835 61051 ** copy. 59836 61052 */ 59837 61053 case OP_SCopy: { /* in1, out2 */ 59838 61054 pIn1 = &aMem[pOp->p1]; 59839 61055 pOut = &aMem[pOp->p2]; 59840 61056 assert( pOut!=pIn1 ); 59841 61057 sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); 61058 +#ifdef SQLITE_DEBUG 61059 + if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1; 61060 +#endif 59842 61061 REGISTER_TRACE(pOp->p2, pOut); 59843 61062 break; 59844 61063 } 59845 61064 59846 61065 /* Opcode: ResultRow P1 P2 * * * 59847 61066 ** 59848 61067 ** The registers P1 through P1+P2-1 contain a single row of ................................................................................ 59895 61114 59896 61115 /* Make sure the results of the current row are \000 terminated 59897 61116 ** and have an assigned type. The results are de-ephemeralized as 59898 61117 ** as side effect. 59899 61118 */ 59900 61119 u.ad.pMem = p->pResultSet = &aMem[pOp->p1]; 59901 61120 for(u.ad.i=0; u.ad.i<pOp->p2; u.ad.i++){ 61121 + assert( memIsValid(&u.ad.pMem[u.ad.i]) ); 61122 + Deephemeralize(&u.ad.pMem[u.ad.i]); 61123 + assert( (u.ad.pMem[u.ad.i].flags & MEM_Ephem)==0 61124 + || (u.ad.pMem[u.ad.i].flags & (MEM_Str|MEM_Blob))==0 ); 59902 61125 sqlite3VdbeMemNulTerminate(&u.ad.pMem[u.ad.i]); 59903 61126 sqlite3VdbeMemStoreType(&u.ad.pMem[u.ad.i]); 59904 61127 REGISTER_TRACE(pOp->p1+u.ad.i, &u.ad.pMem[u.ad.i]); 59905 61128 } 59906 61129 if( db->mallocFailed ) goto no_mem; 59907 61130 59908 61131 /* Return SQLITE_ROW ................................................................................ 60126 61349 sqlite3_value **apVal; 60127 61350 int n; 60128 61351 #endif /* local variables moved into u.ag */ 60129 61352 60130 61353 u.ag.n = pOp->p5; 60131 61354 u.ag.apVal = p->apArg; 60132 61355 assert( u.ag.apVal || u.ag.n==0 ); 61356 + assert( pOp->p3>0 && pOp->p3<=p->nMem ); 61357 + pOut = &aMem[pOp->p3]; 61358 + memAboutToChange(p, pOut); 60133 61359 60134 61360 assert( u.ag.n==0 || (pOp->p2>0 && pOp->p2+u.ag.n<=p->nMem+1) ); 60135 61361 assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ag.n ); 60136 61362 u.ag.pArg = &aMem[pOp->p2]; 60137 61363 for(u.ag.i=0; u.ag.i<u.ag.n; u.ag.i++, u.ag.pArg++){ 61364 + assert( memIsValid(u.ag.pArg) ); 60138 61365 u.ag.apVal[u.ag.i] = u.ag.pArg; 61366 + Deephemeralize(u.ag.pArg); 60139 61367 sqlite3VdbeMemStoreType(u.ag.pArg); 60140 61368 REGISTER_TRACE(pOp->p2+u.ag.i, u.ag.pArg); 60141 61369 } 60142 61370 60143 61371 assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC ); 60144 61372 if( pOp->p4type==P4_FUNCDEF ){ 60145 61373 u.ag.ctx.pFunc = pOp->p4.pFunc; 60146 61374 u.ag.ctx.pVdbeFunc = 0; 60147 61375 }else{ 60148 61376 u.ag.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc; 60149 61377 u.ag.ctx.pFunc = u.ag.ctx.pVdbeFunc->pFunc; 60150 61378 } 60151 61379 60152 - assert( pOp->p3>0 && pOp->p3<=p->nMem ); 60153 - pOut = &aMem[pOp->p3]; 60154 61380 u.ag.ctx.s.flags = MEM_Null; 60155 61381 u.ag.ctx.s.db = db; 60156 61382 u.ag.ctx.s.xDel = 0; 60157 61383 u.ag.ctx.s.zMalloc = 0; 60158 61384 60159 61385 /* The output cell may already have a buffer allocated. Move 60160 61386 ** the pointer to u.ag.ctx.s so in case the user-function can use ................................................................................ 60166 61392 u.ag.ctx.isError = 0; 60167 61393 if( u.ag.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ 60168 61394 assert( pOp>aOp ); 60169 61395 assert( pOp[-1].p4type==P4_COLLSEQ ); 60170 61396 assert( pOp[-1].opcode==OP_CollSeq ); 60171 61397 u.ag.ctx.pColl = pOp[-1].p4.pColl; 60172 61398 } 60173 - (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); 61399 + (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); /* IMP: R-24505-23230 */ 60174 61400 if( db->mallocFailed ){ 60175 61401 /* Even though a malloc() has failed, the implementation of the 60176 61402 ** user function may have called an sqlite3_result_XXX() function 60177 61403 ** to return a value. The following call releases any resources 60178 61404 ** associated with such a value. 60179 61405 */ 60180 61406 sqlite3VdbeMemRelease(&u.ag.ctx.s); ................................................................................ 60218 61444 ** Take the bit-wise OR of the values in register P1 and P2 and 60219 61445 ** store the result in register P3. 60220 61446 ** If either input is NULL, the result is NULL. 60221 61447 */ 60222 61448 /* Opcode: ShiftLeft P1 P2 P3 * * 60223 61449 ** 60224 61450 ** Shift the integer value in register P2 to the left by the 60225 -** number of bits specified by the integer in regiser P1. 61451 +** number of bits specified by the integer in register P1. 60226 61452 ** Store the result in register P3. 60227 61453 ** If either input is NULL, the result is NULL. 60228 61454 */ 60229 61455 /* Opcode: ShiftRight P1 P2 P3 * * 60230 61456 ** 60231 61457 ** Shift the integer value in register P2 to the right by the 60232 61458 ** number of bits specified by the integer in register P1. ................................................................................ 60268 61494 ** Add the constant P2 to the value in register P1. 60269 61495 ** The result is always an integer. 60270 61496 ** 60271 61497 ** To force any register to be an integer, just add 0. 60272 61498 */ 60273 61499 case OP_AddImm: { /* in1 */ 60274 61500 pIn1 = &aMem[pOp->p1]; 61501 + memAboutToChange(p, pIn1); 60275 61502 sqlite3VdbeMemIntegerify(pIn1); 60276 61503 pIn1->u.i += pOp->p2; 60277 61504 break; 60278 61505 } 60279 61506 60280 61507 /* Opcode: MustBeInt P1 P2 * * * 60281 61508 ** ................................................................................ 60282 61509 ** Force the value in register P1 to be an integer. If the value 60283 61510 ** in P1 is not an integer and cannot be converted into an integer 60284 61511 ** without data loss, then jump immediately to P2, or if P2==0 60285 61512 ** raise an SQLITE_MISMATCH exception. 60286 61513 */ 60287 61514 case OP_MustBeInt: { /* jump, in1 */ 60288 61515 pIn1 = &aMem[pOp->p1]; 61516 + memAboutToChange(p, pIn1); 60289 61517 applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); 60290 61518 if( (pIn1->flags & MEM_Int)==0 ){ 60291 61519 if( pOp->p2==0 ){ 60292 61520 rc = SQLITE_MISMATCH; 60293 61521 goto abort_due_to_error; 60294 61522 }else{ 60295 61523 pc = pOp->p2 - 1; ................................................................................ 60327 61555 ** equivalent of printf(). Blob values are unchanged and 60328 61556 ** are afterwards simply interpreted as text. 60329 61557 ** 60330 61558 ** A NULL value is not changed by this routine. It remains NULL. 60331 61559 */ 60332 61560 case OP_ToText: { /* same as TK_TO_TEXT, in1 */ 60333 61561 pIn1 = &aMem[pOp->p1]; 61562 + memAboutToChange(p, pIn1); 60334 61563 if( pIn1->flags & MEM_Null ) break; 60335 61564 assert( MEM_Str==(MEM_Blob>>3) ); 60336 61565 pIn1->flags |= (pIn1->flags&MEM_Blob)>>3; 60337 61566 applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); 60338 61567 rc = ExpandBlob(pIn1); 60339 61568 assert( pIn1->flags & MEM_Str || db->mallocFailed ); 60340 61569 pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); ................................................................................ 60373 61602 ** equivalent of atoi() or atof() and store 0 if no such conversion 60374 61603 ** is possible. 60375 61604 ** 60376 61605 ** A NULL value is not changed by this routine. It remains NULL. 60377 61606 */ 60378 61607 case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */ 60379 61608 pIn1 = &aMem[pOp->p1]; 60380 - if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){ 60381 - sqlite3VdbeMemNumerify(pIn1); 60382 - } 61609 + sqlite3VdbeMemNumerify(pIn1); 60383 61610 break; 60384 61611 } 60385 61612 #endif /* SQLITE_OMIT_CAST */ 60386 61613 60387 61614 /* Opcode: ToInt P1 * * * * 60388 61615 ** 60389 -** Force the value in register P1 be an integer. If 61616 +** Force the value in register P1 to be an integer. If 60390 61617 ** The value is currently a real number, drop its fractional part. 60391 61618 ** If the value is text or blob, try to convert it to an integer using the 60392 61619 ** equivalent of atoi() and store 0 if no such conversion is possible. 60393 61620 ** 60394 61621 ** A NULL value is not changed by this routine. It remains NULL. 60395 61622 */ 60396 61623 case OP_ToInt: { /* same as TK_TO_INT, in1 */ ................................................................................ 60409 61636 ** If the value is text or blob, try to convert it to an integer using the 60410 61637 ** equivalent of atoi() and store 0.0 if no such conversion is possible. 60411 61638 ** 60412 61639 ** A NULL value is not changed by this routine. It remains NULL. 60413 61640 */ 60414 61641 case OP_ToReal: { /* same as TK_TO_REAL, in1 */ 60415 61642 pIn1 = &aMem[pOp->p1]; 61643 + memAboutToChange(p, pIn1); 60416 61644 if( (pIn1->flags & MEM_Null)==0 ){ 60417 61645 sqlite3VdbeMemRealify(pIn1); 60418 61646 } 60419 61647 break; 60420 61648 } 60421 61649 #endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */ 60422 61650 ................................................................................ 60423 61651 /* Opcode: Lt P1 P2 P3 P4 P5 60424 61652 ** 60425 61653 ** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then 60426 61654 ** jump to address P2. 60427 61655 ** 60428 61656 ** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or 60429 61657 ** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL 60430 -** bit is clear then fall thru if either operand is NULL. 61658 +** bit is clear then fall through if either operand is NULL. 60431 61659 ** 60432 61660 ** The SQLITE_AFF_MASK portion of P5 must be an affinity character - 60433 61661 ** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made 60434 61662 ** to coerce both inputs according to this affinity before the 60435 61663 ** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric 60436 61664 ** affinity is used. Note that the affinity conversions are stored 60437 61665 ** back into the input registers P1 and P3. So this opcode can cause ................................................................................ 60553 61781 case OP_Le: u.ai.res = u.ai.res<=0; break; 60554 61782 case OP_Gt: u.ai.res = u.ai.res>0; break; 60555 61783 default: u.ai.res = u.ai.res>=0; break; 60556 61784 } 60557 61785 60558 61786 if( pOp->p5 & SQLITE_STOREP2 ){ 60559 61787 pOut = &aMem[pOp->p2]; 61788 + memAboutToChange(p, pOut); 60560 61789 MemSetTypeFlag(pOut, MEM_Int); 60561 61790 pOut->u.i = u.ai.res; 60562 61791 REGISTER_TRACE(pOp->p2, pOut); 60563 61792 }else if( u.ai.res ){ 60564 61793 pc = pOp->p2-1; 60565 61794 } 60566 61795 ................................................................................ 60584 61813 assert( pOp->p4.ai ); 60585 61814 aPermute = pOp->p4.ai; 60586 61815 break; 60587 61816 } 60588 61817 60589 61818 /* Opcode: Compare P1 P2 P3 P4 * 60590 61819 ** 60591 -** Compare to vectors of registers in reg(P1)..reg(P1+P3-1) (all this 60592 -** one "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of 61820 +** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this 61821 +** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of 60593 61822 ** the comparison for use by the next OP_Jump instruct. 60594 61823 ** 60595 61824 ** P4 is a KeyInfo structure that defines collating sequences and sort 60596 61825 ** orders for the comparison. The permutation applies to registers 60597 61826 ** only. The KeyInfo elements are used sequentially. 60598 61827 ** 60599 61828 ** The comparison is a sort comparison, so NULLs compare equal, ................................................................................ 60627 61856 }else{ 60628 61857 assert( u.aj.p1>0 && u.aj.p1+u.aj.n<=p->nMem+1 ); 60629 61858 assert( u.aj.p2>0 && u.aj.p2+u.aj.n<=p->nMem+1 ); 60630 61859 } 60631 61860 #endif /* SQLITE_DEBUG */ 60632 61861 for(u.aj.i=0; u.aj.i<u.aj.n; u.aj.i++){ 60633 61862 u.aj.idx = aPermute ? aPermute[u.aj.i] : u.aj.i; 61863 + assert( memIsValid(&aMem[u.aj.p1+u.aj.idx]) ); 61864 + assert( memIsValid(&aMem[u.aj.p2+u.aj.idx]) ); 60634 61865 REGISTER_TRACE(u.aj.p1+u.aj.idx, &aMem[u.aj.p1+u.aj.idx]); 60635 61866 REGISTER_TRACE(u.aj.p2+u.aj.idx, &aMem[u.aj.p2+u.aj.idx]); 60636 61867 assert( u.aj.i<u.aj.pKeyInfo->nField ); 60637 61868 u.aj.pColl = u.aj.pKeyInfo->aColl[u.aj.i]; 60638 61869 u.aj.bRev = u.aj.pKeyInfo->aSortOrder[u.aj.i]; 60639 61870 iCompare = sqlite3MemCompare(&aMem[u.aj.p1+u.aj.idx], &aMem[u.aj.p2+u.aj.idx], u.aj.pColl); 60640 61871 if( iCompare ){ ................................................................................ 60858 62089 u.am.p1 = pOp->p1; 60859 62090 u.am.p2 = pOp->p2; 60860 62091 u.am.pC = 0; 60861 62092 memset(&u.am.sMem, 0, sizeof(u.am.sMem)); 60862 62093 assert( u.am.p1<p->nCursor ); 60863 62094 assert( pOp->p3>0 && pOp->p3<=p->nMem ); 60864 62095 u.am.pDest = &aMem[pOp->p3]; 62096 + memAboutToChange(p, u.am.pDest); 60865 62097 MemSetTypeFlag(u.am.pDest, MEM_Null); 60866 62098 u.am.zRec = 0; 60867 62099 60868 62100 /* This block sets the variable u.am.payloadSize to be the total number of 60869 62101 ** bytes in the record. 60870 62102 ** 60871 62103 ** u.am.zRec is set to be the complete text of the record if it is available. ................................................................................ 60905 62137 assert( sqlite3BtreeCursorIsValid(u.am.pCrsr) ); 60906 62138 rc = sqlite3BtreeDataSize(u.am.pCrsr, &u.am.payloadSize); 60907 62139 assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ 60908 62140 } 60909 62141 }else if( u.am.pC->pseudoTableReg>0 ){ 60910 62142 u.am.pReg = &aMem[u.am.pC->pseudoTableReg]; 60911 62143 assert( u.am.pReg->flags & MEM_Blob ); 62144 + assert( memIsValid(u.am.pReg) ); 60912 62145 u.am.payloadSize = u.am.pReg->n; 60913 62146 u.am.zRec = u.am.pReg->z; 60914 62147 u.am.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr; 60915 62148 assert( u.am.payloadSize==0 || u.am.zRec!=0 ); 60916 62149 }else{ 60917 62150 /* Consider the row to be NULL */ 60918 62151 u.am.payloadSize = 0; ................................................................................ 61129 62362 61130 62363 u.an.zAffinity = pOp->p4.z; 61131 62364 assert( u.an.zAffinity!=0 ); 61132 62365 assert( u.an.zAffinity[pOp->p2]==0 ); 61133 62366 pIn1 = &aMem[pOp->p1]; 61134 62367 while( (u.an.cAff = *(u.an.zAffinity++))!=0 ){ 61135 62368 assert( pIn1 <= &p->aMem[p->nMem] ); 62369 + assert( memIsValid(pIn1) ); 61136 62370 ExpandBlob(pIn1); 61137 62371 applyAffinity(pIn1, u.an.cAff, encoding); 61138 62372 pIn1++; 61139 62373 } 61140 62374 break; 61141 62375 } 61142 62376 61143 62377 /* Opcode: MakeRecord P1 P2 P3 P4 * 61144 62378 ** 61145 -** Convert P2 registers beginning with P1 into a single entry 61146 -** suitable for use as a data record in a database table or as a key 61147 -** in an index. The details of the format are irrelevant as long as 61148 -** the OP_Column opcode can decode the record later. 61149 -** Refer to source code comments for the details of the record 61150 -** format. 62379 +** Convert P2 registers beginning with P1 into the [record format] 62380 +** use as a data record in a database table or as a key 62381 +** in an index. The OP_Column opcode can decode the record later. 61151 62382 ** 61152 62383 ** P4 may be a string that is P2 characters long. The nth character of the 61153 62384 ** string indicates the column affinity that should be used for the nth 61154 62385 ** field of the index key. 61155 62386 ** 61156 62387 ** The mapping from character to affinity is given by the SQLITE_AFF_ 61157 62388 ** macros defined in sqliteInt.h. ................................................................................ 61199 62430 u.ao.nField = pOp->p1; 61200 62431 u.ao.zAffinity = pOp->p4.z; 61201 62432 assert( u.ao.nField>0 && pOp->p2>0 && pOp->p2+u.ao.nField<=p->nMem+1 ); 61202 62433 u.ao.pData0 = &aMem[u.ao.nField]; 61203 62434 u.ao.nField = pOp->p2; 61204 62435 u.ao.pLast = &u.ao.pData0[u.ao.nField-1]; 61205 62436 u.ao.file_format = p->minWriteFileFormat; 62437 + 62438 + /* Identify the output register */ 62439 + assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 ); 62440 + pOut = &aMem[pOp->p3]; 62441 + memAboutToChange(p, pOut); 61206 62442 61207 62443 /* Loop through the elements that will make up the record to figure 61208 62444 ** out how much space is required for the new record. 61209 62445 */ 61210 62446 for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){ 62447 + assert( memIsValid(u.ao.pRec) ); 61211 62448 if( u.ao.zAffinity ){ 61212 62449 applyAffinity(u.ao.pRec, u.ao.zAffinity[u.ao.pRec-u.ao.pData0], encoding); 61213 62450 } 61214 62451 if( u.ao.pRec->flags&MEM_Zero && u.ao.pRec->n>0 ){ 61215 62452 sqlite3VdbeMemExpandBlob(u.ao.pRec); 61216 62453 } 61217 62454 u.ao.serial_type = sqlite3VdbeSerialType(u.ao.pRec, u.ao.file_format); ................................................................................ 61238 62475 } 61239 62476 61240 62477 /* Make sure the output register has a buffer large enough to store 61241 62478 ** the new record. The output register (pOp->p3) is not allowed to 61242 62479 ** be one of the input registers (because the following call to 61243 62480 ** sqlite3VdbeMemGrow() could clobber the value before it is used). 61244 62481 */ 61245 - assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 ); 61246 - pOut = &aMem[pOp->p3]; 61247 62482 if( sqlite3VdbeMemGrow(pOut, (int)u.ao.nByte, 0) ){ 61248 62483 goto no_mem; 61249 62484 } 61250 62485 u.ao.zNewRecord = (u8 *)pOut->z; 61251 62486 61252 62487 /* Write the record */ 61253 62488 u.ao.i = putVarint32(u.ao.zNewRecord, u.ao.nHdr); ................................................................................ 61412 62647 if( rc!=SQLITE_OK ){ 61413 62648 goto abort_due_to_error; 61414 62649 } 61415 62650 } 61416 62651 if( u.aq.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ 61417 62652 sqlite3ExpirePreparedStatements(db); 61418 62653 sqlite3ResetInternalSchema(db, 0); 62654 + db->flags = (db->flags | SQLITE_InternChanges); 61419 62655 } 61420 62656 } 61421 62657 61422 62658 /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all 61423 62659 ** savepoints nested inside of the savepoint being operated on. */ 61424 62660 while( db->pSavepoint!=u.aq.pSavepoint ){ 61425 62661 u.aq.pTmp = db->pSavepoint; ................................................................................ 61802 63038 }else{ 61803 63039 u.aw.wrFlag = 0; 61804 63040 } 61805 63041 if( pOp->p5 ){ 61806 63042 assert( u.aw.p2>0 ); 61807 63043 assert( u.aw.p2<=p->nMem ); 61808 63044 pIn2 = &aMem[u.aw.p2]; 63045 + assert( memIsValid(pIn2) ); 63046 + assert( (pIn2->flags & MEM_Int)!=0 ); 61809 63047 sqlite3VdbeMemIntegerify(pIn2); 61810 63048 u.aw.p2 = (int)pIn2->u.i; 61811 63049 /* The u.aw.p2 value always comes from a prior OP_CreateTable opcode and 61812 63050 ** that opcode will always set the u.aw.p2 value to 2 or more or else fail. 61813 63051 ** If there were a failure, the prepared statement would have halted 61814 63052 ** before reaching this instruction. */ 61815 63053 if( NEVER(u.aw.p2<2) ) { ................................................................................ 61824 63062 }else if( pOp->p4type==P4_INT32 ){ 61825 63063 u.aw.nField = pOp->p4.i; 61826 63064 } 61827 63065 assert( pOp->p1>=0 ); 61828 63066 u.aw.pCur = allocateCursor(p, pOp->p1, u.aw.nField, u.aw.iDb, 1); 61829 63067 if( u.aw.pCur==0 ) goto no_mem; 61830 63068 u.aw.pCur->nullRow = 1; 63069 + u.aw.pCur->isOrdered = 1; 61831 63070 rc = sqlite3BtreeCursor(u.aw.pX, u.aw.p2, u.aw.wrFlag, u.aw.pKeyInfo, u.aw.pCur->pCursor); 61832 63071 u.aw.pCur->pKeyInfo = u.aw.pKeyInfo; 61833 63072 61834 63073 /* Since it performs no memory allocation or IO, the only values that 61835 63074 ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK. 61836 63075 ** SQLITE_EMPTY is only returned when attempting to open the table 61837 63076 ** rooted at page 1 of a zero-byte database. */ ................................................................................ 61876 63115 ** indices in joins. 61877 63116 */ 61878 63117 case OP_OpenAutoindex: 61879 63118 case OP_OpenEphemeral: { 61880 63119 #if 0 /* local variables moved into u.ax */ 61881 63120 VdbeCursor *pCx; 61882 63121 #endif /* local variables moved into u.ax */ 61883 - static const int openFlags = 63122 + static const int vfsFlags = 61884 63123 SQLITE_OPEN_READWRITE | 61885 63124 SQLITE_OPEN_CREATE | 61886 63125 SQLITE_OPEN_EXCLUSIVE | 61887 63126 SQLITE_OPEN_DELETEONCLOSE | 61888 63127 SQLITE_OPEN_TRANSIENT_DB; 61889 63128 61890 63129 assert( pOp->p1>=0 ); 61891 63130 u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); 61892 63131 if( u.ax.pCx==0 ) goto no_mem; 61893 63132 u.ax.pCx->nullRow = 1; 61894 - rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags, 61895 - &u.ax.pCx->pBt); 63133 + rc = sqlite3BtreeOpen(0, db, &u.ax.pCx->pBt, 63134 + BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); 61896 63135 if( rc==SQLITE_OK ){ 61897 63136 rc = sqlite3BtreeBeginTrans(u.ax.pCx->pBt, 1); 61898 63137 } 61899 63138 if( rc==SQLITE_OK ){ 61900 63139 /* If a transient index is required, create it by calling 61901 - ** sqlite3BtreeCreateTable() with the BTREE_ZERODATA flag before 63140 + ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before 61902 63141 ** opening it. If a transient table is required, just use the 61903 - ** automatically created table with root-page 1 (an INTKEY table). 63142 + ** automatically created table with root-page 1 (an BLOB_INTKEY table). 61904 63143 */ 61905 63144 if( pOp->p4.pKeyInfo ){ 61906 63145 int pgno; 61907 63146 assert( pOp->p4type==P4_KEYINFO ); 61908 - rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_ZERODATA); 63147 + rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY); 61909 63148 if( rc==SQLITE_OK ){ 61910 63149 assert( pgno==MASTER_ROOT+1 ); 61911 63150 rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1, 61912 63151 (KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor); 61913 63152 u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo; 61914 63153 u.ax.pCx->pKeyInfo->enc = ENC(p->db); 61915 63154 } 61916 63155 u.ax.pCx->isTable = 0; 61917 63156 }else{ 61918 63157 rc = sqlite3BtreeCursor(u.ax.pCx->pBt, MASTER_ROOT, 1, 0, u.ax.pCx->pCursor); 61919 63158 u.ax.pCx->isTable = 1; 61920 63159 } 61921 63160 } 63161 + u.ax.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); 61922 63162 u.ax.pCx->isIndex = !u.ax.pCx->isTable; 61923 63163 break; 61924 63164 } 61925 63165 61926 63166 /* Opcode: OpenPseudo P1 P2 P3 * * 61927 63167 ** 61928 63168 ** Open a new cursor that points to a fake table that contains a single ................................................................................ 62034 63274 assert( pOp->p2!=0 ); 62035 63275 u.az.pC = p->apCsr[pOp->p1]; 62036 63276 assert( u.az.pC!=0 ); 62037 63277 assert( u.az.pC->pseudoTableReg==0 ); 62038 63278 assert( OP_SeekLe == OP_SeekLt+1 ); 62039 63279 assert( OP_SeekGe == OP_SeekLt+2 ); 62040 63280 assert( OP_SeekGt == OP_SeekLt+3 ); 63281 + assert( u.az.pC->isOrdered ); 62041 63282 if( u.az.pC->pCursor!=0 ){ 62042 63283 u.az.oc = pOp->opcode; 62043 63284 u.az.pC->nullRow = 0; 62044 63285 if( u.az.pC->isTable ){ 62045 63286 /* The input value in P3 might be of any type: integer, real, string, 62046 63287 ** blob, or NULL. But it needs to be an integer before we can do 62047 63288 ** the seek, so covert it. */ ................................................................................ 62116 63357 u.az.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.az.oc - OP_SeekLt))); 62117 63358 assert( u.az.oc!=OP_SeekGt || u.az.r.flags==UNPACKED_INCRKEY ); 62118 63359 assert( u.az.oc!=OP_SeekLe || u.az.r.flags==UNPACKED_INCRKEY ); 62119 63360 assert( u.az.oc!=OP_SeekGe || u.az.r.flags==0 ); 62120 63361 assert( u.az.oc!=OP_SeekLt || u.az.r.flags==0 ); 62121 63362 62122 63363 u.az.r.aMem = &aMem[pOp->p3]; 63364 +#ifdef SQLITE_DEBUG 63365 + { int i; for(i=0; i<u.az.r.nField; i++) assert( memIsValid(&u.az.r.aMem[i]) ); } 63366 +#endif 62123 63367 ExpandBlob(u.az.r.aMem); 62124 63368 rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, &u.az.r, 0, 0, &u.az.res); 62125 63369 if( rc!=SQLITE_OK ){ 62126 63370 goto abort_due_to_error; 62127 63371 } 62128 63372 u.az.pC->rowidIsValid = 0; 62129 63373 } ................................................................................ 62244 63488 if( ALWAYS(u.bb.pC->pCursor!=0) ){ 62245 63489 62246 63490 assert( u.bb.pC->isTable==0 ); 62247 63491 if( pOp->p4.i>0 ){ 62248 63492 u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo; 62249 63493 u.bb.r.nField = (u16)pOp->p4.i; 62250 63494 u.bb.r.aMem = pIn3; 63495 +#ifdef SQLITE_DEBUG 63496 + { int i; for(i=0; i<u.bb.r.nField; i++) assert( memIsValid(&u.bb.r.aMem[i]) ); } 63497 +#endif 62251 63498 u.bb.r.flags = UNPACKED_PREFIX_MATCH; 62252 63499 u.bb.pIdxKey = &u.bb.r; 62253 63500 }else{ 62254 63501 assert( pIn3->flags & MEM_Blob ); 62255 - ExpandBlob(pIn3); 63502 + assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */ 62256 63503 u.bb.pIdxKey = sqlite3VdbeRecordUnpack(u.bb.pC->pKeyInfo, pIn3->n, pIn3->z, 62257 63504 u.bb.aTempRec, sizeof(u.bb.aTempRec)); 62258 63505 if( u.bb.pIdxKey==0 ){ 62259 63506 goto no_mem; 62260 63507 } 62261 63508 u.bb.pIdxKey->flags |= UNPACKED_PREFIX_MATCH; 62262 63509 } ................................................................................ 62343 63590 62344 63591 if( u.bc.pCrsr!=0 ){ 62345 63592 /* Populate the index search key. */ 62346 63593 u.bc.r.pKeyInfo = u.bc.pCx->pKeyInfo; 62347 63594 u.bc.r.nField = u.bc.nField + 1; 62348 63595 u.bc.r.flags = UNPACKED_PREFIX_SEARCH; 62349 63596 u.bc.r.aMem = u.bc.aMx; 63597 +#ifdef SQLITE_DEBUG 63598 + { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); } 63599 +#endif 62350 63600 62351 63601 /* Extract the value of u.bc.R from register P3. */ 62352 63602 sqlite3VdbeMemIntegerify(pIn3); 62353 63603 u.bc.R = pIn3->u.i; 62354 63604 62355 63605 /* Search the B-Tree index. If no conflicting record is found, jump 62356 63606 ** to P2. Otherwise, copy the rowid of the conflicting record to ................................................................................ 62365 63615 break; 62366 63616 } 62367 63617 62368 63618 /* Opcode: NotExists P1 P2 P3 * * 62369 63619 ** 62370 63620 ** Use the content of register P3 as a integer key. If a record 62371 63621 ** with that key does not exist in table of P1, then jump to P2. 62372 -** If the record does exist, then fall thru. The cursor is left 63622 +** If the record does exist, then fall through. The cursor is left 62373 63623 ** pointing to the record if it exists. 62374 63624 ** 62375 63625 ** The difference between this operation and NotFound is that this 62376 63626 ** operation assumes the key is an integer and that P1 is a table whereas 62377 63627 ** NotFound assumes key is a blob constructed from MakeRecord and 62378 63628 ** P1 is an index. 62379 63629 ** ................................................................................ 62523 63773 /* Assert that P3 is a valid memory cell. */ 62524 63774 assert( pOp->p3<=u.be.pFrame->nMem ); 62525 63775 u.be.pMem = &u.be.pFrame->aMem[pOp->p3]; 62526 63776 }else{ 62527 63777 /* Assert that P3 is a valid memory cell. */ 62528 63778 assert( pOp->p3<=p->nMem ); 62529 63779 u.be.pMem = &aMem[pOp->p3]; 63780 + memAboutToChange(p, u.be.pMem); 62530 63781 } 63782 + assert( memIsValid(u.be.pMem) ); 62531 63783 62532 63784 REGISTER_TRACE(pOp->p3, u.be.pMem); 62533 63785 sqlite3VdbeMemIntegerify(u.be.pMem); 62534 63786 assert( (u.be.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ 62535 63787 if( u.be.pMem->u.i==MAX_ROWID || u.be.pC->useRandomRowid ){ 62536 63788 rc = SQLITE_FULL; /* IMP: R-12275-61338 */ 62537 63789 goto abort_due_to_error; ................................................................................ 62542 63794 u.be.pMem->u.i = u.be.v; 62543 63795 } 62544 63796 #endif 62545 63797 62546 63798 sqlite3BtreeSetCachedRowid(u.be.pC->pCursor, u.be.v<MAX_ROWID ? u.be.v+1 : 0); 62547 63799 } 62548 63800 if( u.be.pC->useRandomRowid ){ 62549 - /* IMPLEMENTATION-OF: R-48598-02938 If the largest ROWID is equal to the 63801 + /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the 62550 63802 ** largest possible integer (9223372036854775807) then the database 62551 - ** engine starts picking candidate ROWIDs at random until it finds one 62552 - ** that is not previously used. 62553 - */ 63803 + ** engine starts picking positive candidate ROWIDs at random until 63804 + ** it finds one that is not previously used. */ 62554 63805 assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is 62555 63806 ** an AUTOINCREMENT table. */ 63807 + /* on the first attempt, simply do one more than previous */ 62556 63808 u.be.v = db->lastRowid; 63809 + u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ 63810 + u.be.v++; /* ensure non-zero */ 62557 63811 u.be.cnt = 0; 62558 - do{ 62559 - if( u.be.cnt==0 && (u.be.v&0xffffff)==u.be.v ){ 62560 - u.be.v++; 63812 + while( ((rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v, 63813 + 0, &u.be.res))==SQLITE_OK) 63814 + && (u.be.res==0) 63815 + && (++u.be.cnt<100)){ 63816 + /* collision - try another random rowid */ 63817 + sqlite3_randomness(sizeof(u.be.v), &u.be.v); 63818 + if( u.be.cnt<5 ){ 63819 + /* try "small" random rowids for the initial attempts */ 63820 + u.be.v &= 0xffffff; 62561 63821 }else{ 62562 - sqlite3_randomness(sizeof(u.be.v), &u.be.v); 62563 - if( u.be.cnt<5 ) u.be.v &= 0xffffff; 63822 + u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ 62564 63823 } 62565 - rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v, 0, &u.be.res); 62566 - u.be.cnt++; 62567 - }while( u.be.cnt<100 && rc==SQLITE_OK && u.be.res==0 ); 63824 + u.be.v++; /* ensure non-zero */ 63825 + } 62568 63826 if( rc==SQLITE_OK && u.be.res==0 ){ 62569 63827 rc = SQLITE_FULL; /* IMP: R-38219-53002 */ 62570 63828 goto abort_due_to_error; 62571 63829 } 63830 + assert( u.be.v>0 ); /* EV: R-40812-03570 */ 62572 63831 } 62573 63832 u.be.pC->rowidIsValid = 0; 62574 63833 u.be.pC->deferredMoveto = 0; 62575 63834 u.be.pC->cacheStatus = CACHE_STALE; 62576 63835 } 62577 63836 pOut->u.i = u.be.v; 62578 63837 break; ................................................................................ 62634 63893 const char *zDb; /* database name - used by the update hook */ 62635 63894 const char *zTbl; /* Table name - used by the opdate hook */ 62636 63895 int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ 62637 63896 #endif /* local variables moved into u.bf */ 62638 63897 62639 63898 u.bf.pData = &aMem[pOp->p2]; 62640 63899 assert( pOp->p1>=0 && pOp->p1<p->nCursor ); 63900 + assert( memIsValid(u.bf.pData) ); 62641 63901 u.bf.pC = p->apCsr[pOp->p1]; 62642 63902 assert( u.bf.pC!=0 ); 62643 63903 assert( u.bf.pC->pCursor!=0 ); 62644 63904 assert( u.bf.pC->pseudoTableReg==0 ); 62645 63905 assert( u.bf.pC->isTable ); 62646 63906 REGISTER_TRACE(pOp->p2, u.bf.pData); 62647 63907 62648 63908 if( pOp->opcode==OP_Insert ){ 62649 63909 u.bf.pKey = &aMem[pOp->p3]; 62650 63910 assert( u.bf.pKey->flags & MEM_Int ); 63911 + assert( memIsValid(u.bf.pKey) ); 62651 63912 REGISTER_TRACE(pOp->p3, u.bf.pKey); 62652 63913 u.bf.iKey = u.bf.pKey->u.i; 62653 63914 }else{ 62654 63915 assert( pOp->opcode==OP_InsertInt ); 62655 63916 u.bf.iKey = pOp->p3; 62656 63917 } 62657 63918 ................................................................................ 62795 64056 VdbeCursor *pC; 62796 64057 BtCursor *pCrsr; 62797 64058 u32 n; 62798 64059 i64 n64; 62799 64060 #endif /* local variables moved into u.bh */ 62800 64061 62801 64062 pOut = &aMem[pOp->p2]; 64063 + memAboutToChange(p, pOut); 62802 64064 62803 64065 /* Note that RowKey and RowData are really exactly the same instruction */ 62804 64066 assert( pOp->p1>=0 && pOp->p1<p->nCursor ); 62805 64067 u.bh.pC = p->apCsr[pOp->p1]; 62806 64068 assert( u.bh.pC->isTable || pOp->opcode==OP_RowKey ); 62807 64069 assert( u.bh.pC->isIndex || pOp->opcode==OP_RowData ); 62808 64070 assert( u.bh.pC!=0 ); ................................................................................ 63137 64399 assert( u.bo.pC!=0 ); 63138 64400 u.bo.pCrsr = u.bo.pC->pCursor; 63139 64401 if( ALWAYS(u.bo.pCrsr!=0) ){ 63140 64402 u.bo.r.pKeyInfo = u.bo.pC->pKeyInfo; 63141 64403 u.bo.r.nField = (u16)pOp->p3; 63142 64404 u.bo.r.flags = 0; 63143 64405 u.bo.r.aMem = &aMem[pOp->p2]; 64406 +#ifdef SQLITE_DEBUG 64407 + { int i; for(i=0; i<u.bo.r.nField; i++) assert( memIsValid(&u.bo.r.aMem[i]) ); } 64408 +#endif 63144 64409 rc = sqlite3BtreeMovetoUnpacked(u.bo.pCrsr, &u.bo.r, 0, 0, &u.bo.res); 63145 64410 if( rc==SQLITE_OK && u.bo.res==0 ){ 63146 64411 rc = sqlite3BtreeDelete(u.bo.pCrsr); 63147 64412 } 63148 64413 assert( u.bo.pC->deferredMoveto==0 ); 63149 64414 u.bo.pC->cacheStatus = CACHE_STALE; 63150 64415 } ................................................................................ 63198 64463 ** then jump to P2. Otherwise fall through to the next instruction. 63199 64464 ** 63200 64465 ** If P5 is non-zero then the key value is increased by an epsilon 63201 64466 ** prior to the comparison. This make the opcode work like IdxGT except 63202 64467 ** that if the key from register P3 is a prefix of the key in the cursor, 63203 64468 ** the result is false whereas it would be true with IdxGT. 63204 64469 */ 63205 -/* Opcode: IdxLT P1 P2 P3 * P5 64470 +/* Opcode: IdxLT P1 P2 P3 P4 P5 63206 64471 ** 63207 64472 ** The P4 register values beginning with P3 form an unpacked index 63208 64473 ** key that omits the ROWID. Compare this key value against the index 63209 64474 ** that P1 is currently pointing to, ignoring the ROWID on the P1 index. 63210 64475 ** 63211 64476 ** If the P1 index entry is less than the key value then jump to P2. 63212 64477 ** Otherwise fall through to the next instruction. ................................................................................ 63221 64486 int res; 63222 64487 UnpackedRecord r; 63223 64488 #endif /* local variables moved into u.bq */ 63224 64489 63225 64490 assert( pOp->p1>=0 && pOp->p1<p->nCursor ); 63226 64491 u.bq.pC = p->apCsr[pOp->p1]; 63227 64492 assert( u.bq.pC!=0 ); 64493 + assert( u.bq.pC->isOrdered ); 63228 64494 if( ALWAYS(u.bq.pC->pCursor!=0) ){ 63229 64495 assert( u.bq.pC->deferredMoveto==0 ); 63230 64496 assert( pOp->p5==0 || pOp->p5==1 ); 63231 64497 assert( pOp->p4type==P4_INT32 ); 63232 64498 u.bq.r.pKeyInfo = u.bq.pC->pKeyInfo; 63233 64499 u.bq.r.nField = (u16)pOp->p4.i; 63234 64500 if( pOp->p5 ){ 63235 64501 u.bq.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID; 63236 64502 }else{ 63237 64503 u.bq.r.flags = UNPACKED_IGNORE_ROWID; 63238 64504 } 63239 64505 u.bq.r.aMem = &aMem[pOp->p3]; 64506 +#ifdef SQLITE_DEBUG 64507 + { int i; for(i=0; i<u.bq.r.nField; i++) assert( memIsValid(&u.bq.r.aMem[i]) ); } 64508 +#endif 63240 64509 rc = sqlite3VdbeIdxKeyCompare(u.bq.pC, &u.bq.r, &u.bq.res); 63241 64510 if( pOp->opcode==OP_IdxLT ){ 63242 64511 u.bq.res = -u.bq.res; 63243 64512 }else{ 63244 64513 assert( pOp->opcode==OP_IdxGE ); 63245 64514 u.bq.res++; 63246 64515 } ................................................................................ 63336 64605 assert( (p->btreeMask & (1<<pOp->p2))!=0 ); 63337 64606 rc = sqlite3BtreeClearTable( 63338 64607 db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bs.nChange : 0) 63339 64608 ); 63340 64609 if( pOp->p3 ){ 63341 64610 p->nChange += u.bs.nChange; 63342 64611 if( pOp->p3>0 ){ 64612 + assert( memIsValid(&aMem[pOp->p3]) ); 64613 + memAboutToChange(p, &aMem[pOp->p3]); 63343 64614 aMem[pOp->p3].u.i += u.bs.nChange; 63344 64615 } 63345 64616 } 63346 64617 break; 63347 64618 } 63348 64619 63349 64620 /* Opcode: CreateTable P1 P2 * * * ................................................................................ 63379 64650 u.bt.pgno = 0; 63380 64651 assert( pOp->p1>=0 && pOp->p1<db->nDb ); 63381 64652 assert( (p->btreeMask & (1<<pOp->p1))!=0 ); 63382 64653 u.bt.pDb = &db->aDb[pOp->p1]; 63383 64654 assert( u.bt.pDb->pBt!=0 ); 63384 64655 if( pOp->opcode==OP_CreateTable ){ 63385 64656 /* u.bt.flags = BTREE_INTKEY; */ 63386 - u.bt.flags = BTREE_LEAFDATA|BTREE_INTKEY; 64657 + u.bt.flags = BTREE_INTKEY; 63387 64658 }else{ 63388 - u.bt.flags = BTREE_ZERODATA; 64659 + u.bt.flags = BTREE_BLOBKEY; 63389 64660 } 63390 64661 rc = sqlite3BtreeCreateTable(u.bt.pDb->pBt, &u.bt.pgno, u.bt.flags); 63391 64662 pOut->u.i = u.bt.pgno; 63392 64663 break; 63393 64664 } 63394 64665 63395 64666 /* Opcode: ParseSchema P1 P2 * P4 * ................................................................................ 63710 64981 VdbeFrame *pFrame; /* New vdbe frame to execute in */ 63711 64982 SubProgram *pProgram; /* Sub-program to execute */ 63712 64983 void *t; /* Token identifying trigger */ 63713 64984 #endif /* local variables moved into u.by */ 63714 64985 63715 64986 u.by.pProgram = pOp->p4.pProgram; 63716 64987 u.by.pRt = &aMem[pOp->p3]; 64988 + assert( memIsValid(u.by.pRt) ); 63717 64989 assert( u.by.pProgram->nOp>0 ); 63718 64990 63719 64991 /* If the p5 flag is clear, then recursive invocation of triggers is 63720 64992 ** disabled for backwards compatibility (p5 is set if this sub-program 63721 64993 ** is really a trigger, not a foreign key action, and the flag set 63722 64994 ** and cleared by the "PRAGMA recursive_triggers" command is clear). 63723 64995 ** ................................................................................ 63883 65155 #endif /* local variables moved into u.ca */ 63884 65156 if( p->pFrame ){ 63885 65157 for(u.ca.pFrame=p->pFrame; u.ca.pFrame->pParent; u.ca.pFrame=u.ca.pFrame->pParent); 63886 65158 u.ca.pIn1 = &u.ca.pFrame->aMem[pOp->p1]; 63887 65159 }else{ 63888 65160 u.ca.pIn1 = &aMem[pOp->p1]; 63889 65161 } 65162 + assert( memIsValid(u.ca.pIn1) ); 63890 65163 sqlite3VdbeMemIntegerify(u.ca.pIn1); 63891 65164 pIn2 = &aMem[pOp->p2]; 63892 65165 sqlite3VdbeMemIntegerify(pIn2); 63893 65166 if( u.ca.pIn1->u.i<pIn2->u.i){ 63894 65167 u.ca.pIn1->u.i = pIn2->u.i; 63895 65168 } 63896 65169 break; ................................................................................ 63969 65242 63970 65243 u.cb.n = pOp->p5; 63971 65244 assert( u.cb.n>=0 ); 63972 65245 u.cb.pRec = &aMem[pOp->p2]; 63973 65246 u.cb.apVal = p->apArg; 63974 65247 assert( u.cb.apVal || u.cb.n==0 ); 63975 65248 for(u.cb.i=0; u.cb.i<u.cb.n; u.cb.i++, u.cb.pRec++){ 65249 + assert( memIsValid(u.cb.pRec) ); 63976 65250 u.cb.apVal[u.cb.i] = u.cb.pRec; 65251 + memAboutToChange(p, u.cb.pRec); 63977 65252 sqlite3VdbeMemStoreType(u.cb.pRec); 63978 65253 } 63979 65254 u.cb.ctx.pFunc = pOp->p4.pFunc; 63980 65255 assert( pOp->p3>0 && pOp->p3<=p->nMem ); 63981 65256 u.cb.ctx.pMem = u.cb.pMem = &aMem[pOp->p3]; 63982 65257 u.cb.pMem->n++; 63983 65258 u.cb.ctx.s.flags = MEM_Null; ................................................................................ 63989 65264 u.cb.ctx.pColl = 0; 63990 65265 if( u.cb.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ 63991 65266 assert( pOp>p->aOp ); 63992 65267 assert( pOp[-1].p4type==P4_COLLSEQ ); 63993 65268 assert( pOp[-1].opcode==OP_CollSeq ); 63994 65269 u.cb.ctx.pColl = pOp[-1].p4.pColl; 63995 65270 } 63996 - (u.cb.ctx.pFunc->xStep)(&u.cb.ctx, u.cb.n, u.cb.apVal); 65271 + (u.cb.ctx.pFunc->xStep)(&u.cb.ctx, u.cb.n, u.cb.apVal); /* IMP: R-24505-23230 */ 63997 65272 if( u.cb.ctx.isError ){ 63998 65273 sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cb.ctx.s)); 63999 65274 rc = u.cb.ctx.isError; 64000 65275 } 64001 65276 sqlite3VdbeMemRelease(&u.cb.ctx.s); 64002 65277 break; 64003 65278 } ................................................................................ 64376 65651 int i; 64377 65652 Mem **apArg; 64378 65653 #endif /* local variables moved into u.ch */ 64379 65654 64380 65655 u.ch.pQuery = &aMem[pOp->p3]; 64381 65656 u.ch.pArgc = &u.ch.pQuery[1]; 64382 65657 u.ch.pCur = p->apCsr[pOp->p1]; 65658 + assert( memIsValid(u.ch.pQuery) ); 64383 65659 REGISTER_TRACE(pOp->p3, u.ch.pQuery); 64384 65660 assert( u.ch.pCur->pVtabCursor ); 64385 65661 u.ch.pVtabCursor = u.ch.pCur->pVtabCursor; 64386 65662 u.ch.pVtab = u.ch.pVtabCursor->pVtab; 64387 65663 u.ch.pModule = u.ch.pVtab->pModule; 64388 65664 64389 65665 /* Grab the index number and argc parameters */ ................................................................................ 64433 65709 sqlite3_context sContext; 64434 65710 #endif /* local variables moved into u.ci */ 64435 65711 64436 65712 VdbeCursor *pCur = p->apCsr[pOp->p1]; 64437 65713 assert( pCur->pVtabCursor ); 64438 65714 assert( pOp->p3>0 && pOp->p3<=p->nMem ); 64439 65715 u.ci.pDest = &aMem[pOp->p3]; 65716 + memAboutToChange(p, u.ci.pDest); 64440 65717 if( pCur->nullRow ){ 64441 65718 sqlite3VdbeMemSetNull(u.ci.pDest); 64442 65719 break; 64443 65720 } 64444 65721 u.ci.pVtab = pCur->pVtabCursor->pVtab; 64445 65722 u.ci.pModule = u.ci.pVtab->pModule; 64446 65723 assert( u.ci.pModule->xColumn ); ................................................................................ 64535 65812 sqlite3_vtab *pVtab; 64536 65813 Mem *pName; 64537 65814 #endif /* local variables moved into u.ck */ 64538 65815 64539 65816 u.ck.pVtab = pOp->p4.pVtab->pVtab; 64540 65817 u.ck.pName = &aMem[pOp->p1]; 64541 65818 assert( u.ck.pVtab->pModule->xRename ); 65819 + assert( memIsValid(u.ck.pName) ); 64542 65820 REGISTER_TRACE(pOp->p1, u.ck.pName); 64543 65821 assert( u.ck.pName->flags & MEM_Str ); 64544 65822 rc = u.ck.pVtab->pModule->xRename(u.ck.pVtab, u.ck.pName->z); 64545 65823 importVtabErrMsg(p, u.ck.pVtab); 65824 + p->expired = 0; 64546 65825 64547 65826 break; 64548 65827 } 64549 65828 #endif 64550 65829 64551 65830 #ifndef SQLITE_OMIT_VIRTUALTABLE 64552 65831 /* Opcode: VUpdate P1 P2 P3 P4 * ................................................................................ 64587 65866 u.cl.pModule = (sqlite3_module *)u.cl.pVtab->pModule; 64588 65867 u.cl.nArg = pOp->p2; 64589 65868 assert( pOp->p4type==P4_VTAB ); 64590 65869 if( ALWAYS(u.cl.pModule->xUpdate) ){ 64591 65870 u.cl.apArg = p->apArg; 64592 65871 u.cl.pX = &aMem[pOp->p3]; 64593 65872 for(u.cl.i=0; u.cl.i<u.cl.nArg; u.cl.i++){ 65873 + assert( memIsValid(u.cl.pX) ); 65874 + memAboutToChange(p, u.cl.pX); 64594 65875 sqlite3VdbeMemStoreType(u.cl.pX); 64595 65876 u.cl.apArg[u.cl.i] = u.cl.pX; 64596 65877 u.cl.pX++; 64597 65878 } 64598 65879 rc = u.cl.pModule->xUpdate(u.cl.pVtab, u.cl.nArg, u.cl.apArg, &u.cl.rowid); 64599 65880 importVtabErrMsg(p, u.cl.pVtab); 64600 65881 if( rc==SQLITE_OK && pOp->p1 ){ ................................................................................ 65641 66922 ** an in-memory journal 65642 66923 */ 65643 66924 SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *pJfd){ 65644 66925 return pJfd->pMethods==&MemJournalMethods; 65645 66926 } 65646 66927 65647 66928 /* 65648 -** Return the number of bytes required to store a MemJournal that uses vfs 65649 -** pVfs to create the underlying on-disk files. 66929 +** Return the number of bytes required to store a MemJournal file descriptor. 65650 66930 */ 65651 66931 SQLITE_PRIVATE int sqlite3MemJournalSize(void){ 65652 66932 return sizeof(MemJournal); 65653 66933 } 65654 66934 65655 66935 /************** End of memjournal.c ******************************************/ 65656 66936 /************** Begin file walker.c ******************************************/ ................................................................................ 67545 68825 if( z[1]==0 ){ 67546 68826 /* Wildcard of the form "?". Assign the next variable number */ 67547 68827 assert( z[0]=='?' ); 67548 68828 pExpr->iColumn = (ynVar)(++pParse->nVar); 67549 68829 }else if( z[0]=='?' ){ 67550 68830 /* Wildcard of the form "?nnn". Convert "nnn" to an integer and 67551 68831 ** use it as the variable number */ 67552 - int i = atoi((char*)&z[1]); 68832 + i64 i; 68833 + int bOk = 0==sqlite3Atoi64(&z[1], &i, sqlite3Strlen30(&z[1]), SQLITE_UTF8); 67553 68834 pExpr->iColumn = (ynVar)i; 67554 68835 testcase( i==0 ); 67555 68836 testcase( i==1 ); 67556 68837 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); 67557 68838 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); 67558 - if( i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ 68839 + if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ 67559 68840 sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", 67560 68841 db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); 67561 68842 } 67562 68843 if( i>pParse->nVar ){ 67563 - pParse->nVar = i; 68844 + pParse->nVar = (int)i; 67564 68845 } 67565 68846 }else{ 67566 68847 /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable 67567 68848 ** number as the prior appearance of the same name, or if the name 67568 68849 ** has never appeared before, reuse the same variable number 67569 68850 */ 67570 68851 int i; ................................................................................ 68525 69806 pX->iTable = iTab; 68526 69807 } 68527 69808 return eType; 68528 69809 } 68529 69810 #endif 68530 69811 68531 69812 /* 68532 -** Generate code for scalar subqueries used as an expression 68533 -** and IN operators. Examples: 69813 +** Generate code for scalar subqueries used as a subquery expression, EXISTS, 69814 +** or IN operators. Examples: 68534 69815 ** 68535 69816 ** (SELECT a FROM b) -- subquery 68536 69817 ** EXISTS (SELECT a FROM b) -- EXISTS subquery 68537 69818 ** x IN (4,5,11) -- IN operator with list on right-hand side 68538 69819 ** x IN (SELECT a FROM b) -- IN operator with subquery on the right 68539 69820 ** 68540 69821 ** The pExpr parameter describes the expression that contains the IN ................................................................................ 68589 69870 sqlite3VdbeAddOp1(v, OP_If, mem); 68590 69871 testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem); 68591 69872 assert( testAddr>0 || pParse->db->mallocFailed ); 68592 69873 } 68593 69874 68594 69875 switch( pExpr->op ){ 68595 69876 case TK_IN: { 68596 - char affinity; 68597 - KeyInfo keyInfo; 68598 - int addr; /* Address of OP_OpenEphemeral instruction */ 68599 - Expr *pLeft = pExpr->pLeft; 69877 + char affinity; /* Affinity of the LHS of the IN */ 69878 + KeyInfo keyInfo; /* Keyinfo for the generated table */ 69879 + int addr; /* Address of OP_OpenEphemeral instruction */ 69880 + Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ 68600 69881 68601 69882 if( rMayHaveNull ){ 68602 69883 sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull); 68603 69884 } 68604 69885 68605 69886 affinity = sqlite3ExprAffinity(pLeft); 68606 69887 ................................................................................ 68615 69896 ** SELECT... statement are columns, then numeric affinity is used 68616 69897 ** if either column has NUMERIC or INTEGER affinity. If neither 68617 69898 ** 'x' nor the SELECT... statement are columns, then numeric affinity 68618 69899 ** is used. 68619 69900 */ 68620 69901 pExpr->iTable = pParse->nTab++; 68621 69902 addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); 69903 + if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); 68622 69904 memset(&keyInfo, 0, sizeof(keyInfo)); 68623 69905 keyInfo.nField = 1; 68624 69906 68625 69907 if( ExprHasProperty(pExpr, EP_xIsSelect) ){ 68626 69908 /* Case 1: expr IN (SELECT ...) 68627 69909 ** 68628 69910 ** Generate code to write the results of the select into the temporary ................................................................................ 68907 70189 ** z[n] character is guaranteed to be something that does not look 68908 70190 ** like the continuation of the number. 68909 70191 */ 68910 70192 static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ 68911 70193 if( ALWAYS(z!=0) ){ 68912 70194 double value; 68913 70195 char *zV; 68914 - sqlite3AtoF(z, &value); 70196 + sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); 68915 70197 assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */ 68916 70198 if( negateFlag ) value = -value; 68917 70199 zV = dup8bytes(v, (char*)&value); 68918 70200 sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); 68919 70201 } 68920 70202 } 68921 70203 #endif 68922 70204 68923 70205 68924 70206 /* 68925 70207 ** Generate an instruction that will put the integer describe by 68926 70208 ** text z[0..n-1] into register iMem. 68927 70209 ** 68928 -** The z[] string will probably not be zero-terminated. But the 68929 -** z[n] character is guaranteed to be something that does not look 68930 -** like the continuation of the number. 70210 +** Expr.u.zToken is always UTF8 and zero-terminated. 68931 70211 */ 68932 70212 static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ 68933 70213 Vdbe *v = pParse->pVdbe; 68934 70214 if( pExpr->flags & EP_IntValue ){ 68935 70215 int i = pExpr->u.iValue; 68936 70216 if( negFlag ) i = -i; 68937 70217 sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); 68938 70218 }else{ 70219 + int c; 70220 + i64 value; 68939 70221 const char *z = pExpr->u.zToken; 68940 70222 assert( z!=0 ); 68941 - if( sqlite3FitsIn64Bits(z, negFlag) ){ 68942 - i64 value; 70223 + c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); 70224 + if( c==0 || (c==2 && negFlag) ){ 68943 70225 char *zV; 68944 - sqlite3Atoi64(z, &value); 68945 - if( negFlag ) value = -value; 70226 + if( negFlag ){ value = -value; } 68946 70227 zV = dup8bytes(v, (char*)&value); 68947 70228 sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); 68948 70229 }else{ 68949 70230 #ifdef SQLITE_OMIT_FLOATING_POINT 68950 70231 sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); 68951 70232 #else 68952 70233 codeReal(v, z, negFlag, iMem); ................................................................................ 69223 70504 int r = p->iReg; 69224 70505 if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ 69225 70506 } 69226 70507 return 0; 69227 70508 } 69228 70509 #endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */ 69229 70510 69230 -/* 69231 -** If the last instruction coded is an ephemeral copy of any of 69232 -** the registers in the nReg registers beginning with iReg, then 69233 -** convert the last instruction from OP_SCopy to OP_Copy. 69234 -*/ 69235 -SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){ 69236 - VdbeOp *pOp; 69237 - Vdbe *v; 69238 - 69239 - assert( pParse->db->mallocFailed==0 ); 69240 - v = pParse->pVdbe; 69241 - assert( v!=0 ); 69242 - pOp = sqlite3VdbeGetOp(v, -1); 69243 - assert( pOp!=0 ); 69244 - if( pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){ 69245 - pOp->opcode = OP_Copy; 69246 - } 69247 -} 69248 - 69249 -/* 69250 -** Generate code to store the value of the iAlias-th alias in register 69251 -** target. The first time this is called, pExpr is evaluated to compute 69252 -** the value of the alias. The value is stored in an auxiliary register 69253 -** and the number of that register is returned. On subsequent calls, 69254 -** the register number is returned without generating any code. 69255 -** 69256 -** Note that in order for this to work, code must be generated in the 69257 -** same order that it is executed. 69258 -** 69259 -** Aliases are numbered starting with 1. So iAlias is in the range 69260 -** of 1 to pParse->nAlias inclusive. 69261 -** 69262 -** pParse->aAlias[iAlias-1] records the register number where the value 69263 -** of the iAlias-th alias is stored. If zero, that means that the 69264 -** alias has not yet been computed. 69265 -*/ 69266 -static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){ 69267 -#if 0 69268 - sqlite3 *db = pParse->db; 69269 - int iReg; 69270 - if( pParse->nAliasAlloc<pParse->nAlias ){ 69271 - pParse->aAlias = sqlite3DbReallocOrFree(db, pParse->aAlias, 69272 - sizeof(pParse->aAlias[0])*pParse->nAlias ); 69273 - testcase( db->mallocFailed && pParse->nAliasAlloc>0 ); 69274 - if( db->mallocFailed ) return 0; 69275 - memset(&pParse->aAlias[pParse->nAliasAlloc], 0, 69276 - (pParse->nAlias-pParse->nAliasAlloc)*sizeof(pParse->aAlias[0])); 69277 - pParse->nAliasAlloc = pParse->nAlias; 69278 - } 69279 - assert( iAlias>0 && iAlias<=pParse->nAlias ); 69280 - iReg = pParse->aAlias[iAlias-1]; 69281 - if( iReg==0 ){ 69282 - if( pParse->iCacheLevel>0 ){ 69283 - iReg = sqlite3ExprCodeTarget(pParse, pExpr, target); 69284 - }else{ 69285 - iReg = ++pParse->nMem; 69286 - sqlite3ExprCode(pParse, pExpr, iReg); 69287 - pParse->aAlias[iAlias-1] = iReg; 69288 - } 69289 - } 69290 - return iReg; 69291 -#else 69292 - UNUSED_PARAMETER(iAlias); 69293 - return sqlite3ExprCodeTarget(pParse, pExpr, target); 69294 -#endif 69295 -} 69296 - 69297 70511 /* 69298 70512 ** Generate code into the current Vdbe to evaluate the given 69299 70513 ** expression. Attempt to store the results in register "target". 69300 70514 ** Return the register where results are stored. 69301 70515 ** 69302 70516 ** With this routine, there is no guarantee that results will 69303 70517 ** be stored in target. The result might be stored in some other ................................................................................ 69398 70612 break; 69399 70613 } 69400 70614 case TK_REGISTER: { 69401 70615 inReg = pExpr->iTable; 69402 70616 break; 69403 70617 } 69404 70618 case TK_AS: { 69405 - inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft, target); 70619 + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); 69406 70620 break; 69407 70621 } 69408 70622 #ifndef SQLITE_OMIT_CAST 69409 70623 case TK_CAST: { 69410 70624 /* Expressions of the form: CAST(pLeft AS token) */ 69411 70625 int aff, to_op; 69412 70626 inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); ................................................................................ 69830 71044 testcase( pX->op==TK_REGISTER ); 69831 71045 cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1); 69832 71046 testcase( regFree1==0 ); 69833 71047 cacheX.op = TK_REGISTER; 69834 71048 opCompare.op = TK_EQ; 69835 71049 opCompare.pLeft = &cacheX; 69836 71050 pTest = &opCompare; 71051 + /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: 71052 + ** The value in regFree1 might get SCopy-ed into the file result. 71053 + ** So make sure that the regFree1 register is not reused for other 71054 + ** purposes and possibly overwritten. */ 71055 + regFree1 = 0; 69837 71056 } 69838 71057 for(i=0; i<nExpr; i=i+2){ 69839 71058 sqlite3ExprCachePush(pParse); 69840 71059 if( pX ){ 69841 71060 assert( pTest!=0 ); 69842 71061 opCompare.pRight = aListelem[i].pExpr; 69843 71062 }else{ ................................................................................ 69923 71142 ** results in register target. The results are guaranteed to appear 69924 71143 ** in register target. 69925 71144 */ 69926 71145 SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ 69927 71146 int inReg; 69928 71147 69929 71148 assert( target>0 && target<=pParse->nMem ); 69930 - inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); 69931 - assert( pParse->pVdbe || pParse->db->mallocFailed ); 69932 - if( inReg!=target && pParse->pVdbe ){ 69933 - sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); 71149 + if( pExpr && pExpr->op==TK_REGISTER ){ 71150 + sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target); 71151 + }else{ 71152 + inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); 71153 + assert( pParse->pVdbe || pParse->db->mallocFailed ); 71154 + if( inReg!=target && pParse->pVdbe ){ 71155 + sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); 71156 + } 69934 71157 } 69935 71158 return target; 69936 71159 } 69937 71160 69938 71161 /* 69939 71162 ** Generate code that evalutes the given expression and puts the result 69940 71163 ** in register target. ................................................................................ 70099 71322 int target, /* Where to write results */ 70100 71323 int doHardCopy /* Make a hard copy of every element */ 70101 71324 ){ 70102 71325 struct ExprList_item *pItem; 70103 71326 int i, n; 70104 71327 assert( pList!=0 ); 70105 71328 assert( target>0 ); 71329 + assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ 70106 71330 n = pList->nExpr; 70107 71331 for(pItem=pList->a, i=0; i<n; i++, pItem++){ 70108 - if( pItem->iAlias ){ 70109 - int iReg = codeAlias(pParse, pItem->iAlias, pItem->pExpr, target+i); 70110 - Vdbe *v = sqlite3GetVdbe(pParse); 70111 - if( iReg!=target+i ){ 70112 - sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i); 70113 - } 70114 - }else{ 70115 - sqlite3ExprCode(pParse, pItem->pExpr, target+i); 70116 - } 70117 - if( doHardCopy && !pParse->db->mallocFailed ){ 70118 - sqlite3ExprHardCopy(pParse, target, n); 71332 + Expr *pExpr = pItem->pExpr; 71333 + int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); 71334 + if( inReg!=target+i ){ 71335 + sqlite3VdbeAddOp2(pParse->pVdbe, doHardCopy ? OP_Copy : OP_SCopy, 71336 + inReg, target+i); 70119 71337 } 70120 71338 } 70121 71339 return n; 70122 71340 } 70123 71341 70124 71342 /* 70125 71343 ** Generate code for a BETWEEN operator. ................................................................................ 71093 72311 sqlite3 *db = pParse->db; 71094 72312 for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ 71095 72313 if( pTrig->pSchema==pTempSchema ){ 71096 72314 zWhere = whereOrName(db, zWhere, pTrig->zName); 71097 72315 } 71098 72316 } 71099 72317 } 72318 + if( zWhere ){ 72319 + char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere); 72320 + sqlite3DbFree(pParse->db, zWhere); 72321 + zWhere = zNew; 72322 + } 71100 72323 return zWhere; 71101 72324 } 71102 72325 71103 72326 /* 71104 72327 ** Generate code to drop and reload the internal representation of table 71105 72328 ** pTab from the database, including triggers and temporary triggers. 71106 72329 ** Argument zName is the name of the table in the database schema at ................................................................................ 71700 72923 sqlite3 *db = pParse->db; /* Database handle */ 71701 72924 Index *pIdx; /* An index to being analyzed */ 71702 72925 int iIdxCur; /* Cursor open on index being analyzed */ 71703 72926 Vdbe *v; /* The virtual machine being built up */ 71704 72927 int i; /* Loop counter */ 71705 72928 int topOfLoop; /* The top of the loop */ 71706 72929 int endOfLoop; /* The end of the loop */ 71707 - int addr; /* The address of an instruction */ 72930 + int addr = 0; /* The address of an instruction */ 72931 + int jZeroRows = 0; /* Jump from here if number of rows is zero */ 71708 72932 int iDb; /* Index of database containing pTab */ 71709 72933 int regTabname = iMem++; /* Register containing table name */ 71710 72934 int regIdxname = iMem++; /* Register containing index name */ 71711 72935 int regSampleno = iMem++; /* Register containing next sample number */ 71712 72936 int regCol = iMem++; /* Content of a column analyzed table */ 71713 72937 int regRec = iMem++; /* Register holding completed record */ 71714 72938 int regTemp = iMem++; /* Temporary use register */ ................................................................................ 71719 72943 int regSamplerecno = iMem++; /* Index of next sample to record */ 71720 72944 int regRecno = iMem++; /* Current sample index */ 71721 72945 int regLast = iMem++; /* Index of last sample to record */ 71722 72946 int regFirst = iMem++; /* Index of first sample to record */ 71723 72947 #endif 71724 72948 71725 72949 v = sqlite3GetVdbe(pParse); 71726 - if( v==0 || NEVER(pTab==0) || pTab->pIndex==0 ){ 71727 - /* Do no analysis for tables that have no indices */ 72950 + if( v==0 || NEVER(pTab==0) ){ 72951 + return; 72952 + } 72953 + if( pTab->tnum==0 ){ 72954 + /* Do not gather statistics on views or virtual tables */ 72955 + return; 72956 + } 72957 + if( memcmp(pTab->zName, "sqlite_", 7)==0 ){ 72958 + /* Do not gather statistics on system tables */ 71728 72959 return; 71729 72960 } 71730 72961 assert( sqlite3BtreeHoldsAllMutexes(db) ); 71731 72962 iDb = sqlite3SchemaToIndex(db, pTab->pSchema); 71732 72963 assert( iDb>=0 ); 71733 72964 #ifndef SQLITE_OMIT_AUTHORIZATION 71734 72965 if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, ................................................................................ 71737 72968 } 71738 72969 #endif 71739 72970 71740 72971 /* Establish a read-lock on the table at the shared-cache level. */ 71741 72972 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); 71742 72973 71743 72974 iIdxCur = pParse->nTab++; 72975 + sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); 71744 72976 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ 71745 72977 int nCol = pIdx->nColumn; 71746 72978 KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); 71747 72979 71748 72980 if( iMem+1+(nCol*2)>pParse->nMem ){ 71749 72981 pParse->nMem = iMem+1+(nCol*2); 71750 72982 } ................................................................................ 71751 72983 71752 72984 /* Open a cursor to the index to be analyzed. */ 71753 72985 assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); 71754 72986 sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, 71755 72987 (char *)pKey, P4_KEYINFO_HANDOFF); 71756 72988 VdbeComment((v, "%s", pIdx->zName)); 71757 72989 71758 - /* Populate the registers containing the table and index names. */ 71759 - if( pTab->pIndex==pIdx ){ 71760 - sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); 71761 - } 72990 + /* Populate the register containing the index name. */ 71762 72991 sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0); 71763 72992 71764 72993 #ifdef SQLITE_ENABLE_STAT2 71765 72994 71766 72995 /* If this iteration of the loop is generating code to analyze the 71767 72996 ** first index in the pTab->pIndex list, then register regLast has 71768 72997 ** not been populated. In this case populate it now. */ ................................................................................ 71889 73118 ** 71890 73119 ** I = (K+D-1)/D 71891 73120 ** 71892 73121 ** If K==0 then no entry is made into the sqlite_stat1 table. 71893 73122 ** If K>0 then it is always the case the D>0 so division by zero 71894 73123 ** is never possible. 71895 73124 */ 71896 - addr = sqlite3VdbeAddOp1(v, OP_IfNot, iMem); 71897 73125 sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regSampleno); 73126 + if( jZeroRows==0 ){ 73127 + jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem); 73128 + } 71898 73129 for(i=0; i<nCol; i++){ 71899 73130 sqlite3VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0); 71900 73131 sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regSampleno, regSampleno); 71901 73132 sqlite3VdbeAddOp3(v, OP_Add, iMem, iMem+i+1, regTemp); 71902 73133 sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1); 71903 73134 sqlite3VdbeAddOp3(v, OP_Divide, iMem+i+1, regTemp, regTemp); 71904 73135 sqlite3VdbeAddOp1(v, OP_ToInt, regTemp); 71905 73136 sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regSampleno, regSampleno); 71906 73137 } 71907 73138 sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0); 71908 73139 sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid); 71909 73140 sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid); 71910 73141 sqlite3VdbeChangeP5(v, OPFLAG_APPEND); 73142 + } 73143 + 73144 + /* If the table has no indices, create a single sqlite_stat1 entry 73145 + ** containing NULL as the index name and the row count as the content. 73146 + */ 73147 + if( pTab->pIndex==0 ){ 73148 + sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pTab->tnum, iDb); 73149 + VdbeComment((v, "%s", pTab->zName)); 73150 + sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regSampleno); 73151 + sqlite3VdbeAddOp1(v, OP_Close, iIdxCur); 73152 + }else{ 73153 + assert( jZeroRows>0 ); 73154 + addr = sqlite3VdbeAddOp0(v, OP_Goto); 73155 + sqlite3VdbeJumpHere(v, jZeroRows); 73156 + } 73157 + sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname); 73158 + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0); 73159 + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid); 73160 + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid); 73161 + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); 73162 + if( pParse->nMem<regRec ) pParse->nMem = regRec; 73163 + if( jZeroRows ){ 71911 73164 sqlite3VdbeJumpHere(v, addr); 71912 73165 } 71913 73166 } 71914 73167 71915 73168 /* 71916 73169 ** Generate code that will cause the most recent index analysis to 71917 -** be laoded into internal hash tables where is can be used. 73170 +** be loaded into internal hash tables where is can be used. 71918 73171 */ 71919 73172 static void loadAnalysis(Parse *pParse, int iDb){ 71920 73173 Vdbe *v = sqlite3GetVdbe(pParse); 71921 73174 if( v ){ 71922 73175 sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb); 71923 73176 } 71924 73177 } ................................................................................ 72040 73293 const char *zDatabase; 72041 73294 }; 72042 73295 72043 73296 /* 72044 73297 ** This callback is invoked once for each index when reading the 72045 73298 ** sqlite_stat1 table. 72046 73299 ** 72047 -** argv[0] = name of the index 72048 -** argv[1] = results of analysis - on integer for each column 73300 +** argv[0] = name of the table 73301 +** argv[1] = name of the index (might be NULL) 73302 +** argv[2] = results of analysis - on integer for each column 73303 +** 73304 +** Entries for which argv[1]==NULL simply record the number of rows in 73305 +** the table. 72049 73306 */ 72050 73307 static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ 72051 73308 analysisInfo *pInfo = (analysisInfo*)pData; 72052 73309 Index *pIndex; 72053 - int i, c; 73310 + Table *pTable; 73311 + int i, c, n; 72054 73312 unsigned int v; 72055 73313 const char *z; 72056 73314 72057 - assert( argc==2 ); 73315 + assert( argc==3 ); 72058 73316 UNUSED_PARAMETER2(NotUsed, argc); 72059 73317 72060 - if( argv==0 || argv[0]==0 || argv[1]==0 ){ 73318 + if( argv==0 || argv[0]==0 || argv[2]==0 ){ 72061 73319 return 0; 72062 73320 } 72063 - pIndex = sqlite3FindIndex(pInfo->db, argv[0], pInfo->zDatabase); 72064 - if( pIndex==0 ){ 73321 + pTable = sqlite3FindTable(pInfo->db, argv[0], pInfo->zDatabase); 73322 + if( pTable==0 ){ 72065 73323 return 0; 72066 73324 } 72067 - z = argv[1]; 72068 - for(i=0; *z && i<=pIndex->nColumn; i++){ 73325 + if( argv[1] ){ 73326 + pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase); 73327 + }else{ 73328 + pIndex = 0; 73329 + } 73330 + n = pIndex ? pIndex->nColumn : 0; 73331 + z = argv[2]; 73332 + for(i=0; *z && i<=n; i++){ 72069 73333 v = 0; 72070 73334 while( (c=z[0])>='0' && c<='9' ){ 72071 73335 v = v*10 + c - '0'; 72072 73336 z++; 72073 73337 } 73338 + if( i==0 ) pTable->nRowEst = v; 73339 + if( pIndex==0 ) break; 72074 73340 pIndex->aiRowEst[i] = v; 72075 73341 if( *z==' ' ) z++; 72076 73342 } 72077 73343 return 0; 72078 73344 } 72079 73345 72080 73346 /* ................................................................................ 72090 73356 if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){ 72091 73357 sqlite3DbFree(db, p->u.z); 72092 73358 } 72093 73359 } 72094 73360 sqlite3DbFree(db, pIdx->aSample); 72095 73361 } 72096 73362 #else 73363 + UNUSED_PARAMETER(db); 72097 73364 UNUSED_PARAMETER(pIdx); 72098 73365 #endif 72099 73366 } 72100 73367 72101 73368 /* 72102 73369 ** Load the content of the sqlite_stat1 and sqlite_stat2 tables. The 72103 73370 ** contents of sqlite_stat1 are used to populate the Index.aiRowEst[] ................................................................................ 72141 73408 sInfo.zDatabase = db->aDb[iDb].zName; 72142 73409 if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ 72143 73410 return SQLITE_ERROR; 72144 73411 } 72145 73412 72146 73413 /* Load new statistics out of the sqlite_stat1 table */ 72147 73414 zSql = sqlite3MPrintf(db, 72148 - "SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase); 73415 + "SELECT tbl, idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase); 72149 73416 if( zSql==0 ){ 72150 73417 rc = SQLITE_NOMEM; 72151 73418 }else{ 72152 73419 rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); 72153 73420 sqlite3DbFree(db, zSql); 72154 73421 } 72155 73422 ................................................................................ 72358 73625 aNew = &db->aDb[db->nDb]; 72359 73626 memset(aNew, 0, sizeof(*aNew)); 72360 73627 72361 73628 /* Open the database file. If the btree is successfully opened, use 72362 73629 ** it to obtain the database schema. At this point the schema may 72363 73630 ** or may not be initialised. 72364 73631 */ 72365 - rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE, 72366 - db->openFlags | SQLITE_OPEN_MAIN_DB, 72367 - &aNew->pBt); 73632 + rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0, 73633 + db->openFlags | SQLITE_OPEN_MAIN_DB); 72368 73634 db->nDb++; 72369 73635 if( rc==SQLITE_CONSTRAINT ){ 72370 73636 rc = SQLITE_ERROR; 72371 73637 zErrDyn = sqlite3MPrintf(db, "database is already attached"); 72372 73638 }else if( rc==SQLITE_OK ){ 72373 73639 Pager *pPager; 72374 73640 aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); ................................................................................ 72601 73867 0, /* flags */ 72602 73868 0, /* pUserData */ 72603 73869 0, /* pNext */ 72604 73870 detachFunc, /* xFunc */ 72605 73871 0, /* xStep */ 72606 73872 0, /* xFinalize */ 72607 73873 "sqlite_detach", /* zName */ 72608 - 0 /* pHash */ 73874 + 0, /* pHash */ 73875 + 0 /* pDestructor */ 72609 73876 }; 72610 73877 codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname); 72611 73878 } 72612 73879 72613 73880 /* 72614 73881 ** Called by the parser to compile an ATTACH statement. 72615 73882 ** ................................................................................ 72622 73889 0, /* flags */ 72623 73890 0, /* pUserData */ 72624 73891 0, /* pNext */ 72625 73892 attachFunc, /* xFunc */ 72626 73893 0, /* xStep */ 72627 73894 0, /* xFinalize */ 72628 73895 "sqlite_attach", /* zName */ 72629 - 0 /* pHash */ 73896 + 0, /* pHash */ 73897 + 0 /* pDestructor */ 72630 73898 }; 72631 73899 codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); 72632 73900 } 72633 73901 #endif /* SQLITE_OMIT_ATTACH */ 72634 73902 72635 73903 /* 72636 73904 ** Initialize a DbFixer structure. This routine must be called prior ................................................................................ 73751 75019 ** The call below sets the pName pointer to point at the token (pName1 or 73752 75020 ** pName2) that stores the unqualified table name. The variable iDb is 73753 75021 ** set to the index of the database that the table or view is to be 73754 75022 ** created in. 73755 75023 */ 73756 75024 iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); 73757 75025 if( iDb<0 ) return; 73758 - if( !OMIT_TEMPDB && isTemp && iDb>1 ){ 73759 - /* If creating a temp table, the name may not be qualified */ 75026 + if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){ 75027 + /* If creating a temp table, the name may not be qualified. Unless 75028 + ** the database name is "temp" anyway. */ 73760 75029 sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); 73761 75030 return; 73762 75031 } 73763 75032 if( !OMIT_TEMPDB && isTemp ) iDb = 1; 73764 75033 73765 75034 pParse->sNameToken = *pName; 73766 75035 zName = sqlite3NameFromToken(db, pName); ................................................................................ 73800 75069 ** index or table name in the same database. Issue an error message if 73801 75070 ** it does. The exception is if the statement being parsed was passed 73802 75071 ** to an sqlite3_declare_vtab() call. In that case only the column names 73803 75072 ** and types will be used, so there is no need to test for namespace 73804 75073 ** collisions. 73805 75074 */ 73806 75075 if( !IN_DECLARE_VTAB ){ 75076 + char *zDb = db->aDb[iDb].zName; 73807 75077 if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ 73808 75078 goto begin_table_error; 73809 75079 } 73810 - pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); 75080 + pTable = sqlite3FindTable(db, zName, zDb); 73811 75081 if( pTable ){ 73812 75082 if( !noErr ){ 73813 75083 sqlite3ErrorMsg(pParse, "table %T already exists", pName); 73814 75084 } 73815 75085 goto begin_table_error; 73816 75086 } 73817 - if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){ 75087 + if( sqlite3FindIndex(db, zName, zDb)!=0 ){ 73818 75088 sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); 73819 75089 goto begin_table_error; 73820 75090 } 73821 75091 } 73822 75092 73823 75093 pTable = sqlite3DbMallocZero(db, sizeof(Table)); 73824 75094 if( pTable==0 ){ ................................................................................ 73827 75097 pParse->nErr++; 73828 75098 goto begin_table_error; 73829 75099 } 73830 75100 pTable->zName = zName; 73831 75101 pTable->iPKey = -1; 73832 75102 pTable->pSchema = db->aDb[iDb].pSchema; 73833 75103 pTable->nRef = 1; 75104 + pTable->nRowEst = 1000000; 73834 75105 assert( pParse->pNewTable==0 ); 73835 75106 pParse->pNewTable = pTable; 73836 75107 73837 75108 /* If this is the magic sqlite_sequence table used by autoincrement, 73838 75109 ** then record a pointer to this table in the main database structure 73839 75110 ** so that INSERT can find the table easily. 73840 75111 */ ................................................................................ 74673 75944 if( pParse->nVar>0 ){ 74674 75945 sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); 74675 75946 sqlite3SelectDelete(db, pSelect); 74676 75947 return; 74677 75948 } 74678 75949 sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); 74679 75950 p = pParse->pNewTable; 74680 - if( p==0 ){ 75951 + if( p==0 || pParse->nErr ){ 74681 75952 sqlite3SelectDelete(db, pSelect); 74682 75953 return; 74683 75954 } 74684 - assert( pParse->nErr==0 ); /* If sqlite3StartTable return non-NULL then 74685 - ** there could not have been an error */ 74686 75955 sqlite3TwoPartName(pParse, pName1, pName2, &pName); 74687 75956 iDb = sqlite3SchemaToIndex(db, p->pSchema); 74688 75957 if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) 74689 75958 && sqlite3FixSelect(&sFix, pSelect) 74690 75959 ){ 74691 75960 sqlite3SelectDelete(db, pSelect); 74692 75961 return; ................................................................................ 75796 77065 /* Fill the index with data and reparse the schema. Code an OP_Expire 75797 77066 ** to invalidate all pre-compiled statements. 75798 77067 */ 75799 77068 if( pTblName ){ 75800 77069 sqlite3RefillIndex(pParse, pIndex, iMem); 75801 77070 sqlite3ChangeCookie(pParse, iDb); 75802 77071 sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, 75803 - sqlite3MPrintf(db, "name='%q'", pIndex->zName), P4_DYNAMIC); 77072 + sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 77073 + P4_DYNAMIC); 75804 77074 sqlite3VdbeAddOp1(v, OP_Expire, 0); 75805 77075 } 75806 77076 } 75807 77077 75808 77078 /* When adding an index to the list of indices for a table, make 75809 77079 ** sure all indices labeled OE_Replace come after all those labeled 75810 77080 ** OE_Ignore. This is necessary for the correct constraint check ................................................................................ 75857 77127 ** Apart from that, we have little to go on besides intuition as to 75858 77128 ** how aiRowEst[] should be initialized. The numbers generated here 75859 77129 ** are based on typical values found in actual indices. 75860 77130 */ 75861 77131 SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){ 75862 77132 unsigned *a = pIdx->aiRowEst; 75863 77133 int i; 77134 + unsigned n; 75864 77135 assert( a!=0 ); 75865 - a[0] = 1000000; 75866 - for(i=pIdx->nColumn; i>=5; i--){ 75867 - a[i] = 5; 75868 - } 75869 - while( i>=1 ){ 75870 - a[i] = 11 - i; 75871 - i--; 77136 + a[0] = pIdx->pTable->nRowEst; 77137 + if( a[0]<10 ) a[0] = 10; 77138 + n = 10; 77139 + for(i=1; i<=pIdx->nColumn; i++){ 77140 + a[i] = n; 77141 + if( n>5 ) n--; 75872 77142 } 75873 77143 if( pIdx->onError!=OE_None ){ 75874 77144 a[pIdx->nColumn] = 1; 75875 77145 } 75876 77146 } 75877 77147 75878 77148 /* ................................................................................ 75924 77194 #endif 75925 77195 75926 77196 /* Generate code to remove the index and from the master table */ 75927 77197 v = sqlite3GetVdbe(pParse); 75928 77198 if( v ){ 75929 77199 sqlite3BeginWriteOperation(pParse, 1, iDb); 75930 77200 sqlite3NestedParse(pParse, 75931 - "DELETE FROM %Q.%s WHERE name=%Q", 77201 + "DELETE FROM %Q.%s WHERE name=%Q AND type='index'", 75932 77202 db->aDb[iDb].zName, SCHEMA_TABLE(iDb), 75933 77203 pIndex->zName 75934 77204 ); 75935 77205 if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){ 75936 77206 sqlite3NestedParse(pParse, 75937 77207 "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q", 75938 77208 db->aDb[iDb].zName, pIndex->zName ................................................................................ 76416 77686 static const int flags = 76417 77687 SQLITE_OPEN_READWRITE | 76418 77688 SQLITE_OPEN_CREATE | 76419 77689 SQLITE_OPEN_EXCLUSIVE | 76420 77690 SQLITE_OPEN_DELETEONCLOSE | 76421 77691 SQLITE_OPEN_TEMP_DB; 76422 77692 76423 - rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, &pBt); 77693 + rc = sqlite3BtreeOpen(0, db, &pBt, 0, flags); 76424 77694 if( rc!=SQLITE_OK ){ 76425 77695 sqlite3ErrorMsg(pParse, "unable to open a temporary database " 76426 77696 "file for storing temporary tables"); 76427 77697 pParse->rc = rc; 76428 77698 return 1; 76429 77699 } 76430 77700 db->aDb[1].pBt = pBt; ................................................................................ 77073 78343 /* If no match is found, search the built-in functions. 77074 78344 ** 77075 78345 ** If the SQLITE_PreferBuiltin flag is set, then search the built-in 77076 78346 ** functions even if a prior app-defined function was found. And give 77077 78347 ** priority to built-in functions. 77078 78348 ** 77079 78349 ** Except, if createFlag is true, that means that we are trying to 77080 - ** install a new function. Whatever FuncDef structure is returned will 78350 + ** install a new function. Whatever FuncDef structure is returned it will 77081 78351 ** have fields overwritten with new information appropriate for the 77082 78352 ** new function. But the FuncDefs for built-in functions are read-only. 77083 78353 ** So we must not search for built-ins when creating a new function. 77084 78354 */ 77085 78355 if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){ 77086 78356 FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); 77087 78357 bestScore = 0; ................................................................................ 78089 79359 r = -(double)((sqlite_int64)((-r)+0.5)); 78090 79360 }else{ 78091 79361 zBuf = sqlite3_mprintf("%.*f",n,r); 78092 79362 if( zBuf==0 ){ 78093 79363 sqlite3_result_error_nomem(context); 78094 79364 return; 78095 79365 } 78096 - sqlite3AtoF(zBuf, &r); 79366 + sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8); 78097 79367 sqlite3_free(zBuf); 78098 79368 } 78099 79369 sqlite3_result_double(context, r); 78100 79370 } 78101 79371 #endif 78102 79372 78103 79373 /* ................................................................................ 79254 80524 SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ 79255 80525 struct compareInfo *pInfo; 79256 80526 if( caseSensitive ){ 79257 80527 pInfo = (struct compareInfo*)&likeInfoAlt; 79258 80528 }else{ 79259 80529 pInfo = (struct compareInfo*)&likeInfoNorm; 79260 80530 } 79261 - sqlite3CreateFunc(db, "like", 2, SQLITE_ANY, pInfo, likeFunc, 0, 0); 79262 - sqlite3CreateFunc(db, "like", 3, SQLITE_ANY, pInfo, likeFunc, 0, 0); 80531 + sqlite3CreateFunc(db, "like", 2, SQLITE_ANY, pInfo, likeFunc, 0, 0, 0); 80532 + sqlite3CreateFunc(db, "like", 3, SQLITE_ANY, pInfo, likeFunc, 0, 0, 0); 79263 80533 sqlite3CreateFunc(db, "glob", 2, SQLITE_ANY, 79264 - (struct compareInfo*)&globInfo, likeFunc, 0,0); 80534 + (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0); 79265 80535 setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); 79266 80536 setLikeOptFlag(db, "like", 79267 80537 caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); 79268 80538 } 79269 80539 79270 80540 /* 79271 80541 ** pExpr points to an expression which implements a function. If ................................................................................ 79341 80611 FUNCTION(round, 2, 0, 0, roundFunc ), 79342 80612 #endif 79343 80613 FUNCTION(upper, 1, 0, 0, upperFunc ), 79344 80614 FUNCTION(lower, 1, 0, 0, lowerFunc ), 79345 80615 FUNCTION(coalesce, 1, 0, 0, 0 ), 79346 80616 FUNCTION(coalesce, 0, 0, 0, 0 ), 79347 80617 /* FUNCTION(coalesce, -1, 0, 0, ifnullFunc ), */ 79348 - {-1,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0}, 80618 + {-1,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0,0}, 79349 80619 FUNCTION(hex, 1, 0, 0, hexFunc ), 79350 80620 /* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */ 79351 - {2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0}, 80621 + {2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0,0}, 79352 80622 FUNCTION(random, 0, 0, 0, randomFunc ), 79353 80623 FUNCTION(randomblob, 1, 0, 0, randomBlob ), 79354 80624 FUNCTION(nullif, 2, 0, 1, nullifFunc ), 79355 80625 FUNCTION(sqlite_version, 0, 0, 0, versionFunc ), 79356 80626 FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), 79357 80627 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS 79358 80628 FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ), ................................................................................ 79371 80641 FUNCTION(load_extension, 1, 0, 0, loadExt ), 79372 80642 FUNCTION(load_extension, 2, 0, 0, loadExt ), 79373 80643 #endif 79374 80644 AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ), 79375 80645 AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), 79376 80646 AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), 79377 80647 /* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */ 79378 - {0,SQLITE_UTF8,SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0}, 80648 + {0,SQLITE_UTF8,SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0}, 79379 80649 AGGREGATE(count, 1, 0, 0, countStep, countFinalize ), 79380 80650 AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize), 79381 80651 AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize), 79382 80652 79383 80653 LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), 79384 80654 #ifdef SQLITE_CASE_SENSITIVE_LIKE 79385 80655 LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), ................................................................................ 79782 81052 int regTemp = sqlite3GetTempRange(pParse, nCol); 79783 81053 int regRec = sqlite3GetTempReg(pParse); 79784 81054 KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); 79785 81055 79786 81056 sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb); 79787 81057 sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); 79788 81058 for(i=0; i<nCol; i++){ 79789 - sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[i]+1+regData, regTemp+i); 81059 + sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i); 79790 81060 } 79791 81061 79792 81062 /* If the parent table is the same as the child table, and we are about 79793 81063 ** to increment the constraint-counter (i.e. this is an INSERT operation), 79794 81064 ** then check if the row being inserted matches itself. If so, do not 79795 81065 ** increment the constraint-counter. */ 79796 81066 if( pTab==pFKey->pFrom && nIncr==1 ){ ................................................................................ 84147 85417 ** 84148 85418 ** Get or set the size limit on rollback journal files. 84149 85419 */ 84150 85420 if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){ 84151 85421 Pager *pPager = sqlite3BtreePager(pDb->pBt); 84152 85422 i64 iLimit = -2; 84153 85423 if( zRight ){ 84154 - sqlite3Atoi64(zRight, &iLimit); 85424 + sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8); 84155 85425 if( iLimit<-1 ) iLimit = -1; 84156 85426 } 84157 85427 iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); 84158 85428 returnSingleInt(pParse, "journal_size_limit", iLimit); 84159 85429 }else 84160 85430 84161 85431 #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ ................................................................................ 86380 87650 addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); 86381 87651 sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); 86382 87652 addr2 = sqlite3VdbeAddOp0(v, OP_Goto); 86383 87653 sqlite3VdbeJumpHere(v, addr1); 86384 87654 sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor); 86385 87655 sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor); 86386 87656 sqlite3VdbeJumpHere(v, addr2); 86387 - pSelect->iLimit = 0; 86388 87657 } 86389 87658 } 86390 87659 86391 87660 /* 86392 87661 ** Add code to implement the OFFSET 86393 87662 */ 86394 87663 static void codeOffset( ................................................................................ 86429 87698 r1 = sqlite3GetTempReg(pParse); 86430 87699 sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); 86431 87700 sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); 86432 87701 sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); 86433 87702 sqlite3ReleaseTempReg(pParse, r1); 86434 87703 } 86435 87704 87705 +#ifndef SQLITE_OMIT_SUBQUERY 86436 87706 /* 86437 87707 ** Generate an error message when a SELECT is used within a subexpression 86438 87708 ** (example: "a IN (SELECT * FROM table)") but it has more than 1 result 86439 -** column. We do this in a subroutine because the error occurs in multiple 86440 -** places. 87709 +** column. We do this in a subroutine because the error used to occur 87710 +** in multiple places. (The error only occurs in one place now, but we 87711 +** retain the subroutine to minimize code disruption.) 86441 87712 */ 86442 87713 static int checkForMultiColumnSelectError( 86443 87714 Parse *pParse, /* Parse context. */ 86444 87715 SelectDest *pDest, /* Destination of SELECT results */ 86445 87716 int nExpr /* Number of result columns returned by SELECT */ 86446 87717 ){ 86447 87718 int eDest = pDest->eDest; ................................................................................ 86449 87720 sqlite3ErrorMsg(pParse, "only a single result allowed for " 86450 87721 "a SELECT that is part of an expression"); 86451 87722 return 1; 86452 87723 }else{ 86453 87724 return 0; 86454 87725 } 86455 87726 } 87727 +#endif 86456 87728 86457 87729 /* 86458 87730 ** This routine generates the code for the inside of the inner loop 86459 87731 ** of a SELECT. 86460 87732 ** 86461 87733 ** If srcTab and nColumn are both zero, then the pEList expressions 86462 87734 ** are evaluated in order to get the data for this row. If nColumn>0 ................................................................................ 86528 87800 assert( pEList->nExpr==nColumn ); 86529 87801 codeDistinct(pParse, distinct, iContinue, nColumn, regResult); 86530 87802 if( pOrderBy==0 ){ 86531 87803 codeOffset(v, p, iContinue); 86532 87804 } 86533 87805 } 86534 87806 86535 - if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ 86536 - return; 86537 - } 86538 - 86539 87807 switch( eDest ){ 86540 87808 /* In this mode, write each query result to the key of the temporary 86541 87809 ** table iParm. 86542 87810 */ 86543 87811 #ifndef SQLITE_OMIT_COMPOUND_SELECT 86544 87812 case SRT_Union: { 86545 87813 int r1; ................................................................................ 86660 87928 default: { 86661 87929 assert( eDest==SRT_Discard ); 86662 87930 break; 86663 87931 } 86664 87932 #endif 86665 87933 } 86666 87934 86667 - /* Jump to the end of the loop if the LIMIT is reached. 87935 + /* Jump to the end of the loop if the LIMIT is reached. Except, if 87936 + ** there is a sorter, in which case the sorter has already limited 87937 + ** the output for us. 86668 87938 */ 86669 - if( p->iLimit ){ 86670 - assert( pOrderBy==0 ); /* If there is an ORDER BY, the call to 86671 - ** pushOntoSorter() would have cleared p->iLimit */ 87939 + if( pOrderBy==0 && p->iLimit ){ 86672 87940 sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); 86673 87941 } 86674 87942 } 86675 87943 86676 87944 /* 86677 87945 ** Given an expression list, generate a KeyInfo structure that records 86678 87946 ** the collating sequence for each expression in that expression list. ................................................................................ 86799 88067 } 86800 88068 break; 86801 88069 } 86802 88070 } 86803 88071 sqlite3ReleaseTempReg(pParse, regRow); 86804 88072 sqlite3ReleaseTempReg(pParse, regRowid); 86805 88073 86806 - /* LIMIT has been implemented by the pushOntoSorter() routine. 86807 - */ 86808 - assert( p->iLimit==0 ); 86809 - 86810 88074 /* The bottom of the loop 86811 88075 */ 86812 88076 sqlite3VdbeResolveLabel(v, addrContinue); 86813 88077 sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); 86814 88078 sqlite3VdbeResolveLabel(v, addrBreak); 86815 88079 if( eDest==SRT_Output || eDest==SRT_Coroutine ){ 86816 88080 sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0); ................................................................................ 87441 88705 assert( v!=0 ); /* The VDBE already created by calling function */ 87442 88706 87443 88707 /* Create the destination temporary table if necessary 87444 88708 */ 87445 88709 if( dest.eDest==SRT_EphemTab ){ 87446 88710 assert( p->pEList ); 87447 88711 sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr); 88712 + sqlite3VdbeChangeP5(v, BTREE_UNORDERED); 87448 88713 dest.eDest = SRT_Table; 87449 88714 } 87450 88715 87451 88716 /* Make sure all SELECTs in the statement have the same number of elements 87452 88717 ** in their result sets. 87453 88718 */ 87454 88719 assert( p->pEList && pPrior->pEList ); ................................................................................ 87736 89001 ** The data to be output is contained in pIn->iMem. There are 87737 89002 ** pIn->nMem columns to be output. pDest is where the output should 87738 89003 ** be sent. 87739 89004 ** 87740 89005 ** regReturn is the number of the register holding the subroutine 87741 89006 ** return address. 87742 89007 ** 87743 -** If regPrev>0 then it is a the first register in a vector that 89008 +** If regPrev>0 then it is the first register in a vector that 87744 89009 ** records the previous output. mem[regPrev] is a flag that is false 87745 89010 ** if there has been no previous output. If regPrev>0 then code is 87746 89011 ** generated to suppress duplicates. pKeyInfo is used for comparing 87747 89012 ** keys. 87748 89013 ** 87749 89014 ** If the LIMIT found in p->iLimit is reached, jump immediately to 87750 89015 ** iBreak. ................................................................................ 88119 89384 } 88120 89385 } 88121 89386 } 88122 89387 88123 89388 /* Separate the left and the right query from one another 88124 89389 */ 88125 89390 p->pPrior = 0; 88126 - pPrior->pRightmost = 0; 88127 89391 sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); 88128 89392 if( pPrior->pPrior==0 ){ 88129 89393 sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); 88130 89394 } 88131 89395 88132 89396 /* Compute the limit registers */ 88133 89397 computeLimitRegisters(pParse, p, labelEnd); ................................................................................ 88433 89697 ** Flattening is only attempted if all of the following are true: 88434 89698 ** 88435 89699 ** (1) The subquery and the outer query do not both use aggregates. 88436 89700 ** 88437 89701 ** (2) The subquery is not an aggregate or the outer query is not a join. 88438 89702 ** 88439 89703 ** (3) The subquery is not the right operand of a left outer join 88440 -** (Originally ticket #306. Strenghtened by ticket #3300) 89704 +** (Originally ticket #306. Strengthened by ticket #3300) 88441 89705 ** 88442 -** (4) The subquery is not DISTINCT or the outer query is not a join. 89706 +** (4) The subquery is not DISTINCT. 88443 89707 ** 88444 -** (5) The subquery is not DISTINCT or the outer query does not use 88445 -** aggregates. 89708 +** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT 89709 +** sub-queries that were excluded from this optimization. Restriction 89710 +** (4) has since been expanded to exclude all DISTINCT subqueries. 88446 89711 ** 88447 89712 ** (6) The subquery does not use aggregates or the outer query is not 88448 89713 ** DISTINCT. 88449 89714 ** 88450 89715 ** (7) The subquery has a FROM clause. 88451 89716 ** 88452 89717 ** (8) The subquery does not use LIMIT or the outer query is not a join. ................................................................................ 88458 89723 ** use LIMIT. 88459 89724 ** 88460 89725 ** (11) The subquery and the outer query do not both have ORDER BY clauses. 88461 89726 ** 88462 89727 ** (**) Not implemented. Subsumed into restriction (3). Was previously 88463 89728 ** a separate restriction deriving from ticket #350. 88464 89729 ** 88465 -** (13) The subquery and outer query do not both use LIMIT 89730 +** (13) The subquery and outer query do not both use LIMIT. 88466 89731 ** 88467 -** (14) The subquery does not use OFFSET 89732 +** (14) The subquery does not use OFFSET. 88468 89733 ** 88469 89734 ** (15) The outer query is not part of a compound select or the 88470 89735 ** subquery does not have a LIMIT clause. 88471 89736 ** (See ticket #2339 and ticket [02a8e81d44]). 88472 89737 ** 88473 89738 ** (16) The outer query is not an aggregate or the subquery does 88474 89739 ** not contain ORDER BY. (Ticket #2942) This used to not matter ................................................................................ 88551 89816 ** and (14). */ 88552 89817 if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ 88553 89818 if( pSub->pOffset ) return 0; /* Restriction (14) */ 88554 89819 if( p->pRightmost && pSub->pLimit ){ 88555 89820 return 0; /* Restriction (15) */ 88556 89821 } 88557 89822 if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ 88558 - if( ((pSub->selFlags & SF_Distinct)!=0 || pSub->pLimit) 88559 - && (pSrc->nSrc>1 || isAgg) ){ /* Restrictions (4)(5)(8)(9) */ 88560 - return 0; 89823 + if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */ 89824 + if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){ 89825 + return 0; /* Restrictions (8)(9) */ 88561 89826 } 88562 89827 if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){ 88563 89828 return 0; /* Restriction (6) */ 88564 89829 } 88565 89830 if( p->pOrderBy && pSub->pOrderBy ){ 88566 89831 return 0; /* Restriction (11) */ 88567 89832 } ................................................................................ 89402 90667 int addrNext = 0; 89403 90668 int regAgg; 89404 90669 ExprList *pList = pF->pExpr->x.pList; 89405 90670 assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); 89406 90671 if( pList ){ 89407 90672 nArg = pList->nExpr; 89408 90673 regAgg = sqlite3GetTempRange(pParse, nArg); 89409 - sqlite3ExprCodeExprList(pParse, pList, regAgg, 0); 90674 + sqlite3ExprCodeExprList(pParse, pList, regAgg, 1); 89410 90675 }else{ 89411 90676 nArg = 0; 89412 90677 regAgg = 0; 89413 90678 } 89414 90679 if( pF->iDistinct>=0 ){ 89415 90680 addrNext = sqlite3VdbeMakeLabel(v); 89416 90681 assert( nArg==1 ); ................................................................................ 89561 90826 isAgg = (p->selFlags & SF_Aggregate)!=0; 89562 90827 assert( pEList!=0 ); 89563 90828 89564 90829 /* Begin generating code. 89565 90830 */ 89566 90831 v = sqlite3GetVdbe(pParse); 89567 90832 if( v==0 ) goto select_end; 90833 + 90834 + /* If writing to memory or generating a set 90835 + ** only a single column may be output. 90836 + */ 90837 +#ifndef SQLITE_OMIT_SUBQUERY 90838 + if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ 90839 + goto select_end; 90840 + } 90841 +#endif 89568 90842 89569 90843 /* Generate code for all sub-queries in the FROM clause 89570 90844 */ 89571 90845 #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) 89572 90846 for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ 89573 90847 struct SrcList_item *pItem = &pTabList->a[i]; 89574 90848 SelectDest dest; ................................................................................ 89635 90909 return 1; 89636 90910 } 89637 90911 } 89638 90912 return multiSelect(pParse, p, pDest); 89639 90913 } 89640 90914 #endif 89641 90915 89642 - /* If writing to memory or generating a set 89643 - ** only a single column may be output. 89644 - */ 89645 -#ifndef SQLITE_OMIT_SUBQUERY 89646 - if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ 89647 - goto select_end; 89648 - } 89649 -#endif 89650 - 89651 90916 /* If possible, rewrite the query to use GROUP BY instead of DISTINCT. 89652 90917 ** GROUP BY might use an index, DISTINCT never does. 89653 90918 */ 89654 90919 assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 ); 89655 90920 if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){ 89656 90921 p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); 89657 90922 pGroupBy = p->pGroupBy; ................................................................................ 89706 90971 if( isDistinct ){ 89707 90972 KeyInfo *pKeyInfo; 89708 90973 assert( isAgg || pGroupBy ); 89709 90974 distinct = pParse->nTab++; 89710 90975 pKeyInfo = keyInfoFromExprList(pParse, p->pEList); 89711 90976 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0, 89712 90977 (char*)pKeyInfo, P4_KEYINFO_HANDOFF); 90978 + sqlite3VdbeChangeP5(v, BTREE_UNORDERED); 89713 90979 }else{ 89714 90980 distinct = -1; 89715 90981 } 89716 90982 89717 90983 /* Aggregate and non-aggregate queries are handled differently */ 89718 90984 if( !isAgg && pGroupBy==0 ){ 89719 90985 /* This case is for non-aggregate queries ................................................................................ 92181 93447 92182 93448 /* Create the ephemeral table into which the update results will 92183 93449 ** be stored. 92184 93450 */ 92185 93451 assert( v ); 92186 93452 ephemTab = pParse->nTab++; 92187 93453 sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0)); 93454 + sqlite3VdbeChangeP5(v, BTREE_UNORDERED); 92188 93455 92189 93456 /* fill the ephemeral table 92190 93457 */ 92191 93458 sqlite3SelectDestInit(&dest, SRT_Table, ephemTab); 92192 93459 sqlite3Select(pParse, pSelect, &dest); 92193 93460 92194 93461 /* Generate code to scan the ephemeral table and call VUpdate. */ ................................................................................ 92319 93586 int isMemDb; /* True if vacuuming a :memory: database */ 92320 93587 int nRes; /* Bytes of reserved space at the end of each page */ 92321 93588 int nDb; /* Number of attached databases */ 92322 93589 92323 93590 if( !db->autoCommit ){ 92324 93591 sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); 92325 93592 return SQLITE_ERROR; 93593 + } 93594 + if( db->activeVdbeCnt>1 ){ 93595 + sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress"); 93596 + return SQLITE_ERROR; 92326 93597 } 92327 93598 92328 93599 /* Save the current value of the database flags so that it can be 92329 93600 ** restored before returning. Then set the writable-schema flag, and 92330 93601 ** disable CHECK and foreign key constraints. */ 92331 93602 saved_flags = db->flags; 92332 93603 saved_nChange = db->nChange; ................................................................................ 92921 94192 pParse->regRowid 92922 94193 ); 92923 94194 sqlite3DbFree(db, zStmt); 92924 94195 v = sqlite3GetVdbe(pParse); 92925 94196 sqlite3ChangeCookie(pParse, iDb); 92926 94197 92927 94198 sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); 92928 - zWhere = sqlite3MPrintf(db, "name='%q'", pTab->zName); 94199 + zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); 92929 94200 sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 1, 0, zWhere, P4_DYNAMIC); 92930 94201 sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, 92931 94202 pTab->zName, sqlite3Strlen30(pTab->zName) + 1); 92932 94203 } 92933 94204 92934 94205 /* If we are rereading the sqlite_master table create the in-memory 92935 94206 ** record of the table. The xConnect() method is not called until ................................................................................ 93223 94494 pTab->nCol = pParse->pNewTable->nCol; 93224 94495 pParse->pNewTable->nCol = 0; 93225 94496 pParse->pNewTable->aCol = 0; 93226 94497 } 93227 94498 db->pVTab = 0; 93228 94499 }else{ 93229 94500 sqlite3Error(db, SQLITE_ERROR, zErr); 93230 - sqlite3_free(zErr); 94501 + sqlite3DbFree(db, zErr); 93231 94502 rc = SQLITE_ERROR; 93232 94503 } 93233 94504 pParse->declareVtab = 0; 93234 94505 93235 94506 if( pParse->pVdbe ){ 93236 94507 sqlite3VdbeFinalize(pParse->pVdbe); 93237 94508 } ................................................................................ 94161 95432 pRight = pList->a[0].pExpr; 94162 95433 op = pRight->op; 94163 95434 if( op==TK_REGISTER ){ 94164 95435 op = pRight->op2; 94165 95436 } 94166 95437 if( op==TK_VARIABLE ){ 94167 95438 Vdbe *pReprepare = pParse->pReprepare; 94168 - pVal = sqlite3VdbeGetValue(pReprepare, pRight->iColumn, SQLITE_AFF_NONE); 95439 + int iCol = pRight->iColumn; 95440 + pVal = sqlite3VdbeGetValue(pReprepare, iCol, SQLITE_AFF_NONE); 94169 95441 if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){ 94170 95442 z = (char *)sqlite3_value_text(pVal); 94171 95443 } 94172 - sqlite3VdbeSetVarmask(pParse->pVdbe, pRight->iColumn); 95444 + sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); /* IMP: R-23257-02778 */ 94173 95445 assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); 94174 95446 }else if( op==TK_STRING ){ 94175 95447 z = pRight->u.zToken; 94176 95448 } 94177 95449 if( z ){ 94178 95450 cnt = 0; 94179 95451 while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ ................................................................................ 94183 95455 Expr *pPrefix; 94184 95456 *pisComplete = c==wc[0] && z[cnt+1]==0; 94185 95457 pPrefix = sqlite3Expr(db, TK_STRING, z); 94186 95458 if( pPrefix ) pPrefix->u.zToken[cnt] = 0; 94187 95459 *ppPrefix = pPrefix; 94188 95460 if( op==TK_VARIABLE ){ 94189 95461 Vdbe *v = pParse->pVdbe; 94190 - sqlite3VdbeSetVarmask(v, pRight->iColumn); 95462 + sqlite3VdbeSetVarmask(v, pRight->iColumn); /* IMP: R-23257-02778 */ 94191 95463 if( *pisComplete && pRight->u.zToken[1] ){ 94192 95464 /* If the rhs of the LIKE expression is a variable, and the current 94193 95465 ** value of the variable means there is no need to invoke the LIKE 94194 95466 ** function, then no OP_Variable will be added to the program. 94195 95467 ** This causes problems for the sqlite3_bind_parameter_name() 94196 95468 ** API. To workaround them, add a dummy OP_Variable here. 94197 95469 */ ................................................................................ 95047 96319 #define TRACE_IDX_OUTPUTS(A) 95048 96320 #endif 95049 96321 95050 96322 /* 95051 96323 ** Required because bestIndex() is called by bestOrClauseIndex() 95052 96324 */ 95053 96325 static void bestIndex( 95054 - Parse*, WhereClause*, struct SrcList_item*, Bitmask, ExprList*, WhereCost*); 96326 + Parse*, WhereClause*, struct SrcList_item*, 96327 + Bitmask, Bitmask, ExprList*, WhereCost*); 95055 96328 95056 96329 /* 95057 96330 ** This routine attempts to find an scanning strategy that can be used 95058 96331 ** to optimize an 'OR' expression that is part of a WHERE clause. 95059 96332 ** 95060 96333 ** The table associated with FROM clause term pSrc may be either a 95061 96334 ** regular B-Tree table or a virtual table. 95062 96335 */ 95063 96336 static void bestOrClauseIndex( 95064 96337 Parse *pParse, /* The parsing context */ 95065 96338 WhereClause *pWC, /* The WHERE clause */ 95066 96339 struct SrcList_item *pSrc, /* The FROM clause term to search */ 95067 - Bitmask notReady, /* Mask of cursors that are not available */ 96340 + Bitmask notReady, /* Mask of cursors not available for indexing */ 96341 + Bitmask notValid, /* Cursors not available for any purpose */ 95068 96342 ExprList *pOrderBy, /* The ORDER BY clause */ 95069 96343 WhereCost *pCost /* Lowest cost query plan */ 95070 96344 ){ 95071 96345 #ifndef SQLITE_OMIT_OR_OPTIMIZATION 95072 96346 const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ 95073 96347 const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */ 95074 96348 WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */ ................................................................................ 95096 96370 for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ 95097 96371 WhereCost sTermCost; 95098 96372 WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", 95099 96373 (pOrTerm - pOrWC->a), (pTerm - pWC->a) 95100 96374 )); 95101 96375 if( pOrTerm->eOperator==WO_AND ){ 95102 96376 WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc; 95103 - bestIndex(pParse, pAndWC, pSrc, notReady, 0, &sTermCost); 96377 + bestIndex(pParse, pAndWC, pSrc, notReady, notValid, 0, &sTermCost); 95104 96378 }else if( pOrTerm->leftCursor==iCur ){ 95105 96379 WhereClause tempWC; 95106 96380 tempWC.pParse = pWC->pParse; 95107 96381 tempWC.pMaskSet = pWC->pMaskSet; 95108 96382 tempWC.op = TK_AND; 95109 96383 tempWC.a = pOrTerm; 95110 96384 tempWC.nTerm = 1; 95111 - bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost); 96385 + bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost); 95112 96386 }else{ 95113 96387 continue; 95114 96388 } 95115 96389 rTotal += sTermCost.rCost; 95116 96390 nRow += sTermCost.nRow; 95117 96391 used |= sTermCost.used; 95118 96392 if( rTotal>=pCost->rCost ) break; ................................................................................ 95197 96471 if( pSrc->notIndexed ){ 95198 96472 /* The NOT INDEXED clause appears in the SQL. */ 95199 96473 return; 95200 96474 } 95201 96475 95202 96476 assert( pParse->nQueryLoop >= (double)1 ); 95203 96477 pTable = pSrc->pTab; 95204 - nTableRow = pTable->pIndex ? pTable->pIndex->aiRowEst[0] : 1000000; 96478 + nTableRow = pTable->nRowEst; 95205 96479 logN = estLog(nTableRow); 95206 96480 costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1); 95207 96481 if( costTempIdx>=pCost->rCost ){ 95208 96482 /* The cost of creating the transient table would be greater than 95209 96483 ** doing the full table scan */ 95210 96484 return; 95211 96485 } ................................................................................ 95551 96825 ** routine takes care of freeing the sqlite3_index_info structure after 95552 96826 ** everybody has finished with it. 95553 96827 */ 95554 96828 static void bestVirtualIndex( 95555 96829 Parse *pParse, /* The parsing context */ 95556 96830 WhereClause *pWC, /* The WHERE clause */ 95557 96831 struct SrcList_item *pSrc, /* The FROM clause term to search */ 95558 - Bitmask notReady, /* Mask of cursors that are not available */ 96832 + Bitmask notReady, /* Mask of cursors not available for index */ 96833 + Bitmask notValid, /* Cursors not valid for any purpose */ 95559 96834 ExprList *pOrderBy, /* The order by clause */ 95560 96835 WhereCost *pCost, /* Lowest cost query plan */ 95561 96836 sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */ 95562 96837 ){ 95563 96838 Table *pTab = pSrc->pTab; 95564 96839 sqlite3_index_info *pIdxInfo; 95565 96840 struct sqlite3_index_constraint *pIdxCons; ................................................................................ 95681 96956 } 95682 96957 pCost->plan.nEq = 0; 95683 96958 pIdxInfo->nOrderBy = nOrderBy; 95684 96959 95685 96960 /* Try to find a more efficient access pattern by using multiple indexes 95686 96961 ** to optimize an OR expression within the WHERE clause. 95687 96962 */ 95688 - bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost); 96963 + bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost); 95689 96964 } 95690 96965 #endif /* SQLITE_OMIT_VIRTUALTABLE */ 95691 96966 95692 96967 /* 95693 96968 ** Argument pIdx is a pointer to an index structure that has an array of 95694 96969 ** SQLITE_INDEX_SAMPLES evenly spaced samples of the first indexed column 95695 96970 ** stored in Index.aSample. The domain of values stored in said column ................................................................................ 95807 97082 sqlite3_value **pp 95808 97083 ){ 95809 97084 /* The evalConstExpr() function will have already converted any TK_VARIABLE 95810 97085 ** expression involved in an comparison into a TK_REGISTER. */ 95811 97086 assert( pExpr->op!=TK_VARIABLE ); 95812 97087 if( pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE ){ 95813 97088 int iVar = pExpr->iColumn; 95814 - sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); 97089 + sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); /* IMP: R-23257-02778 */ 95815 97090 *pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff); 95816 97091 return SQLITE_OK; 95817 97092 } 95818 97093 return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp); 95819 97094 } 95820 97095 #endif 95821 97096 ................................................................................ 95962 97237 ** selected plan may still take advantage of the tables built-in rowid 95963 97238 ** index. 95964 97239 */ 95965 97240 static void bestBtreeIndex( 95966 97241 Parse *pParse, /* The parsing context */ 95967 97242 WhereClause *pWC, /* The WHERE clause */ 95968 97243 struct SrcList_item *pSrc, /* The FROM clause term to search */ 95969 - Bitmask notReady, /* Mask of cursors that are not available */ 97244 + Bitmask notReady, /* Mask of cursors not available for indexing */ 97245 + Bitmask notValid, /* Cursors not available for any purpose */ 95970 97246 ExprList *pOrderBy, /* The ORDER BY clause */ 95971 97247 WhereCost *pCost /* Lowest cost query plan */ 95972 97248 ){ 95973 97249 int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ 95974 97250 Index *pProbe; /* An index we are evaluating */ 95975 97251 Index *pIdx; /* Copy of pProbe, or zero for IPK index */ 95976 97252 int eqTermMask; /* Current mask of valid equality operators */ ................................................................................ 96004 97280 /* There is no INDEXED BY clause. Create a fake Index object to 96005 97281 ** represent the primary key */ 96006 97282 Index *pFirst; /* Any other index on the table */ 96007 97283 memset(&sPk, 0, sizeof(Index)); 96008 97284 sPk.nColumn = 1; 96009 97285 sPk.aiColumn = &aiColumnPk; 96010 97286 sPk.aiRowEst = aiRowEstPk; 96011 - aiRowEstPk[1] = 1; 96012 97287 sPk.onError = OE_Replace; 96013 97288 sPk.pTable = pSrc->pTab; 97289 + aiRowEstPk[0] = pSrc->pTab->nRowEst; 97290 + aiRowEstPk[1] = 1; 96014 97291 pFirst = pSrc->pTab->pIndex; 96015 97292 if( pSrc->notIndexed==0 ){ 96016 97293 sPk.pNext = pFirst; 96017 97294 } 96018 - /* The aiRowEstPk[0] is an estimate of the total number of rows in the 96019 - ** table. Get this information from the ANALYZE information if it is 96020 - ** available. If not available, assume the table 1 million rows in size. 96021 - */ 96022 - if( pFirst ){ 96023 - assert( pFirst->aiRowEst!=0 ); /* Allocated together with pFirst */ 96024 - aiRowEstPk[0] = pFirst->aiRowEst[0]; 96025 - }else{ 96026 - aiRowEstPk[0] = 1000000; 96027 - } 96028 97295 pProbe = &sPk; 96029 97296 wsFlagMask = ~( 96030 97297 WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE 96031 97298 ); 96032 97299 eqTermMask = WO_EQ|WO_IN; 96033 97300 pIdx = 0; 96034 97301 } ................................................................................ 96233 97500 /* If there are additional constraints on this table that cannot 96234 97501 ** be used with the current index, but which might lower the number 96235 97502 ** of output rows, adjust the nRow value accordingly. This only 96236 97503 ** matters if the current index is the least costly, so do not bother 96237 97504 ** with this step if we already know this index will not be chosen. 96238 97505 ** Also, never reduce the output row count below 2 using this step. 96239 97506 ** 96240 - ** Do not reduce the output row count if pSrc is the only table that 96241 - ** is notReady; if notReady is a power of two. This will be the case 96242 - ** when the main sqlite3WhereBegin() loop is scanning for a table with 96243 - ** and "optimal" index, and on such a scan the output row count 96244 - ** reduction is not valid because it does not update the "pCost->used" 96245 - ** bitmap. The notReady bitmap will also be a power of two when we 96246 - ** are scanning for the last table in a 64-way join. We are willing 96247 - ** to bypass this optimization in that corner case. 97507 + ** It is critical that the notValid mask be used here instead of 97508 + ** the notReady mask. When computing an "optimal" index, the notReady 97509 + ** mask will only have one bit set - the bit for the current table. 97510 + ** The notValid mask, on the other hand, always has all bits set for 97511 + ** tables that are not in outer loops. If notReady is used here instead 97512 + ** of notValid, then a optimal index that depends on inner joins loops 97513 + ** might be selected even when there exists an optimal index that has 97514 + ** no such dependency. 96248 97515 */ 96249 - if( nRow>2 && cost<=pCost->rCost && (notReady & (notReady-1))!=0 ){ 97516 + if( nRow>2 && cost<=pCost->rCost ){ 96250 97517 int k; /* Loop counter */ 96251 97518 int nSkipEq = nEq; /* Number of == constraints to skip */ 96252 97519 int nSkipRange = nBound; /* Number of < constraints to skip */ 96253 97520 Bitmask thisTab; /* Bitmap for pSrc */ 96254 97521 96255 97522 thisTab = getMask(pWC->pMaskSet, iCur); 96256 97523 for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){ 96257 97524 if( pTerm->wtFlags & TERM_VIRTUAL ) continue; 96258 - if( (pTerm->prereqAll & notReady)!=thisTab ) continue; 97525 + if( (pTerm->prereqAll & notValid)!=thisTab ) continue; 96259 97526 if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){ 96260 97527 if( nSkipEq ){ 96261 97528 /* Ignore the first nEq equality matches since the index 96262 97529 ** has already accounted for these */ 96263 97530 nSkipEq--; 96264 97531 }else{ 96265 97532 /* Assume each additional equality match reduces the result ................................................................................ 96333 97600 ); 96334 97601 96335 97602 WHERETRACE(("best index is: %s\n", 96336 97603 ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" : 96337 97604 pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk") 96338 97605 )); 96339 97606 96340 - bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost); 97607 + bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost); 96341 97608 bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost); 96342 97609 pCost->plan.wsFlags |= eqTermMask; 96343 97610 } 96344 97611 96345 97612 /* 96346 97613 ** Find the query plan for accessing table pSrc->pTab. Write the 96347 97614 ** best query plan and its cost into the WhereCost object supplied ................................................................................ 96348 97615 ** as the last parameter. This function may calculate the cost of 96349 97616 ** both real and virtual table scans. 96350 97617 */ 96351 97618 static void bestIndex( 96352 97619 Parse *pParse, /* The parsing context */ 96353 97620 WhereClause *pWC, /* The WHERE clause */ 96354 97621 struct SrcList_item *pSrc, /* The FROM clause term to search */ 96355 - Bitmask notReady, /* Mask of cursors that are not available */ 97622 + Bitmask notReady, /* Mask of cursors not available for indexing */ 97623 + Bitmask notValid, /* Cursors not available for any purpose */ 96356 97624 ExprList *pOrderBy, /* The ORDER BY clause */ 96357 97625 WhereCost *pCost /* Lowest cost query plan */ 96358 97626 ){ 96359 97627 #ifndef SQLITE_OMIT_VIRTUALTABLE 96360 97628 if( IsVirtual(pSrc->pTab) ){ 96361 97629 sqlite3_index_info *p = 0; 96362 - bestVirtualIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost, &p); 97630 + bestVirtualIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost,&p); 96363 97631 if( p->needToFreeIdxStr ){ 96364 97632 sqlite3_free(p->idxStr); 96365 97633 } 96366 97634 sqlite3DbFree(pParse->db, p); 96367 97635 }else 96368 97636 #endif 96369 97637 { 96370 - bestBtreeIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost); 97638 + bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost); 96371 97639 } 96372 97640 } 96373 97641 96374 97642 /* 96375 97643 ** Disable a term in the WHERE clause. Except, do not disable the term 96376 97644 ** if it controls a LEFT OUTER JOIN and it did not originate in the ON 96377 97645 ** or USING clause of that join. ................................................................................ 96857 98125 ** If there are no inequality constraints, then N is at 96858 98126 ** least one. 96859 98127 ** 96860 98128 ** This case is also used when there are no WHERE clause 96861 98129 ** constraints but an index is selected anyway, in order 96862 98130 ** to force the output order to conform to an ORDER BY. 96863 98131 */ 96864 - int aStartOp[] = { 98132 + static const u8 aStartOp[] = { 96865 98133 0, 96866 98134 0, 96867 98135 OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ 96868 98136 OP_Last, /* 3: (!start_constraints && startEq && bRev) */ 96869 98137 OP_SeekGt, /* 4: (start_constraints && !startEq && !bRev) */ 96870 98138 OP_SeekLt, /* 5: (start_constraints && !startEq && bRev) */ 96871 98139 OP_SeekGe, /* 6: (start_constraints && startEq && !bRev) */ 96872 98140 OP_SeekLe /* 7: (start_constraints && startEq && bRev) */ 96873 98141 }; 96874 - int aEndOp[] = { 98142 + static const u8 aEndOp[] = { 96875 98143 OP_Noop, /* 0: (!end_constraints) */ 96876 98144 OP_IdxGE, /* 1: (end_constraints && !bRev) */ 96877 98145 OP_IdxLT /* 2: (end_constraints && bRev) */ 96878 98146 }; 96879 - int nEq = pLevel->plan.nEq; 98147 + int nEq = pLevel->plan.nEq; /* Number of == or IN terms */ 96880 98148 int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ 96881 98149 int regBase; /* Base register holding constraint values */ 96882 98150 int r1; /* Temp register */ 96883 98151 WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ 96884 98152 WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ 96885 98153 int startEq; /* True if range start uses ==, >= or <= */ 96886 98154 int endEq; /* True if range end uses ==, >= or <= */ 96887 98155 int start_constraints; /* Start of range is constrained */ 96888 98156 int nConstraint; /* Number of constraint terms */ 96889 - Index *pIdx; /* The index we will be using */ 96890 - int iIdxCur; /* The VDBE cursor for the index */ 96891 - int nExtraReg = 0; /* Number of extra registers needed */ 96892 - int op; /* Instruction opcode */ 98157 + Index *pIdx; /* The index we will be using */ 98158 + int iIdxCur; /* The VDBE cursor for the index */ 98159 + int nExtraReg = 0; /* Number of extra registers needed */ 98160 + int op; /* Instruction opcode */ 96893 98161 char *zStartAff; /* Affinity for start of range constraint */ 96894 98162 char *zEndAff; /* Affinity for end of range constraint */ 96895 98163 96896 98164 pIdx = pLevel->plan.u.pIdx; 96897 98165 iIdxCur = pLevel->iIdxCur; 96898 98166 k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */ 96899 98167 ................................................................................ 97578 98846 ** were used as the innermost nested loop. In other words, a table 97579 98847 ** is chosen such that the cost of running that table cannot be reduced 97580 98848 ** by waiting for other tables to run first. This "optimal" test works 97581 98849 ** by first assuming that the FROM clause is on the inner loop and finding 97582 98850 ** its query plan, then checking to see if that query plan uses any 97583 98851 ** other FROM clause terms that are notReady. If no notReady terms are 97584 98852 ** used then the "optimal" query plan works. 98853 + ** 98854 + ** Note that the WhereCost.nRow parameter for an optimal scan might 98855 + ** not be as small as it would be if the table really were the innermost 98856 + ** join. The nRow value can be reduced by WHERE clause constraints 98857 + ** that do not use indices. But this nRow reduction only happens if the 98858 + ** table really is the innermost join. 97585 98859 ** 97586 98860 ** The second loop iteration is only performed if no optimal scan 97587 - ** strategies were found by the first loop. This 2nd iteration is used to 97588 - ** search for the lowest cost scan overall. 98861 + ** strategies were found by the first iteration. This second iteration 98862 + ** is used to search for the lowest cost scan overall. 97589 98863 ** 97590 98864 ** Previous versions of SQLite performed only the second iteration - 97591 98865 ** the next outermost loop was always that with the lowest overall 97592 98866 ** cost. However, this meant that SQLite could select the wrong plan 97593 98867 ** for scripts such as the following: 97594 98868 ** 97595 98869 ** CREATE TABLE t1(a, b); 97596 98870 ** CREATE TABLE t2(c, d); 97597 98871 ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a; 97598 98872 ** 97599 98873 ** The best strategy is to iterate through table t1 first. However it 97600 98874 ** is not possible to determine this with a simple greedy algorithm. 97601 - ** However, since the cost of a linear scan through table t2 is the same 98875 + ** Since the cost of a linear scan through table t2 is the same 97602 98876 ** as the cost of a linear scan through table t1, a simple greedy 97603 98877 ** algorithm may choose to use t2 for the outer loop, which is a much 97604 98878 ** costlier approach. 97605 98879 */ 97606 98880 nUnconstrained = 0; 97607 98881 notIndexed = 0; 97608 - for(isOptimal=(iFrom<nTabList-1); isOptimal>=0; isOptimal--){ 98882 + for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){ 97609 98883 Bitmask mask; /* Mask of tables not yet ready */ 97610 98884 for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){ 97611 98885 int doNotReorder; /* True if this table should not be reordered */ 97612 98886 WhereCost sCost; /* Cost information from best[Virtual]Index() */ 97613 98887 ExprList *pOrderBy; /* ORDER BY clause for index to optimize */ 97614 98888 97615 98889 doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0; ................................................................................ 97623 98897 pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0); 97624 98898 if( pTabItem->pIndex==0 ) nUnconstrained++; 97625 98899 97626 98900 assert( pTabItem->pTab ); 97627 98901 #ifndef SQLITE_OMIT_VIRTUALTABLE 97628 98902 if( IsVirtual(pTabItem->pTab) ){ 97629 98903 sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo; 97630 - bestVirtualIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost, pp); 98904 + bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy, 98905 + &sCost, pp); 97631 98906 }else 97632 98907 #endif 97633 98908 { 97634 - bestBtreeIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost); 98909 + bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy, 98910 + &sCost); 97635 98911 } 97636 98912 assert( isOptimal || (sCost.used¬Ready)==0 ); 97637 98913 97638 98914 /* If an INDEXED BY clause is present, then the plan must use that 97639 98915 ** index if it uses any index at all */ 97640 98916 assert( pTabItem->pIndex==0 97641 98917 || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ................................................................................ 102663 103939 #endif /* __cplusplus */ 102664 103940 102665 103941 102666 103942 /************** End of sqliteicu.h *******************************************/ 102667 103943 /************** Continuing where we left off in main.c ***********************/ 102668 103944 #endif 102669 103945 102670 -/* 102671 -** The version of the library 102672 -*/ 102673 103946 #ifndef SQLITE_AMALGAMATION 103947 +/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant 103948 +** contains the text of SQLITE_VERSION macro. 103949 +*/ 102674 103950 SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; 102675 103951 #endif 103952 + 103953 +/* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns 103954 +** a pointer to the to the sqlite3_version[] string constant. 103955 +*/ 102676 103956 SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } 103957 + 103958 +/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a 103959 +** pointer to a string constant whose value is the same as the 103960 +** SQLITE_SOURCE_ID C preprocessor macro. 103961 +*/ 102677 103962 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } 103963 + 103964 +/* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function 103965 +** returns an integer equal to SQLITE_VERSION_NUMBER. 103966 +*/ 102678 103967 SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } 103968 + 103969 +/* IMPLEMENTATION-OF: R-54823-41343 The sqlite3_threadsafe() function returns 103970 +** zero if and only if SQLite was compiled mutexing code omitted due to 103971 +** the SQLITE_THREADSAFE compile-time option being set to 0. 103972 +*/ 102679 103973 SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } 102680 103974 102681 103975 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) 102682 103976 /* 102683 103977 ** If the following function pointer is not NULL and if 102684 103978 ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing 102685 103979 ** I/O active are written using this function. These messages ................................................................................ 102792 104086 } 102793 104087 102794 104088 /* Do the rest of the initialization under the recursive mutex so 102795 104089 ** that we will be able to handle recursive calls into 102796 104090 ** sqlite3_initialize(). The recursive calls normally come through 102797 104091 ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other 102798 104092 ** recursive calls might also be possible. 104093 + ** 104094 + ** IMPLEMENTATION-OF: R-00140-37445 SQLite automatically serializes calls 104095 + ** to the xInit method, so the xInit method need not be threadsafe. 104096 + ** 104097 + ** The following mutex is what serializes access to the appdef pcache xInit 104098 + ** methods. The sqlite3_pcache_methods.xInit() all is embedded in the 104099 + ** call to sqlite3PcacheInitialize(). 102799 104100 */ 102800 104101 sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex); 102801 104102 if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ 102802 104103 FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); 102803 104104 sqlite3GlobalConfig.inProgress = 1; 102804 104105 memset(pHash, 0, sizeof(sqlite3GlobalFunctions)); 102805 104106 sqlite3RegisterGlobalFunctions(); ................................................................................ 103072 104373 */ 103073 104374 if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0; 103074 104375 if( cnt<0 ) cnt = 0; 103075 104376 if( sz==0 || cnt==0 ){ 103076 104377 sz = 0; 103077 104378 pStart = 0; 103078 104379 }else if( pBuf==0 ){ 103079 - sz = ROUND8(sz); 104380 + sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */ 103080 104381 sqlite3BeginBenignMalloc(); 103081 - pStart = sqlite3Malloc( sz*cnt ); 104382 + pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */ 103082 104383 sqlite3EndBenignMalloc(); 103083 104384 }else{ 103084 - sz = ROUNDDOWN8(sz); 104385 + sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */ 103085 104386 pStart = pBuf; 103086 104387 } 103087 104388 db->lookaside.pStart = pStart; 103088 104389 db->lookaside.pFree = 0; 103089 104390 db->lookaside.sz = (u16)sz; 103090 104391 if( pStart ){ 103091 104392 int i; ................................................................................ 103120 104421 */ 103121 104422 SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ 103122 104423 va_list ap; 103123 104424 int rc; 103124 104425 va_start(ap, op); 103125 104426 switch( op ){ 103126 104427 case SQLITE_DBCONFIG_LOOKASIDE: { 103127 - void *pBuf = va_arg(ap, void*); 103128 - int sz = va_arg(ap, int); 103129 - int cnt = va_arg(ap, int); 104428 + void *pBuf = va_arg(ap, void*); /* IMP: R-21112-12275 */ 104429 + int sz = va_arg(ap, int); /* IMP: R-47871-25994 */ 104430 + int cnt = va_arg(ap, int); /* IMP: R-04460-53386 */ 103130 104431 rc = setupLookaside(db, pBuf, sz, cnt); 103131 104432 break; 103132 104433 } 103133 104434 default: { 103134 - rc = SQLITE_ERROR; 104435 + rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ 103135 104436 break; 103136 104437 } 103137 104438 } 103138 104439 va_end(ap); 103139 104440 return rc; 103140 104441 } 103141 104442 ................................................................................ 103231 104532 db->pSavepoint = pTmp->pNext; 103232 104533 sqlite3DbFree(db, pTmp); 103233 104534 } 103234 104535 db->nSavepoint = 0; 103235 104536 db->nStatement = 0; 103236 104537 db->isTransactionSavepoint = 0; 103237 104538 } 104539 + 104540 +/* 104541 +** Invoke the destructor function associated with FuncDef p, if any. Except, 104542 +** if this is not the last copy of the function, do not invoke it. Multiple 104543 +** copies of a single function are created when create_function() is called 104544 +** with SQLITE_ANY as the encoding. 104545 +*/ 104546 +static void functionDestroy(sqlite3 *db, FuncDef *p){ 104547 + FuncDestructor *pDestructor = p->pDestructor; 104548 + if( pDestructor ){ 104549 + pDestructor->nRef--; 104550 + if( pDestructor->nRef==0 ){ 104551 + pDestructor->xDestroy(pDestructor->pUserData); 104552 + sqlite3DbFree(db, pDestructor); 104553 + } 104554 + } 104555 +} 103238 104556 103239 104557 /* 103240 104558 ** Close an existing SQLite database 103241 104559 */ 103242 104560 SQLITE_API int sqlite3_close(sqlite3 *db){ 103243 - HashElem *i; 104561 + HashElem *i; /* Hash table iterator */ 103244 104562 int j; 103245 104563 103246 104564 if( !db ){ 103247 104565 return SQLITE_OK; 103248 104566 } 103249 104567 if( !sqlite3SafetyCheckSickOrOk(db) ){ 103250 104568 return SQLITE_MISUSE_BKPT; ................................................................................ 103304 104622 assert( db->nDb<=2 ); 103305 104623 assert( db->aDb==db->aDbStatic ); 103306 104624 for(j=0; j<ArraySize(db->aFunc.a); j++){ 103307 104625 FuncDef *pNext, *pHash, *p; 103308 104626 for(p=db->aFunc.a[j]; p; p=pHash){ 103309 104627 pHash = p->pHash; 103310 104628 while( p ){ 104629 + functionDestroy(db, p); 103311 104630 pNext = p->pNext; 103312 104631 sqlite3DbFree(db, p); 103313 104632 p = pNext; 103314 104633 } 103315 104634 } 103316 104635 } 103317 104636 for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ ................................................................................ 103578 104897 sqlite3 *db, 103579 104898 const char *zFunctionName, 103580 104899 int nArg, 103581 104900 int enc, 103582 104901 void *pUserData, 103583 104902 void (*xFunc)(sqlite3_context*,int,sqlite3_value **), 103584 104903 void (*xStep)(sqlite3_context*,int,sqlite3_value **), 103585 - void (*xFinal)(sqlite3_context*) 104904 + void (*xFinal)(sqlite3_context*), 104905 + FuncDestructor *pDestructor 103586 104906 ){ 103587 104907 FuncDef *p; 103588 104908 int nName; 103589 104909 103590 104910 assert( sqlite3_mutex_held(db->mutex) ); 103591 104911 if( zFunctionName==0 || 103592 104912 (xFunc && (xFinal || xStep)) || ................................................................................ 103606 104926 ** to the hash table. 103607 104927 */ 103608 104928 if( enc==SQLITE_UTF16 ){ 103609 104929 enc = SQLITE_UTF16NATIVE; 103610 104930 }else if( enc==SQLITE_ANY ){ 103611 104931 int rc; 103612 104932 rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, 103613 - pUserData, xFunc, xStep, xFinal); 104933 + pUserData, xFunc, xStep, xFinal, pDestructor); 103614 104934 if( rc==SQLITE_OK ){ 103615 104935 rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, 103616 - pUserData, xFunc, xStep, xFinal); 104936 + pUserData, xFunc, xStep, xFinal, pDestructor); 103617 104937 } 103618 104938 if( rc!=SQLITE_OK ){ 103619 104939 return rc; 103620 104940 } 103621 104941 enc = SQLITE_UTF16BE; 103622 104942 } 103623 104943 #else ................................................................................ 103642 104962 } 103643 104963 103644 104964 p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 1); 103645 104965 assert(p || db->mallocFailed); 103646 104966 if( !p ){ 103647 104967 return SQLITE_NOMEM; 103648 104968 } 104969 + 104970 + /* If an older version of the function with a configured destructor is 104971 + ** being replaced invoke the destructor function here. */ 104972 + functionDestroy(db, p); 104973 + 104974 + if( pDestructor ){ 104975 + pDestructor->nRef++; 104976 + } 104977 + p->pDestructor = pDestructor; 103649 104978 p->flags = 0; 103650 104979 p->xFunc = xFunc; 103651 104980 p->xStep = xStep; 103652 104981 p->xFinalize = xFinal; 103653 104982 p->pUserData = pUserData; 103654 104983 p->nArg = (u16)nArg; 103655 104984 return SQLITE_OK; ................................................................................ 103656 104985 } 103657 104986 103658 104987 /* 103659 104988 ** Create new user functions. 103660 104989 */ 103661 104990 SQLITE_API int sqlite3_create_function( 103662 104991 sqlite3 *db, 103663 - const char *zFunctionName, 104992 + const char *zFunc, 103664 104993 int nArg, 103665 104994 int enc, 103666 104995 void *p, 103667 104996 void (*xFunc)(sqlite3_context*,int,sqlite3_value **), 103668 104997 void (*xStep)(sqlite3_context*,int,sqlite3_value **), 103669 104998 void (*xFinal)(sqlite3_context*) 103670 104999 ){ 103671 - int rc; 105000 + return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xFunc, xStep, 105001 + xFinal, 0); 105002 +} 105003 + 105004 +SQLITE_API int sqlite3_create_function_v2( 105005 + sqlite3 *db, 105006 + const char *zFunc, 105007 + int nArg, 105008 + int enc, 105009 + void *p, 105010 + void (*xFunc)(sqlite3_context*,int,sqlite3_value **), 105011 + void (*xStep)(sqlite3_context*,int,sqlite3_value **), 105012 + void (*xFinal)(sqlite3_context*), 105013 + void (*xDestroy)(void *) 105014 +){ 105015 + int rc = SQLITE_ERROR; 105016 + FuncDestructor *pArg = 0; 103672 105017 sqlite3_mutex_enter(db->mutex); 103673 - rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); 105018 + if( xDestroy ){ 105019 + pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor)); 105020 + if( !pArg ){ 105021 + xDestroy(p); 105022 + goto out; 105023 + } 105024 + pArg->xDestroy = xDestroy; 105025 + pArg->pUserData = p; 105026 + } 105027 + rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xFunc, xStep, xFinal, pArg); 105028 + if( pArg && pArg->nRef==0 ){ 105029 + assert( rc!=SQLITE_OK ); 105030 + xDestroy(p); 105031 + sqlite3DbFree(db, pArg); 105032 + } 105033 + 105034 + out: 103674 105035 rc = sqlite3ApiExit(db, rc); 103675 105036 sqlite3_mutex_leave(db->mutex); 103676 105037 return rc; 103677 105038 } 103678 105039 103679 105040 #ifndef SQLITE_OMIT_UTF16 103680 105041 SQLITE_API int sqlite3_create_function16( ................................................................................ 103688 105049 void (*xFinal)(sqlite3_context*) 103689 105050 ){ 103690 105051 int rc; 103691 105052 char *zFunc8; 103692 105053 sqlite3_mutex_enter(db->mutex); 103693 105054 assert( !db->mallocFailed ); 103694 105055 zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); 103695 - rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); 105056 + rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal,0); 103696 105057 sqlite3DbFree(db, zFunc8); 103697 105058 rc = sqlite3ApiExit(db, rc); 103698 105059 sqlite3_mutex_leave(db->mutex); 103699 105060 return rc; 103700 105061 } 103701 105062 #endif 103702 105063 ................................................................................ 103719 105080 int nArg 103720 105081 ){ 103721 105082 int nName = sqlite3Strlen30(zName); 103722 105083 int rc; 103723 105084 sqlite3_mutex_enter(db->mutex); 103724 105085 if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ 103725 105086 sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, 103726 - 0, sqlite3InvalidFunction, 0, 0); 105087 + 0, sqlite3InvalidFunction, 0, 0, 0); 103727 105088 } 103728 105089 rc = sqlite3ApiExit(db, SQLITE_OK); 103729 105090 sqlite3_mutex_leave(db->mutex); 103730 105091 return rc; 103731 105092 } 103732 105093 103733 105094 #ifndef SQLITE_OMIT_TRACE ................................................................................ 103857 105218 ** 103858 105219 ** The callback registered by this function replaces any existing callback 103859 105220 ** registered using sqlite3_wal_hook(). Likewise, registering a callback 103860 105221 ** using sqlite3_wal_hook() disables the automatic checkpoint mechanism 103861 105222 ** configured by this function. 103862 105223 */ 103863 105224 SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ 103864 -#ifndef SQLITE_OMIT_WAL 105225 +#ifdef SQLITE_OMIT_WAL 105226 + UNUSED_PARAMETER(db); 105227 + UNUSED_PARAMETER(nFrame); 105228 +#else 103865 105229 if( nFrame>0 ){ 103866 105230 sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame)); 103867 105231 }else{ 103868 105232 sqlite3_wal_hook(db, 0, 0); 103869 105233 } 103870 105234 #endif 103871 105235 return SQLITE_OK; ................................................................................ 103987 105351 return 1; 103988 105352 #endif 103989 105353 #if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3 103990 105354 return 0; 103991 105355 #endif 103992 105356 } 103993 105357 103994 -/* 103995 -** This routine is called to create a connection to a database BTree 103996 -** driver. If zFilename is the name of a file, then that file is 103997 -** opened and used. If zFilename is the magic name ":memory:" then 103998 -** the database is stored in memory (and is thus forgotten as soon as 103999 -** the connection is closed.) If zFilename is NULL then the database 104000 -** is a "virtual" database for transient use only and is deleted as 104001 -** soon as the connection is closed. 104002 -** 104003 -** A virtual database can be either a disk file (that is automatically 104004 -** deleted when the file is closed) or it an be held entirely in memory. 104005 -** The sqlite3TempInMemory() function is used to determine which. 104006 -*/ 104007 -SQLITE_PRIVATE int sqlite3BtreeFactory( 104008 - sqlite3 *db, /* Main database when opening aux otherwise 0 */ 104009 - const char *zFilename, /* Name of the file containing the BTree database */ 104010 - int omitJournal, /* if TRUE then do not journal this file */ 104011 - int nCache, /* How many pages in the page cache */ 104012 - int vfsFlags, /* Flags passed through to vfsOpen */ 104013 - Btree **ppBtree /* Pointer to new Btree object written here */ 104014 -){ 104015 - int btFlags = 0; 104016 - int rc; 104017 - 104018 - assert( sqlite3_mutex_held(db->mutex) ); 104019 - assert( ppBtree != 0); 104020 - if( omitJournal ){ 104021 - btFlags |= BTREE_OMIT_JOURNAL; 104022 - } 104023 - if( db->flags & SQLITE_NoReadlock ){ 104024 - btFlags |= BTREE_NO_READLOCK; 104025 - } 104026 -#ifndef SQLITE_OMIT_MEMORYDB 104027 - if( zFilename==0 && sqlite3TempInMemory(db) ){ 104028 - zFilename = ":memory:"; 104029 - } 104030 -#endif 104031 - 104032 - if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (zFilename==0 || *zFilename==0) ){ 104033 - vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; 104034 - } 104035 - rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btFlags, vfsFlags); 104036 - 104037 - /* If the B-Tree was successfully opened, set the pager-cache size to the 104038 - ** default value. Except, if the call to BtreeOpen() returned a handle 104039 - ** open on an existing shared pager-cache, do not change the pager-cache 104040 - ** size. 104041 - */ 104042 - if( rc==SQLITE_OK && 0==sqlite3BtreeSchema(*ppBtree, 0, 0) ){ 104043 - sqlite3BtreeSetCacheSize(*ppBtree, nCache); 104044 - } 104045 - return rc; 104046 -} 104047 - 104048 105358 /* 104049 105359 ** Return UTF-8 encoded English language explanation of the most recent 104050 105360 ** error. 104051 105361 */ 104052 105362 SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ 104053 105363 const char *z; 104054 105364 if( !db ){ ................................................................................ 104283 105593 ** 104284 105594 ** A new lower limit does not shrink existing constructs. 104285 105595 ** It merely prevents new constructs that exceed the limit 104286 105596 ** from forming. 104287 105597 */ 104288 105598 SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ 104289 105599 int oldLimit; 105600 + 105601 + 105602 + /* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE_LIMIT_NAME 105603 + ** there is a hard upper bound set at compile-time by a C preprocessor 105604 + ** macro called SQLITE_MAX_NAME. (The "_LIMIT_" in the name is changed to 105605 + ** "_MAX_".) 105606 + */ 105607 + assert( aHardLimit[SQLITE_LIMIT_LENGTH]==SQLITE_MAX_LENGTH ); 105608 + assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH ); 105609 + assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN ); 105610 + assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH ); 105611 + assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT); 105612 + assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP ); 105613 + assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG ); 105614 + assert( aHardLimit[SQLITE_LIMIT_ATTACHED]==SQLITE_MAX_ATTACHED ); 105615 + assert( aHardLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]== 105616 + SQLITE_MAX_LIKE_PATTERN_LENGTH ); 105617 + assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER); 105618 + assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH ); 105619 + assert( SQLITE_LIMIT_TRIGGER_DEPTH==(SQLITE_N_LIMIT-1) ); 105620 + 105621 + 104290 105622 if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ 104291 105623 return -1; 104292 105624 } 104293 105625 oldLimit = db->aLimit[limitId]; 104294 - if( newLimit>=0 ){ 105626 + if( newLimit>=0 ){ /* IMP: R-52476-28732 */ 104295 105627 if( newLimit>aHardLimit[limitId] ){ 104296 - newLimit = aHardLimit[limitId]; 105628 + newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */ 104297 105629 } 104298 105630 db->aLimit[limitId] = newLimit; 104299 105631 } 104300 - return oldLimit; 105632 + return oldLimit; /* IMP: R-53341-35419 */ 104301 105633 } 104302 105634 104303 105635 /* 104304 105636 ** This routine does the work of opening a database on behalf of 104305 105637 ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" 104306 105638 ** is UTF-8 encoded. 104307 105639 */ ................................................................................ 104316 105648 int isThreadsafe; 104317 105649 104318 105650 *ppDb = 0; 104319 105651 #ifndef SQLITE_OMIT_AUTOINIT 104320 105652 rc = sqlite3_initialize(); 104321 105653 if( rc ) return rc; 104322 105654 #endif 105655 + 105656 + /* Only allow sensible combinations of bits in the flags argument. 105657 + ** Throw an error if any non-sense combination is used. If we 105658 + ** do not block illegal combinations here, it could trigger 105659 + ** assert() statements in deeper layers. Sensible combinations 105660 + ** are: 105661 + ** 105662 + ** 1: SQLITE_OPEN_READONLY 105663 + ** 2: SQLITE_OPEN_READWRITE 105664 + ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE 105665 + */ 105666 + assert( SQLITE_OPEN_READONLY == 0x01 ); 105667 + assert( SQLITE_OPEN_READWRITE == 0x02 ); 105668 + assert( SQLITE_OPEN_CREATE == 0x04 ); 105669 + testcase( (1<<(flags&7))==0x02 ); /* READONLY */ 105670 + testcase( (1<<(flags&7))==0x04 ); /* READWRITE */ 105671 + testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */ 105672 + if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE; 104323 105673 104324 105674 if( sqlite3GlobalConfig.bCoreMutex==0 ){ 104325 105675 isThreadsafe = 0; 104326 105676 }else if( flags & SQLITE_OPEN_NOMUTEX ){ 104327 105677 isThreadsafe = 0; 104328 105678 }else if( flags & SQLITE_OPEN_FULLMUTEX ){ 104329 105679 isThreadsafe = 1; ................................................................................ 104350 105700 SQLITE_OPEN_TEMP_DB | 104351 105701 SQLITE_OPEN_TRANSIENT_DB | 104352 105702 SQLITE_OPEN_MAIN_JOURNAL | 104353 105703 SQLITE_OPEN_TEMP_JOURNAL | 104354 105704 SQLITE_OPEN_SUBJOURNAL | 104355 105705 SQLITE_OPEN_MASTER_JOURNAL | 104356 105706 SQLITE_OPEN_NOMUTEX | 104357 - SQLITE_OPEN_FULLMUTEX 105707 + SQLITE_OPEN_FULLMUTEX | 105708 + SQLITE_OPEN_WAL 104358 105709 ); 104359 105710 104360 105711 /* Allocate the sqlite data structure */ 104361 105712 db = sqlite3MallocZero( sizeof(sqlite3) ); 104362 105713 if( db==0 ) goto opendb_out; 104363 105714 if( isThreadsafe ){ 104364 105715 db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); ................................................................................ 104422 105773 104423 105774 /* Also add a UTF-8 case-insensitive collation sequence. */ 104424 105775 createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0, 104425 105776 nocaseCollatingFunc, 0); 104426 105777 104427 105778 /* Open the backend database driver */ 104428 105779 db->openFlags = flags; 104429 - rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE, 104430 - flags | SQLITE_OPEN_MAIN_DB, 104431 - &db->aDb[0].pBt); 105780 + rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0, 105781 + flags | SQLITE_OPEN_MAIN_DB); 104432 105782 if( rc!=SQLITE_OK ){ 104433 105783 if( rc==SQLITE_IOERR_NOMEM ){ 104434 105784 rc = SQLITE_NOMEM; 104435 105785 } 104436 105786 sqlite3Error(db, rc, 0); 104437 105787 goto opendb_out; 104438 105788 } ................................................................................ 105130 106480 ** 105131 106481 ** Return the size of a pcache header in bytes. 105132 106482 */ 105133 106483 case SQLITE_TESTCTRL_PGHDRSZ: { 105134 106484 rc = sizeof(PgHdr); 105135 106485 break; 105136 106486 } 106487 + 106488 + /* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree); 106489 + ** 106490 + ** Pass pFree into sqlite3ScratchFree(). 106491 + ** If sz>0 then allocate a scratch buffer into pNew. 106492 + */ 106493 + case SQLITE_TESTCTRL_SCRATCHMALLOC: { 106494 + void *pFree, **ppNew; 106495 + int sz; 106496 + sz = va_arg(ap, int); 106497 + ppNew = va_arg(ap, void**); 106498 + pFree = va_arg(ap, void*); 106499 + if( sz ) *ppNew = sqlite3ScratchMalloc(sz); 106500 + sqlite3ScratchFree(pFree); 106501 + break; 106502 + } 105137 106503 105138 106504 } 105139 106505 va_end(ap); 105140 106506 #endif /* SQLITE_OMIT_BUILTIN_TEST */ 105141 106507 return rc; 105142 106508 } 105143 106509 ................................................................................ 106319 107685 Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, 106320 107686 int (*)(Fts3Table *, void *, char *, int, char *, int), void * 106321 107687 ); 106322 107688 SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); 106323 107689 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); 106324 107690 SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*); 106325 107691 SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*); 107692 +SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); 106326 107693 106327 107694 /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ 106328 107695 #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 106329 107696 #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 106330 107697 #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 106331 107698 #define FTS3_SEGMENT_PREFIX 0x00000008 106332 107699 ................................................................................ 108268 109635 if( rc==SQLITE_ERROR ){ 108269 109636 p->base.zErrMsg = sqlite3_mprintf("malformed MATCH expression: [%s]", 108270 109637 zQuery); 108271 109638 } 108272 109639 return rc; 108273 109640 } 108274 109641 109642 + rc = sqlite3Fts3ReadLock(p); 109643 + if( rc!=SQLITE_OK ) return rc; 109644 + 108275 109645 rc = evalFts3Expr(p, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0); 108276 109646 pCsr->pNextId = pCsr->aDoclist; 108277 109647 pCsr->iPrevId = 0; 108278 109648 } 108279 109649 108280 109650 if( rc!=SQLITE_OK ) return rc; 108281 109651 return fts3NextMethod(pCursor); ................................................................................ 108646 110016 ** Implementation of FTS3 xRename method. Rename an fts3 table. 108647 110017 */ 108648 110018 static int fts3RenameMethod( 108649 110019 sqlite3_vtab *pVtab, /* Virtual table handle */ 108650 110020 const char *zName /* New name of table */ 108651 110021 ){ 108652 110022 Fts3Table *p = (Fts3Table *)pVtab; 108653 - sqlite3 *db; /* Database connection */ 110023 + sqlite3 *db = p->db; /* Database connection */ 108654 110024 int rc; /* Return Code */ 108655 - 108656 - db = p->db; 108657 - rc = SQLITE_OK; 110025 + 110026 + rc = sqlite3Fts3PendingTermsFlush(p); 110027 + if( rc!=SQLITE_OK ){ 110028 + return rc; 110029 + } 110030 + 108658 110031 fts3DbExec(&rc, db, 108659 110032 "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", 108660 110033 p->zDb, p->zName, zName 108661 110034 ); 108662 110035 if( rc==SQLITE_ERROR ) rc = SQLITE_OK; 108663 110036 if( p->bHasDocsize ){ 108664 110037 fts3DbExec(&rc, db, ................................................................................ 108718 110091 /* 108719 110092 ** The fts3 built-in tokenizers - "simple" and "porter" - are implemented 108720 110093 ** in files fts3_tokenizer1.c and fts3_porter.c respectively. The following 108721 110094 ** two forward declarations are for functions declared in these files 108722 110095 ** used to retrieve the respective implementations. 108723 110096 ** 108724 110097 ** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed 108725 -** to by the argument to point a the "simple" tokenizer implementation. 110098 +** to by the argument to point to the "simple" tokenizer implementation. 108726 110099 ** Function ...PorterTokenizerModule() sets *pModule to point to the 108727 110100 ** porter tokenizer/stemmer implementation. 108728 110101 */ 108729 110102 SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); 108730 110103 SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule); 108731 110104 SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); 108732 110105 ................................................................................ 108920 110293 ** an integer that falls outside of the range of the unsigned char type 108921 110294 ** is undefined (and sometimes, "undefined" means segfault). This wrapper 108922 110295 ** is defined to accept an argument of type char, and always returns 0 for 108923 110296 ** any values that fall outside of the range of the unsigned char type (i.e. 108924 110297 ** negative values). 108925 110298 */ 108926 110299 static int fts3isspace(char c){ 108927 - return (c&0x80)==0 ? isspace(c) : 0; 110300 + return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f'; 108928 110301 } 108929 110302 108930 110303 /* 108931 110304 ** Extract the next token from buffer z (length n) using the tokenizer 108932 110305 ** and other information (column names etc.) in pParse. Create an Fts3Expr 108933 110306 ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this 108934 110307 ** single token and set *ppExpr to point to it. If the end of the buffer is ................................................................................ 111307 112680 int nTokenAllocated; /* space allocated to zToken buffer */ 111308 112681 } simple_tokenizer_cursor; 111309 112682 111310 112683 111311 112684 static int simpleDelim(simple_tokenizer *t, unsigned char c){ 111312 112685 return c<0x80 && t->delim[c]; 111313 112686 } 112687 +static int fts3_isalnum(int x){ 112688 + return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z'); 112689 +} 111314 112690 111315 112691 /* 111316 112692 ** Create a new tokenizer instance. 111317 112693 */ 111318 112694 static int simpleCreate( 111319 112695 int argc, const char * const *argv, 111320 112696 sqlite3_tokenizer **ppTokenizer ................................................................................ 111341 112717 } 111342 112718 t->delim[ch] = 1; 111343 112719 } 111344 112720 } else { 111345 112721 /* Mark non-alphanumeric ASCII characters as delimiters */ 111346 112722 int i; 111347 112723 for(i=1; i<0x80; i++){ 111348 - t->delim[i] = !isalnum(i) ? -1 : 0; 112724 + t->delim[i] = !fts3_isalnum(i) ? -1 : 0; 111349 112725 } 111350 112726 } 111351 112727 111352 112728 *ppTokenizer = &t->base; 111353 112729 return SQLITE_OK; 111354 112730 } 111355 112731 ................................................................................ 111447 112823 c->pToken = pNew; 111448 112824 } 111449 112825 for(i=0; i<n; i++){ 111450 112826 /* TODO(shess) This needs expansion to handle UTF-8 111451 112827 ** case-insensitivity. 111452 112828 */ 111453 112829 unsigned char ch = p[iStartOffset+i]; 111454 - c->pToken[i] = (char)(ch<0x80 ? tolower(ch) : ch); 112830 + c->pToken[i] = (char)((ch>='A' && ch<='Z') ? ch-'A'+'a' : ch); 111455 112831 } 111456 112832 *ppToken = c->pToken; 111457 112833 *pnBytes = n; 111458 112834 *piStartOffset = iStartOffset; 111459 112835 *piEndOffset = c->iOffset; 111460 112836 *piPosition = c->iToken++; 111461 112837 ................................................................................ 111806 113182 *pzBlock = (char *)sqlite3_column_blob(pStmt, 0); 111807 113183 if( sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){ 111808 113184 return SQLITE_CORRUPT; 111809 113185 } 111810 113186 } 111811 113187 return SQLITE_OK; 111812 113188 } 113189 + 113190 +/* 113191 +** This function ensures that the caller has obtained a shared-cache 113192 +** table-lock on the %_content table. This is required before reading 113193 +** data from the fts3 table. If this lock is not acquired first, then 113194 +** the caller may end up holding read-locks on the %_segments and %_segdir 113195 +** tables, but no read-lock on the %_content table. If this happens 113196 +** a second connection will be able to write to the fts3 table, but 113197 +** attempting to commit those writes might return SQLITE_LOCKED or 113198 +** SQLITE_LOCKED_SHAREDCACHE (because the commit attempts to obtain 113199 +** write-locks on the %_segments and %_segdir ** tables). 113200 +** 113201 +** We try to avoid this because if FTS3 returns any error when committing 113202 +** a transaction, the whole transaction will be rolled back. And this is 113203 +** not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. It can 113204 +** still happen if the user reads data directly from the %_segments or 113205 +** %_segdir tables instead of going through FTS3 though. 113206 +*/ 113207 +SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *p){ 113208 + int rc; /* Return code */ 113209 + sqlite3_stmt *pStmt; /* Statement used to obtain lock */ 113210 + 113211 + rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0); 113212 + if( rc==SQLITE_OK ){ 113213 + sqlite3_bind_null(pStmt, 1); 113214 + sqlite3_step(pStmt); 113215 + rc = sqlite3_reset(pStmt); 113216 + } 113217 + return rc; 113218 +} 111813 113219 111814 113220 /* 111815 113221 ** Set *ppStmt to a statement handle that may be used to iterate through 111816 113222 ** all rows in the %_segdir table, from oldest to newest. If successful, 111817 113223 ** return SQLITE_OK. If an error occurs while preparing the statement, 111818 113224 ** return an SQLite error code. 111819 113225 ** ................................................................................ 115297 116703 ** May you find forgiveness for yourself and forgive others. 115298 116704 ** May you share freely, never taking more than you give. 115299 116705 ** 115300 116706 ************************************************************************* 115301 116707 ** This file contains code for implementations of the r-tree and r*-tree 115302 116708 ** algorithms packaged as an SQLite virtual table module. 115303 116709 */ 116710 + 116711 +/* 116712 +** Database Format of R-Tree Tables 116713 +** -------------------------------- 116714 +** 116715 +** The data structure for a single virtual r-tree table is stored in three 116716 +** native SQLite tables declared as follows. In each case, the '%' character 116717 +** in the table name is replaced with the user-supplied name of the r-tree 116718 +** table. 116719 +** 116720 +** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB) 116721 +** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) 116722 +** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER) 116723 +** 116724 +** The data for each node of the r-tree structure is stored in the %_node 116725 +** table. For each node that is not the root node of the r-tree, there is 116726 +** an entry in the %_parent table associating the node with its parent. 116727 +** And for each row of data in the table, there is an entry in the %_rowid 116728 +** table that maps from the entries rowid to the id of the node that it 116729 +** is stored on. 116730 +** 116731 +** The root node of an r-tree always exists, even if the r-tree table is 116732 +** empty. The nodeno of the root node is always 1. All other nodes in the 116733 +** table must be the same size as the root node. The content of each node 116734 +** is formatted as follows: 116735 +** 116736 +** 1. If the node is the root node (node 1), then the first 2 bytes 116737 +** of the node contain the tree depth as a big-endian integer. 116738 +** For non-root nodes, the first 2 bytes are left unused. 116739 +** 116740 +** 2. The next 2 bytes contain the number of entries currently 116741 +** stored in the node. 116742 +** 116743 +** 3. The remainder of the node contains the node entries. Each entry 116744 +** consists of a single 8-byte integer followed by an even number 116745 +** of 4-byte coordinates. For leaf nodes the integer is the rowid 116746 +** of a record. For internal nodes it is the node number of a 116747 +** child page. 116748 +*/ 115304 116749 115305 116750 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) 115306 116751 115307 116752 /* 115308 116753 ** This file contains an implementation of a couple of different variants 115309 116754 ** of the r-tree algorithm. See the README file for further details. The 115310 116755 ** same data-structure is used for all, but the algorithms for insert and ................................................................................ 115338 116783 #define PickSeeds LinearPickSeeds 115339 116784 #define AssignCells splitNodeGuttman 115340 116785 #endif 115341 116786 #if VARIANT_RSTARTREE_SPLIT 115342 116787 #define AssignCells splitNodeStartree 115343 116788 #endif 115344 116789 116790 +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) 116791 +# define NDEBUG 1 116792 +#endif 115345 116793 115346 116794 #ifndef SQLITE_CORE 115347 116795 SQLITE_EXTENSION_INIT1 115348 116796 #else 115349 116797 #endif 115350 116798 115351 116799 115352 116800 #ifndef SQLITE_AMALGAMATION 116801 +#include "sqlite3rtree.h" 115353 116802 typedef sqlite3_int64 i64; 115354 116803 typedef unsigned char u8; 115355 116804 typedef unsigned int u32; 115356 116805 #endif 115357 116806 115358 116807 typedef struct Rtree Rtree; 115359 116808 typedef struct RtreeCursor RtreeCursor; 115360 116809 typedef struct RtreeNode RtreeNode; 115361 116810 typedef struct RtreeCell RtreeCell; 115362 116811 typedef struct RtreeConstraint RtreeConstraint; 116812 +typedef struct RtreeMatchArg RtreeMatchArg; 116813 +typedef struct RtreeGeomCallback RtreeGeomCallback; 115363 116814 typedef union RtreeCoord RtreeCoord; 115364 116815 115365 116816 /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ 115366 116817 #define RTREE_MAX_DIMENSIONS 5 115367 116818 115368 116819 /* Size of hash table Rtree.aHash. This hash table is not expected to 115369 116820 ** ever contain very many entries, so a fixed number of buckets is ................................................................................ 115425 116876 ** If an R*-tree "Reinsert" operation is required, the same number of 115426 116877 ** cells are removed from the overfull node and reinserted into the tree. 115427 116878 */ 115428 116879 #define RTREE_MINCELLS(p) ((((p)->iNodeSize-4)/(p)->nBytesPerCell)/3) 115429 116880 #define RTREE_REINSERT(p) RTREE_MINCELLS(p) 115430 116881 #define RTREE_MAXCELLS 51 115431 116882 116883 +/* 116884 +** The smallest possible node-size is (512-64)==448 bytes. And the largest 116885 +** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates). 116886 +** Therefore all non-root nodes must contain at least 3 entries. Since 116887 +** 2^40 is greater than 2^64, an r-tree structure always has a depth of 116888 +** 40 or less. 116889 +*/ 116890 +#define RTREE_MAX_DEPTH 40 116891 + 115432 116892 /* 115433 116893 ** An rtree cursor object. 115434 116894 */ 115435 116895 struct RtreeCursor { 115436 116896 sqlite3_vtab_cursor base; 115437 116897 RtreeNode *pNode; /* Node cursor is currently pointing at */ 115438 116898 int iCell; /* Index of current cell in pNode */ ................................................................................ 115457 116917 ((double)coord.i) \ 115458 116918 ) 115459 116919 115460 116920 /* 115461 116921 ** A search constraint. 115462 116922 */ 115463 116923 struct RtreeConstraint { 115464 - int iCoord; /* Index of constrained coordinate */ 115465 - int op; /* Constraining operation */ 115466 - double rValue; /* Constraint value. */ 116924 + int iCoord; /* Index of constrained coordinate */ 116925 + int op; /* Constraining operation */ 116926 + double rValue; /* Constraint value. */ 116927 + int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); 116928 + sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ 115467 116929 }; 115468 116930 115469 116931 /* Possible values for RtreeConstraint.op */ 115470 -#define RTREE_EQ 0x41 115471 -#define RTREE_LE 0x42 115472 -#define RTREE_LT 0x43 115473 -#define RTREE_GE 0x44 115474 -#define RTREE_GT 0x45 116932 +#define RTREE_EQ 0x41 116933 +#define RTREE_LE 0x42 116934 +#define RTREE_LT 0x43 116935 +#define RTREE_GE 0x44 116936 +#define RTREE_GT 0x45 116937 +#define RTREE_MATCH 0x46 115475 116938 115476 116939 /* 115477 116940 ** An rtree structure node. 115478 -** 115479 -** Data format (RtreeNode.zData): 115480 -** 115481 -** 1. If the node is the root node (node 1), then the first 2 bytes 115482 -** of the node contain the tree depth as a big-endian integer. 115483 -** For non-root nodes, the first 2 bytes are left unused. 115484 -** 115485 -** 2. The next 2 bytes contain the number of entries currently 115486 -** stored in the node. 115487 -** 115488 -** 3. The remainder of the node contains the node entries. Each entry 115489 -** consists of a single 8-byte integer followed by an even number 115490 -** of 4-byte coordinates. For leaf nodes the integer is the rowid 115491 -** of a record. For internal nodes it is the node number of a 115492 -** child page. 115493 116941 */ 115494 116942 struct RtreeNode { 115495 116943 RtreeNode *pParent; /* Parent node */ 115496 116944 i64 iNode; 115497 116945 int nRef; 115498 116946 int isDirty; 115499 116947 u8 *zData; ................................................................................ 115505 116953 ** Structure to store a deserialized rtree record. 115506 116954 */ 115507 116955 struct RtreeCell { 115508 116956 i64 iRowid; 115509 116957 RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; 115510 116958 }; 115511 116959 116960 + 116961 +/* 116962 +** Value for the first field of every RtreeMatchArg object. The MATCH 116963 +** operator tests that the first field of a blob operand matches this 116964 +** value to avoid operating on invalid blobs (which could cause a segfault). 116965 +*/ 116966 +#define RTREE_GEOMETRY_MAGIC 0x891245AB 116967 + 116968 +/* 116969 +** An instance of this structure must be supplied as a blob argument to 116970 +** the right-hand-side of an SQL MATCH operator used to constrain an 116971 +** r-tree query. 116972 +*/ 116973 +struct RtreeMatchArg { 116974 + u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ 116975 + int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); 116976 + void *pContext; 116977 + int nParam; 116978 + double aParam[1]; 116979 +}; 116980 + 116981 +/* 116982 +** When a geometry callback is created (see sqlite3_rtree_geometry_callback), 116983 +** a single instance of the following structure is allocated. It is used 116984 +** as the context for the user-function created by by s_r_g_c(). The object 116985 +** is eventually deleted by the destructor mechanism provided by 116986 +** sqlite3_create_function_v2() (which is called by s_r_g_c() to create 116987 +** the geometry callback function). 116988 +*/ 116989 +struct RtreeGeomCallback { 116990 + int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); 116991 + void *pContext; 116992 +}; 116993 + 115512 116994 #ifndef MAX 115513 116995 # define MAX(x,y) ((x) < (y) ? (y) : (x)) 115514 116996 #endif 115515 116997 #ifndef MIN 115516 116998 # define MIN(x,y) ((x) > (y) ? (y) : (x)) 115517 116999 #endif 115518 117000 ................................................................................ 115587 117069 } 115588 117070 } 115589 117071 115590 117072 /* 115591 117073 ** Clear the content of node p (set all bytes to 0x00). 115592 117074 */ 115593 117075 static void nodeZero(Rtree *pRtree, RtreeNode *p){ 115594 - if( p ){ 115595 - memset(&p->zData[2], 0, pRtree->iNodeSize-2); 115596 - p->isDirty = 1; 115597 - } 117076 + memset(&p->zData[2], 0, pRtree->iNodeSize-2); 117077 + p->isDirty = 1; 115598 117078 } 115599 117079 115600 117080 /* 115601 117081 ** Given a node number iNode, return the corresponding key to use 115602 117082 ** in the Rtree.aHash table. 115603 117083 */ 115604 117084 static int nodeHash(i64 iNode){ ................................................................................ 115610 117090 115611 117091 /* 115612 117092 ** Search the node hash table for node iNode. If found, return a pointer 115613 117093 ** to it. Otherwise, return 0. 115614 117094 */ 115615 117095 static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){ 115616 117096 RtreeNode *p; 115617 - assert( iNode!=0 ); 115618 117097 for(p=pRtree->aHash[nodeHash(iNode)]; p && p->iNode!=iNode; p=p->pNext); 115619 117098 return p; 115620 117099 } 115621 117100 115622 117101 /* 115623 117102 ** Add node pNode to the node hash table. 115624 117103 */ 115625 117104 static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){ 115626 - if( pNode ){ 115627 - int iHash; 115628 - assert( pNode->pNext==0 ); 115629 - iHash = nodeHash(pNode->iNode); 115630 - pNode->pNext = pRtree->aHash[iHash]; 115631 - pRtree->aHash[iHash] = pNode; 115632 - } 117105 + int iHash; 117106 + assert( pNode->pNext==0 ); 117107 + iHash = nodeHash(pNode->iNode); 117108 + pNode->pNext = pRtree->aHash[iHash]; 117109 + pRtree->aHash[iHash] = pNode; 115633 117110 } 115634 117111 115635 117112 /* 115636 117113 ** Remove node pNode from the node hash table. 115637 117114 */ 115638 117115 static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){ 115639 117116 RtreeNode **pp; ................................................................................ 115647 117124 115648 117125 /* 115649 117126 ** Allocate and return new r-tree node. Initially, (RtreeNode.iNode==0), 115650 117127 ** indicating that node has not yet been assigned a node number. It is 115651 117128 ** assigned a node number when nodeWrite() is called to write the 115652 117129 ** node contents out to the database. 115653 117130 */ 115654 -static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent, int zero){ 117131 +static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ 115655 117132 RtreeNode *pNode; 115656 117133 pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize); 115657 117134 if( pNode ){ 115658 - memset(pNode, 0, sizeof(RtreeNode) + (zero?pRtree->iNodeSize:0)); 117135 + memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); 115659 117136 pNode->zData = (u8 *)&pNode[1]; 115660 117137 pNode->nRef = 1; 115661 117138 pNode->pParent = pParent; 115662 117139 pNode->isDirty = 1; 115663 117140 nodeReference(pParent); 115664 117141 } 115665 117142 return pNode; ................................................................................ 115672 117149 nodeAcquire( 115673 117150 Rtree *pRtree, /* R-tree structure */ 115674 117151 i64 iNode, /* Node number to load */ 115675 117152 RtreeNode *pParent, /* Either the parent node or NULL */ 115676 117153 RtreeNode **ppNode /* OUT: Acquired node */ 115677 117154 ){ 115678 117155 int rc; 117156 + int rc2 = SQLITE_OK; 115679 117157 RtreeNode *pNode; 115680 117158 115681 117159 /* Check if the requested node is already in the hash table. If so, 115682 117160 ** increase its reference count and return it. 115683 117161 */ 115684 117162 if( (pNode = nodeHashLookup(pRtree, iNode)) ){ 115685 117163 assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); ................................................................................ 115688 117166 pNode->pParent = pParent; 115689 117167 } 115690 117168 pNode->nRef++; 115691 117169 *ppNode = pNode; 115692 117170 return SQLITE_OK; 115693 117171 } 115694 117172 115695 - pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize); 115696 - if( !pNode ){ 115697 - *ppNode = 0; 115698 - return SQLITE_NOMEM; 115699 - } 115700 - pNode->pParent = pParent; 115701 - pNode->zData = (u8 *)&pNode[1]; 115702 - pNode->nRef = 1; 115703 - pNode->iNode = iNode; 115704 - pNode->isDirty = 0; 115705 - pNode->pNext = 0; 115706 - 115707 117173 sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); 115708 117174 rc = sqlite3_step(pRtree->pReadNode); 115709 117175 if( rc==SQLITE_ROW ){ 115710 117176 const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); 115711 - assert( sqlite3_column_bytes(pRtree->pReadNode, 0)==pRtree->iNodeSize ); 115712 - memcpy(pNode->zData, zBlob, pRtree->iNodeSize); 115713 - nodeReference(pParent); 117177 + if( pRtree->iNodeSize==sqlite3_column_bytes(pRtree->pReadNode, 0) ){ 117178 + pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize); 117179 + if( !pNode ){ 117180 + rc2 = SQLITE_NOMEM; 117181 + }else{ 117182 + pNode->pParent = pParent; 117183 + pNode->zData = (u8 *)&pNode[1]; 117184 + pNode->nRef = 1; 117185 + pNode->iNode = iNode; 117186 + pNode->isDirty = 0; 117187 + pNode->pNext = 0; 117188 + memcpy(pNode->zData, zBlob, pRtree->iNodeSize); 117189 + nodeReference(pParent); 117190 + } 117191 + } 117192 + } 117193 + rc = sqlite3_reset(pRtree->pReadNode); 117194 + if( rc==SQLITE_OK ) rc = rc2; 117195 + 117196 + /* If the root node was just loaded, set pRtree->iDepth to the height 117197 + ** of the r-tree structure. A height of zero means all data is stored on 117198 + ** the root node. A height of one means the children of the root node 117199 + ** are the leaves, and so on. If the depth as specified on the root node 117200 + ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt. 117201 + */ 117202 + if( pNode && iNode==1 ){ 117203 + pRtree->iDepth = readInt16(pNode->zData); 117204 + if( pRtree->iDepth>RTREE_MAX_DEPTH ){ 117205 + rc = SQLITE_CORRUPT; 117206 + } 117207 + } 117208 + 117209 + /* If no error has occurred so far, check if the "number of entries" 117210 + ** field on the node is too large. If so, set the return code to 117211 + ** SQLITE_CORRUPT. 117212 + */ 117213 + if( pNode && rc==SQLITE_OK ){ 117214 + if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){ 117215 + rc = SQLITE_CORRUPT; 117216 + } 117217 + } 117218 + 117219 + if( rc==SQLITE_OK ){ 117220 + if( pNode!=0 ){ 117221 + nodeHashInsert(pRtree, pNode); 117222 + }else{ 117223 + rc = SQLITE_CORRUPT; 117224 + } 117225 + *ppNode = pNode; 115714 117226 }else{ 115715 117227 sqlite3_free(pNode); 115716 - pNode = 0; 117228 + *ppNode = 0; 115717 117229 } 115718 117230 115719 - *ppNode = pNode; 115720 - rc = sqlite3_reset(pRtree->pReadNode); 115721 - 115722 - if( rc==SQLITE_OK && iNode==1 ){ 115723 - pRtree->iDepth = readInt16(pNode->zData); 115724 - } 115725 - 115726 - assert( (rc==SQLITE_OK && pNode) || (pNode==0 && rc!=SQLITE_OK) ); 115727 - nodeHashInsert(pRtree, pNode); 115728 - 115729 117231 return rc; 115730 117232 } 115731 117233 115732 117234 /* 115733 117235 ** Overwrite cell iCell of node pNode with the contents of pCell. 115734 117236 */ 115735 117237 static void nodeOverwriteCell( ................................................................................ 115773 117275 ){ 115774 117276 int nCell; /* Current number of cells in pNode */ 115775 117277 int nMaxCell; /* Maximum number of cells for pNode */ 115776 117278 115777 117279 nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell; 115778 117280 nCell = NCELL(pNode); 115779 117281 115780 - assert(nCell<=nMaxCell); 115781 - 117282 + assert( nCell<=nMaxCell ); 115782 117283 if( nCell<nMaxCell ){ 115783 117284 nodeOverwriteCell(pRtree, pNode, pCell, nCell); 115784 117285 writeInt16(&pNode->zData[2], nCell+1); 115785 117286 pNode->isDirty = 1; 115786 117287 } 115787 117288 115788 117289 return (nCell==nMaxCell); ................................................................................ 115994 117495 rc = SQLITE_OK; 115995 117496 } 115996 117497 *ppCursor = (sqlite3_vtab_cursor *)pCsr; 115997 117498 115998 117499 return rc; 115999 117500 } 116000 117501 117502 + 117503 +/* 117504 +** Free the RtreeCursor.aConstraint[] array and its contents. 117505 +*/ 117506 +static void freeCursorConstraints(RtreeCursor *pCsr){ 117507 + if( pCsr->aConstraint ){ 117508 + int i; /* Used to iterate through constraint array */ 117509 + for(i=0; i<pCsr->nConstraint; i++){ 117510 + sqlite3_rtree_geometry *pGeom = pCsr->aConstraint[i].pGeom; 117511 + if( pGeom ){ 117512 + if( pGeom->xDelUser ) pGeom->xDelUser(pGeom->pUser); 117513 + sqlite3_free(pGeom); 117514 + } 117515 + } 117516 + sqlite3_free(pCsr->aConstraint); 117517 + pCsr->aConstraint = 0; 117518 + } 117519 +} 117520 + 116001 117521 /* 116002 117522 ** Rtree virtual table module xClose method. 116003 117523 */ 116004 117524 static int rtreeClose(sqlite3_vtab_cursor *cur){ 116005 117525 Rtree *pRtree = (Rtree *)(cur->pVtab); 116006 117526 int rc; 116007 117527 RtreeCursor *pCsr = (RtreeCursor *)cur; 116008 - sqlite3_free(pCsr->aConstraint); 117528 + freeCursorConstraints(pCsr); 116009 117529 rc = nodeRelease(pRtree, pCsr->pNode); 116010 117530 sqlite3_free(pCsr); 116011 117531 return rc; 116012 117532 } 116013 117533 116014 117534 /* 116015 117535 ** Rtree virtual table module xEof method. ................................................................................ 116017 117537 ** Return non-zero if the cursor does not currently point to a valid 116018 117538 ** record (i.e if the scan has finished), or zero otherwise. 116019 117539 */ 116020 117540 static int rtreeEof(sqlite3_vtab_cursor *cur){ 116021 117541 RtreeCursor *pCsr = (RtreeCursor *)cur; 116022 117542 return (pCsr->pNode==0); 116023 117543 } 117544 + 117545 +/* 117546 +** The r-tree constraint passed as the second argument to this function is 117547 +** guaranteed to be a MATCH constraint. 117548 +*/ 117549 +static int testRtreeGeom( 117550 + Rtree *pRtree, /* R-Tree object */ 117551 + RtreeConstraint *pConstraint, /* MATCH constraint to test */ 117552 + RtreeCell *pCell, /* Cell to test */ 117553 + int *pbRes /* OUT: Test result */ 117554 +){ 117555 + int i; 117556 + double aCoord[RTREE_MAX_DIMENSIONS*2]; 117557 + int nCoord = pRtree->nDim*2; 117558 + 117559 + assert( pConstraint->op==RTREE_MATCH ); 117560 + assert( pConstraint->pGeom ); 117561 + 117562 + for(i=0; i<nCoord; i++){ 117563 + aCoord[i] = DCOORD(pCell->aCoord[i]); 117564 + } 117565 + return pConstraint->xGeom(pConstraint->pGeom, nCoord, aCoord, pbRes); 117566 +} 116024 117567 116025 117568 /* 116026 117569 ** Cursor pCursor currently points to a cell in a non-leaf page. 116027 -** Return true if the sub-tree headed by the cell is filtered 117570 +** Set *pbEof to true if the sub-tree headed by the cell is filtered 116028 117571 ** (excluded) by the constraints in the pCursor->aConstraint[] 116029 117572 ** array, or false otherwise. 117573 +** 117574 +** Return SQLITE_OK if successful or an SQLite error code if an error 117575 +** occurs within a geometry callback. 116030 117576 */ 116031 -static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor){ 117577 +static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ 116032 117578 RtreeCell cell; 116033 117579 int ii; 116034 117580 int bRes = 0; 116035 117581 116036 117582 nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); 116037 117583 for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){ 116038 117584 RtreeConstraint *p = &pCursor->aConstraint[ii]; 116039 117585 double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); 116040 117586 double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); 116041 117587 116042 117588 assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 116043 - || p->op==RTREE_GT || p->op==RTREE_EQ 117589 + || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH 116044 117590 ); 116045 117591 116046 117592 switch( p->op ){ 116047 - case RTREE_LE: case RTREE_LT: bRes = p->rValue<cell_min; break; 116048 - case RTREE_GE: case RTREE_GT: bRes = p->rValue>cell_max; break; 116049 - case RTREE_EQ: 117593 + case RTREE_LE: case RTREE_LT: 117594 + bRes = p->rValue<cell_min; 117595 + break; 117596 + 117597 + case RTREE_GE: case RTREE_GT: 117598 + bRes = p->rValue>cell_max; 117599 + break; 117600 + 117601 + case RTREE_EQ: 116050 117602 bRes = (p->rValue>cell_max || p->rValue<cell_min); 116051 117603 break; 117604 + 117605 + default: { 117606 + int rc; 117607 + assert( p->op==RTREE_MATCH ); 117608 + rc = testRtreeGeom(pRtree, p, &cell, &bRes); 117609 + if( rc!=SQLITE_OK ){ 117610 + return rc; 117611 + } 117612 + bRes = !bRes; 117613 + break; 117614 + } 116052 117615 } 116053 117616 } 116054 117617 116055 - return bRes; 117618 + *pbEof = bRes; 117619 + return SQLITE_OK; 116056 117620 } 116057 117621 116058 117622 /* 116059 -** Return true if the cell that cursor pCursor currently points to 117623 +** Test if the cell that cursor pCursor currently points to 116060 117624 ** would be filtered (excluded) by the constraints in the 116061 -** pCursor->aConstraint[] array, or false otherwise. 117625 +** pCursor->aConstraint[] array. If so, set *pbEof to true before 117626 +** returning. If the cell is not filtered (excluded) by the constraints, 117627 +** set pbEof to zero. 117628 +** 117629 +** Return SQLITE_OK if successful or an SQLite error code if an error 117630 +** occurs within a geometry callback. 116062 117631 ** 116063 117632 ** This function assumes that the cell is part of a leaf node. 116064 117633 */ 116065 -static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor){ 117634 +static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ 116066 117635 RtreeCell cell; 116067 117636 int ii; 117637 + *pbEof = 0; 116068 117638 116069 117639 nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); 116070 117640 for(ii=0; ii<pCursor->nConstraint; ii++){ 116071 117641 RtreeConstraint *p = &pCursor->aConstraint[ii]; 116072 117642 double coord = DCOORD(cell.aCoord[p->iCoord]); 116073 117643 int res; 116074 117644 assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 116075 - || p->op==RTREE_GT || p->op==RTREE_EQ 117645 + || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH 116076 117646 ); 116077 117647 switch( p->op ){ 116078 117648 case RTREE_LE: res = (coord<=p->rValue); break; 116079 117649 case RTREE_LT: res = (coord<p->rValue); break; 116080 117650 case RTREE_GE: res = (coord>=p->rValue); break; 116081 117651 case RTREE_GT: res = (coord>p->rValue); break; 116082 117652 case RTREE_EQ: res = (coord==p->rValue); break; 117653 + default: { 117654 + int rc; 117655 + assert( p->op==RTREE_MATCH ); 117656 + rc = testRtreeGeom(pRtree, p, &cell, &res); 117657 + if( rc!=SQLITE_OK ){ 117658 + return rc; 117659 + } 117660 + break; 117661 + } 116083 117662 } 116084 117663 116085 - if( !res ) return 1; 117664 + if( !res ){ 117665 + *pbEof = 1; 117666 + return SQLITE_OK; 117667 + } 116086 117668 } 116087 117669 116088 - return 0; 117670 + return SQLITE_OK; 116089 117671 } 116090 117672 116091 117673 /* 116092 117674 ** Cursor pCursor currently points at a node that heads a sub-tree of 116093 117675 ** height iHeight (if iHeight==0, then the node is a leaf). Descend 116094 117676 ** to point to the left-most cell of the sub-tree that matches the 116095 117677 ** configured constraints. ................................................................................ 116108 117690 116109 117691 RtreeNode *pSavedNode = pCursor->pNode; 116110 117692 int iSavedCell = pCursor->iCell; 116111 117693 116112 117694 assert( iHeight>=0 ); 116113 117695 116114 117696 if( iHeight==0 ){ 116115 - isEof = testRtreeEntry(pRtree, pCursor); 117697 + rc = testRtreeEntry(pRtree, pCursor, &isEof); 116116 117698 }else{ 116117 - isEof = testRtreeCell(pRtree, pCursor); 117699 + rc = testRtreeCell(pRtree, pCursor, &isEof); 116118 117700 } 116119 - if( isEof || iHeight==0 ){ 117701 + if( rc!=SQLITE_OK || isEof || iHeight==0 ){ 116120 117702 *pEof = isEof; 116121 - return SQLITE_OK; 117703 + return rc; 116122 117704 } 116123 117705 116124 117706 iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell); 116125 117707 rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild); 116126 117708 if( rc!=SQLITE_OK ){ 116127 117709 return rc; 116128 117710 } ................................................................................ 116150 117732 return SQLITE_OK; 116151 117733 } 116152 117734 116153 117735 /* 116154 117736 ** One of the cells in node pNode is guaranteed to have a 64-bit 116155 117737 ** integer value equal to iRowid. Return the index of this cell. 116156 117738 */ 116157 -static int nodeRowidIndex(Rtree *pRtree, RtreeNode *pNode, i64 iRowid){ 117739 +static int nodeRowidIndex( 117740 + Rtree *pRtree, 117741 + RtreeNode *pNode, 117742 + i64 iRowid, 117743 + int *piIndex 117744 +){ 116158 117745 int ii; 116159 - for(ii=0; nodeGetRowid(pRtree, pNode, ii)!=iRowid; ii++){ 116160 - assert( ii<(NCELL(pNode)-1) ); 117746 + int nCell = NCELL(pNode); 117747 + for(ii=0; ii<nCell; ii++){ 117748 + if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){ 117749 + *piIndex = ii; 117750 + return SQLITE_OK; 117751 + } 116161 117752 } 116162 - return ii; 117753 + return SQLITE_CORRUPT; 116163 117754 } 116164 117755 116165 117756 /* 116166 117757 ** Return the index of the cell containing a pointer to node pNode 116167 117758 ** in its parent. If pNode is the root node, return -1. 116168 117759 */ 116169 -static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode){ 117760 +static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){ 116170 117761 RtreeNode *pParent = pNode->pParent; 116171 117762 if( pParent ){ 116172 - return nodeRowidIndex(pRtree, pParent, pNode->iNode); 117763 + return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex); 116173 117764 } 116174 - return -1; 117765 + *piIndex = -1; 117766 + return SQLITE_OK; 116175 117767 } 116176 117768 116177 117769 /* 116178 117770 ** Rtree virtual table module xNext method. 116179 117771 */ 116180 117772 static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ 116181 117773 Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab); 116182 117774 RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; 116183 117775 int rc = SQLITE_OK; 117776 + 117777 + /* RtreeCursor.pNode must not be NULL. If is is NULL, then this cursor is 117778 + ** already at EOF. It is against the rules to call the xNext() method of 117779 + ** a cursor that has already reached EOF. 117780 + */ 117781 + assert( pCsr->pNode ); 116184 117782 116185 117783 if( pCsr->iStrategy==1 ){ 116186 117784 /* This "scan" is a direct lookup by rowid. There is no next entry. */ 116187 117785 nodeRelease(pRtree, pCsr->pNode); 116188 117786 pCsr->pNode = 0; 116189 - } 116190 - 116191 - else if( pCsr->pNode ){ 117787 + }else{ 116192 117788 /* Move to the next entry that matches the configured constraints. */ 116193 117789 int iHeight = 0; 116194 117790 while( pCsr->pNode ){ 116195 117791 RtreeNode *pNode = pCsr->pNode; 116196 117792 int nCell = NCELL(pNode); 116197 117793 for(pCsr->iCell++; pCsr->iCell<nCell; pCsr->iCell++){ 116198 117794 int isEof; 116199 117795 rc = descendToCell(pRtree, pCsr, iHeight, &isEof); 116200 117796 if( rc!=SQLITE_OK || !isEof ){ 116201 117797 return rc; 116202 117798 } 116203 117799 } 116204 117800 pCsr->pNode = pNode->pParent; 116205 - pCsr->iCell = nodeParentIndex(pRtree, pNode); 117801 + rc = nodeParentIndex(pRtree, pNode, &pCsr->iCell); 117802 + if( rc!=SQLITE_OK ){ 117803 + return rc; 117804 + } 116206 117805 nodeReference(pCsr->pNode); 116207 117806 nodeRelease(pRtree, pNode); 116208 117807 iHeight++; 116209 117808 } 116210 117809 } 116211 117810 116212 117811 return rc; ................................................................................ 116266 117865 sqlite3_reset(pRtree->pReadRowid); 116267 117866 }else{ 116268 117867 rc = sqlite3_reset(pRtree->pReadRowid); 116269 117868 } 116270 117869 return rc; 116271 117870 } 116272 117871 117872 +/* 117873 +** This function is called to configure the RtreeConstraint object passed 117874 +** as the second argument for a MATCH constraint. The value passed as the 117875 +** first argument to this function is the right-hand operand to the MATCH 117876 +** operator. 117877 +*/ 117878 +static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ 117879 + RtreeMatchArg *p; 117880 + sqlite3_rtree_geometry *pGeom; 117881 + int nBlob; 117882 + 117883 + /* Check that value is actually a blob. */ 117884 + if( !sqlite3_value_type(pValue)==SQLITE_BLOB ) return SQLITE_ERROR; 117885 + 117886 + /* Check that the blob is roughly the right size. */ 117887 + nBlob = sqlite3_value_bytes(pValue); 117888 + if( nBlob<sizeof(RtreeMatchArg) 117889 + || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0 117890 + ){ 117891 + return SQLITE_ERROR; 117892 + } 117893 + 117894 + pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc( 117895 + sizeof(sqlite3_rtree_geometry) + nBlob 117896 + ); 117897 + if( !pGeom ) return SQLITE_NOMEM; 117898 + memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); 117899 + p = (RtreeMatchArg *)&pGeom[1]; 117900 + 117901 + memcpy(p, sqlite3_value_blob(pValue), nBlob); 117902 + if( p->magic!=RTREE_GEOMETRY_MAGIC 117903 + || nBlob!=(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) 117904 + ){ 117905 + sqlite3_free(pGeom); 117906 + return SQLITE_ERROR; 117907 + } 117908 + 117909 + pGeom->pContext = p->pContext; 117910 + pGeom->nParam = p->nParam; 117911 + pGeom->aParam = p->aParam; 117912 + 117913 + pCons->xGeom = p->xGeom; 117914 + pCons->pGeom = pGeom; 117915 + return SQLITE_OK; 117916 +} 116273 117917 116274 117918 /* 116275 117919 ** Rtree virtual table module xFilter method. 116276 117920 */ 116277 117921 static int rtreeFilter( 116278 117922 sqlite3_vtab_cursor *pVtabCursor, 116279 117923 int idxNum, const char *idxStr, ................................................................................ 116284 117928 116285 117929 RtreeNode *pRoot = 0; 116286 117930 int ii; 116287 117931 int rc = SQLITE_OK; 116288 117932 116289 117933 rtreeReference(pRtree); 116290 117934 116291 - sqlite3_free(pCsr->aConstraint); 116292 - pCsr->aConstraint = 0; 117935 + freeCursorConstraints(pCsr); 116293 117936 pCsr->iStrategy = idxNum; 116294 117937 116295 117938 if( idxNum==1 ){ 116296 117939 /* Special case - lookup by rowid. */ 116297 117940 RtreeNode *pLeaf; /* Leaf on which the required cell resides */ 116298 117941 i64 iRowid = sqlite3_value_int64(argv[0]); 116299 117942 rc = findLeafNode(pRtree, iRowid, &pLeaf); 116300 117943 pCsr->pNode = pLeaf; 116301 - if( pLeaf && rc==SQLITE_OK ){ 116302 - pCsr->iCell = nodeRowidIndex(pRtree, pLeaf, iRowid); 117944 + if( pLeaf ){ 117945 + assert( rc==SQLITE_OK ); 117946 + rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &pCsr->iCell); 116303 117947 } 116304 117948 }else{ 116305 117949 /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array 116306 117950 ** with the configured constraints. 116307 117951 */ 116308 117952 if( argc>0 ){ 116309 117953 pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc); 116310 117954 pCsr->nConstraint = argc; 116311 117955 if( !pCsr->aConstraint ){ 116312 117956 rc = SQLITE_NOMEM; 116313 117957 }else{ 117958 + memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc); 116314 117959 assert( (idxStr==0 && argc==0) || strlen(idxStr)==argc*2 ); 116315 117960 for(ii=0; ii<argc; ii++){ 116316 117961 RtreeConstraint *p = &pCsr->aConstraint[ii]; 116317 117962 p->op = idxStr[ii*2]; 116318 117963 p->iCoord = idxStr[ii*2+1]-'a'; 116319 - p->rValue = sqlite3_value_double(argv[ii]); 117964 + if( p->op==RTREE_MATCH ){ 117965 + /* A MATCH operator. The right-hand-side must be a blob that 117966 + ** can be cast into an RtreeMatchArg object. One created using 117967 + ** an sqlite3_rtree_geometry_callback() SQL user function. 117968 + */ 117969 + rc = deserializeGeometry(argv[ii], p); 117970 + if( rc!=SQLITE_OK ){ 117971 + break; 117972 + } 117973 + }else{ 117974 + p->rValue = sqlite3_value_double(argv[ii]); 117975 + } 116320 117976 } 116321 117977 } 116322 117978 } 116323 117979 116324 117980 if( rc==SQLITE_OK ){ 116325 117981 pCsr->pNode = 0; 116326 117982 rc = nodeAcquire(pRtree, 1, 0, &pRoot); ................................................................................ 116353 118009 ** Rtree virtual table module xBestIndex method. There are three 116354 118010 ** table scan strategies to choose from (in order from most to 116355 118011 ** least desirable): 116356 118012 ** 116357 118013 ** idxNum idxStr Strategy 116358 118014 ** ------------------------------------------------ 116359 118015 ** 1 Unused Direct lookup by rowid. 116360 -** 2 See below R-tree query. 116361 -** 3 Unused Full table scan. 118016 +** 2 See below R-tree query or full-table scan. 116362 118017 ** ------------------------------------------------ 116363 118018 ** 116364 -** If strategy 1 or 3 is used, then idxStr is not meaningful. If strategy 118019 +** If strategy 1 is used, then idxStr is not meaningful. If strategy 116365 118020 ** 2 is used, idxStr is formatted to contain 2 bytes for each 116366 118021 ** constraint used. The first two bytes of idxStr correspond to 116367 118022 ** the constraint in sqlite3_index_info.aConstraintUsage[] with 116368 118023 ** (argvIndex==1) etc. 116369 118024 ** 116370 118025 ** The first of each pair of bytes in idxStr identifies the constraint 116371 118026 ** operator as follows: ................................................................................ 116373 118028 ** Operator Byte Value 116374 118029 ** ---------------------- 116375 118030 ** = 0x41 ('A') 116376 118031 ** <= 0x42 ('B') 116377 118032 ** < 0x43 ('C') 116378 118033 ** >= 0x44 ('D') 116379 118034 ** > 0x45 ('E') 118035 +** MATCH 0x46 ('F') 116380 118036 ** ---------------------- 116381 118037 ** 116382 118038 ** The second of each pair of bytes identifies the coordinate column 116383 118039 ** to which the constraint applies. The leftmost coordinate column 116384 118040 ** is 'a', the second from the left 'b' etc. 116385 118041 */ 116386 118042 static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ ................................................................................ 116411 118067 ** considered almost as quick as a direct rowid lookup (for which 116412 118068 ** sqlite uses an internal cost of 0.0). 116413 118069 */ 116414 118070 pIdxInfo->estimatedCost = 10.0; 116415 118071 return SQLITE_OK; 116416 118072 } 116417 118073 116418 - if( p->usable && p->iColumn>0 ){ 118074 + if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ 118075 + int j, opmsk; 118076 + static const unsigned char compatible[] = { 0, 0, 1, 1, 2, 2 }; 116419 118077 u8 op = 0; 116420 118078 switch( p->op ){ 116421 118079 case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; 116422 118080 case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break; 116423 118081 case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; 116424 118082 case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break; 116425 118083 case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; 116426 - } 116427 - if( op ){ 116428 - /* Make sure this particular constraint has not been used before. 116429 - ** If it has been used before, ignore it. 116430 - ** 116431 - ** A <= or < can be used if there is a prior >= or >. 116432 - ** A >= or > can be used if there is a prior < or <=. 116433 - ** A <= or < is disqualified if there is a prior <=, <, or ==. 116434 - ** A >= or > is disqualified if there is a prior >=, >, or ==. 116435 - ** A == is disqualifed if there is any prior constraint. 116436 - */ 116437 - int j, opmsk; 116438 - static const unsigned char compatible[] = { 0, 0, 1, 1, 2, 2 }; 116439 - assert( compatible[RTREE_EQ & 7]==0 ); 116440 - assert( compatible[RTREE_LT & 7]==1 ); 116441 - assert( compatible[RTREE_LE & 7]==1 ); 116442 - assert( compatible[RTREE_GT & 7]==2 ); 116443 - assert( compatible[RTREE_GE & 7]==2 ); 116444 - cCol = p->iColumn - 1 + 'a'; 116445 - opmsk = compatible[op & 7]; 116446 - for(j=0; j<iIdx; j+=2){ 116447 - if( zIdxStr[j+1]==cCol && (compatible[zIdxStr[j] & 7] & opmsk)!=0 ){ 116448 - op = 0; 116449 - break; 116450 - } 118084 + default: 118085 + assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH ); 118086 + op = RTREE_MATCH; 118087 + break; 118088 + } 118089 + assert( op!=0 ); 118090 + 118091 + /* Make sure this particular constraint has not been used before. 118092 + ** If it has been used before, ignore it. 118093 + ** 118094 + ** A <= or < can be used if there is a prior >= or >. 118095 + ** A >= or > can be used if there is a prior < or <=. 118096 + ** A <= or < is disqualified if there is a prior <=, <, or ==. 118097 + ** A >= or > is disqualified if there is a prior >=, >, or ==. 118098 + ** A == is disqualifed if there is any prior constraint. 118099 + */ 118100 + assert( compatible[RTREE_EQ & 7]==0 ); 118101 + assert( compatible[RTREE_LT & 7]==1 ); 118102 + assert( compatible[RTREE_LE & 7]==1 ); 118103 + assert( compatible[RTREE_GT & 7]==2 ); 118104 + assert( compatible[RTREE_GE & 7]==2 ); 118105 + cCol = p->iColumn - 1 + 'a'; 118106 + opmsk = compatible[op & 7]; 118107 + for(j=0; j<iIdx; j+=2){ 118108 + if( zIdxStr[j+1]==cCol && (compatible[zIdxStr[j] & 7] & opmsk)!=0 ){ 118109 + op = 0; 118110 + break; 116451 118111 } 116452 118112 } 116453 118113 if( op ){ 116454 118114 assert( iIdx<sizeof(zIdxStr)-1 ); 116455 118115 zIdxStr[iIdx++] = op; 116456 118116 zIdxStr[iIdx++] = cCol; 116457 118117 pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); ................................................................................ 116551 118211 RtreeCell *aCell, 116552 118212 int nCell, 116553 118213 int iExclude 116554 118214 ){ 116555 118215 int ii; 116556 118216 float overlap = 0.0; 116557 118217 for(ii=0; ii<nCell; ii++){ 116558 - if( ii!=iExclude ){ 118218 +#if VARIANT_RSTARTREE_CHOOSESUBTREE 118219 + if( ii!=iExclude ) 118220 +#else 118221 + assert( iExclude==-1 ); 118222 +#endif 118223 + { 116559 118224 int jj; 116560 118225 float o = 1.0; 116561 118226 for(jj=0; jj<(pRtree->nDim*2); jj+=2){ 116562 118227 double x1; 116563 118228 double x2; 116564 118229 116565 118230 x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); ................................................................................ 116644 118309 #endif 116645 118310 116646 118311 /* Select the child node which will be enlarged the least if pCell 116647 118312 ** is inserted into it. Resolve ties by choosing the entry with 116648 118313 ** the smallest area. 116649 118314 */ 116650 118315 for(iCell=0; iCell<nCell; iCell++){ 118316 + int bBest = 0; 116651 118317 float growth; 116652 118318 float area; 116653 118319 float overlap = 0.0; 116654 118320 nodeGetCell(pRtree, pNode, iCell, &cell); 116655 118321 growth = cellGrowth(pRtree, &cell, pCell); 116656 118322 area = cellArea(pRtree, &cell); 118323 + 116657 118324 #if VARIANT_RSTARTREE_CHOOSESUBTREE 116658 118325 if( ii==(pRtree->iDepth-1) ){ 116659 118326 overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell); 116660 118327 } 116661 -#endif 116662 118328 if( (iCell==0) 116663 118329 || (overlap<fMinOverlap) 116664 118330 || (overlap==fMinOverlap && growth<fMinGrowth) 116665 118331 || (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea) 116666 118332 ){ 118333 + bBest = 1; 118334 + } 118335 +#else 118336 + if( iCell==0||growth<fMinGrowth||(growth==fMinGrowth && area<fMinArea) ){ 118337 + bBest = 1; 118338 + } 118339 +#endif 118340 + if( bBest ){ 116667 118341 fMinOverlap = overlap; 116668 118342 fMinGrowth = growth; 116669 118343 fMinArea = area; 116670 118344 iBest = cell.iRowid; 116671 118345 } 116672 118346 } 116673 118347 ................................................................................ 116682 118356 } 116683 118357 116684 118358 /* 116685 118359 ** A cell with the same content as pCell has just been inserted into 116686 118360 ** the node pNode. This function updates the bounding box cells in 116687 118361 ** all ancestor elements. 116688 118362 */ 116689 -static void AdjustTree( 118363 +static int AdjustTree( 116690 118364 Rtree *pRtree, /* Rtree table */ 116691 118365 RtreeNode *pNode, /* Adjust ancestry of this node. */ 116692 118366 RtreeCell *pCell /* This cell was just inserted */ 116693 118367 ){ 116694 118368 RtreeNode *p = pNode; 116695 118369 while( p->pParent ){ 116696 - RtreeCell cell; 116697 118370 RtreeNode *pParent = p->pParent; 116698 - int iCell = nodeParentIndex(pRtree, p); 118371 + RtreeCell cell; 118372 + int iCell; 118373 + 118374 + if( nodeParentIndex(pRtree, p, &iCell) ){ 118375 + return SQLITE_CORRUPT; 118376 + } 116699 118377 116700 118378 nodeGetCell(pRtree, pParent, iCell, &cell); 116701 118379 if( !cellContains(pRtree, &cell, pCell) ){ 116702 118380 cellUnion(pRtree, &cell, pCell); 116703 118381 nodeOverwriteCell(pRtree, pParent, &cell, iCell); 116704 118382 } 116705 118383 116706 118384 p = pParent; 116707 118385 } 118386 + return SQLITE_OK; 116708 118387 } 116709 118388 116710 118389 /* 116711 118390 ** Write mapping (iRowid->iNode) to the <rtree>_rowid table. 116712 118391 */ 116713 118392 static int rowidWrite(Rtree *pRtree, sqlite3_int64 iRowid, sqlite3_int64 iNode){ 116714 118393 sqlite3_bind_int64(pRtree->pWriteRowid, 1, iRowid); ................................................................................ 117229 118908 nodeGetCell(pRtree, pNode, i, &aCell[i]); 117230 118909 } 117231 118910 nodeZero(pRtree, pNode); 117232 118911 memcpy(&aCell[nCell], pCell, sizeof(RtreeCell)); 117233 118912 nCell++; 117234 118913 117235 118914 if( pNode->iNode==1 ){ 117236 - pRight = nodeNew(pRtree, pNode, 1); 117237 - pLeft = nodeNew(pRtree, pNode, 1); 118915 + pRight = nodeNew(pRtree, pNode); 118916 + pLeft = nodeNew(pRtree, pNode); 117238 118917 pRtree->iDepth++; 117239 118918 pNode->isDirty = 1; 117240 118919 writeInt16(pNode->zData, pRtree->iDepth); 117241 118920 }else{ 117242 118921 pLeft = pNode; 117243 - pRight = nodeNew(pRtree, pLeft->pParent, 1); 118922 + pRight = nodeNew(pRtree, pLeft->pParent); 117244 118923 nodeReference(pLeft); 117245 118924 } 117246 118925 117247 118926 if( !pLeft || !pRight ){ 117248 118927 rc = SQLITE_NOMEM; 117249 118928 goto splitnode_out; 117250 118929 } ................................................................................ 117253 118932 memset(pRight->zData, 0, pRtree->iNodeSize); 117254 118933 117255 118934 rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox); 117256 118935 if( rc!=SQLITE_OK ){ 117257 118936 goto splitnode_out; 117258 118937 } 117259 118938 117260 - /* Ensure both child nodes have node numbers assigned to them. */ 117261 - if( (0==pRight->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pRight))) 118939 + /* Ensure both child nodes have node numbers assigned to them by calling 118940 + ** nodeWrite(). Node pRight always needs a node number, as it was created 118941 + ** by nodeNew() above. But node pLeft sometimes already has a node number. 118942 + ** In this case avoid the all to nodeWrite(). 118943 + */ 118944 + if( SQLITE_OK!=(rc = nodeWrite(pRtree, pRight)) 117262 118945 || (0==pLeft->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pLeft))) 117263 118946 ){ 117264 118947 goto splitnode_out; 117265 118948 } 117266 118949 117267 118950 rightbbox.iRowid = pRight->iNode; 117268 118951 leftbbox.iRowid = pLeft->iNode; ................................................................................ 117270 118953 if( pNode->iNode==1 ){ 117271 118954 rc = rtreeInsertCell(pRtree, pLeft->pParent, &leftbbox, iHeight+1); 117272 118955 if( rc!=SQLITE_OK ){ 117273 118956 goto splitnode_out; 117274 118957 } 117275 118958 }else{ 117276 118959 RtreeNode *pParent = pLeft->pParent; 117277 - int iCell = nodeParentIndex(pRtree, pLeft); 117278 - nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell); 117279 - AdjustTree(pRtree, pParent, &leftbbox); 118960 + int iCell; 118961 + rc = nodeParentIndex(pRtree, pLeft, &iCell); 118962 + if( rc==SQLITE_OK ){ 118963 + nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell); 118964 + rc = AdjustTree(pRtree, pParent, &leftbbox); 118965 + } 118966 + if( rc!=SQLITE_OK ){ 118967 + goto splitnode_out; 118968 + } 117280 118969 } 117281 118970 if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){ 117282 118971 goto splitnode_out; 117283 118972 } 117284 118973 117285 118974 for(i=0; i<NCELL(pRight); i++){ 117286 118975 i64 iRowid = nodeGetRowid(pRtree, pRight, i); ................................................................................ 117316 119005 splitnode_out: 117317 119006 nodeRelease(pRtree, pRight); 117318 119007 nodeRelease(pRtree, pLeft); 117319 119008 sqlite3_free(aCell); 117320 119009 return rc; 117321 119010 } 117322 119011 119012 +/* 119013 +** If node pLeaf is not the root of the r-tree and its pParent pointer is 119014 +** still NULL, load all ancestor nodes of pLeaf into memory and populate 119015 +** the pLeaf->pParent chain all the way up to the root node. 119016 +** 119017 +** This operation is required when a row is deleted (or updated - an update 119018 +** is implemented as a delete followed by an insert). SQLite provides the 119019 +** rowid of the row to delete, which can be used to find the leaf on which 119020 +** the entry resides (argument pLeaf). Once the leaf is located, this 119021 +** function is called to determine its ancestry. 119022 +*/ 117323 119023 static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){ 117324 119024 int rc = SQLITE_OK; 117325 - if( pLeaf->iNode!=1 && pLeaf->pParent==0 ){ 117326 - sqlite3_bind_int64(pRtree->pReadParent, 1, pLeaf->iNode); 117327 - if( sqlite3_step(pRtree->pReadParent)==SQLITE_ROW ){ 117328 - i64 iNode = sqlite3_column_int64(pRtree->pReadParent, 0); 117329 - rc = nodeAcquire(pRtree, iNode, 0, &pLeaf->pParent); 117330 - }else{ 117331 - rc = SQLITE_ERROR; 119025 + RtreeNode *pChild = pLeaf; 119026 + while( rc==SQLITE_OK && pChild->iNode!=1 && pChild->pParent==0 ){ 119027 + int rc2 = SQLITE_OK; /* sqlite3_reset() return code */ 119028 + sqlite3_bind_int64(pRtree->pReadParent, 1, pChild->iNode); 119029 + rc = sqlite3_step(pRtree->pReadParent); 119030 + if( rc==SQLITE_ROW ){ 119031 + RtreeNode *pTest; /* Used to test for reference loops */ 119032 + i64 iNode; /* Node number of parent node */ 119033 + 119034 + /* Before setting pChild->pParent, test that we are not creating a 119035 + ** loop of references (as we would if, say, pChild==pParent). We don't 119036 + ** want to do this as it leads to a memory leak when trying to delete 119037 + ** the referenced counted node structures. 119038 + */ 119039 + iNode = sqlite3_column_int64(pRtree->pReadParent, 0); 119040 + for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent); 119041 + if( !pTest ){ 119042 + rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent); 119043 + } 117332 119044 } 117333 - sqlite3_reset(pRtree->pReadParent); 117334 - if( rc==SQLITE_OK ){ 117335 - rc = fixLeafParent(pRtree, pLeaf->pParent); 117336 - } 119045 + rc = sqlite3_reset(pRtree->pReadParent); 119046 + if( rc==SQLITE_OK ) rc = rc2; 119047 + if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT; 119048 + pChild = pChild->pParent; 117337 119049 } 117338 119050 return rc; 117339 119051 } 117340 119052 117341 119053 static int deleteCell(Rtree *, RtreeNode *, int, int); 117342 119054 117343 119055 static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){ 117344 119056 int rc; 119057 + int rc2; 117345 119058 RtreeNode *pParent; 117346 119059 int iCell; 117347 119060 117348 119061 assert( pNode->nRef==1 ); 117349 119062 117350 119063 /* Remove the entry in the parent cell. */ 117351 - iCell = nodeParentIndex(pRtree, pNode); 117352 - pParent = pNode->pParent; 117353 - pNode->pParent = 0; 117354 - if( SQLITE_OK!=(rc = deleteCell(pRtree, pParent, iCell, iHeight+1)) 117355 - || SQLITE_OK!=(rc = nodeRelease(pRtree, pParent)) 117356 - ){ 119064 + rc = nodeParentIndex(pRtree, pNode, &iCell); 119065 + if( rc==SQLITE_OK ){ 119066 + pParent = pNode->pParent; 119067 + pNode->pParent = 0; 119068 + rc = deleteCell(pRtree, pParent, iCell, iHeight+1); 119069 + } 119070 + rc2 = nodeRelease(pRtree, pParent); 119071 + if( rc==SQLITE_OK ){ 119072 + rc = rc2; 119073 + } 119074 + if( rc!=SQLITE_OK ){ 117357 119075 return rc; 117358 119076 } 117359 119077 117360 119078 /* Remove the xxx_node entry. */ 117361 119079 sqlite3_bind_int64(pRtree->pDeleteNode, 1, pNode->iNode); 117362 119080 sqlite3_step(pRtree->pDeleteNode); 117363 119081 if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteNode)) ){ ................................................................................ 117379 119097 pNode->pNext = pRtree->pDeleted; 117380 119098 pNode->nRef++; 117381 119099 pRtree->pDeleted = pNode; 117382 119100 117383 119101 return SQLITE_OK; 117384 119102 } 117385 119103 117386 -static void fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){ 119104 +static int fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){ 117387 119105 RtreeNode *pParent = pNode->pParent; 119106 + int rc = SQLITE_OK; 117388 119107 if( pParent ){ 117389 119108 int ii; 117390 119109 int nCell = NCELL(pNode); 117391 119110 RtreeCell box; /* Bounding box for pNode */ 117392 119111 nodeGetCell(pRtree, pNode, 0, &box); 117393 119112 for(ii=1; ii<nCell; ii++){ 117394 119113 RtreeCell cell; 117395 119114 nodeGetCell(pRtree, pNode, ii, &cell); 117396 119115 cellUnion(pRtree, &box, &cell); 117397 119116 } 117398 119117 box.iRowid = pNode->iNode; 117399 - ii = nodeParentIndex(pRtree, pNode); 117400 - nodeOverwriteCell(pRtree, pParent, &box, ii); 117401 - fixBoundingBox(pRtree, pParent); 119118 + rc = nodeParentIndex(pRtree, pNode, &ii); 119119 + if( rc==SQLITE_OK ){ 119120 + nodeOverwriteCell(pRtree, pParent, &box, ii); 119121 + rc = fixBoundingBox(pRtree, pParent); 119122 + } 117402 119123 } 119124 + return rc; 117403 119125 } 117404 119126 117405 119127 /* 117406 119128 ** Delete the cell at index iCell of node pNode. After removing the 117407 119129 ** cell, adjust the r-tree data structure if required. 117408 119130 */ 117409 119131 static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){ 119132 + RtreeNode *pParent; 117410 119133 int rc; 117411 119134 117412 119135 if( SQLITE_OK!=(rc = fixLeafParent(pRtree, pNode)) ){ 117413 119136 return rc; 117414 119137 } 117415 119138 117416 119139 /* Remove the cell from the node. This call just moves bytes around ................................................................................ 117419 119142 nodeDeleteCell(pRtree, pNode, iCell); 117420 119143 117421 119144 /* If the node is not the tree root and now has less than the minimum 117422 119145 ** number of cells, remove it from the tree. Otherwise, update the 117423 119146 ** cell in the parent node so that it tightly contains the updated 117424 119147 ** node. 117425 119148 */ 117426 - if( pNode->iNode!=1 ){ 117427 - RtreeNode *pParent = pNode->pParent; 117428 - if( (pParent->iNode!=1 || NCELL(pParent)!=1) 117429 - && (NCELL(pNode)<RTREE_MINCELLS(pRtree)) 117430 - ){ 119149 + pParent = pNode->pParent; 119150 + assert( pParent || pNode->iNode==1 ); 119151 + if( pParent ){ 119152 + if( NCELL(pNode)<RTREE_MINCELLS(pRtree) ){ 117431 119153 rc = removeNode(pRtree, pNode, iHeight); 117432 119154 }else{ 117433 - fixBoundingBox(pRtree, pNode); 119155 + rc = fixBoundingBox(pRtree, pNode); 117434 119156 } 117435 119157 } 117436 119158 117437 119159 return rc; 117438 119160 } 117439 119161 117440 119162 static int Reinsert( ................................................................................ 117509 119231 rc = rowidWrite(pRtree, p->iRowid, pNode->iNode); 117510 119232 }else{ 117511 119233 rc = parentWrite(pRtree, p->iRowid, pNode->iNode); 117512 119234 } 117513 119235 } 117514 119236 } 117515 119237 if( rc==SQLITE_OK ){ 117516 - fixBoundingBox(pRtree, pNode); 119238 + rc = fixBoundingBox(pRtree, pNode); 117517 119239 } 117518 119240 for(; rc==SQLITE_OK && ii<nCell; ii++){ 117519 119241 /* Find a node to store this cell in. pNode->iNode currently contains 117520 119242 ** the height of the sub-tree headed by the cell. 117521 119243 */ 117522 119244 RtreeNode *pInsert; 117523 119245 RtreeCell *p = &aCell[aOrder[ii]]; ................................................................................ 117563 119285 pRtree->iReinsertHeight = iHeight; 117564 119286 rc = Reinsert(pRtree, pNode, pCell, iHeight); 117565 119287 } 117566 119288 #else 117567 119289 rc = SplitNode(pRtree, pNode, pCell, iHeight); 117568 119290 #endif 117569 119291 }else{ 117570 - AdjustTree(pRtree, pNode, pCell); 117571 - if( iHeight==0 ){ 117572 - rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode); 117573 - }else{ 117574 - rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode); 119292 + rc = AdjustTree(pRtree, pNode, pCell); 119293 + if( rc==SQLITE_OK ){ 119294 + if( iHeight==0 ){ 119295 + rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode); 119296 + }else{ 119297 + rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode); 119298 + } 117575 119299 } 117576 119300 } 117577 119301 return rc; 117578 119302 } 117579 119303 117580 119304 static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){ 117581 119305 int ii; ................................................................................ 117637 119361 ){ 117638 119362 Rtree *pRtree = (Rtree *)pVtab; 117639 119363 int rc = SQLITE_OK; 117640 119364 117641 119365 rtreeReference(pRtree); 117642 119366 117643 119367 assert(nData>=1); 117644 - assert(hashIsEmpty(pRtree)); 117645 119368 117646 119369 /* If azData[0] is not an SQL NULL value, it is the rowid of a 117647 119370 ** record to delete from the r-tree table. The following block does 117648 119371 ** just that. 117649 119372 */ 117650 119373 if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){ 117651 119374 i64 iDelete; /* The rowid to delete */ ................................................................................ 117663 119386 iDelete = sqlite3_value_int64(azData[0]); 117664 119387 rc = findLeafNode(pRtree, iDelete, &pLeaf); 117665 119388 } 117666 119389 117667 119390 /* Delete the cell in question from the leaf node. */ 117668 119391 if( rc==SQLITE_OK ){ 117669 119392 int rc2; 117670 - iCell = nodeRowidIndex(pRtree, pLeaf, iDelete); 117671 - rc = deleteCell(pRtree, pLeaf, iCell, 0); 119393 + rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell); 119394 + if( rc==SQLITE_OK ){ 119395 + rc = deleteCell(pRtree, pLeaf, iCell, 0); 119396 + } 117672 119397 rc2 = nodeRelease(pRtree, pLeaf); 117673 119398 if( rc==SQLITE_OK ){ 117674 119399 rc = rc2; 117675 119400 } 117676 119401 } 117677 119402 117678 119403 /* Delete the corresponding entry in the <rtree>_rowid table. */ ................................................................................ 117686 119411 ** it, schedule the contents of the child for reinsertion and 117687 119412 ** reduce the tree height by one. 117688 119413 ** 117689 119414 ** This is equivalent to copying the contents of the child into 117690 119415 ** the root node (the operation that Gutman's paper says to perform 117691 119416 ** in this scenario). 117692 119417 */ 117693 - if( rc==SQLITE_OK && pRtree->iDepth>0 ){ 117694 - if( rc==SQLITE_OK && NCELL(pRoot)==1 ){ 117695 - RtreeNode *pChild; 117696 - i64 iChild = nodeGetRowid(pRtree, pRoot, 0); 117697 - rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); 117698 - if( rc==SQLITE_OK ){ 117699 - rc = removeNode(pRtree, pChild, pRtree->iDepth-1); 117700 - } 117701 - if( rc==SQLITE_OK ){ 117702 - pRtree->iDepth--; 117703 - writeInt16(pRoot->zData, pRtree->iDepth); 117704 - pRoot->isDirty = 1; 117705 - } 119418 + if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){ 119419 + int rc2; 119420 + RtreeNode *pChild; 119421 + i64 iChild = nodeGetRowid(pRtree, pRoot, 0); 119422 + rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); 119423 + if( rc==SQLITE_OK ){ 119424 + rc = removeNode(pRtree, pChild, pRtree->iDepth-1); 119425 + } 119426 + rc2 = nodeRelease(pRtree, pChild); 119427 + if( rc==SQLITE_OK ) rc = rc2; 119428 + if( rc==SQLITE_OK ){ 119429 + pRtree->iDepth--; 119430 + writeInt16(pRoot->zData, pRtree->iDepth); 119431 + pRoot->isDirty = 1; 117706 119432 } 117707 119433 } 117708 119434 117709 119435 /* Re-insert the contents of any underfull nodes removed from the tree. */ 117710 119436 for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){ 117711 119437 if( rc==SQLITE_OK ){ 117712 119438 rc = reinsertNodeContent(pRtree, pLeaf); ................................................................................ 117988 119714 char **pzErr, /* OUT: Error message, if any */ 117989 119715 int isCreate /* True for xCreate, false for xConnect */ 117990 119716 ){ 117991 119717 int rc = SQLITE_OK; 117992 119718 Rtree *pRtree; 117993 119719 int nDb; /* Length of string argv[1] */ 117994 119720 int nName; /* Length of string argv[2] */ 117995 - int eCoordType = (int)pAux; 119721 + int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32); 117996 119722 117997 119723 const char *aErrMsg[] = { 117998 119724 0, /* 0 */ 117999 119725 "Wrong number of columns for an rtree table", /* 1 */ 118000 119726 "Too few columns for an rtree table", /* 2 */ 118001 119727 "Too many columns for an rtree table" /* 3 */ 118002 119728 }; ................................................................................ 118134 119860 118135 119861 /* 118136 119862 ** Register the r-tree module with database handle db. This creates the 118137 119863 ** virtual table module "rtree" and the debugging/analysis scalar 118138 119864 ** function "rtreenode". 118139 119865 */ 118140 119866 SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db){ 118141 - int rc = SQLITE_OK; 119867 + const int utf8 = SQLITE_UTF8; 119868 + int rc; 118142 119869 118143 - if( rc==SQLITE_OK ){ 118144 - int utf8 = SQLITE_UTF8; 118145 - rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); 118146 - } 119870 + rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); 118147 119871 if( rc==SQLITE_OK ){ 118148 119872 int utf8 = SQLITE_UTF8; 118149 119873 rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); 118150 119874 } 118151 119875 if( rc==SQLITE_OK ){ 118152 119876 void *c = (void *)RTREE_COORD_REAL32; 118153 119877 rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); ................................................................................ 118155 119879 if( rc==SQLITE_OK ){ 118156 119880 void *c = (void *)RTREE_COORD_INT32; 118157 119881 rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0); 118158 119882 } 118159 119883 118160 119884 return rc; 118161 119885 } 119886 + 119887 +/* 119888 +** A version of sqlite3_free() that can be used as a callback. This is used 119889 +** in two places - as the destructor for the blob value returned by the 119890 +** invocation of a geometry function, and as the destructor for the geometry 119891 +** functions themselves. 119892 +*/ 119893 +static void doSqlite3Free(void *p){ 119894 + sqlite3_free(p); 119895 +} 119896 + 119897 +/* 119898 +** Each call to sqlite3_rtree_geometry_callback() creates an ordinary SQLite 119899 +** scalar user function. This C function is the callback used for all such 119900 +** registered SQL functions. 119901 +** 119902 +** The scalar user functions return a blob that is interpreted by r-tree 119903 +** table MATCH operators. 119904 +*/ 119905 +static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ 119906 + RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); 119907 + RtreeMatchArg *pBlob; 119908 + int nBlob; 119909 + 119910 + nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(double); 119911 + pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob); 119912 + if( !pBlob ){ 119913 + sqlite3_result_error_nomem(ctx); 119914 + }else{ 119915 + int i; 119916 + pBlob->magic = RTREE_GEOMETRY_MAGIC; 119917 + pBlob->xGeom = pGeomCtx->xGeom; 119918 + pBlob->pContext = pGeomCtx->pContext; 119919 + pBlob->nParam = nArg; 119920 + for(i=0; i<nArg; i++){ 119921 + pBlob->aParam[i] = sqlite3_value_double(aArg[i]); 119922 + } 119923 + sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); 119924 + } 119925 +} 119926 + 119927 +/* 119928 +** Register a new geometry function for use with the r-tree MATCH operator. 119929 +*/ 119930 +SQLITE_API int sqlite3_rtree_geometry_callback( 119931 + sqlite3 *db, 119932 + const char *zGeom, 119933 + int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *), 119934 + void *pContext 119935 +){ 119936 + RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ 119937 + 119938 + /* Allocate and populate the context object. */ 119939 + pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); 119940 + if( !pGeomCtx ) return SQLITE_NOMEM; 119941 + pGeomCtx->xGeom = xGeom; 119942 + pGeomCtx->pContext = pContext; 119943 + 119944 + /* Create the new user-function. Register a destructor function to delete 119945 + ** the context object when it is no longer required. */ 119946 + return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, 119947 + (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free 119948 + ); 119949 +} 118162 119950 118163 119951 #if !SQLITE_CORE 118164 119952 SQLITE_API int sqlite3_extension_init( 118165 119953 sqlite3 *db, 118166 119954 char **pzErrMsg, 118167 119955 const sqlite3_api_routines *pApi 118168 119956 ){
Changes to src/sqlite3.h.
93 93 ** The SQLITE_VERSION_NUMBER for any given release of SQLite will also 94 94 ** be larger than the release from which it is derived. Either Y will 95 95 ** be held constant and Z will be incremented or else Y will be incremented 96 96 ** and Z will be reset to zero. 97 97 ** 98 98 ** Since version 3.6.18, SQLite source code has been stored in the 99 99 ** <a href="http://www.fossil-scm.org/">Fossil configuration management 100 -** system</a>. ^The SQLITE_SOURCE_ID macro evalutes to 100 +** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to 101 101 ** a string which identifies a particular check-in of SQLite 102 102 ** within its configuration management system. ^The SQLITE_SOURCE_ID 103 103 ** string contains the date and time of the check-in (UTC) and an SHA1 104 104 ** hash of the entire source tree. 105 105 ** 106 106 ** See also: [sqlite3_libversion()], 107 107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()], 108 108 ** [sqlite_version()] and [sqlite_source_id()]. 109 109 */ 110 -#define SQLITE_VERSION "3.7.1" 111 -#define SQLITE_VERSION_NUMBER 3007001 112 -#define SQLITE_SOURCE_ID "2010-08-05 03:21:40 fbe70e1106bcc5086ceb9d8f39cc39baf3643092" 110 +#define SQLITE_VERSION "3.7.3" 111 +#define SQLITE_VERSION_NUMBER 3007003 112 +#define SQLITE_SOURCE_ID "2010-10-07 13:29:13 e55ada89246d4cc5f476891c70572dc7c1c3643e" 113 113 114 114 /* 115 115 ** CAPI3REF: Run-Time Library Version Numbers 116 116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid 117 117 ** 118 118 ** These interfaces provide the same information as the [SQLITE_VERSION], 119 119 ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ................................................................................ 150 150 ** CAPI3REF: Run-Time Library Compilation Options Diagnostics 151 151 ** 152 152 ** ^The sqlite3_compileoption_used() function returns 0 or 1 153 153 ** indicating whether the specified option was defined at 154 154 ** compile time. ^The SQLITE_ prefix may be omitted from the 155 155 ** option name passed to sqlite3_compileoption_used(). 156 156 ** 157 -** ^The sqlite3_compileoption_get() function allows interating 157 +** ^The sqlite3_compileoption_get() function allows iterating 158 158 ** over the list of options that were defined at compile time by 159 159 ** returning the N-th compile time option string. ^If N is out of range, 160 160 ** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ 161 161 ** prefix is omitted from any strings returned by 162 162 ** sqlite3_compileoption_get(). 163 163 ** 164 164 ** ^Support for the diagnostic functions sqlite3_compileoption_used() 165 -** and sqlite3_compileoption_get() may be omitted by specifing the 165 +** and sqlite3_compileoption_get() may be omitted by specifying the 166 166 ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. 167 167 ** 168 168 ** See also: SQL functions [sqlite_compileoption_used()] and 169 169 ** [sqlite_compileoption_get()] and the [compile_options pragma]. 170 170 */ 171 171 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS 172 172 SQLITE_API int sqlite3_compileoption_used(const char *zOptName); ................................................................................ 264 264 #endif 265 265 266 266 /* 267 267 ** CAPI3REF: Closing A Database Connection 268 268 ** 269 269 ** ^The sqlite3_close() routine is the destructor for the [sqlite3] object. 270 270 ** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is 271 -** successfullly destroyed and all associated resources are deallocated. 271 +** successfully destroyed and all associated resources are deallocated. 272 272 ** 273 273 ** Applications must [sqlite3_finalize | finalize] all [prepared statements] 274 274 ** and [sqlite3_blob_close | close] all [BLOB handles] associated with 275 275 ** the [sqlite3] object prior to attempting to close the object. ^If 276 276 ** sqlite3_close() is called on a [database connection] that still has 277 277 ** outstanding [prepared statements] or [BLOB handles], then it returns 278 278 ** SQLITE_BUSY. ................................................................................ 691 691 ** 692 692 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS 693 693 ** layer a hint of how large the database file will grow to be during the 694 694 ** current transaction. This hint is not guaranteed to be accurate but it 695 695 ** is often close. The underlying VFS might choose to preallocate database 696 696 ** file space based on this hint in order to help writes to the database 697 697 ** file run faster. 698 +** 699 +** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS 700 +** extends and truncates the database file in chunks of a size specified 701 +** by the user. The fourth argument to [sqlite3_file_control()] should 702 +** point to an integer (type int) containing the new chunk-size to use 703 +** for the nominated database. Allocating database file space in large 704 +** chunks (say 1MB at a time), may reduce file-system fragmentation and 705 +** improve performance on some systems. 698 706 */ 699 707 #define SQLITE_FCNTL_LOCKSTATE 1 700 708 #define SQLITE_GET_LOCKPROXYFILE 2 701 709 #define SQLITE_SET_LOCKPROXYFILE 3 702 710 #define SQLITE_LAST_ERRNO 4 703 711 #define SQLITE_FCNTL_SIZE_HINT 5 712 +#define SQLITE_FCNTL_CHUNK_SIZE 6 704 713 705 714 /* 706 715 ** CAPI3REF: Mutex Handle 707 716 ** 708 717 ** The mutex module within SQLite defines [sqlite3_mutex] to be an 709 718 ** abstract type for a mutex object. The SQLite core never looks 710 719 ** at the internal representation of an [sqlite3_mutex]. It only ................................................................................ 744 753 ** or modify this field while holding a particular static mutex. 745 754 ** The application should never modify anything within the sqlite3_vfs 746 755 ** object once the object has been registered. 747 756 ** 748 757 ** The zName field holds the name of the VFS module. The name must 749 758 ** be unique across all VFS modules. 750 759 ** 751 -** SQLite will guarantee that the zFilename parameter to xOpen 760 +** ^SQLite guarantees that the zFilename parameter to xOpen 752 761 ** is either a NULL pointer or string obtained 753 -** from xFullPathname(). SQLite further guarantees that 762 +** from xFullPathname() with an optional suffix added. 763 +** ^If a suffix is added to the zFilename parameter, it will 764 +** consist of a single "-" character followed by no more than 765 +** 10 alphanumeric and/or "-" characters. 766 +** ^SQLite further guarantees that 754 767 ** the string will be valid and unchanged until xClose() is 755 768 ** called. Because of the previous sentence, 756 769 ** the [sqlite3_file] can safely store a pointer to the 757 770 ** filename if it needs to remember the filename for some reason. 758 -** If the zFilename parameter is xOpen is a NULL pointer then xOpen 759 -** must invent its own temporary name for the file. Whenever the 771 +** If the zFilename parameter to xOpen is a NULL pointer then xOpen 772 +** must invent its own temporary name for the file. ^Whenever the 760 773 ** xFilename parameter is NULL it will also be the case that the 761 774 ** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. 762 775 ** 763 776 ** The flags argument to xOpen() includes all bits set in 764 777 ** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] 765 778 ** or [sqlite3_open16()] is used, then flags includes at least 766 779 ** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. 767 780 ** If xOpen() opens a file read-only then it sets *pOutFlags to 768 781 ** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. 769 782 ** 770 -** SQLite will also add one of the following flags to the xOpen() 783 +** ^(SQLite will also add one of the following flags to the xOpen() 771 784 ** call, depending on the object being opened: 772 785 ** 773 786 ** <ul> 774 787 ** <li> [SQLITE_OPEN_MAIN_DB] 775 788 ** <li> [SQLITE_OPEN_MAIN_JOURNAL] 776 789 ** <li> [SQLITE_OPEN_TEMP_DB] 777 790 ** <li> [SQLITE_OPEN_TEMP_JOURNAL] 778 791 ** <li> [SQLITE_OPEN_TRANSIENT_DB] 779 792 ** <li> [SQLITE_OPEN_SUBJOURNAL] 780 793 ** <li> [SQLITE_OPEN_MASTER_JOURNAL] 781 -** </ul> 794 +** <li> [SQLITE_OPEN_WAL] 795 +** </ul>)^ 782 796 ** 783 797 ** The file I/O implementation can use the object type flags to 784 798 ** change the way it deals with files. For example, an application 785 799 ** that does not care about crash recovery or rollback might make 786 800 ** the open of a journal file a no-op. Writes to this journal would 787 801 ** also be no-ops, and any attempt to read the journal would return 788 802 ** SQLITE_IOERR. Or the implementation might recognize that a database ................................................................................ 793 807 ** 794 808 ** <ul> 795 809 ** <li> [SQLITE_OPEN_DELETEONCLOSE] 796 810 ** <li> [SQLITE_OPEN_EXCLUSIVE] 797 811 ** </ul> 798 812 ** 799 813 ** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be 800 -** deleted when it is closed. The [SQLITE_OPEN_DELETEONCLOSE] 801 -** will be set for TEMP databases, journals and for subjournals. 814 +** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] 815 +** will be set for TEMP databases and their journals, transient 816 +** databases, and subjournals. 802 817 ** 803 -** The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction 818 +** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction 804 819 ** with the [SQLITE_OPEN_CREATE] flag, which are both directly 805 820 ** analogous to the O_EXCL and O_CREAT flags of the POSIX open() 806 821 ** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the 807 822 ** SQLITE_OPEN_CREATE, is used to indicate that file should always 808 823 ** be created, and that it is an error if it already exists. 809 824 ** It is <i>not</i> used to indicate the file should be opened 810 825 ** for exclusive access. 811 826 ** 812 -** At least szOsFile bytes of memory are allocated by SQLite 827 +** ^At least szOsFile bytes of memory are allocated by SQLite 813 828 ** to hold the [sqlite3_file] structure passed as the third 814 829 ** argument to xOpen. The xOpen method does not have to 815 830 ** allocate the structure; it should just fill it in. Note that 816 831 ** the xOpen method must set the sqlite3_file.pMethods to either 817 832 ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do 818 833 ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods 819 834 ** element will be valid after xOpen returns regardless of the success 820 835 ** or failure of the xOpen call. 821 836 ** 822 -** The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] 837 +** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] 823 838 ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to 824 839 ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] 825 840 ** to test whether a file is at least readable. The file can be a 826 841 ** directory. 827 842 ** 828 -** SQLite will always allocate at least mxPathname+1 bytes for the 843 +** ^SQLite will always allocate at least mxPathname+1 bytes for the 829 844 ** output buffer xFullPathname. The exact size of the output buffer 830 845 ** is also passed as a parameter to both methods. If the output buffer 831 846 ** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is 832 847 ** handled as a fatal error by SQLite, vfs implementations should endeavor 833 848 ** to prevent this by setting mxPathname to a sufficiently large value. 834 849 ** 835 850 ** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64() 836 851 ** interfaces are not strictly a part of the filesystem, but they are 837 852 ** included in the VFS structure for completeness. 838 853 ** The xRandomness() function attempts to return nBytes bytes 839 854 ** of good-quality randomness into zOut. The return value is 840 855 ** the actual number of bytes of randomness obtained. 841 856 ** The xSleep() method causes the calling thread to sleep for at 842 -** least the number of microseconds given. The xCurrentTime() 857 +** least the number of microseconds given. ^The xCurrentTime() 843 858 ** method returns a Julian Day Number for the current date and time as 844 859 ** a floating point value. 845 -** The xCurrentTimeInt64() method returns, as an integer, the Julian 860 +** ^The xCurrentTimeInt64() method returns, as an integer, the Julian 846 861 ** Day Number multipled by 86400000 (the number of milliseconds in 847 862 ** a 24-hour day). 848 863 ** ^SQLite will use the xCurrentTimeInt64() method to get the current 849 864 ** date and time if that method is available (if iVersion is 2 or 850 865 ** greater and the function pointer is not NULL) and will fall back 851 866 ** to xCurrentTime() if xCurrentTimeInt64() is unavailable. 852 867 */ ................................................................................ 1235 1250 ** <dd> ^This option takes single argument of type int, interpreted as a 1236 1251 ** boolean, which enables or disables the collection of memory allocation 1237 1252 ** statistics. ^(When memory allocation statistics are disabled, the 1238 1253 ** following SQLite interfaces become non-operational: 1239 1254 ** <ul> 1240 1255 ** <li> [sqlite3_memory_used()] 1241 1256 ** <li> [sqlite3_memory_highwater()] 1242 -** <li> [sqlite3_soft_heap_limit()] 1257 +** <li> [sqlite3_soft_heap_limit64()] 1243 1258 ** <li> [sqlite3_status()] 1244 1259 ** </ul>)^ 1245 1260 ** ^Memory allocation statistics are enabled by default unless SQLite is 1246 1261 ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory 1247 1262 ** allocation statistics are disabled by default. 1248 1263 ** </dd> 1249 1264 ** 1250 1265 ** <dt>SQLITE_CONFIG_SCRATCH</dt> 1251 1266 ** <dd> ^This option specifies a static memory buffer that SQLite can use for 1252 1267 ** scratch memory. There are three arguments: A pointer an 8-byte 1253 1268 ** aligned memory buffer from which the scrach allocations will be 1254 1269 ** drawn, the size of each scratch allocation (sz), 1255 1270 ** and the maximum number of scratch allocations (N). The sz 1256 -** argument must be a multiple of 16. The sz parameter should be a few bytes 1257 -** larger than the actual scratch space required due to internal overhead. 1271 +** argument must be a multiple of 16. 1258 1272 ** The first argument must be a pointer to an 8-byte aligned buffer 1259 1273 ** of at least sz*N bytes of memory. 1260 -** ^SQLite will use no more than one scratch buffer per thread. So 1261 -** N should be set to the expected maximum number of threads. ^SQLite will 1262 -** never require a scratch buffer that is more than 6 times the database 1263 -** page size. ^If SQLite needs needs additional scratch memory beyond 1264 -** what is provided by this configuration option, then 1274 +** ^SQLite will use no more than two scratch buffers per thread. So 1275 +** N should be set to twice the expected maximum number of threads. 1276 +** ^SQLite will never require a scratch buffer that is more than 6 1277 +** times the database page size. ^If SQLite needs needs additional 1278 +** scratch memory beyond what is provided by this configuration option, then 1265 1279 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd> 1266 1280 ** 1267 1281 ** <dt>SQLITE_CONFIG_PAGECACHE</dt> 1268 1282 ** <dd> ^This option specifies a static memory buffer that SQLite can use for 1269 1283 ** the database page cache with the default page cache implemenation. 1270 1284 ** This configuration should not be used if an application-define page 1271 1285 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option. ................................................................................ 1277 1291 ** the host architecture. ^It is harmless, apart from the wasted memory, 1278 1292 ** to make sz a little too large. The first 1279 1293 ** argument should point to an allocation of at least sz*N bytes of memory. 1280 1294 ** ^SQLite will use the memory provided by the first argument to satisfy its 1281 1295 ** memory needs for the first N pages that it adds to cache. ^If additional 1282 1296 ** page cache memory is needed beyond what is provided by this option, then 1283 1297 ** SQLite goes to [sqlite3_malloc()] for the additional storage space. 1284 -** ^The implementation might use one or more of the N buffers to hold 1285 -** memory accounting information. The pointer in the first argument must 1298 +** The pointer in the first argument must 1286 1299 ** be aligned to an 8-byte boundary or subsequent behavior of SQLite 1287 1300 ** will be undefined.</dd> 1288 1301 ** 1289 1302 ** <dt>SQLITE_CONFIG_HEAP</dt> 1290 1303 ** <dd> ^This option specifies a static memory buffer that SQLite will use 1291 1304 ** for all of its dynamic memory allocation needs beyond those provided 1292 1305 ** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. ................................................................................ 1407 1420 ** may be NULL in which case SQLite will allocate the 1408 1421 ** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the 1409 1422 ** size of each lookaside buffer slot. ^The third argument is the number of 1410 1423 ** slots. The size of the buffer in the first argument must be greater than 1411 1424 ** or equal to the product of the second and third arguments. The buffer 1412 1425 ** must be aligned to an 8-byte boundary. ^If the second argument to 1413 1426 ** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally 1414 -** rounded down to the next smaller 1415 -** multiple of 8. See also: [SQLITE_CONFIG_LOOKASIDE]</dd> 1427 +** rounded down to the next smaller multiple of 8. ^(The lookaside memory 1428 +** configuration for a database connection can only be changed when that 1429 +** connection is not currently using lookaside memory, or in other words 1430 +** when the "current value" returned by 1431 +** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. 1432 +** Any attempt to change the lookaside memory configuration when lookaside 1433 +** memory is in use leaves the configuration unchanged and returns 1434 +** [SQLITE_BUSY].)^</dd> 1416 1435 ** 1417 1436 ** </dl> 1418 1437 */ 1419 1438 #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ 1420 1439 1421 1440 1422 1441 /* ................................................................................ 1712 1731 ** was defined (using [sqlite3_busy_handler()]) prior to calling 1713 1732 ** this routine, that other busy handler is cleared.)^ 1714 1733 */ 1715 1734 SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); 1716 1735 1717 1736 /* 1718 1737 ** CAPI3REF: Convenience Routines For Running Queries 1738 +** 1739 +** This is a legacy interface that is preserved for backwards compatibility. 1740 +** Use of this interface is not recommended. 1719 1741 ** 1720 1742 ** Definition: A <b>result table</b> is memory data structure created by the 1721 1743 ** [sqlite3_get_table()] interface. A result table records the 1722 1744 ** complete query results from one or more queries. 1723 1745 ** 1724 1746 ** The table conceptually has a number of rows and columns. But 1725 1747 ** these numbers are not part of the result table itself. These ................................................................................ 1733 1755 ** in NULL pointers. All other values are in their UTF-8 zero-terminated 1734 1756 ** string representation as returned by [sqlite3_column_text()]. 1735 1757 ** 1736 1758 ** A result table might consist of one or more memory allocations. 1737 1759 ** It is not safe to pass a result table directly to [sqlite3_free()]. 1738 1760 ** A result table should be deallocated using [sqlite3_free_table()]. 1739 1761 ** 1740 -** As an example of the result table format, suppose a query result 1762 +** ^(As an example of the result table format, suppose a query result 1741 1763 ** is as follows: 1742 1764 ** 1743 1765 ** <blockquote><pre> 1744 1766 ** Name | Age 1745 1767 ** ----------------------- 1746 1768 ** Alice | 43 1747 1769 ** Bob | 28 ................................................................................ 1757 1779 ** azResult[1] = "Age"; 1758 1780 ** azResult[2] = "Alice"; 1759 1781 ** azResult[3] = "43"; 1760 1782 ** azResult[4] = "Bob"; 1761 1783 ** azResult[5] = "28"; 1762 1784 ** azResult[6] = "Cindy"; 1763 1785 ** azResult[7] = "21"; 1764 -** </pre></blockquote> 1786 +** </pre></blockquote>)^ 1765 1787 ** 1766 1788 ** ^The sqlite3_get_table() function evaluates one or more 1767 1789 ** semicolon-separated SQL statements in the zero-terminated UTF-8 1768 1790 ** string of its 2nd parameter and returns a result table to the 1769 1791 ** pointer given in its 3rd parameter. 1770 1792 ** 1771 1793 ** After the application has finished with the result from sqlite3_get_table(), 1772 -** it should pass the result table pointer to sqlite3_free_table() in order to 1794 +** it must pass the result table pointer to sqlite3_free_table() in order to 1773 1795 ** release the memory that was malloced. Because of the way the 1774 1796 ** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling 1775 1797 ** function must not try to call [sqlite3_free()] directly. Only 1776 1798 ** [sqlite3_free_table()] is able to release the memory properly and safely. 1777 1799 ** 1778 -** ^(The sqlite3_get_table() interface is implemented as a wrapper around 1800 +** The sqlite3_get_table() interface is implemented as a wrapper around 1779 1801 ** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access 1780 1802 ** to any internal data structures of SQLite. It uses only the public 1781 1803 ** interface defined here. As a consequence, errors that occur in the 1782 1804 ** wrapper layer outside of the internal [sqlite3_exec()] call are not 1783 1805 ** reflected in subsequent calls to [sqlite3_errcode()] or 1784 -** [sqlite3_errmsg()].)^ 1806 +** [sqlite3_errmsg()]. 1785 1807 */ 1786 1808 SQLITE_API int sqlite3_get_table( 1787 1809 sqlite3 *db, /* An open database */ 1788 1810 const char *zSql, /* SQL to be evaluated */ 1789 1811 char ***pazResult, /* Results of the query */ 1790 1812 int *pnRow, /* Number of result rows written here */ 1791 1813 int *pnColumn, /* Number of result columns written here */ ................................................................................ 1929 1951 ** ^If M is the size of the prior allocation, then min(N,M) bytes 1930 1952 ** of the prior allocation are copied into the beginning of buffer returned 1931 1953 ** by sqlite3_realloc() and the prior allocation is freed. 1932 1954 ** ^If sqlite3_realloc() returns NULL, then the prior allocation 1933 1955 ** is not freed. 1934 1956 ** 1935 1957 ** ^The memory returned by sqlite3_malloc() and sqlite3_realloc() 1936 -** is always aligned to at least an 8 byte boundary. 1958 +** is always aligned to at least an 8 byte boundary, or to a 1959 +** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time 1960 +** option is used. 1937 1961 ** 1938 1962 ** In SQLite version 3.5.0 and 3.5.1, it was possible to define 1939 1963 ** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in 1940 1964 ** implementation of these routines to be omitted. That capability 1941 1965 ** is no longer provided. Only built-in memory allocators can be used. 1942 1966 ** 1943 1967 ** The Windows OS interface layer calls ................................................................................ 2187 2211 SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); 2188 2212 SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, 2189 2213 void(*xProfile)(void*,const char*,sqlite3_uint64), void*); 2190 2214 2191 2215 /* 2192 2216 ** CAPI3REF: Query Progress Callbacks 2193 2217 ** 2194 -** ^This routine configures a callback function - the 2195 -** progress callback - that is invoked periodically during long 2196 -** running calls to [sqlite3_exec()], [sqlite3_step()] and 2197 -** [sqlite3_get_table()]. An example use for this 2218 +** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback 2219 +** function X to be invoked periodically during long running calls to 2220 +** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for 2221 +** database connection D. An example use for this 2198 2222 ** interface is to keep a GUI updated during a large query. 2223 +** 2224 +** ^The parameter P is passed through as the only parameter to the 2225 +** callback function X. ^The parameter N is the number of 2226 +** [virtual machine instructions] that are evaluated between successive 2227 +** invocations of the callback X. 2228 +** 2229 +** ^Only a single progress handler may be defined at one time per 2230 +** [database connection]; setting a new progress handler cancels the 2231 +** old one. ^Setting parameter X to NULL disables the progress handler. 2232 +** ^The progress handler is also disabled by setting N to a value less 2233 +** than 1. 2199 2234 ** 2200 2235 ** ^If the progress callback returns non-zero, the operation is 2201 2236 ** interrupted. This feature can be used to implement a 2202 2237 ** "Cancel" button on a GUI progress dialog box. 2203 2238 ** 2204 -** The progress handler must not do anything that will modify 2239 +** The progress handler callback must not do anything that will modify 2205 2240 ** the database connection that invoked the progress handler. 2206 2241 ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their 2207 2242 ** database connections for the meaning of "modify" in this paragraph. 2208 2243 ** 2209 2244 */ 2210 2245 SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); 2211 2246 ................................................................................ 2256 2291 ** it does not already exist. This is the behavior that is always used for 2257 2292 ** sqlite3_open() and sqlite3_open16().</dd>)^ 2258 2293 ** </dl> 2259 2294 ** 2260 2295 ** If the 3rd parameter to sqlite3_open_v2() is not one of the 2261 2296 ** combinations shown above or one of the combinations shown above combined 2262 2297 ** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], 2263 -** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_SHAREDCACHE] flags, 2298 +** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags, 2264 2299 ** then the behavior is undefined. 2265 2300 ** 2266 2301 ** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection 2267 2302 ** opens in the multi-thread [threading mode] as long as the single-thread 2268 2303 ** mode has not been set at compile-time or start-time. ^If the 2269 2304 ** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens 2270 2305 ** in the serialized [threading mode] unless single-thread was ................................................................................ 2381 2416 ** CAPI3REF: Run-time Limits 2382 2417 ** 2383 2418 ** ^(This interface allows the size of various constructs to be limited 2384 2419 ** on a connection by connection basis. The first parameter is the 2385 2420 ** [database connection] whose limit is to be set or queried. The 2386 2421 ** second parameter is one of the [limit categories] that define a 2387 2422 ** class of constructs to be size limited. The third parameter is the 2388 -** new limit for that construct. The function returns the old limit.)^ 2423 +** new limit for that construct.)^ 2389 2424 ** 2390 2425 ** ^If the new limit is a negative number, the limit is unchanged. 2391 -** ^(For the limit category of SQLITE_LIMIT_XYZ there is a 2426 +** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a 2392 2427 ** [limits | hard upper bound] 2393 -** set by a compile-time C preprocessor macro named 2394 -** [limits | SQLITE_MAX_XYZ]. 2428 +** set at compile-time by a C preprocessor macro called 2429 +** [limits | SQLITE_MAX_<i>NAME</i>]. 2395 2430 ** (The "_LIMIT_" in the name is changed to "_MAX_".))^ 2396 2431 ** ^Attempts to increase a limit above its hard upper bound are 2397 2432 ** silently truncated to the hard upper bound. 2398 2433 ** 2434 +** ^Regardless of whether or not the limit was changed, the 2435 +** [sqlite3_limit()] interface returns the prior value of the limit. 2436 +** ^Hence, to find the current value of a limit without changing it, 2437 +** simply invoke this interface with the third parameter set to -1. 2438 +** 2399 2439 ** Run-time limits are intended for use in applications that manage 2400 2440 ** both their own internal database and also databases that are controlled 2401 2441 ** by untrusted external sources. An example application might be a 2402 2442 ** web browser that has its own databases for storing history and 2403 2443 ** separate databases controlled by JavaScript applications downloaded 2404 2444 ** off the Internet. The internal databases can be given the 2405 2445 ** large, default limits. Databases managed by external sources can ................................................................................ 2420 2460 ** These constants define various performance limits 2421 2461 ** that can be lowered at run-time using [sqlite3_limit()]. 2422 2462 ** The synopsis of the meanings of the various limits is shown below. 2423 2463 ** Additional information is available at [limits | Limits in SQLite]. 2424 2464 ** 2425 2465 ** <dl> 2426 2466 ** ^(<dt>SQLITE_LIMIT_LENGTH</dt> 2427 -** <dd>The maximum size of any string or BLOB or table row.<dd>)^ 2467 +** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^ 2428 2468 ** 2429 2469 ** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt> 2430 2470 ** <dd>The maximum length of an SQL statement, in bytes.</dd>)^ 2431 2471 ** 2432 2472 ** ^(<dt>SQLITE_LIMIT_COLUMN</dt> 2433 2473 ** <dd>The maximum number of columns in a table definition or in the 2434 2474 ** result set of a [SELECT] or the maximum number of columns in an index ................................................................................ 2438 2478 ** <dd>The maximum depth of the parse tree on any expression.</dd>)^ 2439 2479 ** 2440 2480 ** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt> 2441 2481 ** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^ 2442 2482 ** 2443 2483 ** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt> 2444 2484 ** <dd>The maximum number of instructions in a virtual machine program 2445 -** used to implement an SQL statement.</dd>)^ 2485 +** used to implement an SQL statement. This limit is not currently 2486 +** enforced, though that might be added in some future release of 2487 +** SQLite.</dd>)^ 2446 2488 ** 2447 2489 ** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt> 2448 2490 ** <dd>The maximum number of arguments on a function.</dd>)^ 2449 2491 ** 2450 2492 ** ^(<dt>SQLITE_LIMIT_ATTACHED</dt> 2451 2493 ** <dd>The maximum number of [ATTACH | attached databases].)^</dd> 2452 2494 ** 2453 2495 ** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt> 2454 2496 ** <dd>The maximum length of the pattern argument to the [LIKE] or 2455 2497 ** [GLOB] operators.</dd>)^ 2456 2498 ** 2457 2499 ** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt> 2458 -** <dd>The maximum number of variables in an SQL statement that can 2459 -** be bound.</dd>)^ 2500 +** <dd>The maximum index number of any [parameter] in an SQL statement.)^ 2460 2501 ** 2461 2502 ** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt> 2462 2503 ** <dd>The maximum depth of recursion for triggers.</dd>)^ 2463 2504 ** </dl> 2464 2505 */ 2465 2506 #define SQLITE_LIMIT_LENGTH 0 2466 2507 #define SQLITE_LIMIT_SQL_LENGTH 1 ................................................................................ 2524 2565 ** original SQL text. This causes the [sqlite3_step()] interface to 2525 2566 ** behave differently in three ways: 2526 2567 ** 2527 2568 ** <ol> 2528 2569 ** <li> 2529 2570 ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it 2530 2571 ** always used to do, [sqlite3_step()] will automatically recompile the SQL 2531 -** statement and try to run it again. ^If the schema has changed in 2532 -** a way that makes the statement no longer valid, [sqlite3_step()] will still 2533 -** return [SQLITE_SCHEMA]. But unlike the legacy behavior, [SQLITE_SCHEMA] is 2534 -** now a fatal error. Calling [sqlite3_prepare_v2()] again will not make the 2535 -** error go away. Note: use [sqlite3_errmsg()] to find the text 2536 -** of the parsing error that results in an [SQLITE_SCHEMA] return. 2572 +** statement and try to run it again. 2537 2573 ** </li> 2538 2574 ** 2539 2575 ** <li> 2540 2576 ** ^When an error occurs, [sqlite3_step()] will return one of the detailed 2541 2577 ** [error codes] or [extended error codes]. ^The legacy behavior was that 2542 2578 ** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code 2543 2579 ** and the application would have to make a second call to [sqlite3_reset()] 2544 2580 ** in order to find the underlying cause of the problem. With the "v2" prepare 2545 2581 ** interfaces, the underlying reason for the error is returned immediately. 2546 2582 ** </li> 2547 2583 ** 2548 2584 ** <li> 2549 -** ^If the value of a [parameter | host parameter] in the WHERE clause might 2550 -** change the query plan for a statement, then the statement may be 2551 -** automatically recompiled (as if there had been a schema change) on the first 2552 -** [sqlite3_step()] call following any change to the 2553 -** [sqlite3_bind_text | bindings] of the [parameter]. 2585 +** ^If the specific value bound to [parameter | host parameter] in the 2586 +** WHERE clause might influence the choice of query plan for a statement, 2587 +** then the statement will be automatically recompiled, as if there had been 2588 +** a schema change, on the first [sqlite3_step()] call following any change 2589 +** to the [sqlite3_bind_text | bindings] of that [parameter]. 2590 +** ^The specific value of WHERE-clause [parameter] might influence the 2591 +** choice of query plan if the parameter is the left-hand side of a [LIKE] 2592 +** or [GLOB] operator or if the parameter is compared to an indexed column 2593 +** and the [SQLITE_ENABLE_STAT2] compile-time option is enabled. 2594 +** the 2554 2595 ** </li> 2555 2596 ** </ol> 2556 2597 */ 2557 2598 SQLITE_API int sqlite3_prepare( 2558 2599 sqlite3 *db, /* Database handle */ 2559 2600 const char *zSql, /* SQL statement, UTF-8 encoded */ 2560 2601 int nByte, /* Maximum length of zSql in bytes. */ ................................................................................ 2613 2654 ** sqlite3_value object. If SQLite is compiled to be single-threaded 2614 2655 ** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) 2615 2656 ** or if SQLite is run in one of reduced mutex modes 2616 2657 ** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] 2617 2658 ** then there is no distinction between protected and unprotected 2618 2659 ** sqlite3_value objects and they can be used interchangeably. However, 2619 2660 ** for maximum code portability it is recommended that applications 2620 -** still make the distinction between between protected and unprotected 2661 +** still make the distinction between protected and unprotected 2621 2662 ** sqlite3_value objects even when not strictly required. 2622 2663 ** 2623 2664 ** ^The sqlite3_value objects that are passed as parameters into the 2624 2665 ** implementation of [application-defined SQL functions] are protected. 2625 2666 ** ^The sqlite3_value object returned by 2626 2667 ** [sqlite3_column_value()] is unprotected. 2627 2668 ** Unprotected sqlite3_value objects may only be used with ................................................................................ 2659 2700 ** <li> ?NNN 2660 2701 ** <li> :VVV 2661 2702 ** <li> @VVV 2662 2703 ** <li> $VVV 2663 2704 ** </ul> 2664 2705 ** 2665 2706 ** In the templates above, NNN represents an integer literal, 2666 -** and VVV represents an alphanumeric identifer.)^ ^The values of these 2707 +** and VVV represents an alphanumeric identifier.)^ ^The values of these 2667 2708 ** parameters (also called "host parameter names" or "SQL parameters") 2668 2709 ** can be set using the sqlite3_bind_*() routines defined here. 2669 2710 ** 2670 2711 ** ^The first argument to the sqlite3_bind_*() routines is always 2671 2712 ** a pointer to the [sqlite3_stmt] object returned from 2672 2713 ** [sqlite3_prepare_v2()] or its variants. 2673 2714 ** ................................................................................ 2808 2849 2809 2850 /* 2810 2851 ** CAPI3REF: Number Of Columns In A Result Set 2811 2852 ** 2812 2853 ** ^Return the number of columns in the result set returned by the 2813 2854 ** [prepared statement]. ^This routine returns 0 if pStmt is an SQL 2814 2855 ** statement that does not return data (for example an [UPDATE]). 2856 +** 2857 +** See also: [sqlite3_data_count()] 2815 2858 */ 2816 2859 SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); 2817 2860 2818 2861 /* 2819 2862 ** CAPI3REF: Column Names In A Result Set 2820 2863 ** 2821 2864 ** ^These routines return the name assigned to a particular column ................................................................................ 2998 3041 ** by sqlite3_step(). The use of the "v2" interface is recommended. 2999 3042 */ 3000 3043 SQLITE_API int sqlite3_step(sqlite3_stmt*); 3001 3044 3002 3045 /* 3003 3046 ** CAPI3REF: Number of columns in a result set 3004 3047 ** 3005 -** ^The sqlite3_data_count(P) the number of columns in the 3006 -** of the result set of [prepared statement] P. 3048 +** ^The sqlite3_data_count(P) interface returns the number of columns in the 3049 +** current row of the result set of [prepared statement] P. 3050 +** ^If prepared statement P does not have results ready to return 3051 +** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of 3052 +** interfaces) then sqlite3_data_count(P) returns 0. 3053 +** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. 3054 +** 3055 +** See also: [sqlite3_column_count()] 3007 3056 */ 3008 3057 SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); 3009 3058 3010 3059 /* 3011 3060 ** CAPI3REF: Fundamental Datatypes 3012 3061 ** KEYWORDS: SQLITE_TEXT 3013 3062 ** ................................................................................ 3079 3128 ** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() 3080 3129 ** routine returns the number of bytes in that BLOB or string. 3081 3130 ** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts 3082 3131 ** the string to UTF-8 and then returns the number of bytes. 3083 3132 ** ^If the result is a numeric value then sqlite3_column_bytes() uses 3084 3133 ** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns 3085 3134 ** the number of bytes in that string. 3086 -** ^The value returned does not include the zero terminator at the end 3087 -** of the string. ^For clarity: the value returned is the number of 3135 +** ^If the result is NULL, then sqlite3_column_bytes() returns zero. 3136 +** 3137 +** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() 3138 +** routine returns the number of bytes in that BLOB or string. 3139 +** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts 3140 +** the string to UTF-16 and then returns the number of bytes. 3141 +** ^If the result is a numeric value then sqlite3_column_bytes16() uses 3142 +** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns 3143 +** the number of bytes in that string. 3144 +** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. 3145 +** 3146 +** ^The values returned by [sqlite3_column_bytes()] and 3147 +** [sqlite3_column_bytes16()] do not include the zero terminators at the end 3148 +** of the string. ^For clarity: the values returned by 3149 +** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of 3088 3150 ** bytes in the string, not the number of characters. 3089 3151 ** 3090 3152 ** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), 3091 3153 ** even empty strings, are always zero terminated. ^The return 3092 -** value from sqlite3_column_blob() for a zero-length BLOB is an arbitrary 3093 -** pointer, possibly even a NULL pointer. 3094 -** 3095 -** ^The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() 3096 -** but leaves the result in UTF-16 in native byte order instead of UTF-8. 3097 -** ^The zero terminator is not included in this count. 3154 +** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. 3098 3155 ** 3099 3156 ** ^The object returned by [sqlite3_column_value()] is an 3100 3157 ** [unprotected sqlite3_value] object. An unprotected sqlite3_value object 3101 3158 ** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. 3102 3159 ** If the [unprotected sqlite3_value] object returned by 3103 3160 ** [sqlite3_column_value()] is used in any other way, including calls 3104 3161 ** to routines like [sqlite3_value_int()], [sqlite3_value_text()], ................................................................................ 3135 3192 ** 3136 3193 ** The table above makes reference to standard C library functions atoi() 3137 3194 ** and atof(). SQLite does not really use these functions. It has its 3138 3195 ** own equivalent internal routines. The atoi() and atof() names are 3139 3196 ** used in the table for brevity and because they are familiar to most 3140 3197 ** C programmers. 3141 3198 ** 3142 -** ^Note that when type conversions occur, pointers returned by prior 3199 +** Note that when type conversions occur, pointers returned by prior 3143 3200 ** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or 3144 3201 ** sqlite3_column_text16() may be invalidated. 3145 -** ^(Type conversions and pointer invalidations might occur 3202 +** Type conversions and pointer invalidations might occur 3146 3203 ** in the following cases: 3147 3204 ** 3148 3205 ** <ul> 3149 3206 ** <li> The initial content is a BLOB and sqlite3_column_text() or 3150 3207 ** sqlite3_column_text16() is called. A zero-terminator might 3151 3208 ** need to be added to the string.</li> 3152 3209 ** <li> The initial content is UTF-8 text and sqlite3_column_bytes16() or 3153 3210 ** sqlite3_column_text16() is called. The content must be converted 3154 3211 ** to UTF-16.</li> 3155 3212 ** <li> The initial content is UTF-16 text and sqlite3_column_bytes() or 3156 3213 ** sqlite3_column_text() is called. The content must be converted 3157 3214 ** to UTF-8.</li> 3158 -** </ul>)^ 3215 +** </ul> 3159 3216 ** 3160 3217 ** ^Conversions between UTF-16be and UTF-16le are always done in place and do 3161 3218 ** not invalidate a prior pointer, though of course the content of the buffer 3162 -** that the prior pointer points to will have been modified. Other kinds 3219 +** that the prior pointer references will have been modified. Other kinds 3163 3220 ** of conversion are done in place when it is possible, but sometimes they 3164 3221 ** are not possible and in those cases prior pointers are invalidated. 3165 3222 ** 3166 -** ^(The safest and easiest to remember policy is to invoke these routines 3223 +** The safest and easiest to remember policy is to invoke these routines 3167 3224 ** in one of the following ways: 3168 3225 ** 3169 3226 ** <ul> 3170 3227 ** <li>sqlite3_column_text() followed by sqlite3_column_bytes()</li> 3171 3228 ** <li>sqlite3_column_blob() followed by sqlite3_column_bytes()</li> 3172 3229 ** <li>sqlite3_column_text16() followed by sqlite3_column_bytes16()</li> 3173 -** </ul>)^ 3230 +** </ul> 3174 3231 ** 3175 3232 ** In other words, you should call sqlite3_column_text(), 3176 3233 ** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result 3177 3234 ** into the desired format, then invoke sqlite3_column_bytes() or 3178 3235 ** sqlite3_column_bytes16() to find the size of the result. Do not mix calls 3179 3236 ** to sqlite3_column_text() or sqlite3_column_blob() with calls to 3180 3237 ** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() ................................................................................ 3204 3261 SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); 3205 3262 SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); 3206 3263 3207 3264 /* 3208 3265 ** CAPI3REF: Destroy A Prepared Statement Object 3209 3266 ** 3210 3267 ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. 3211 -** ^If the statement was executed successfully or not executed at all, then 3212 -** SQLITE_OK is returned. ^If execution of the statement failed then an 3213 -** [error code] or [extended error code] is returned. 3268 +** ^If the most recent evaluation of the statement encountered no errors or 3269 +** or if the statement is never been evaluated, then sqlite3_finalize() returns 3270 +** SQLITE_OK. ^If the most recent evaluation of statement S failed, then 3271 +** sqlite3_finalize(S) returns the appropriate [error code] or 3272 +** [extended error code]. 3214 3273 ** 3215 -** ^This routine can be called at any point during the execution of the 3216 -** [prepared statement]. ^If the virtual machine has not 3217 -** completed execution when this routine is called, that is like 3218 -** encountering an error or an [sqlite3_interrupt | interrupt]. 3219 -** ^Incomplete updates may be rolled back and transactions canceled, 3220 -** depending on the circumstances, and the 3221 -** [error code] returned will be [SQLITE_ABORT]. 3274 +** ^The sqlite3_finalize(S) routine can be called at any point during 3275 +** the life cycle of [prepared statement] S: 3276 +** before statement S is ever evaluated, after 3277 +** one or more calls to [sqlite3_reset()], or after any call 3278 +** to [sqlite3_step()] regardless of whether or not the statement has 3279 +** completed execution. 3280 +** 3281 +** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. 3282 +** 3283 +** The application must finalize every [prepared statement] in order to avoid 3284 +** resource leaks. It is a grievous error for the application to try to use 3285 +** a prepared statement after it has been finalized. Any use of a prepared 3286 +** statement after it has been finalized can result in undefined and 3287 +** undesirable behavior such as segfaults and heap corruption. 3222 3288 */ 3223 3289 SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); 3224 3290 3225 3291 /* 3226 3292 ** CAPI3REF: Reset A Prepared Statement Object 3227 3293 ** 3228 3294 ** The sqlite3_reset() function is called to reset a [prepared statement] ................................................................................ 3250 3316 3251 3317 /* 3252 3318 ** CAPI3REF: Create Or Redefine SQL Functions 3253 3319 ** KEYWORDS: {function creation routines} 3254 3320 ** KEYWORDS: {application-defined SQL function} 3255 3321 ** KEYWORDS: {application-defined SQL functions} 3256 3322 ** 3257 -** ^These two functions (collectively known as "function creation routines") 3323 +** ^These functions (collectively known as "function creation routines") 3258 3324 ** are used to add SQL functions or aggregates or to redefine the behavior 3259 -** of existing SQL functions or aggregates. The only difference between the 3260 -** two is that the second parameter, the name of the (scalar) function or 3261 -** aggregate, is encoded in UTF-8 for sqlite3_create_function() and UTF-16 3262 -** for sqlite3_create_function16(). 3325 +** of existing SQL functions or aggregates. The only differences between 3326 +** these routines are the text encoding expected for 3327 +** the the second parameter (the name of the function being created) 3328 +** and the presence or absence of a destructor callback for 3329 +** the application data pointer. 3263 3330 ** 3264 3331 ** ^The first parameter is the [database connection] to which the SQL 3265 3332 ** function is to be added. ^If an application uses more than one database 3266 3333 ** connection then application-defined SQL functions must be added 3267 3334 ** to each database connection separately. 3268 3335 ** 3269 -** The second parameter is the name of the SQL function to be created or 3270 -** redefined. ^The length of the name is limited to 255 bytes, exclusive of 3271 -** the zero-terminator. Note that the name length limit is in bytes, not 3272 -** characters. ^Any attempt to create a function with a longer name 3273 -** will result in [SQLITE_ERROR] being returned. 3336 +** ^The second parameter is the name of the SQL function to be created or 3337 +** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 3338 +** representation, exclusive of the zero-terminator. ^Note that the name 3339 +** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. 3340 +** ^Any attempt to create a function with a longer name 3341 +** will result in [SQLITE_MISUSE] being returned. 3274 3342 ** 3275 3343 ** ^The third parameter (nArg) 3276 3344 ** is the number of arguments that the SQL function or 3277 3345 ** aggregate takes. ^If this parameter is -1, then the SQL function or 3278 3346 ** aggregate may take any number of arguments between 0 and the limit 3279 3347 ** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third 3280 3348 ** parameter is less than -1 or greater than 127 then the behavior is 3281 3349 ** undefined. 3282 3350 ** 3283 -** The fourth parameter, eTextRep, specifies what 3351 +** ^The fourth parameter, eTextRep, specifies what 3284 3352 ** [SQLITE_UTF8 | text encoding] this SQL function prefers for 3285 -** its parameters. Any SQL function implementation should be able to work 3286 -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be 3353 +** its parameters. Every SQL function implementation must be able to work 3354 +** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be 3287 3355 ** more efficient with one encoding than another. ^An application may 3288 3356 ** invoke sqlite3_create_function() or sqlite3_create_function16() multiple 3289 3357 ** times with the same function but with different values of eTextRep. 3290 3358 ** ^When multiple implementations of the same function are available, SQLite 3291 3359 ** will pick the one that involves the least amount of data conversion. 3292 3360 ** If there is only a single implementation which does not care what text 3293 3361 ** encoding is used, then the fourth argument should be [SQLITE_ANY]. 3294 3362 ** 3295 3363 ** ^(The fifth parameter is an arbitrary pointer. The implementation of the 3296 3364 ** function can gain access to this pointer using [sqlite3_user_data()].)^ 3297 3365 ** 3298 -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are 3366 +** ^The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are 3299 3367 ** pointers to C-language functions that implement the SQL function or 3300 3368 ** aggregate. ^A scalar SQL function requires an implementation of the xFunc 3301 -** callback only; NULL pointers should be passed as the xStep and xFinal 3369 +** callback only; NULL pointers must be passed as the xStep and xFinal 3302 3370 ** parameters. ^An aggregate SQL function requires an implementation of xStep 3303 -** and xFinal and NULL should be passed for xFunc. ^To delete an existing 3304 -** SQL function or aggregate, pass NULL for all three function callbacks. 3371 +** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing 3372 +** SQL function or aggregate, pass NULL poiners for all three function 3373 +** callbacks. 3374 +** 3375 +** ^If the tenth parameter to sqlite3_create_function_v2() is not NULL, 3376 +** then it is invoked when the function is deleted, either by being 3377 +** overloaded or when the database connection closes. 3378 +** ^When the destructure callback of the tenth parameter is invoked, it 3379 +** is passed a single argument which is a copy of the pointer which was 3380 +** the fifth parameter to sqlite3_create_function_v2(). 3305 3381 ** 3306 3382 ** ^It is permitted to register multiple implementations of the same 3307 3383 ** functions with the same name but with either differing numbers of 3308 3384 ** arguments or differing preferred text encodings. ^SQLite will use 3309 3385 ** the implementation that most closely matches the way in which the 3310 3386 ** SQL function is used. ^A function implementation with a non-negative 3311 3387 ** nArg parameter is a better match than a function implementation with ................................................................................ 3313 3389 ** matches the database encoding is a better 3314 3390 ** match than a function where the encoding is different. 3315 3391 ** ^A function where the encoding difference is between UTF16le and UTF16be 3316 3392 ** is a closer match than a function where the encoding difference is 3317 3393 ** between UTF8 and UTF16. 3318 3394 ** 3319 3395 ** ^Built-in functions may be overloaded by new application-defined functions. 3320 -** ^The first application-defined function with a given name overrides all 3321 -** built-in functions in the same [database connection] with the same name. 3322 -** ^Subsequent application-defined functions of the same name only override 3323 -** prior application-defined functions that are an exact match for the 3324 -** number of parameters and preferred encoding. 3325 3396 ** 3326 3397 ** ^An application-defined function is permitted to call other 3327 3398 ** SQLite interfaces. However, such calls must not 3328 3399 ** close the database connection nor finalize or reset the prepared 3329 3400 ** statement in which the function is running. 3330 3401 */ 3331 3402 SQLITE_API int sqlite3_create_function( ................................................................................ 3343 3414 const void *zFunctionName, 3344 3415 int nArg, 3345 3416 int eTextRep, 3346 3417 void *pApp, 3347 3418 void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 3348 3419 void (*xStep)(sqlite3_context*,int,sqlite3_value**), 3349 3420 void (*xFinal)(sqlite3_context*) 3421 +); 3422 +SQLITE_API int sqlite3_create_function_v2( 3423 + sqlite3 *db, 3424 + const char *zFunctionName, 3425 + int nArg, 3426 + int eTextRep, 3427 + void *pApp, 3428 + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 3429 + void (*xStep)(sqlite3_context*,int,sqlite3_value**), 3430 + void (*xFinal)(sqlite3_context*), 3431 + void(*xDestroy)(void*) 3350 3432 ); 3351 3433 3352 3434 /* 3353 3435 ** CAPI3REF: Text Encodings 3354 3436 ** 3355 3437 ** These constant define integer codes that represent the various 3356 3438 ** text encodings supported by SQLite. ................................................................................ 3438 3520 SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); 3439 3521 SQLITE_API int sqlite3_value_type(sqlite3_value*); 3440 3522 SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); 3441 3523 3442 3524 /* 3443 3525 ** CAPI3REF: Obtain Aggregate Function Context 3444 3526 ** 3445 -** Implementions of aggregate SQL functions use this 3527 +** Implementations of aggregate SQL functions use this 3446 3528 ** routine to allocate memory for storing their state. 3447 3529 ** 3448 3530 ** ^The first time the sqlite3_aggregate_context(C,N) routine is called 3449 3531 ** for a particular aggregate function, SQLite 3450 3532 ** allocates N of memory, zeroes out that memory, and returns a pointer 3451 3533 ** to the new memory. ^On second and subsequent calls to 3452 3534 ** sqlite3_aggregate_context() for the same aggregate function instance, ................................................................................ 3690 3772 SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); 3691 3773 SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); 3692 3774 SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); 3693 3775 3694 3776 /* 3695 3777 ** CAPI3REF: Define New Collating Sequences 3696 3778 ** 3697 -** These functions are used to add new collation sequences to the 3698 -** [database connection] specified as the first argument. 3779 +** ^These functions add, remove, or modify a [collation] associated 3780 +** with the [database connection] specified as the first argument. 3699 3781 ** 3700 -** ^The name of the new collation sequence is specified as a UTF-8 string 3782 +** ^The name of the collation is a UTF-8 string 3701 3783 ** for sqlite3_create_collation() and sqlite3_create_collation_v2() 3702 -** and a UTF-16 string for sqlite3_create_collation16(). ^In all cases 3703 -** the name is passed as the second function argument. 3704 -** 3705 -** ^The third argument may be one of the constants [SQLITE_UTF8], 3706 -** [SQLITE_UTF16LE], or [SQLITE_UTF16BE], indicating that the user-supplied 3707 -** routine expects to be passed pointers to strings encoded using UTF-8, 3708 -** UTF-16 little-endian, or UTF-16 big-endian, respectively. ^The 3709 -** third argument might also be [SQLITE_UTF16] to indicate that the routine 3710 -** expects pointers to be UTF-16 strings in the native byte order, or the 3711 -** argument can be [SQLITE_UTF16_ALIGNED] if the 3712 -** the routine expects pointers to 16-bit word aligned strings 3713 -** of UTF-16 in the native byte order. 3714 -** 3715 -** A pointer to the user supplied routine must be passed as the fifth 3716 -** argument. ^If it is NULL, this is the same as deleting the collation 3717 -** sequence (so that SQLite cannot call it anymore). 3718 -** ^Each time the application supplied function is invoked, it is passed 3719 -** as its first parameter a copy of the void* passed as the fourth argument 3720 -** to sqlite3_create_collation() or sqlite3_create_collation16(). 3721 -** 3722 -** ^The remaining arguments to the application-supplied routine are two strings, 3723 -** each represented by a (length, data) pair and encoded in the encoding 3724 -** that was passed as the third argument when the collation sequence was 3725 -** registered. The application defined collation routine should 3726 -** return negative, zero or positive if the first string is less than, 3727 -** equal to, or greater than the second string. i.e. (STRING1 - STRING2). 3784 +** and a UTF-16 string in native byte order for sqlite3_create_collation16(). 3785 +** ^Collation names that compare equal according to [sqlite3_strnicmp()] are 3786 +** considered to be the same name. 3787 +** 3788 +** ^(The third argument (eTextRep) must be one of the constants: 3789 +** <ul> 3790 +** <li> [SQLITE_UTF8], 3791 +** <li> [SQLITE_UTF16LE], 3792 +** <li> [SQLITE_UTF16BE], 3793 +** <li> [SQLITE_UTF16], or 3794 +** <li> [SQLITE_UTF16_ALIGNED]. 3795 +** </ul>)^ 3796 +** ^The eTextRep argument determines the encoding of strings passed 3797 +** to the collating function callback, xCallback. 3798 +** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep 3799 +** force strings to be UTF16 with native byte order. 3800 +** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin 3801 +** on an even byte address. 3802 +** 3803 +** ^The fourth argument, pArg, is a application data pointer that is passed 3804 +** through as the first argument to the collating function callback. 3805 +** 3806 +** ^The fifth argument, xCallback, is a pointer to the collating function. 3807 +** ^Multiple collating functions can be registered using the same name but 3808 +** with different eTextRep parameters and SQLite will use whichever 3809 +** function requires the least amount of data transformation. 3810 +** ^If the xCallback argument is NULL then the collating function is 3811 +** deleted. ^When all collating functions having the same name are deleted, 3812 +** that collation is no longer usable. 3813 +** 3814 +** ^The collating function callback is invoked with a copy of the pArg 3815 +** application data pointer and with two strings in the encoding specified 3816 +** by the eTextRep argument. The collating function must return an 3817 +** integer that is negative, zero, or positive 3818 +** if the first string is less than, equal to, or greater than the second, 3819 +** respectively. A collating function must alway return the same answer 3820 +** given the same inputs. If two or more collating functions are registered 3821 +** to the same collation name (using different eTextRep values) then all 3822 +** must give an equivalent answer when invoked with equivalent strings. 3823 +** The collating function must obey the following properties for all 3824 +** strings A, B, and C: 3825 +** 3826 +** <ol> 3827 +** <li> If A==B then B==A. 3828 +** <li> If A==B and B==C then A==C. 3829 +** <li> If A<B THEN B>A. 3830 +** <li> If A<B and B<C then A<C. 3831 +** </ol> 3832 +** 3833 +** If a collating function fails any of the above constraints and that 3834 +** collating function is registered and used, then the behavior of SQLite 3835 +** is undefined. 3728 3836 ** 3729 3837 ** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() 3730 -** except that it takes an extra argument which is a destructor for 3731 -** the collation. ^The destructor is called when the collation is 3732 -** destroyed and is passed a copy of the fourth parameter void* pointer 3733 -** of the sqlite3_create_collation_v2(). 3734 -** ^Collations are destroyed when they are overridden by later calls to the 3735 -** collation creation functions or when the [database connection] is closed 3736 -** using [sqlite3_close()]. 3838 +** with the addition that the xDestroy callback is invoked on pArg when 3839 +** the collating function is deleted. 3840 +** ^Collating functions are deleted when they are overridden by later 3841 +** calls to the collation creation functions or when the 3842 +** [database connection] is closed using [sqlite3_close()]. 3737 3843 ** 3738 3844 ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. 3739 3845 */ 3740 3846 SQLITE_API int sqlite3_create_collation( 3741 3847 sqlite3*, 3742 3848 const char *zName, 3743 3849 int eTextRep, 3744 - void*, 3850 + void *pArg, 3745 3851 int(*xCompare)(void*,int,const void*,int,const void*) 3746 3852 ); 3747 3853 SQLITE_API int sqlite3_create_collation_v2( 3748 3854 sqlite3*, 3749 3855 const char *zName, 3750 3856 int eTextRep, 3751 - void*, 3857 + void *pArg, 3752 3858 int(*xCompare)(void*,int,const void*,int,const void*), 3753 3859 void(*xDestroy)(void*) 3754 3860 ); 3755 3861 SQLITE_API int sqlite3_create_collation16( 3756 3862 sqlite3*, 3757 3863 const void *zName, 3758 3864 int eTextRep, 3759 - void*, 3865 + void *pArg, 3760 3866 int(*xCompare)(void*,int,const void*,int,const void*) 3761 3867 ); 3762 3868 3763 3869 /* 3764 3870 ** CAPI3REF: Collation Needed Callbacks 3765 3871 ** 3766 3872 ** ^To avoid having to register all collation sequences before a database ................................................................................ 3841 3947 const char *zPassPhrase /* Activation phrase */ 3842 3948 ); 3843 3949 #endif 3844 3950 3845 3951 /* 3846 3952 ** CAPI3REF: Suspend Execution For A Short Time 3847 3953 ** 3848 -** ^The sqlite3_sleep() function causes the current thread to suspend execution 3954 +** The sqlite3_sleep() function causes the current thread to suspend execution 3849 3955 ** for at least a number of milliseconds specified in its parameter. 3850 3956 ** 3851 -** ^If the operating system does not support sleep requests with 3957 +** If the operating system does not support sleep requests with 3852 3958 ** millisecond time resolution, then the time will be rounded up to 3853 -** the nearest second. ^The number of milliseconds of sleep actually 3959 +** the nearest second. The number of milliseconds of sleep actually 3854 3960 ** requested from the operating system is returned. 3855 3961 ** 3856 3962 ** ^SQLite implements this interface by calling the xSleep() 3857 -** method of the default [sqlite3_vfs] object. 3963 +** method of the default [sqlite3_vfs] object. If the xSleep() method 3964 +** of the default VFS is not implemented correctly, or not implemented at 3965 +** all, then the behavior of sqlite3_sleep() may deviate from the description 3966 +** in the previous paragraphs. 3858 3967 */ 3859 3968 SQLITE_API int sqlite3_sleep(int); 3860 3969 3861 3970 /* 3862 3971 ** CAPI3REF: Name Of The Folder Holding Temporary Files 3863 3972 ** 3864 3973 ** ^(If this global variable is made to point to a string which is ................................................................................ 4072 4181 ** 4073 4182 ** ^The sqlite3_release_memory() interface attempts to free N bytes 4074 4183 ** of heap memory by deallocating non-essential memory allocations 4075 4184 ** held by the database library. Memory used to cache database 4076 4185 ** pages to improve performance is an example of non-essential memory. 4077 4186 ** ^sqlite3_release_memory() returns the number of bytes actually freed, 4078 4187 ** which might be more or less than the amount requested. 4188 +** ^The sqlite3_release_memory() routine is a no-op returning zero 4189 +** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. 4079 4190 */ 4080 4191 SQLITE_API int sqlite3_release_memory(int); 4081 4192 4082 4193 /* 4083 4194 ** CAPI3REF: Impose A Limit On Heap Size 4084 4195 ** 4085 -** ^The sqlite3_soft_heap_limit() interface places a "soft" limit 4086 -** on the amount of heap memory that may be allocated by SQLite. 4087 -** ^If an internal allocation is requested that would exceed the 4088 -** soft heap limit, [sqlite3_release_memory()] is invoked one or 4089 -** more times to free up some space before the allocation is performed. 4090 -** 4091 -** ^The limit is called "soft" because if [sqlite3_release_memory()] 4092 -** cannot free sufficient memory to prevent the limit from being exceeded, 4093 -** the memory is allocated anyway and the current operation proceeds. 4094 -** 4095 -** ^A negative or zero value for N means that there is no soft heap limit and 4096 -** [sqlite3_release_memory()] will only be called when memory is exhausted. 4097 -** ^The default value for the soft heap limit is zero. 4098 -** 4099 -** ^(SQLite makes a best effort to honor the soft heap limit. 4100 -** But if the soft heap limit cannot be honored, execution will 4101 -** continue without error or notification.)^ This is why the limit is 4102 -** called a "soft" limit. It is advisory only. 4103 -** 4104 -** Prior to SQLite version 3.5.0, this routine only constrained the memory 4105 -** allocated by a single thread - the same thread in which this routine 4106 -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is 4107 -** applied to all threads. The value specified for the soft heap limit 4108 -** is an upper bound on the total memory allocation for all threads. In 4109 -** version 3.5.0 there is no mechanism for limiting the heap usage for 4110 -** individual threads. 4111 -*/ 4112 -SQLITE_API void sqlite3_soft_heap_limit(int); 4196 +** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the 4197 +** soft limit on the amount of heap memory that may be allocated by SQLite. 4198 +** ^SQLite strives to keep heap memory utilization below the soft heap 4199 +** limit by reducing the number of pages held in the page cache 4200 +** as heap memory usages approaches the limit. 4201 +** ^The soft heap limit is "soft" because even though SQLite strives to stay 4202 +** below the limit, it will exceed the limit rather than generate 4203 +** an [SQLITE_NOMEM] error. In other words, the soft heap limit 4204 +** is advisory only. 4205 +** 4206 +** ^The return value from sqlite3_soft_heap_limit64() is the size of 4207 +** the soft heap limit prior to the call. ^If the argument N is negative 4208 +** then no change is made to the soft heap limit. Hence, the current 4209 +** size of the soft heap limit can be determined by invoking 4210 +** sqlite3_soft_heap_limit64() with a negative argument. 4211 +** 4212 +** ^If the argument N is zero then the soft heap limit is disabled. 4213 +** 4214 +** ^(The soft heap limit is not enforced in the current implementation 4215 +** if one or more of following conditions are true: 4216 +** 4217 +** <ul> 4218 +** <li> The soft heap limit is set to zero. 4219 +** <li> Memory accounting is disabled using a combination of the 4220 +** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and 4221 +** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. 4222 +** <li> An alternative page cache implementation is specifed using 4223 +** [sqlite3_config]([SQLITE_CONFIG_PCACHE],...). 4224 +** <li> The page cache allocates from its own memory pool supplied 4225 +** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than 4226 +** from the heap. 4227 +** </ul>)^ 4228 +** 4229 +** Beginning with SQLite version 3.7.3, the soft heap limit is enforced 4230 +** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] 4231 +** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], 4232 +** the soft heap limit is enforced on every memory allocation. Without 4233 +** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced 4234 +** when memory is allocated by the page cache. Testing suggests that because 4235 +** the page cache is the predominate memory user in SQLite, most 4236 +** applications will achieve adequate soft heap limit enforcement without 4237 +** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. 4238 +** 4239 +** The circumstances under which SQLite will enforce the soft heap limit may 4240 +** changes in future releases of SQLite. 4241 +*/ 4242 +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); 4243 + 4244 +/* 4245 +** CAPI3REF: Deprecated Soft Heap Limit Interface 4246 +** DEPRECATED 4247 +** 4248 +** This is a deprecated version of the [sqlite3_soft_heap_limit64()] 4249 +** interface. This routine is provided for historical compatibility 4250 +** only. All new applications should use the 4251 +** [sqlite3_soft_heap_limit64()] interface rather than this one. 4252 +*/ 4253 +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); 4254 + 4113 4255 4114 4256 /* 4115 4257 ** CAPI3REF: Extract Metadata About A Column Of A Table 4116 4258 ** 4117 4259 ** ^This routine returns metadata about a specific column of a specific 4118 4260 ** database table accessible using the [database connection] handle 4119 4261 ** passed as the first function argument. ................................................................................ 4229 4371 ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 4230 4372 ** to turn extension loading on and call it with onoff==0 to turn 4231 4373 ** it back off again. 4232 4374 */ 4233 4375 SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); 4234 4376 4235 4377 /* 4236 -** CAPI3REF: Automatically Load An Extensions 4237 -** 4238 -** ^This API can be invoked at program startup in order to register 4239 -** one or more statically linked extensions that will be available 4240 -** to all new [database connections]. 4241 -** 4242 -** ^(This routine stores a pointer to the extension entry point 4243 -** in an array that is obtained from [sqlite3_malloc()]. That memory 4244 -** is deallocated by [sqlite3_reset_auto_extension()].)^ 4245 -** 4246 -** ^This function registers an extension entry point that is 4247 -** automatically invoked whenever a new [database connection] 4248 -** is opened using [sqlite3_open()], [sqlite3_open16()], 4249 -** or [sqlite3_open_v2()]. 4250 -** ^Duplicate extensions are detected so calling this routine 4251 -** multiple times with the same extension is harmless. 4252 -** ^Automatic extensions apply across all threads. 4378 +** CAPI3REF: Automatically Load Statically Linked Extensions 4379 +** 4380 +** ^This interface causes the xEntryPoint() function to be invoked for 4381 +** each new [database connection] that is created. The idea here is that 4382 +** xEntryPoint() is the entry point for a statically linked SQLite extension 4383 +** that is to be automatically loaded into all new database connections. 4384 +** 4385 +** ^(Even though the function prototype shows that xEntryPoint() takes 4386 +** no arguments and returns void, SQLite invokes xEntryPoint() with three 4387 +** arguments and expects and integer result as if the signature of the 4388 +** entry point where as follows: 4389 +** 4390 +** <blockquote><pre> 4391 +** int xEntryPoint( 4392 +** sqlite3 *db, 4393 +** const char **pzErrMsg, 4394 +** const struct sqlite3_api_routines *pThunk 4395 +** ); 4396 +** </pre></blockquote>)^ 4397 +** 4398 +** If the xEntryPoint routine encounters an error, it should make *pzErrMsg 4399 +** point to an appropriate error message (obtained from [sqlite3_mprintf()]) 4400 +** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg 4401 +** is NULL before calling the xEntryPoint(). ^SQLite will invoke 4402 +** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any 4403 +** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], 4404 +** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. 4405 +** 4406 +** ^Calling sqlite3_auto_extension(X) with an entry point X that is already 4407 +** on the list of automatic extensions is a harmless no-op. ^No entry point 4408 +** will be called more than once for each database connection that is opened. 4409 +** 4410 +** See also: [sqlite3_reset_auto_extension()]. 4253 4411 */ 4254 4412 SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); 4255 4413 4256 4414 /* 4257 4415 ** CAPI3REF: Reset Automatic Extension Loading 4258 4416 ** 4259 -** ^(This function disables all previously registered automatic 4260 -** extensions. It undoes the effect of all prior 4261 -** [sqlite3_auto_extension()] calls.)^ 4262 -** 4263 -** ^This function disables automatic extensions in all threads. 4417 +** ^This interface disables all automatic extensions previously 4418 +** registered using [sqlite3_auto_extension()]. 4264 4419 */ 4265 4420 SQLITE_API void sqlite3_reset_auto_extension(void); 4266 4421 4267 4422 /* 4268 4423 ** The interface to the virtual-table mechanism is currently considered 4269 4424 ** to be experimental. The interface might change in incompatible ways. 4270 4425 ** If this is a problem for you, do not use the interface at this time. ................................................................................ 4895 5050 ** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. 4896 5051 ** Additionally, an instance of this structure can be used as an 4897 5052 ** output variable when querying the system for the current mutex 4898 5053 ** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. 4899 5054 ** 4900 5055 ** ^The xMutexInit method defined by this structure is invoked as 4901 5056 ** part of system initialization by the sqlite3_initialize() function. 4902 -** ^The xMutexInit routine is calle by SQLite exactly once for each 5057 +** ^The xMutexInit routine is called by SQLite exactly once for each 4903 5058 ** effective call to [sqlite3_initialize()]. 4904 5059 ** 4905 5060 ** ^The xMutexEnd method defined by this structure is invoked as 4906 5061 ** part of system shutdown by the sqlite3_shutdown() function. The 4907 5062 ** implementation of this method is expected to release all outstanding 4908 5063 ** resources obtained by the mutex methods implementation, especially 4909 5064 ** those obtained by the xMutexInit method. ^The xMutexEnd() ................................................................................ 4928 5083 ** of a valid mutex handle. The implementations of the methods defined 4929 5084 ** by this structure are not required to handle this case, the results 4930 5085 ** of passing a NULL pointer instead of a valid mutex handle are undefined 4931 5086 ** (i.e. it is acceptable to provide an implementation that segfaults if 4932 5087 ** it is passed a NULL pointer). 4933 5088 ** 4934 5089 ** The xMutexInit() method must be threadsafe. ^It must be harmless to 4935 -** invoke xMutexInit() mutiple times within the same process and without 5090 +** invoke xMutexInit() multiple times within the same process and without 4936 5091 ** intervening calls to xMutexEnd(). Second and subsequent calls to 4937 5092 ** xMutexInit() must be no-ops. 4938 5093 ** 4939 5094 ** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] 4940 5095 ** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory 4941 5096 ** allocation for a static mutex. ^However xMutexAlloc() may use SQLite 4942 5097 ** memory allocation for a fast or recursive mutex. ................................................................................ 5092 5247 #define SQLITE_TESTCTRL_PENDING_BYTE 11 5093 5248 #define SQLITE_TESTCTRL_ASSERT 12 5094 5249 #define SQLITE_TESTCTRL_ALWAYS 13 5095 5250 #define SQLITE_TESTCTRL_RESERVE 14 5096 5251 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 5097 5252 #define SQLITE_TESTCTRL_ISKEYWORD 16 5098 5253 #define SQLITE_TESTCTRL_PGHDRSZ 17 5099 -#define SQLITE_TESTCTRL_LAST 17 5254 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 18 5255 +#define SQLITE_TESTCTRL_LAST 18 5100 5256 5101 5257 /* 5102 5258 ** CAPI3REF: SQLite Runtime Status 5103 5259 ** 5104 5260 ** ^This interface is used to retrieve runtime status information 5105 -** about the preformance of SQLite, and optionally to reset various 5261 +** about the performance of SQLite, and optionally to reset various 5106 5262 ** highwater marks. ^The first argument is an integer code for 5107 5263 ** the specific parameter to measure. ^(Recognized integer codes 5108 5264 ** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^ 5109 5265 ** ^The current value of the parameter is returned into *pCurrent. 5110 5266 ** ^The highest recorded value is returned in *pHighwater. ^If the 5111 5267 ** resetFlag is true, then the highest record value is reset after 5112 5268 ** *pHighwater is written. ^(Some parameters do not record the highest 5113 5269 ** value. For those parameters 5114 5270 ** nothing is written into *pHighwater and the resetFlag is ignored.)^ 5115 5271 ** ^(Other parameters record only the highwater mark and not the current 5116 5272 ** value. For these latter parameters nothing is written into *pCurrent.)^ 5117 5273 ** 5118 -** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a 5274 +** ^The sqlite3_status() routine returns SQLITE_OK on success and a 5119 5275 ** non-zero [error code] on failure. 5120 5276 ** 5121 5277 ** This routine is threadsafe but is not atomic. This routine can be 5122 5278 ** called while other threads are running the same or different SQLite 5123 5279 ** interfaces. However the values returned in *pCurrent and 5124 5280 ** *pHighwater reflect the status of SQLite at different points in time 5125 5281 ** and it is possible that another thread might change the parameter ................................................................................ 5161 5317 ** <dd>This parameter returns the number of pages used out of the 5162 5318 ** [pagecache memory allocator] that was configured using 5163 5319 ** [SQLITE_CONFIG_PAGECACHE]. The 5164 5320 ** value returned is in pages, not in bytes.</dd>)^ 5165 5321 ** 5166 5322 ** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt> 5167 5323 ** <dd>This parameter returns the number of bytes of page cache 5168 -** allocation which could not be statisfied by the [SQLITE_CONFIG_PAGECACHE] 5324 +** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] 5169 5325 ** buffer and where forced to overflow to [sqlite3_malloc()]. The 5170 5326 ** returned value includes allocations that overflowed because they 5171 5327 ** where too large (they were larger than the "sz" parameter to 5172 5328 ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because 5173 5329 ** no space was left in the page cache.</dd>)^ 5174 5330 ** 5175 5331 ** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt> ................................................................................ 5184 5340 ** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not 5185 5341 ** in bytes. Since a single thread may only have one scratch allocation 5186 5342 ** outstanding at time, this parameter also reports the number of threads 5187 5343 ** using scratch memory at the same time.</dd>)^ 5188 5344 ** 5189 5345 ** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt> 5190 5346 ** <dd>This parameter returns the number of bytes of scratch memory 5191 -** allocation which could not be statisfied by the [SQLITE_CONFIG_SCRATCH] 5347 +** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] 5192 5348 ** buffer and where forced to overflow to [sqlite3_malloc()]. The values 5193 5349 ** returned include overflows because the requested allocation was too 5194 5350 ** larger (that is, because the requested allocation was larger than the 5195 5351 ** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer 5196 5352 ** slots were available. 5197 5353 ** </dd>)^ 5198 5354 ** ................................................................................ 5224 5380 ** CAPI3REF: Database Connection Status 5225 5381 ** 5226 5382 ** ^This interface is used to retrieve runtime status information 5227 5383 ** about a single [database connection]. ^The first argument is the 5228 5384 ** database connection object to be interrogated. ^The second argument 5229 5385 ** is an integer constant, taken from the set of 5230 5386 ** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that 5231 -** determiness the parameter to interrogate. The set of 5387 +** determines the parameter to interrogate. The set of 5232 5388 ** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely 5233 5389 ** to grow in future releases of SQLite. 5234 5390 ** 5235 5391 ** ^The current value of the requested parameter is written into *pCur 5236 5392 ** and the highest instantaneous value is written into *pHiwtr. ^If 5237 5393 ** the resetFlg is true, then the highest instantaneous value is 5238 5394 ** reset back down to the current value. 5395 +** 5396 +** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a 5397 +** non-zero [error code] on failure. 5239 5398 ** 5240 5399 ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. 5241 5400 */ 5242 5401 SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); 5243 5402 5244 5403 /* 5245 5404 ** CAPI3REF: Status Parameters for database connections ................................................................................ 5359 5518 5360 5519 /* 5361 5520 ** CAPI3REF: Application Defined Page Cache. 5362 5521 ** KEYWORDS: {page cache} 5363 5522 ** 5364 5523 ** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can 5365 5524 ** register an alternative page cache implementation by passing in an 5366 -** instance of the sqlite3_pcache_methods structure.)^ The majority of the 5367 -** heap memory used by SQLite is used by the page cache to cache data read 5368 -** from, or ready to be written to, the database file. By implementing a 5369 -** custom page cache using this API, an application can control more 5370 -** precisely the amount of memory consumed by SQLite, the way in which 5525 +** instance of the sqlite3_pcache_methods structure.)^ 5526 +** In many applications, most of the heap memory allocated by 5527 +** SQLite is used for the page cache. 5528 +** By implementing a 5529 +** custom page cache using this API, an application can better control 5530 +** the amount of memory consumed by SQLite, the way in which 5371 5531 ** that memory is allocated and released, and the policies used to 5372 5532 ** determine exactly which parts of a database file are cached and for 5373 5533 ** how long. 5374 5534 ** 5535 +** The alternative page cache mechanism is an 5536 +** extreme measure that is only needed by the most demanding applications. 5537 +** The built-in page cache is recommended for most uses. 5538 +** 5375 5539 ** ^(The contents of the sqlite3_pcache_methods structure are copied to an 5376 5540 ** internal buffer by SQLite within the call to [sqlite3_config]. Hence 5377 5541 ** the application may discard the parameter after the call to 5378 5542 ** [sqlite3_config()] returns.)^ 5379 5543 ** 5380 -** ^The xInit() method is called once for each call to [sqlite3_initialize()] 5544 +** ^(The xInit() method is called once for each effective 5545 +** call to [sqlite3_initialize()])^ 5381 5546 ** (usually only once during the lifetime of the process). ^(The xInit() 5382 5547 ** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^ 5383 -** ^The xInit() method can set up up global structures and/or any mutexes 5548 +** The intent of the xInit() method is to set up global data structures 5384 5549 ** required by the custom page cache implementation. 5550 +** ^(If the xInit() method is NULL, then the 5551 +** built-in default page cache is used instead of the application defined 5552 +** page cache.)^ 5385 5553 ** 5386 -** ^The xShutdown() method is called from within [sqlite3_shutdown()], 5387 -** if the application invokes this API. It can be used to clean up 5554 +** ^The xShutdown() method is called by [sqlite3_shutdown()]. 5555 +** It can be used to clean up 5388 5556 ** any outstanding resources before process shutdown, if required. 5557 +** ^The xShutdown() method may be NULL. 5389 5558 ** 5390 -** ^SQLite holds a [SQLITE_MUTEX_RECURSIVE] mutex when it invokes 5391 -** the xInit method, so the xInit method need not be threadsafe. ^The 5559 +** ^SQLite automatically serializes calls to the xInit method, 5560 +** so the xInit method need not be threadsafe. ^The 5392 5561 ** xShutdown method is only called from [sqlite3_shutdown()] so it does 5393 5562 ** not need to be threadsafe either. All other methods must be threadsafe 5394 5563 ** in multithreaded applications. 5395 5564 ** 5396 5565 ** ^SQLite will never invoke xInit() more than once without an intervening 5397 5566 ** call to xShutdown(). 5398 5567 ** 5399 -** ^The xCreate() method is used to construct a new cache instance. SQLite 5400 -** will typically create one cache instance for each open database file, 5568 +** ^SQLite invokes the xCreate() method to construct a new cache instance. 5569 +** SQLite will typically create one cache instance for each open database file, 5401 5570 ** though this is not guaranteed. ^The 5402 5571 ** first parameter, szPage, is the size in bytes of the pages that must 5403 5572 ** be allocated by the cache. ^szPage will not be a power of two. ^szPage 5404 5573 ** will the page size of the database file that is to be cached plus an 5405 -** increment (here called "R") of about 100 or 200. ^SQLite will use the 5574 +** increment (here called "R") of about 100 or 200. SQLite will use the 5406 5575 ** extra R bytes on each page to store metadata about the underlying 5407 5576 ** database page on disk. The value of R depends 5408 5577 ** on the SQLite version, the target platform, and how SQLite was compiled. 5409 5578 ** ^R is constant for a particular build of SQLite. ^The second argument to 5410 5579 ** xCreate(), bPurgeable, is true if the cache being created will 5411 5580 ** be used to cache database pages of a file stored on disk, or 5412 -** false if it is used for an in-memory database. ^The cache implementation 5581 +** false if it is used for an in-memory database. The cache implementation 5413 5582 ** does not have to do anything special based with the value of bPurgeable; 5414 5583 ** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will 5415 5584 ** never invoke xUnpin() except to deliberately delete a page. 5416 -** ^In other words, a cache created with bPurgeable set to false will 5585 +** ^In other words, calls to xUnpin() on a cache with bPurgeable set to 5586 +** false will always have the "discard" flag set to true. 5587 +** ^Hence, a cache created with bPurgeable false will 5417 5588 ** never contain any unpinned pages. 5418 5589 ** 5419 5590 ** ^(The xCachesize() method may be called at any time by SQLite to set the 5420 5591 ** suggested maximum cache-size (number of pages stored by) the cache 5421 5592 ** instance passed as the first argument. This is the value configured using 5422 -** the SQLite "[PRAGMA cache_size]" command.)^ ^As with the bPurgeable 5593 +** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable 5423 5594 ** parameter, the implementation is not required to do anything with this 5424 5595 ** value; it is advisory only. 5425 5596 ** 5426 -** ^The xPagecount() method should return the number of pages currently 5427 -** stored in the cache. 5597 +** The xPagecount() method must return the number of pages currently 5598 +** stored in the cache, both pinned and unpinned. 5428 5599 ** 5429 -** ^The xFetch() method is used to fetch a page and return a pointer to it. 5430 -** ^A 'page', in this context, is a buffer of szPage bytes aligned at an 5431 -** 8-byte boundary. ^The page to be fetched is determined by the key. ^The 5432 -** mimimum key value is 1. After it has been retrieved using xFetch, the page 5600 +** The xFetch() method locates a page in the cache and returns a pointer to 5601 +** the page, or a NULL pointer. 5602 +** A "page", in this context, means a buffer of szPage bytes aligned at an 5603 +** 8-byte boundary. The page to be fetched is determined by the key. ^The 5604 +** mimimum key value is 1. After it has been retrieved using xFetch, the page 5433 5605 ** is considered to be "pinned". 5434 5606 ** 5435 -** ^If the requested page is already in the page cache, then the page cache 5607 +** If the requested page is already in the page cache, then the page cache 5436 5608 ** implementation must return a pointer to the page buffer with its content 5437 -** intact. ^(If the requested page is not already in the cache, then the 5438 -** behavior of the cache implementation is determined by the value of the 5439 -** createFlag parameter passed to xFetch, according to the following table: 5609 +** intact. If the requested page is not already in the cache, then the 5610 +** behavior of the cache implementation should use the value of the createFlag 5611 +** parameter to help it determined what action to take: 5440 5612 ** 5441 5613 ** <table border=1 width=85% align=center> 5442 5614 ** <tr><th> createFlag <th> Behaviour when page is not already in cache 5443 5615 ** <tr><td> 0 <td> Do not allocate a new page. Return NULL. 5444 5616 ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so. 5445 5617 ** Otherwise return NULL. 5446 5618 ** <tr><td> 2 <td> Make every effort to allocate a new page. Only return 5447 5619 ** NULL if allocating a new page is effectively impossible. 5448 -** </table>)^ 5620 +** </table> 5449 5621 ** 5450 -** SQLite will normally invoke xFetch() with a createFlag of 0 or 1. If 5451 -** a call to xFetch() with createFlag==1 returns NULL, then SQLite will 5622 +** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite 5623 +** will only use a createFlag of 2 after a prior call with a createFlag of 1 5624 +** failed.)^ In between the to xFetch() calls, SQLite may 5452 5625 ** attempt to unpin one or more cache pages by spilling the content of 5453 -** pinned pages to disk and synching the operating system disk cache. After 5454 -** attempting to unpin pages, the xFetch() method will be invoked again with 5455 -** a createFlag of 2. 5626 +** pinned pages to disk and synching the operating system disk cache. 5456 5627 ** 5457 5628 ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page 5458 -** as its second argument. ^(If the third parameter, discard, is non-zero, 5459 -** then the page should be evicted from the cache. In this case SQLite 5460 -** assumes that the next time the page is retrieved from the cache using 5461 -** the xFetch() method, it will be zeroed.)^ ^If the discard parameter is 5462 -** zero, then the page is considered to be unpinned. ^The cache implementation 5629 +** as its second argument. If the third parameter, discard, is non-zero, 5630 +** then the page must be evicted from the cache. 5631 +** ^If the discard parameter is 5632 +** zero, then the page may be discarded or retained at the discretion of 5633 +** page cache implementation. ^The page cache implementation 5463 5634 ** may choose to evict unpinned pages at any time. 5464 5635 ** 5465 -** ^(The cache is not required to perform any reference counting. A single 5636 +** The cache must not perform any reference counting. A single 5466 5637 ** call to xUnpin() unpins the page regardless of the number of prior calls 5467 -** to xFetch().)^ 5638 +** to xFetch(). 5468 5639 ** 5469 -** ^The xRekey() method is used to change the key value associated with the 5470 -** page passed as the second argument from oldKey to newKey. ^If the cache 5471 -** previously contains an entry associated with newKey, it should be 5640 +** The xRekey() method is used to change the key value associated with the 5641 +** page passed as the second argument. If the cache 5642 +** previously contains an entry associated with newKey, it must be 5472 5643 ** discarded. ^Any prior cache entry associated with newKey is guaranteed not 5473 5644 ** to be pinned. 5474 5645 ** 5475 -** ^When SQLite calls the xTruncate() method, the cache must discard all 5646 +** When SQLite calls the xTruncate() method, the cache must discard all 5476 5647 ** existing cache entries with page numbers (keys) greater than or equal 5477 -** to the value of the iLimit parameter passed to xTruncate(). ^If any 5648 +** to the value of the iLimit parameter passed to xTruncate(). If any 5478 5649 ** of these pages are pinned, they are implicitly unpinned, meaning that 5479 5650 ** they can be safely discarded. 5480 5651 ** 5481 5652 ** ^The xDestroy() method is used to delete a cache allocated by xCreate(). 5482 5653 ** All resources associated with the specified cache should be freed. ^After 5483 5654 ** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] 5484 5655 ** handle invalid, and will not use it with any other sqlite3_pcache_methods ................................................................................ 5646 5817 ** is not a permanent error and does not affect the return value of 5647 5818 ** sqlite3_backup_finish(). 5648 5819 ** 5649 5820 ** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b> 5650 5821 ** 5651 5822 ** ^Each call to sqlite3_backup_step() sets two values inside 5652 5823 ** the [sqlite3_backup] object: the number of pages still to be backed 5653 -** up and the total number of pages in the source databae file. 5824 +** up and the total number of pages in the source database file. 5654 5825 ** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces 5655 5826 ** retrieve these two values, respectively. 5656 5827 ** 5657 5828 ** ^The values returned by these functions are only updated by 5658 5829 ** sqlite3_backup_step(). ^If the source database is modified during a backup 5659 5830 ** operation, then the values are not updated to account for any extra 5660 5831 ** pages that need to be updated or the size of the source database file ................................................................................ 5742 5913 ** the other connections to use as the blocking connection. 5743 5914 ** 5744 5915 ** ^(There may be at most one unlock-notify callback registered by a 5745 5916 ** blocked connection. If sqlite3_unlock_notify() is called when the 5746 5917 ** blocked connection already has a registered unlock-notify callback, 5747 5918 ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is 5748 5919 ** called with a NULL pointer as its second argument, then any existing 5749 -** unlock-notify callback is cancelled. ^The blocked connections 5920 +** unlock-notify callback is canceled. ^The blocked connections 5750 5921 ** unlock-notify callback may also be canceled by closing the blocked 5751 5922 ** connection using [sqlite3_close()]. 5752 5923 ** 5753 5924 ** The unlock-notify callback is not reentrant. If an application invokes 5754 5925 ** any sqlite3_xxx API functions from within an unlock-notify callback, a 5755 5926 ** crash or deadlock may be the result. 5756 5927 ** ................................................................................ 5824 5995 5825 5996 5826 5997 /* 5827 5998 ** CAPI3REF: String Comparison 5828 5999 ** 5829 6000 ** ^The [sqlite3_strnicmp()] API allows applications and extensions to 5830 6001 ** compare the contents of two buffers containing UTF-8 strings in a 5831 -** case-indendent fashion, using the same definition of case independence 6002 +** case-independent fashion, using the same definition of case independence 5832 6003 ** that SQLite uses internally when comparing identifiers. 5833 6004 */ 5834 6005 SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); 5835 6006 5836 6007 /* 5837 6008 ** CAPI3REF: Error Logging Interface 5838 6009 ** ................................................................................ 5948 6119 #endif 5949 6120 5950 6121 #ifdef __cplusplus 5951 6122 } /* End of the 'extern "C"' block */ 5952 6123 #endif 5953 6124 #endif 5954 6125 6126 +/* 6127 +** 2010 August 30 6128 +** 6129 +** The author disclaims copyright to this source code. In place of 6130 +** a legal notice, here is a blessing: 6131 +** 6132 +** May you do good and not evil. 6133 +** May you find forgiveness for yourself and forgive others. 6134 +** May you share freely, never taking more than you give. 6135 +** 6136 +************************************************************************* 6137 +*/ 6138 + 6139 +#ifndef _SQLITE3RTREE_H_ 6140 +#define _SQLITE3RTREE_H_ 6141 + 6142 + 6143 +#ifdef __cplusplus 6144 +extern "C" { 6145 +#endif 6146 + 6147 +typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; 6148 + 6149 +/* 6150 +** Register a geometry callback named zGeom that can be used as part of an 6151 +** R-Tree geometry query as follows: 6152 +** 6153 +** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...) 6154 +*/ 6155 +SQLITE_API int sqlite3_rtree_geometry_callback( 6156 + sqlite3 *db, 6157 + const char *zGeom, 6158 + int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), 6159 + void *pContext 6160 +); 6161 + 6162 + 6163 +/* 6164 +** A pointer to a structure of the following type is passed as the first 6165 +** argument to callbacks registered using rtree_geometry_callback(). 6166 +*/ 6167 +struct sqlite3_rtree_geometry { 6168 + void *pContext; /* Copy of pContext passed to s_r_g_c() */ 6169 + int nParam; /* Size of array aParam[] */ 6170 + double *aParam; /* Parameters passed to SQL geom function */ 6171 + void *pUser; /* Callback implementation user data */ 6172 + void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ 6173 +}; 6174 + 6175 + 6176 +#ifdef __cplusplus 6177 +} /* end of the 'extern "C"' block */ 6178 +#endif 6179 + 6180 +#endif /* ifndef _SQLITE3RTREE_H_ */ 6181 +
Changes to src/stat.c.
24 24 25 25 /* 26 26 ** WEBPAGE: stat 27 27 ** 28 28 ** Show statistics and global information about the repository. 29 29 */ 30 30 void stat_page(void){ 31 - i64 t; 32 - int n, m, fsize; 31 + i64 t, fsize; 32 + int n, m; 33 + int szMax, szAvg; 33 34 char zBuf[100]; 35 + 34 36 login_check_credentials(); 35 37 if( !g.okRead ){ login_needed(); return; } 36 38 style_header("Repository Statistics"); 37 - @ <p><table class="label-value"> 39 + @ <table class="label-value"> 38 40 @ <tr><th>Repository Size:</th><td> 39 41 fsize = file_size(g.zRepositoryName); 40 - @ %d(fsize) bytes 42 + sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", fsize); 43 + @ %s(zBuf) bytes 41 44 @ </td></tr> 42 45 @ <tr><th>Number Of Artifacts:</th><td> 43 46 n = db_int(0, "SELECT count(*) FROM blob"); 44 47 m = db_int(0, "SELECT count(*) FROM delta"); 45 48 @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs) 46 49 @ </td></tr> 47 50 if( n>0 ){ 48 51 int a, b; 52 + Stmt q; 49 53 @ <tr><th>Uncompressed Artifact Size:</th><td> 50 - t = db_int64(0, "SELECT total(size) FROM blob WHERE size>0"); 54 + db_prepare(&q, "SELECT total(size), avg(size), max(size)" 55 + " FROM blob WHERE size>0"); 56 + db_step(&q); 57 + t = db_column_int64(&q, 0); 58 + szAvg = db_column_int(&q, 1); 59 + szMax = db_column_int(&q, 2); 60 + db_finalize(&q); 51 61 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t); 52 - @ %d((int)(((double)t)/(double)n)) bytes average, %s(zBuf) bytes total 62 + @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total 53 63 @ </td></tr> 54 64 @ <tr><th>Compression Ratio:</th><td> 55 65 if( t/fsize < 5 ){ 56 66 b = 10; 57 67 fsize /= 10; 58 68 }else{ 59 69 b = 1; ................................................................................ 80 90 " WHERE +tagname GLOB 'tkt-*'"); 81 91 @ %d(n) 82 92 @ </td></tr> 83 93 @ <tr><th>Duration Of Project:</th><td> 84 94 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)" 85 95 " + 0.99"); 86 96 @ %d(n) days 97 + sqlite3_snprintf(sizeof(zBuf), zBuf, "%.2f", n/365.24); 98 + @ or approximately %s(zBuf) years 87 99 @ </td></tr> 88 100 @ <tr><th>Project ID:</th><td> 89 101 @ %h(db_get("project-code","")) 90 102 @ </td></tr> 91 103 @ <tr><th>Server ID:</th><td> 92 104 @ %h(db_get("server-code","")) 93 105 @ </td></tr> 94 106 95 107 @ <tr><th>Fossil Version:</th><td> 96 - @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION) 108 + @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION) (%h(COMPILER_NAME)) 97 109 @ </td></tr> 98 110 @ <tr><th>SQLite Version:</th><td> 99 - @ %h(db_text(0, "SELECT substr(sqlite_source_id(),1,30)")) 100 - @ (%h(SQLITE_VERSION)) 111 + sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)", 112 + SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION); 113 + @ %s(zBuf) 101 114 @ </td></tr> 102 115 @ <tr><th>Database Stats:</th><td> 103 116 @ %d(db_int(0, "PRAGMA %s.page_count", g.zRepoDb)) pages, 104 117 @ %d(db_int(0, "PRAGMA %s.page_size", g.zRepoDb)) bytes/page, 105 118 @ %d(db_int(0, "PRAGMA %s.freelist_count", g.zRepoDb)) free pages, 106 119 @ %s(db_text(0, "PRAGMA %s.encoding", g.zRepoDb)), 107 120 @ %s(db_text(0, "PRAGMA %s.journal_mode", g.zRepoDb)) mode 108 121 @ </td></tr> 109 122 110 - @ </table></p> 123 + @ </table> 111 124 style_footer(); 112 125 }
Changes to src/style.c.
38 38 39 39 /* 40 40 ** Remember that the header has been generated. The footer is omitted 41 41 ** if an error occurs before the header. 42 42 */ 43 43 static int headerHasBeenGenerated = 0; 44 44 45 +/* 46 +** remember, if a sidebox was used 47 +*/ 48 +static int sideboxUsed = 0; 49 + 45 50 /* 46 51 ** Add a new element to the submenu 47 52 */ 48 53 void style_submenu_element( 49 54 const char *zLabel, 50 55 const char *zTitle, 51 56 const char *zLink, ................................................................................ 81 86 82 87 va_start(ap, zTitleFormat); 83 88 zTitle = vmprintf(zTitleFormat, ap); 84 89 va_end(ap); 85 90 86 91 cgi_destination(CGI_HEADER); 87 92 cgi_printf("%s", 88 - "<!DOCTYPE html PUBLIC \"-//W3C/DTD XHTML 1.0 Strict//EN\"" 93 + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" 89 94 " \"http://www.x3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); 90 95 91 96 if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); 92 97 93 98 /* Generate the header up through the main menu */ 94 99 Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); 95 100 Th_Store("title", zTitle); 96 101 Th_Store("baseurl", g.zBaseURL); 97 102 Th_Store("index_page", db_get("index-page","/home")); 98 103 Th_Store("current_page", g.zPath); 99 104 Th_Store("manifest_version", MANIFEST_VERSION); 100 105 Th_Store("manifest_date", MANIFEST_DATE); 106 + Th_Store("compiler_name", COMPILER_NAME); 101 107 if( g.zLogin ){ 102 108 Th_Store("login", g.zLogin); 103 109 } 104 110 if( g.thTrace ) Th_Trace("BEGIN_HEADER_SCRIPT<br />\n", -1); 105 111 Th_Render(zHeader); 106 112 if( g.thTrace ) Th_Trace("END_HEADER<br />\n", -1); 107 113 Th_Unstore("title"); /* Avoid collisions with ticket field names */ 108 114 cgi_destination(CGI_BODY); 109 115 g.cgiOutput = 1; 110 116 headerHasBeenGenerated = 1; 117 + sideboxUsed = 0; 111 118 } 112 119 113 120 /* 114 121 ** Draw the footer at the bottom of the page. 115 122 */ 116 123 void style_footer(void){ 117 124 const char *zFooter; ................................................................................ 136 143 } 137 144 } 138 145 @ </div> 139 146 } 140 147 @ <div class="content"> 141 148 cgi_destination(CGI_BODY); 142 149 143 - /* Put the footer at the bottom of the page. 144 - */ 145 - @ </div><br clear="both"/> 150 + if (sideboxUsed) { 151 + /* Put the footer at the bottom of the page. 152 + ** the additional clear/both is needed to extend the content 153 + ** part to the end of an optional sidebox. 154 + */ 155 + @ <div class="endContent"></div> 156 + } 157 + @ </div> 146 158 zFooter = db_get("footer", (char*)zDefaultFooter); 147 159 if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); 148 160 Th_Render(zFooter); 149 161 if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1); 150 162 151 163 /* Render trace log if TH1 tracing is enabled. */ 152 164 if( g.thTrace ){ 153 - cgi_append_content("<font color=\"red\"><hr>\n", -1); 165 + cgi_append_content("<span class=\"thTrace\"><hr />\n", -1); 154 166 cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog)); 155 - cgi_append_content("</font>\n", -1); 167 + cgi_append_content("</span>\n", -1); 156 168 } 157 169 } 158 170 159 171 /* 160 172 ** Begin a side-box on the right-hand side of a page. The title and 161 173 ** the width of the box are given as arguments. The width is usually 162 174 ** a percentage of total screen width. 163 175 */ 164 176 void style_sidebox_begin(const char *zTitle, const char *zWidth){ 165 - @ <table width="%s(zWidth)" align="right" border="1" cellpadding=5 166 - @ vspace=5 hspace=5> 167 - @ <tr><td> 168 - @ <b>%h(zTitle)</b> 177 + sideboxUsed = 1; 178 + @ <div class="sidebox" style="width:%s(zWidth)"> 179 + @ <div class="sideboxTitle">%h(zTitle)</div> 169 180 } 170 181 171 182 /* End the side-box 172 183 */ 173 184 void style_sidebox_end(void){ 174 - @ </td></tr></table> 185 + @ </div> 175 186 } 176 187 177 188 /* @-comment: // */ 178 189 /* 179 190 ** The default page header. 180 191 */ 181 192 const char zDefaultHeader[] = 182 193 @ <html> 183 194 @ <head> 184 195 @ <title>$<project_name>: $<title></title> 185 196 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" 186 -@ href="$baseurl/timeline.rss"> 197 +@ href="$baseurl/timeline.rss" /> 187 198 @ <link rel="stylesheet" href="$baseurl/style.css?default" type="text/css" 188 -@ media="screen"> 199 +@ media="screen" /> 189 200 @ </head> 190 201 @ <body> 191 202 @ <div class="header"> 192 203 @ <div class="logo"> 193 -@ <img src="$baseurl/logo" alt="logo"> 204 +@ <img src="$baseurl/logo" alt="logo" /> 194 205 @ </div> 195 -@ <div class="title"><small>$<project_name></small><br>$<title></div> 196 -@ <div class="status"><nobr><th1> 206 +@ <div class="title"><small>$<project_name></small><br />$<title></div> 207 +@ <div class="status"><th1> 197 208 @ if {[info exists login]} { 198 209 @ puts "Logged in as $login" 199 210 @ } else { 200 211 @ puts "Not logged in" 201 212 @ } 202 -@ </th1></nobr></div> 213 +@ </th1></div> 203 214 @ </div> 204 215 @ <div class="mainmenu"><th1> 205 216 @ html "<a href='$baseurl$index_page'>Home</a> " 206 217 @ if {[anycap jor]} { 207 218 @ html "<a href='$baseurl/timeline'>Timeline</a> " 208 219 @ } 209 220 @ if {[hascap oh]} { ................................................................................ 241 252 @ Fossil version $manifest_version $manifest_date 242 253 @ </div> 243 254 @ </body></html> 244 255 ; 245 256 246 257 /* 247 258 ** The default Cascading Style Sheet. 259 +** It's assembled by different strings for each class. 260 +** The default css conatains all definitions. 261 +** The style sheet, send to the client only contains the ones, 262 +** not defined in the user defined css. 248 263 */ 249 264 const char zDefaultCSS[] = 250 265 @ /* General settings for the entire page */ 251 266 @ body { 252 267 @ margin: 0ex 1ex; 253 268 @ padding: 0px; 254 269 @ background-color: white; ................................................................................ 270 285 @ display: table-cell; 271 286 @ font-size: 2em; 272 287 @ font-weight: bold; 273 288 @ text-align: center; 274 289 @ padding: 0 0 0 1em; 275 290 @ color: #558195; 276 291 @ vertical-align: bottom; 277 -@ width: 100%; 292 +@ width: 100% ; 278 293 @ } 279 294 @ 280 295 @ /* The login status message in the top right-hand corner */ 281 296 @ div.status { 282 297 @ display: table-cell; 283 298 @ text-align: right; 284 299 @ vertical-align: bottom; 285 300 @ color: #558195; 286 301 @ font-size: 0.8em; 287 302 @ font-weight: bold; 288 303 @ min-width: 200px; 304 +@ white-space: nowrap; 289 305 @ } 290 306 @ 291 307 @ /* The header across the top of the page */ 292 308 @ div.header { 293 309 @ display: table; 294 -@ width: 100%; 310 +@ width: 100% ; 295 311 @ } 296 312 @ 297 313 @ /* The main menu bar that appears at the top of the page beneath 298 314 @ ** the header */ 299 315 @ div.mainmenu { 300 316 @ padding: 5px 10px 5px 10px; 301 317 @ font-size: 0.9em; ................................................................................ 335 351 @ margin-bottom: 0px; 336 352 @ margin-top: 1em; 337 353 @ padding: 1px 1px 1px 1px; 338 354 @ font-size: 1.2em; 339 355 @ font-weight: bold; 340 356 @ background-color: #558195; 341 357 @ color: white; 358 +@ white-space: nowrap; 342 359 @ } 343 360 @ 344 361 @ /* The "Date" that occurs on the left hand side of timelines */ 345 362 @ div.divider { 346 363 @ background: #a1c4d4; 347 364 @ border: 2px #558195 solid; 348 365 @ font-size: 1em; font-weight: normal; 349 366 @ padding: .25em; 350 367 @ margin: .2em 0 .2em 0; 351 368 @ float: left; 352 369 @ clear: left; 370 +@ white-space: nowrap; 353 371 @ } 354 372 @ 355 373 @ /* The footer at the very bottom of the page */ 356 374 @ div.footer { 375 +@ clear: both; 357 376 @ font-size: 0.8em; 358 377 @ margin-top: 12px; 359 378 @ padding: 5px 10px 5px 10px; 360 379 @ text-align: right; 361 380 @ background-color: #558195; 362 381 @ color: white; 363 382 @ } ................................................................................ 364 383 @ 365 384 @ /* Hyperlink colors in the footer */ 366 385 @ div.footer a { color: white; } 367 386 @ div.footer a:link { color: white; } 368 387 @ div.footer a:visited { color: white; } 369 388 @ div.footer a:hover { background-color: white; color: #558195; } 370 389 @ 371 -@ /* <verbatim> blocks */ 390 +@ /* verbatim blocks */ 372 391 @ pre.verbatim { 373 392 @ background-color: #f5f5f5; 374 393 @ padding: 0.5em; 375 394 @} 376 395 @ 377 396 @ /* The label/value pairs on (for example) the ci page */ 378 397 @ table.label-value th { 379 398 @ vertical-align: top; 380 399 @ text-align: right; 381 400 @ padding: 0.2ex 2ex; 382 401 @ } 402 +@ 383 403 ; 384 404 405 + 406 +/* The following table contains bits of default CSS that must 407 +** be included if they are not found in the application-defined 408 +** CSS. 409 +*/ 410 +const struct strctCssDefaults { 411 + char const * const elementClass; /* Name of element needed */ 412 + char const * const comment; /* Comment text */ 413 + char const * const value; /* CSS text */ 414 +} cssDefaultList[] = { 415 + { "", 416 + "", 417 + zDefaultCSS 418 + }, 419 + { "div.sidebox", 420 + "The nomenclature sidebox for branches,..", 421 + @ float: right; 422 + @ background-color: white; 423 + @ border-width: medium; 424 + @ border-style: double; 425 + @ margin: 10; 426 + }, 427 + { "div.sideboxTitle", 428 + "The nomenclature title in sideboxes for branches,..", 429 + @ display: inline; 430 + @ font-weight: bold; 431 + }, 432 + { "div.sideboxDescribed", 433 + "The defined element in sideboxes for branches,..", 434 + @ display: inline; 435 + @ font-weight: bold; 436 + }, 437 + { "span.disabled", 438 + "The defined element in sideboxes for branches,..", 439 + @ color: red; 440 + }, 441 + { "span.timelineDisabled", 442 + "The suppressed duplicates lines in timeline, ..", 443 + @ font-style: italic; 444 + @ font-size: small; 445 + }, 446 + { "table.timelineTable", 447 + "the format for the timeline data table", 448 + @ cellspacing: 0; 449 + @ border: 0; 450 + @ cellpadding: 0 451 + }, 452 + { "td.timelineTableCell", 453 + "the format for the timeline data cells", 454 + @ valign: top; 455 + @ align: left; 456 + }, 457 + { "span.timelineLeaf", 458 + "the format for the timeline leaf marks", 459 + @ font-weight: bold; 460 + }, 461 + { "a.timelineHistLink", 462 + "the format for the timeline version links", 463 + @ 464 + }, 465 + { "span.timelineHistDsp", 466 + "the format for the timeline version display(no history permission!)", 467 + @ font-weight: bold; 468 + }, 469 + { "td.timelineTime", 470 + "the format for the timeline time display", 471 + @ vertical-align: top; 472 + @ text-align: right; 473 + }, 474 + { "td.timelineGraph", 475 + "the format for the grap placeholder cells in timelines", 476 + @ width: 20; 477 + @ text-align: left; 478 + @ vertical-align: top; 479 + }, 480 + { "a.tagLink", 481 + "the format for the tag links", 482 + @ 483 + }, 484 + { "span.tagDsp", 485 + "the format for the tag display(no history permission!)", 486 + @ font-weight: bold; 487 + }, 488 + { "span.wikiError", 489 + "the format for wiki errors", 490 + @ font-weight: bold; 491 + @ color: red; 492 + }, 493 + { "span.infoTagCancelled", 494 + "the format for fixed/canceled tags,..", 495 + @ font-weight: bold; 496 + @ text-decoration: line-through; 497 + }, 498 + { "span.infoTag", 499 + "the format for tags,..", 500 + @ font-weight: bold; 501 + }, 502 + { "span.wikiTagCancelled", 503 + "the format for fixed/cancelled tags,.. on wiki pages", 504 + @ text-decoration: line-through; 505 + }, 506 + { "table.browser", 507 + "format for the file display table", 508 + @ /* the format for wiki errors */ 509 + @ width: 100% ; 510 + @ border: 0; 511 + }, 512 + { "td.browser", 513 + "format for cells in the file browser", 514 + @ width: 24% ; 515 + @ vertical-align: top; 516 + }, 517 + { "ul.browser", 518 + "format for the list in the file browser", 519 + @ margin-left: 0.5em; 520 + @ padding-left: 0.5em; 521 + }, 522 + { "table.login_out", 523 + "table format for login/out label/input table", 524 + @ text-align: left; 525 + @ margin-right: 10px; 526 + @ margin-left: 10px; 527 + @ margin-top: 10px; 528 + }, 529 + { "div.captcha", 530 + "captcha display options", 531 + @ text-align: center; 532 + }, 533 + { "table.captcha", 534 + "format for the layout table, used for the captcha display", 535 + @ margin: auto; 536 + @ padding: 10px; 537 + @ border-width: 4px; 538 + @ border-style: double; 539 + @ border-color: black; 540 + }, 541 + { "td.login_out_label", 542 + "format for the label cells in the login/out table", 543 + @ text-align: center; 544 + }, 545 + { "span.loginError", 546 + "format for login error messages", 547 + @ color: red; 548 + }, 549 + { "span.note", 550 + "format for leading text for notes", 551 + @ font-weight: bold; 552 + }, 553 + { "span.textareaLabel", 554 + "format for textare labels", 555 + @ font-weight: bold; 556 + }, 557 + { "table.usetupLayoutTable", 558 + "format for the user setup layout table", 559 + @ outline-style: none; 560 + @ padding: 0; 561 + @ margin: 25px; 562 + }, 563 + { "td.usetupColumnLayout", 564 + "format of the columns on the user setup list page", 565 + @ vertical-align: top 566 + }, 567 + { "table.usetupUserList", 568 + "format for the user list table on the user setup page", 569 + @ outline-style: double; 570 + @ outline-width: 1; 571 + @ padding: 10px; 572 + }, 573 + { "th.usetupListUser", 574 + "format for table header user in user list on user setup page", 575 + @ text-align: right; 576 + @ padding-right: 20px; 577 + }, 578 + { "th.usetupListCap", 579 + "format for table header capabilities in user list on user setup page", 580 + @ text-align: center; 581 + @ padding-right: 15px; 582 + }, 583 + { "th.usetupListCon", 584 + "format for table header contact info in user list on user setup page", 585 + @ text-align: left; 586 + }, 587 + { "td.usetupListUser", 588 + "format for table cell user in user list on user setup page", 589 + @ text-align: right; 590 + @ padding-right: 20px; 591 + @ white-space:nowrap; 592 + }, 593 + { "td.usetupListCap", 594 + "format for table cell capabilities in user list on user setup page", 595 + @ text-align: center; 596 + @ padding-right: 15px; 597 + }, 598 + { "td.usetupListCon", 599 + "format for table cell contact info in user list on user setup page", 600 + @ text-align: left 601 + }, 602 + { "div.ueditCapBox", 603 + "layout definition for the capabilities box on the user edit detail page", 604 + @ float: left; 605 + @ margin-right: 20px; 606 + @ margin-bottom: 20px; 607 + }, 608 + { "td.usetupEditLabel", 609 + "format of the label cells in the detailed user edit page", 610 + @ text-align: right; 611 + @ vertical-align: top; 612 + @ white-space: nowrap; 613 + }, 614 + { "span.ueditInheritNobody", 615 + "color for capabilities, inherited by nobody", 616 + @ color: green; 617 + }, 618 + { "span.ueditInheritDeveloper", 619 + "color for capabilities, inherited by developer", 620 + @ color: red; 621 + }, 622 + { "span.ueditInheritReader", 623 + "color for capabilities, inherited by reader", 624 + @ color: black; 625 + }, 626 + { "span.ueditInheritAnonymous", 627 + "color for capabilities, inherited by anonymous", 628 + @ color: blue; 629 + }, 630 + { "span.capability", 631 + "format for capabilites, mentioned on the user edit page", 632 + @ font-weight: bold; 633 + }, 634 + { "span.usertype", 635 + "format for different user types, mentioned on the user edit page", 636 + @ font-weight: bold; 637 + }, 638 + { "span.usertype:before", 639 + "leading text for user types, mentioned on the user edit page", 640 + @ content:"'"; 641 + }, 642 + { "span.usertype:after", 643 + "trailing text for user types, mentioned on the user edit page", 644 + @ content:"'"; 645 + }, 646 + { "p.missingPriv", 647 + "format for missing priviliges note on user setup page", 648 + @ color: blue; 649 + }, 650 + { "span.wikiruleHead", 651 + "format for leading text in wikirules definitions", 652 + @ font-weight: bold; 653 + }, 654 + { "td.tktDspLabel", 655 + "format for labels on ticket display page", 656 + @ text-align: right; 657 + }, 658 + { "td.tktDspValue", 659 + "format for values on ticket display page", 660 + @ text-align: left; 661 + @ vertical-align: top; 662 + @ background-color: #d0d0d0; 663 + }, 664 + { "span.tktError", 665 + "format for ticket error messages", 666 + @ color: red; 667 + @ font-weight: bold; 668 + }, 669 + { "table.rpteditex", 670 + "format for example tables on the report edit page", 671 + @ float: right; 672 + @ margin: 0; 673 + @ padding: 0; 674 + @ width: 125px; 675 + @ text-align: center; 676 + @ border-collapse: collapse; 677 + @ border-spacing: 0; 678 + }, 679 + { "td.rpteditex", 680 + "format for example table cells on the report edit page", 681 + @ border-width: thin; 682 + @ border-color: #000000; 683 + @ border-style: solid; 684 + }, 685 + { "input.checkinUserColor", 686 + "format for user color input on checkin edit page", 687 + @ # no special definitions, class defined, to enable color pickers, f.e.: 688 + @ # add the color picker found at http:jscolor.com as java script include 689 + @ # to the header and configure the java script file with 690 + @ # 1. use as bindClass :checkinUserColor 691 + @ # 2. change the default hash adding behaviour to ON 692 + @ # or change the class defition of element identified by id="clrcust" 693 + @ # to a standard jscolor definition with java script in the footer. 694 + }, 695 + { "div.endContent", 696 + "format for end of content area, to be used to clear page flow(sidebox on branch,..", 697 + @ clear: both; 698 + }, 699 + { "p.generalError", 700 + "format for general errors", 701 + @ color: red; 702 + }, 703 + { "p.tktsetupError", 704 + "format for tktsetup errors", 705 + @ color: red; 706 + @ font-weight: bold; 707 + }, 708 + { "p.thmainError", 709 + "format for th script errors", 710 + @ color: red; 711 + @ font-weight: bold; 712 + }, 713 + { "span.thTrace", 714 + "format for th script trace messages", 715 + @ color: red; 716 + }, 717 + { "p:reportError", 718 + "format for report configuration errors", 719 + @ color: red; 720 + @ font-weight: bold; 721 + }, 722 + { "blockquote.reportError", 723 + "format for report configuration errors", 724 + @ color: red; 725 + @ font-weight: bold; 726 + }, 727 + { "p.noMoreShun", 728 + "format for artifact lines, no longer shunned", 729 + @ color: blue; 730 + }, 731 + { "p.shunned", 732 + "format for artifact lines beeing shunned", 733 + @ color: blue; 734 + }, 735 + { 0, 736 + 0, 737 + 0 738 + } 739 +}; 740 + 741 +/* 742 +** Append all of the default CSS to the CGI output. 743 +*/ 744 +void cgi_append_default_css(void) { 745 + int i; 746 + 747 + for (i=0;cssDefaultList[i].elementClass;i++){ 748 + if (cssDefaultList[i].elementClass[0]){ 749 + cgi_printf("/* %s */\n%s {\n%s\n}\n\n", 750 + cssDefaultList[i].comment, 751 + cssDefaultList[i].elementClass, 752 + cssDefaultList[i].value 753 + ); 754 + }else{ 755 + cgi_printf("%s", 756 + cssDefaultList[i].value 757 + ); 758 + } 759 + } 760 +} 761 + 385 762 /* 386 763 ** WEBPAGE: style.css 387 764 */ 388 765 void page_style_css(void){ 389 - char *zCSS = 0; 766 + const char *zCSS = 0; 767 + int i; 390 768 391 769 cgi_set_content_type("text/css"); 392 770 zCSS = db_get("css",(char*)zDefaultCSS); 771 + /* append user defined css */ 393 772 cgi_append_content(zCSS, -1); 773 + /* add special missing definitions */ 774 + for (i=1;cssDefaultList[i].elementClass;i++) 775 + if (!strstr(zCSS,cssDefaultList[i].elementClass)) { 776 + cgi_append_content("/* ", -1); 777 + cgi_append_content(cssDefaultList[i].comment, -1); 778 + cgi_append_content(" */\n", -1); 779 + cgi_append_content(cssDefaultList[i].elementClass, -1); 780 + cgi_append_content(" {\n", -1); 781 + cgi_append_content(cssDefaultList[i].value, -1); 782 + cgi_append_content("}\n\n", -1); 783 + } 394 784 g.isConst = 1; 395 785 } 396 786 397 787 /* 398 788 ** WEBPAGE: test_env 399 789 */ 400 790 void page_test_env(void){ 401 791 style_header("Environment Test"); 402 -#if !defined(__MINGW32__) 403 - @ uid=%d(getuid()), gid=%d(getgid())<br> 792 +#if !defined(_WIN32) 793 + @ uid=%d(getuid()), gid=%d(getgid())<br /> 404 794 #endif 405 - @ g.zBaseURL = %h(g.zBaseURL)<br> 406 - @ g.zTop = %h(g.zTop)<br> 407 - @ g.zRepositoryName = %h(g.zRepositoryName)<br> 795 + @ g.zBaseURL = %h(g.zBaseURL)<br /> 796 + @ g.zTop = %h(g.zTop)<br /> 408 797 cgi_print_all(); 409 798 style_footer(); 410 799 }
Changes to src/sync.c.
54 54 }else{ 55 55 /* Autosync defaults on. To make it default off, "return" here. */ 56 56 } 57 57 zUrl = db_get("last-sync-url", 0); 58 58 if( zUrl==0 ){ 59 59 return; /* No default server */ 60 60 } 61 - zPw = db_get("last-sync-pw", 0); 61 + zPw = unobscure(db_get("last-sync-pw", 0)); 62 62 url_parse(zUrl); 63 63 if( g.urlUser!=0 && g.urlPasswd==0 ){ 64 64 g.urlPasswd = mprintf("%s", zPw); 65 65 } 66 66 if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){ 67 67 /* When doing an automatic pull, also automatically pull shuns from 68 68 ** the server if pull_shuns is enabled. ................................................................................ 91 91 int urlOptional = find_option("autourl",0,0)!=0; 92 92 g.dontKeepUrl = find_option("once",0,0)!=0; 93 93 url_proxy_options(); 94 94 db_find_and_open_repository(1); 95 95 db_open_config(0); 96 96 if( g.argc==2 ){ 97 97 zUrl = db_get("last-sync-url", 0); 98 - zPw = db_get("last-sync-pw", 0); 98 + zPw = unobscure(db_get("last-sync-pw", 0)); 99 99 if( db_get_boolean("auto-sync",1) ) configSync = CONFIGSET_SHUN; 100 100 }else if( g.argc==3 ){ 101 101 zUrl = g.argv[2]; 102 102 } 103 103 if( zUrl==0 ){ 104 104 if( urlOptional ) fossil_exit(0); 105 105 usage("URL"); 106 106 } 107 107 url_parse(zUrl); 108 108 if( !g.dontKeepUrl ){ 109 109 db_set("last-sync-url", g.urlCanonical, 0); 110 - if( g.urlPasswd ) db_set("last-sync-pw", g.urlPasswd, 0); 110 + if( g.urlPasswd ) db_set("last-sync-pw", obscure(g.urlPasswd), 0); 111 111 } 112 112 if( g.urlUser!=0 && g.urlPasswd==0 ){ 113 113 if( zPw==0 ){ 114 114 url_prompt_for_password(); 115 115 }else{ 116 116 g.urlPasswd = mprintf("%s", zPw); 117 117 } ................................................................................ 230 230 }else{ 231 231 url_parse(g.argv[2]); 232 232 if( g.urlUser && g.urlPasswd==0 ){ 233 233 url_prompt_for_password(); 234 234 } 235 235 db_set("last-sync-url", g.urlCanonical, 0); 236 236 if( g.urlPasswd ){ 237 - db_set("last-sync-pw", g.urlPasswd, 0); 237 + db_set("last-sync-pw", obscure(g.urlPasswd), 0); 238 238 }else{ 239 239 db_unset("last-sync-pw", 0); 240 240 } 241 241 } 242 242 } 243 243 zUrl = db_get("last-sync-url", 0); 244 244 if( zUrl==0 ){
Changes to src/tag.c.
256 256 ** or cancels a tag. 257 257 */ 258 258 void tag_add_artifact( 259 259 const char *zPrefix, /* Prefix to prepend to tag name */ 260 260 const char *zTagname, /* The tag to add or cancel */ 261 261 const char *zObjName, /* Name of object attached to */ 262 262 const char *zValue, /* Value for the tag. Might be NULL */ 263 - int tagtype /* 0:cancel 1:singleton 2:propagated */ 263 + int tagtype, /* 0:cancel 1:singleton 2:propagated */ 264 + const char *zDateOvrd, /* Override date string */ 265 + const char *zUserOvrd /* Override user name */ 264 266 ){ 265 267 int rid; 266 268 int nrid; 267 269 char *zDate; 268 270 Blob uuid; 269 271 Blob ctrl; 270 272 Blob cksum; ................................................................................ 287 289 fossil_fatal( 288 290 "invalid tag name \"%s\" - might be confused with" 289 291 " a hexadecimal artifact ID", 290 292 zTagname 291 293 ); 292 294 } 293 295 #endif 294 - zDate = db_text(0, "SELECT datetime('now')"); 296 + zDate = date_in_standard_format(zDateOvrd ? zDateOvrd : "now"); 295 297 zDate[10] = 'T'; 296 298 blob_appendf(&ctrl, "D %s\n", zDate); 297 299 blob_appendf(&ctrl, "T %c%s%F %b", 298 300 zTagtype[tagtype], zPrefix, zTagname, &uuid); 299 301 if( tagtype>0 && zValue && zValue[0] ){ 300 302 blob_appendf(&ctrl, " %F\n", zValue); 301 303 }else{ 302 304 blob_appendf(&ctrl, "\n"); 303 305 } 304 - blob_appendf(&ctrl, "U %F\n", g.zLogin); 306 + blob_appendf(&ctrl, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); 305 307 md5sum_blob(&ctrl, &cksum); 306 308 blob_appendf(&ctrl, "Z %b\n", &cksum); 307 309 nrid = content_put(&ctrl, 0, 0); 308 310 manifest_crosslink(nrid, &ctrl); 309 311 } 310 312 311 313 /* ................................................................................ 350 352 ** will be taken as an artifact or baseline ID and fossil will 351 353 ** probably complain that no such revision was found. However 352 354 ** 353 355 ** fossil update tag:decaf 354 356 ** 355 357 ** will assume that "decaf" is a tag/branch name. 356 358 ** 359 +** only allow --date-override and --user-override in 360 +** %fossil tag add --date-override 'YYYY-MMM-DD HH:MM:SS' \\ 361 +** --user-override user 362 +** in order to import history from other scm systems 357 363 */ 358 364 void tag_cmd(void){ 359 365 int n; 360 366 int fRaw = find_option("raw","",0)!=0; 361 367 int fPropagate = find_option("propagate","",0)!=0; 362 368 const char *zPrefix = fRaw ? "" : "sym-"; 363 369 ................................................................................ 368 374 n = strlen(g.argv[2]); 369 375 if( n==0 ){ 370 376 goto tag_cmd_usage; 371 377 } 372 378 373 379 if( strncmp(g.argv[2],"add",n)==0 ){ 374 380 char *zValue; 381 + const char *zDateOvrd = find_option("date-override",0,1); 382 + const char *zUserOvrd = find_option("user-override",0,1); 375 383 if( g.argc!=5 && g.argc!=6 ){ 376 384 usage("add ?--raw? ?--propagate? TAGNAME CHECK-IN ?VALUE?"); 377 385 } 378 386 zValue = g.argc==6 ? g.argv[5] : 0; 379 387 db_begin_transaction(); 380 - tag_add_artifact(zPrefix, g.argv[3], g.argv[4], zValue, 1+fPropagate); 388 + tag_add_artifact(zPrefix, g.argv[3], g.argv[4], zValue, 389 + 1+fPropagate,zDateOvrd,zUserOvrd); 381 390 db_end_transaction(0); 382 391 }else 383 392 384 393 if( strncmp(g.argv[2],"branch",n)==0 ){ 385 394 fossil_fatal("the \"fossil tag branch\" command is discontinued\n" 386 395 "Use the \"fossil branch new\" command instead."); 387 396 }else 388 397 389 398 if( strncmp(g.argv[2],"cancel",n)==0 ){ 390 399 if( g.argc!=5 ){ 391 400 usage("cancel ?--raw? TAGNAME CHECK-IN"); 392 401 } 393 402 db_begin_transaction(); 394 - tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, 0); 403 + tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, 0, 0, 0); 395 404 db_end_transaction(0); 396 405 }else 397 406 398 407 if( strncmp(g.argv[2],"find",n)==0 ){ 399 408 Stmt q; 400 409 if( g.argc!=4 ){ 401 410 usage("find ?--raw? TAGNAME"); ................................................................................ 512 521 " AND tagname GLOB 'sym-*'" 513 522 " ORDER BY tagname" 514 523 ); 515 524 @ <ul> 516 525 while( db_step(&q)==SQLITE_ROW ){ 517 526 const char *zName = db_column_text(&q, 0); 518 527 if( g.okHistory ){ 519 - @ <li><a href=%s(g.zBaseURL)/timeline?t=%T(zName)>%h(zName)</a></li> 528 + @ <li><a class="tagLink" href="%s(g.zBaseURL)/timeline?t=%T(zName)"> 529 + @ %h(zName)</a></li> 520 530 }else{ 521 - @ <li><strong>%h(zName)</strong></li> 531 + @ <li><span class="tagDsp">%h(zName)</span></li> 522 532 } 523 533 } 524 534 @ </ul> 525 535 db_finalize(&q); 526 536 style_footer(); 527 537 } 528 538 ................................................................................ 540 550 " AND tagxref.tagtype>0 AND tagxref.srcid>0" 541 551 " AND tag.tagname GLOB 'sym-*'", 542 552 rid 543 553 ); 544 554 while( db_step(&q)==SQLITE_ROW ){ 545 555 const char *zTagName = db_column_text(&q, 0); 546 556 if( g.okHistory ){ 547 - @ <a href="%s(g.zBaseURL)/timeline?t=%T(zTagName)">[%h(zTagName)]</a> 557 + @ <a class="tagLink" href="%s(g.zBaseURL)/timeline?t=%T(zTagName)"> 558 + @ [%h(zTagName)]</a> 548 559 }else{ 549 - @ <b>[%h(zTagName)]</b> 560 + @ <span class="tagDsp">[%h(zTagName)]</span> 550 561 } 551 562 } 552 563 db_finalize(&q); 553 564 } 554 565 555 566 /* 556 567 ** WEBPAGE: /tagtimeline ................................................................................ 571 582 " AND tagid IN (SELECT tagid FROM tag " 572 583 " WHERE tagname GLOB 'sym-*'))" 573 584 " ORDER BY event.mtime DESC", 574 585 timeline_query_for_www() 575 586 ); 576 587 www_print_timeline(&q, 0, tagtimeline_extra); 577 588 db_finalize(&q); 578 - @ <br clear="both"> 579 - @ <script> 589 + @ <br /> 590 + @ <script type="text/JavaScript"> 580 591 @ function xin(id){ 581 592 @ } 582 593 @ function xout(id){ 583 594 @ } 584 595 @ </script> 585 596 style_footer(); 586 597 }
Changes to src/th.c.
844 844 continue; 845 845 } 846 846 847 847 /* Gobble up input a word at a time until the end of the command 848 848 ** (a semi-colon or end of line). 849 849 */ 850 850 while( rc==TH_OK && *zInput!=';' && !thEndOfLine(zInput, nInput) ){ 851 - int nWord; 851 + int nWord=0; 852 852 thNextSpace(interp, zInput, nInput, &nSpace); 853 853 rc = thNextWord(interp, &zInput[nSpace], nInput-nSpace, &nWord, 1); 854 854 zInput += (nSpace+nWord); 855 855 nInput -= (nSpace+nWord); 856 856 } 857 857 if( rc!=TH_OK ) continue; 858 858
Changes to src/th_lang.c.
5 5 ** 6 6 ** All built-in commands are implemented using the public interface 7 7 ** declared in th.h, so this file serves as both a part of the language 8 8 ** implementation and an example of how to extend the language with 9 9 ** new commands. 10 10 */ 11 11 12 +#include "config.h" 12 13 #include "th.h" 13 14 #include <string.h> 14 15 #include <assert.h> 15 16 16 17 int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg){ 17 18 Th_ErrorMessage(interp, "wrong # args: should be \"", zMsg, -1); 18 19 return TH_ERROR; ................................................................................ 569 570 ){ 570 571 if( argc!=1 && argc!=2 ){ 571 572 return Th_WrongNumArgs(interp, "return ?value?"); 572 573 } 573 574 if( argc==2 ){ 574 575 Th_SetResult(interp, argv[1], argl[1]); 575 576 } 576 - return (int)ctx; 577 + return FOSSIL_PTR_TO_INT(ctx); 577 578 } 578 579 579 580 /* 580 581 ** TH Syntax: 581 582 ** 582 583 ** return ?-code code? ?value? 583 584 */
Changes to src/th_main.c.
28 28 */ 29 29 static int nOutstandingMalloc = 0; 30 30 31 31 /* 32 32 ** Implementations of malloc() and free() to pass to the interpreter. 33 33 */ 34 34 static void *xMalloc(unsigned int n){ 35 - void *p = malloc(n); 35 + void *p = fossil_malloc(n); 36 36 if( p ){ 37 37 nOutstandingMalloc++; 38 38 } 39 39 return p; 40 40 } 41 41 static void xFree(void *p){ 42 42 if( p ){ ................................................................................ 276 276 sendText(z, -1, 0); 277 277 free(z); 278 278 blob_reset(&name); 279 279 for(i=0; i<nElem; i++){ 280 280 zH = htmlize((char*)azElem[i], aszElem[i]); 281 281 if( zValue && aszElem[i]==nValue 282 282 && memcmp(zValue, azElem[i], nValue)==0 ){ 283 - z = mprintf("<option value=\"%s\" selected>%s</option>", zH, zH); 283 + z = mprintf("<option value=\"%s\" selected=\"selected\">%s</option>", 284 + zH, zH); 284 285 }else{ 285 286 z = mprintf("<option value=\"%s\">%s</option>", zH, zH); 286 287 } 287 288 free(zH); 288 289 sendText(z, -1, 0); 289 290 free(z); 290 291 } ................................................................................ 432 433 static int validVarName(const char *z){ 433 434 int i = 0; 434 435 int inBracket = 0; 435 436 if( z[0]=='<' ){ 436 437 inBracket = 1; 437 438 z++; 438 439 } 439 - if( z[0]==':' && z[1]==':' && isalpha(z[2]) ){ 440 + if( z[0]==':' && z[1]==':' && fossil_isalpha(z[2]) ){ 440 441 z += 3; 441 442 i += 3; 442 - }else if( isalpha(z[0]) ){ 443 + }else if( fossil_isalpha(z[0]) ){ 443 444 z ++; 444 445 i += 1; 445 446 }else{ 446 447 return 0; 447 448 } 448 - while( isalnum(z[0]) || z[0]=='_' ){ 449 + while( fossil_isalnum(z[0]) || z[0]=='_' ){ 449 450 z++; 450 451 i++; 451 452 } 452 453 if( inBracket ){ 453 454 if( z[0]!='>' ) return 0; 454 455 i += 2; 455 456 } ................................................................................ 501 502 if( z[0] ){ z += 6; } 502 503 i = 0; 503 504 }else{ 504 505 i++; 505 506 } 506 507 } 507 508 if( rc==TH_ERROR ){ 508 - sendText("<hr><p><font color=\"red\"><b>ERROR: ", -1, 0); 509 + sendText("<hr><p class=\"thmainError\">ERROR: ", -1, 0); 509 510 zResult = (char*)Th_GetResult(g.interp, &n); 510 511 sendText((char*)zResult, n, 1); 511 - sendText("</b></font></p>", -1, 0); 512 + sendText("</p>", -1, 0); 512 513 }else{ 513 514 sendText(z, i, 0); 514 515 } 515 516 return rc; 516 517 } 517 518 518 519 /*
Changes to src/timeline.c.
46 46 /* 47 47 ** Generate a hyperlink to a version. 48 48 */ 49 49 void hyperlink_to_uuid(const char *zUuid){ 50 50 char zShortUuid[UUID_SIZE+1]; 51 51 shorten_uuid(zShortUuid, zUuid); 52 52 if( g.okHistory ){ 53 - @ <a href="%s(g.zBaseURL)/info/%s(zShortUuid)">[%s(zShortUuid)]</a> 53 + @ <a class="timelineHistLink" href="%s(g.zBaseURL)/info/%s(zShortUuid)"> 54 + @ [%s(zShortUuid)]</a> 54 55 }else{ 55 - @ <b>[%s(zShortUuid)]</b> 56 + @ <span class="timelineHistDsp">[%s(zShortUuid)]</span> 56 57 } 57 58 } 58 59 59 60 /* 60 61 ** Generate a hyperlink that invokes javascript to highlight 61 62 ** a version on mouseover. 62 63 */ ................................................................................ 81 82 ** Generate a hyperlink to a diff between two versions. 82 83 */ 83 84 void hyperlink_to_diff(const char *zV1, const char *zV2){ 84 85 if( g.okHistory ){ 85 86 if( zV2==0 ){ 86 87 @ <a href="%s(g.zBaseURL)/diff?v2=%s(zV1)">[diff]</a> 87 88 }else{ 88 - @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a> 89 + @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a> 89 90 } 90 91 } 91 92 } 92 93 93 94 /* 94 95 ** Generate a hyperlink to a date & time. 95 96 */ ................................................................................ 107 108 ** events by that user. If the date+time is specified, then the timeline 108 109 ** is centered on that date+time. 109 110 */ 110 111 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){ 111 112 if( zSuf==0 ) zSuf = ""; 112 113 if( g.okHistory ){ 113 114 if( zD && zD[0] ){ 114 - @ <a href="%s(g.zTop)/timeline?c=%T(zD)&u=%T(zU)">%h(zU)</a>%s(zSuf) 115 + @ <a href="%s(g.zTop)/timeline?c=%T(zD)&u=%T(zU)">%h(zU)</a>%s(zSuf) 115 116 }else{ 116 117 @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf) 117 118 } 118 119 }else{ 119 120 @ %s(zU) 120 121 } 121 122 } ................................................................................ 162 163 ** 2. Date/Time 163 164 ** 3. Comment string 164 165 ** 4. User 165 166 ** 5. True if is a leaf 166 167 ** 6. background color 167 168 ** 7. type ("ci", "w", "t") 168 169 ** 8. list of symbolic tags. 169 -** 9. tagid for ticket or wiki 170 +** 9. tagid for ticket or wiki or event 170 171 ** 10. Short comment to user for repeated tickets and wiki 171 172 */ 172 173 void www_print_timeline( 173 174 Stmt *pQuery, /* Query to implement the timeline */ 174 175 int tmFlags, /* Flags controlling display behavior */ 175 176 void (*xExtra)(int) /* Routine to call on each line of display */ 176 177 ){ ................................................................................ 187 188 if( db_get_boolean("timeline-block-markup", 0) ){ 188 189 wikiFlags = WIKI_INLINE; 189 190 }else{ 190 191 wikiFlags = WIKI_INLINE | WIKI_NOBLOCK; 191 192 } 192 193 if( tmFlags & TIMELINE_GRAPH ){ 193 194 pGraph = graph_init(); 195 + /* style is not moved to css, because this is 196 + ** a technical div for the timeline graph 197 + */ 194 198 @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div> 195 199 } 196 200 197 - @ <table cellspacing=0 border=0 cellpadding=0> 201 + @ <table class="timelineTable"> 198 202 blob_zero(&comment); 199 203 while( db_step(pQuery)==SQLITE_ROW ){ 200 204 int rid = db_column_int(pQuery, 0); 201 205 const char *zUuid = db_column_text(pQuery, 1); 202 206 int isLeaf = db_column_int(pQuery, 5); 203 207 const char *zBgClr = db_column_text(pQuery, 6); 204 208 const char *zDate = db_column_text(pQuery, 2); ................................................................................ 216 220 }else{ 217 221 commentColumn = 10; 218 222 } 219 223 } 220 224 } 221 225 prevTagid = tagid; 222 226 if( suppressCnt ){ 223 - @ <tr><td><td><td> 224 - @ <small><i>... %d(suppressCnt) similar 225 - @ event%s(suppressCnt>1?"s":"") omitted.</i></small></tr> 227 + @ <tr><td /><td /><td> 228 + @ <span class="timelineDisabled">... %d(suppressCnt) similar 229 + @ event%s(suppressCnt>1?"s":"") omitted.</span></td></tr> 226 230 suppressCnt = 0; 227 231 } 228 232 if( strcmp(zType,"div")==0 ){ 229 - @ <tr><td colspan=3><hr></td></tr> 233 + @ <tr><td colspan="3"><hr /></td></tr> 230 234 continue; 231 235 } 232 236 if( memcmp(zDate, zPrevDate, 10) ){ 233 237 sprintf(zPrevDate, "%.10s", zDate); 234 238 @ <tr><td> 235 - @ <div class="divider"><nobr>%s(zPrevDate)</nobr></div> 239 + @ <div class="divider">%s(zPrevDate)</div> 236 240 @ </td></tr> 237 241 } 238 242 memcpy(zTime, &zDate[11], 5); 239 243 zTime[5] = 0; 240 244 @ <tr> 241 - @ <td valign="top" align="right">%s(zTime)</td> 242 - @ <td width="20" align="left" valign="top"> 245 + @ <td class="timelineTime">%s(zTime)</td> 246 + @ <td class="timelineGraph"> 243 247 if( pGraph && zType[0]=='c' ){ 244 248 int nParent = 0; 245 249 int aParent[32]; 246 250 const char *zBr; 247 251 int gidx; 248 252 static Stmt qparent; 249 253 static Stmt qbranch; ................................................................................ 265 269 }else{ 266 270 zBr = "trunk"; 267 271 } 268 272 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr); 269 273 db_reset(&qbranch); 270 274 @ <div id="m%d(gidx)"></div> 271 275 } 276 + @</td> 272 277 if( zBgClr && zBgClr[0] ){ 273 - @ <td valign="top" align="left" bgcolor="%h(zBgClr)"> 278 + @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> 274 279 }else{ 275 - @ <td valign="top" align="left"> 280 + @ <td class="timelineTableCell"> 276 281 } 277 282 if( zType[0]=='c' ){ 278 283 hyperlink_to_uuid(zUuid); 279 284 if( isLeaf ){ 280 285 if( db_exists("SELECT 1 FROM tagxref" 281 286 " WHERE rid=%d AND tagid=%d AND tagtype>0", 282 287 rid, TAG_CLOSED) ){ 283 - @ <b>Closed-Leaf:</b> 288 + @ <span class="timelineLeaf">Closed-Leaf:</span> 284 289 }else{ 285 - @ <b>Leaf:</b> 290 + @ <span class="timelineLeaf">Leaf:</span> 286 291 } 287 292 } 293 + }else if( zType[0]=='e' && tagid ){ 294 + hyperlink_to_event_tagid(tagid); 288 295 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ 289 296 hyperlink_to_uuid(zUuid); 290 297 } 291 298 db_column_blob(pQuery, commentColumn, &comment); 292 299 if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ 293 300 Blob truncated; 294 301 blob_zero(&truncated); ................................................................................ 307 314 } 308 315 if( xExtra ){ 309 316 xExtra(rid); 310 317 } 311 318 @ </td></tr> 312 319 } 313 320 if( suppressCnt ){ 314 - @ <tr><td><td><td> 315 - @ <small><i>... %d(suppressCnt) similar 316 - @ event%s(suppressCnt>1?"s":"") omitted.</i></small></tr> 321 + @ <tr><td /><td /><td> 322 + @ <span class="timelineDisabled">... %d(suppressCnt) similar 323 + @ event%s(suppressCnt>1?"s":"") omitted.</span></td></tr> 317 324 suppressCnt = 0; 318 325 } 319 326 if( pGraph ){ 320 327 graph_finish(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0); 321 328 if( pGraph->nErr ){ 322 329 graph_free(pGraph); 323 330 pGraph = 0; 324 331 }else{ 325 - @ <tr><td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div> 332 + /* style is not moved to css, because this is 333 + ** a technical div for the timeline graph 334 + */ 335 + @ <tr><td /><td> 336 + @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> 337 + @ </td></tr> 326 338 } 327 339 } 328 340 @ </table> 329 341 timeline_output_graph_javascript(pGraph); 330 342 } 331 343 332 344 /* ................................................................................ 334 346 ** graph. 335 347 */ 336 348 void timeline_output_graph_javascript(GraphContext *pGraph){ 337 349 if( pGraph && pGraph->nErr==0 ){ 338 350 GraphRow *pRow; 339 351 int i; 340 352 char cSep; 341 - @ <script type="text/JavaScript"> 353 + @ <script type="text/JavaScript"> 354 + @ /* <![CDATA[ */ 342 355 cgi_printf("var rowinfo = [\n"); 343 356 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ 344 357 cgi_printf("{id:\"m%d\",bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,au:", 345 358 pRow->idx, 346 359 pRow->zBgClr, 347 360 pRow->iRail, 348 361 pRow->bDescender, ................................................................................ 350 363 pRow->mergeUpto, 351 364 pRow->aiRaiser[pRow->iRail] 352 365 ); 353 366 cSep = '['; 354 367 for(i=0; i<GR_MAX_RAIL; i++){ 355 368 if( i==pRow->iRail ) continue; 356 369 if( pRow->aiRaiser[i]>0 ){ 357 - cgi_printf("%c%d,%d", cSep, pGraph->railMap[i], pRow->aiRaiser[i]); 370 + cgi_printf("%c%d,%d", cSep, i, pRow->aiRaiser[i]); 358 371 cSep = ','; 359 372 } 360 373 } 361 374 if( cSep=='[' ) cgi_printf("["); 362 375 cgi_printf("],mi:"); 363 376 cSep = '['; 364 377 for(i=0; i<GR_MAX_RAIL; i++){ 365 378 if( pRow->mergeIn & (1<<i) ){ 366 - cgi_printf("%c%d", cSep, pGraph->railMap[i]); 379 + cgi_printf("%c%d", cSep, i); 367 380 cSep = ','; 368 381 } 369 382 } 370 383 if( cSep=='[' ) cgi_printf("["); 371 384 cgi_printf("]}%s", pRow->pNext ? ",\n" : "];\n"); 372 385 } 373 386 cgi_printf("var nrail = %d\n", pGraph->mxRail+1); ................................................................................ 480 493 @ var canvasY = absoluteY("canvas"); 481 494 @ var left = absoluteX(rowinfo[0].id) - absoluteX("canvas") + 15; 482 495 @ var width = nrail*20; 483 496 @ for(var i in rowinfo){ 484 497 @ rowinfo[i].y = absoluteY(rowinfo[i].id) + 10 - canvasY; 485 498 @ rowinfo[i].x = left + rowinfo[i].r*20; 486 499 @ } 487 - @ var btm = rowinfo[rowinfo.length-1].y + 20; 500 + @ var btm = absoluteY("grbtm") + 10 - canvasY; 488 501 @ if( btm<32768 ){ 489 502 @ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+ 490 503 @ 'style="position:absolute;left:'+(left-5)+'px;"' + 491 - @ ' width="'+width+'" height="'+btm+'"></canvas>'; 504 + @ ' width="'+width+'" height="'+btm+'"><'+'/canvas>'; 492 505 @ realCanvas = document.getElementById('timeline-canvas'); 493 506 @ }else{ 494 507 @ realCanvas = 0; 495 508 @ } 496 509 @ var context; 497 510 @ if( realCanvas && realCanvas.getContext 498 511 @ && (context = realCanvas.getContext('2d'))) { ................................................................................ 516 529 @ if( h!=lastY ){ 517 530 @ renderGraph(); 518 531 @ lastY = h; 519 532 @ } 520 533 @ setTimeout("checkHeight();", 1000); 521 534 @ } 522 535 @ checkHeight(); 536 + @ /* ]]> */ 523 537 @ </script> 524 538 } 525 539 } 526 540 527 541 /* 528 542 ** Create a temporary table suitable for storing timeline data. 529 543 */ ................................................................................ 625 639 ** c=TIMESTAMP "circa" this date. 626 640 ** n=COUNT number of events in output 627 641 ** p=RID artifact RID and up to COUNT parents and ancestors 628 642 ** d=RID artifact RID and up to COUNT descendants 629 643 ** t=TAGID show only check-ins with the given tagid 630 644 ** r=TAGID show check-ins related to tagid 631 645 ** u=USER only if belonging to this user 632 -** y=TYPE 'ci', 'w', 't' 646 +** y=TYPE 'ci', 'w', 't', 'e' 633 647 ** s=TEXT string search (comment and brief) 634 648 ** ng Suppress the graph if present 635 649 ** 636 650 ** p= and d= can appear individually or together. If either p= or d= 637 651 ** appear, then u=, y=, a=, and b= are ignored. 638 652 ** 639 653 ** If a= and b= appear, only a= is used. If neither appear, the most ................................................................................ 735 749 blob_appendf(&desc, " of <a href='%s/info/%s'>[%.10s]</a>", 736 750 g.zBaseURL, zUuid, zUuid); 737 751 }else{ 738 752 blob_appendf(&desc, " of check-in [%.10s]", zUuid); 739 753 } 740 754 }else{ 741 755 int n; 742 - const char *zEType = "event"; 756 + const char *zEType = "timeline item"; 743 757 char *zDate; 744 758 char *zNEntry = mprintf("%d", nEntry); 745 759 url_initialize(&url, "timeline"); 746 760 url_add_parameter(&url, "n", zNEntry); 747 761 if( tagid>0 ){ 748 - zType = "ci"; 762 + if( zType[0]!='e' ) zType = "ci"; 749 763 blob_appendf(&sql, 750 764 "AND (EXISTS(SELECT 1 FROM tagxref" 751 765 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid); 752 766 753 - if( zBrName ){ 767 + if( zBrName && zType[0]=='c' ){ 754 768 /* The next two blob_appendf() calls add SQL that causes checkins that 755 769 ** are not part of the branch which are parents or childen of the branch 756 770 ** to be included in the report. This related check-ins are useful 757 771 ** in helping to visualize what has happened on a quiescent branch 758 772 ** that is infrequently merged with a much more activate branch. 759 773 */ 760 774 url_add_parameter(&url, "r", zBrName); ................................................................................ 767 781 }else{ 768 782 url_add_parameter(&url, "t", zTagName); 769 783 } 770 784 blob_appendf(&sql, ")"); 771 785 } 772 786 if( (zType[0]=='w' && !g.okRdWiki) 773 787 || (zType[0]=='t' && !g.okRdTkt) 788 + || (zType[0]=='e' && !g.okRdWiki) 774 789 || (zType[0]=='c' && !g.okRead) 775 790 ){ 776 791 zType = "all"; 777 792 } 778 793 if( zType[0]=='a' ){ 779 794 if( !g.okRead || !g.okRdWiki || !g.okRdTkt ){ 780 795 char cSep = '('; 781 796 blob_appendf(&sql, " AND event.type IN "); 782 797 if( g.okRead ){ 783 798 blob_appendf(&sql, "%c'ci'", cSep); 784 799 cSep = ','; 785 800 } 786 801 if( g.okRdWiki ){ 787 - blob_appendf(&sql, "%c'w'", cSep); 802 + blob_appendf(&sql, "%c'w','e'", cSep); 788 803 cSep = ','; 789 804 } 790 805 if( g.okRdTkt ){ 791 806 blob_appendf(&sql, "%c't'", cSep); 792 807 cSep = ','; 793 808 } 794 809 blob_appendf(&sql, ")"); ................................................................................ 798 813 url_add_parameter(&url, "y", zType); 799 814 if( zType[0]=='c' ){ 800 815 zEType = "checkin"; 801 816 }else if( zType[0]=='w' ){ 802 817 zEType = "wiki edit"; 803 818 }else if( zType[0]=='t' ){ 804 819 zEType = "ticket change"; 820 + }else if( zType[0]=='e' ){ 821 + zEType = "event"; 805 822 } 806 823 } 807 824 if( zUser ){ 808 825 blob_appendf(&sql, " AND event.user=%Q", zUser); 809 826 url_add_parameter(&url, "u", zUser); 810 827 } 811 828 if ( zSearch ){ 812 829 blob_appendf(&sql, 813 830 " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')", 814 831 zSearch, zSearch); 815 832 url_add_parameter(&url, "s", zSearch); 816 833 } 817 834 if( zAfter ){ 818 - while( isspace(zAfter[0]) ){ zAfter++; } 835 + while( fossil_isspace(zAfter[0]) ){ zAfter++; } 819 836 if( zAfter[0] ){ 820 837 blob_appendf(&sql, 821 838 " AND event.mtime>=(SELECT julianday(%Q, 'utc'))" 822 839 " ORDER BY event.mtime ASC", zAfter); 823 840 url_add_parameter(&url, "a", zAfter); 824 841 zBefore = 0; 825 842 }else{ 826 843 zAfter = 0; 827 844 } 828 845 }else if( zBefore ){ 829 - while( isspace(zBefore[0]) ){ zBefore++; } 846 + while( fossil_isspace(zBefore[0]) ){ zBefore++; } 830 847 if( zBefore[0] ){ 831 848 blob_appendf(&sql, 832 849 " AND event.mtime<=(SELECT julianday(%Q, 'utc'))" 833 850 " ORDER BY event.mtime DESC", zBefore); 834 851 url_add_parameter(&url, "b", zBefore); 835 852 }else{ 836 853 zBefore = 0; 837 854 } 838 855 }else if( zCirca ){ 839 - while( isspace(zCirca[0]) ){ zCirca++; } 856 + while( fossil_isspace(zCirca[0]) ){ zCirca++; } 840 857 if( zCirca[0] ){ 841 858 double rCirca = db_double(0.0, "SELECT julianday(%Q, 'utc')", zCirca); 842 859 Blob sql2; 843 860 blob_init(&sql2, blob_str(&sql), -1); 844 861 blob_appendf(&sql2, 845 862 " AND event.mtime<=%f ORDER BY event.mtime DESC LIMIT %d", 846 863 rCirca, (nEntry+1)/2 ................................................................................ 880 897 blob_appendf(&desc, " tagged with \"%h\"", zTagName); 881 898 tmFlags |= TIMELINE_DISJOINT; 882 899 }else if( zBrName ){ 883 900 blob_appendf(&desc, " related to \"%h\"", zBrName); 884 901 tmFlags |= TIMELINE_DISJOINT; 885 902 } 886 903 if( zAfter ){ 887 - blob_appendf(&desc, " occurring on or after %h.<br>", zAfter); 904 + blob_appendf(&desc, " occurring on or after %h.<br />", zAfter); 888 905 }else if( zBefore ){ 889 - blob_appendf(&desc, " occurring on or before %h.<br>", zBefore); 906 + blob_appendf(&desc, " occurring on or before %h.<br />", zBefore); 890 907 }else if( zCirca ){ 891 - blob_appendf(&desc, " occurring around %h.<br>", zCirca); 908 + blob_appendf(&desc, " occurring around %h.<br />", zCirca); 892 909 } 893 910 if( zSearch ){ 894 911 blob_appendf(&desc, " matching \"%h\"", zSearch); 895 912 } 896 913 if( g.okHistory ){ 897 914 if( zAfter || n==nEntry ){ 898 915 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); ................................................................................ 912 929 } 913 930 if( zType[0]!='c' && g.okRead ){ 914 931 timeline_submenu(&url, "Checkins Only", "y", "ci", 0); 915 932 } 916 933 if( zType[0]!='t' && g.okRdTkt ){ 917 934 timeline_submenu(&url, "Tickets Only", "y", "t", 0); 918 935 } 936 + if( zType[0]!='e' && g.okRdWiki ){ 937 + timeline_submenu(&url, "Events Only", "y", "e", 0); 938 + } 919 939 } 920 940 if( nEntry>20 ){ 921 - timeline_submenu(&url, "20 Events", "n", "20", 0); 941 + timeline_submenu(&url, "20 Entries", "n", "20", 0); 922 942 } 923 943 if( nEntry<200 ){ 924 - timeline_submenu(&url, "200 Events", "n", "200", 0); 944 + timeline_submenu(&url, "200 Entries", "n", "200", 0); 925 945 } 926 946 } 927 947 } 948 + if( P("showsql") ){ 949 + @ <blockquote>%h(blob_str(&sql))</blockquote> 950 + } 928 951 blob_zero(&sql); 929 952 db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC /*scan*/"); 930 953 @ <h2>%b(&desc)</h2> 931 954 blob_reset(&desc); 932 955 www_print_timeline(&q, tmFlags, 0); 933 956 db_finalize(&q); 934 957 style_footer(); ................................................................................ 1035 1058 ** Return true if the input string is a date in the ISO 8601 format: 1036 1059 ** YYYY-MM-DD. 1037 1060 */ 1038 1061 static int isIsoDate(const char *z){ 1039 1062 return strlen(z)==10 1040 1063 && z[4]=='-' 1041 1064 && z[7]=='-' 1042 - && isdigit(z[0]) 1043 - && isdigit(z[5]); 1065 + && fossil_isdigit(z[0]) 1066 + && fossil_isdigit(z[5]); 1044 1067 } 1045 1068 1046 1069 /* 1047 1070 ** COMMAND: timeline 1048 1071 ** 1049 1072 ** Usage: %fossil timeline ?WHEN? ?BASELINE|DATETIME? ?-n N? ?-t TYPE? 1050 1073 **
Changes to src/tkt.c.
51 51 int i; 52 52 if( nField>0 ) return; 53 53 db_prepare(&q, "PRAGMA table_info(ticket)"); 54 54 while( db_step(&q)==SQLITE_ROW ){ 55 55 const char *zField = db_column_text(&q, 1); 56 56 if( strncmp(zField,"tkt_",4)==0 ) continue; 57 57 if( nField%10==0 ){ 58 - azField = realloc(azField, sizeof(azField)*3*(nField+10) ); 59 - if( azField==0 ){ 60 - fossil_fatal("out of memory"); 61 - } 58 + azField = fossil_realloc(azField, sizeof(azField)*3*(nField+10) ); 62 59 } 63 60 azField[nField] = mprintf("%s", zField); 64 61 nField++; 65 62 } 66 63 db_finalize(&q); 67 64 qsort(azField, nField, sizeof(azField[0]), nameCmpr); 68 65 azAppend = &azField[nField]; ................................................................................ 215 212 /* 216 213 ** Rebuild an entire entry in the TICKET table 217 214 */ 218 215 void ticket_rebuild_entry(const char *zTktUuid){ 219 216 char *zTag = mprintf("tkt-%s", zTktUuid); 220 217 int tagid = tag_findid(zTag, 1); 221 218 Stmt q; 222 - Manifest manifest; 223 - Blob content; 219 + Manifest *pTicket; 224 220 int createFlag = 1; 225 221 226 222 db_multi_exec( 227 223 "DELETE FROM ticket WHERE tkt_uuid=%Q", zTktUuid 228 224 ); 229 225 db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid); 230 226 while( db_step(&q)==SQLITE_ROW ){ 231 227 int rid = db_column_int(&q, 0); 232 - content_get(rid, &content); 233 - manifest_parse(&manifest, &content); 234 - ticket_insert(&manifest, createFlag, rid); 235 - manifest_ticket_event(rid, &manifest, createFlag, tagid); 236 - manifest_clear(&manifest); 228 + pTicket = manifest_get(rid, CFTYPE_TICKET); 229 + if( pTicket ){ 230 + ticket_insert(pTicket, createFlag, rid); 231 + manifest_ticket_event(rid, pTicket, createFlag, tagid); 232 + manifest_destroy(pTicket); 233 + } 237 234 createFlag = 0; 238 235 } 239 236 db_finalize(&q); 240 237 } 241 238 242 239 /* 243 240 ** Create the subscript interpreter and load the "common" code. ................................................................................ 311 308 } 312 309 if( g.okNewTkt ){ 313 310 style_submenu_element("New Ticket", "Create a new ticket", 314 311 "%s/tktnew", g.zTop); 315 312 } 316 313 if( g.okApndTkt && g.okAttach ){ 317 314 style_submenu_element("Attach", "Add An Attachment", 318 - "%s/attachadd?tkt=%T&from=%s/tktview/%t", 315 + "%s/attachadd?tkt=%T&from=%s/tktview/%t", 319 316 g.zTop, zUuid, g.zTop, zUuid); 320 317 } 321 318 style_header("View Ticket"); 322 319 if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); 323 320 ticket_init(); 324 321 initializeVariablesFromDb(); 325 322 zScript = ticket_viewpage_code(); ................................................................................ 340 337 " ORDER BY mtime DESC", 341 338 zFullName); 342 339 while( db_step(&q)==SQLITE_ROW ){ 343 340 const char *zDate = db_column_text(&q, 0); 344 341 const char *zFile = db_column_text(&q, 1); 345 342 const char *zUser = db_column_text(&q, 2); 346 343 if( cnt==0 ){ 347 - @ <hr><h2>Attachments:</h2> 344 + @ <hr /><h2>Attachments:</h2> 348 345 @ <ul> 349 346 } 350 347 cnt++; 351 - @ <li><a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> 352 - @ %h(zFile)</a> add by %h(zUser) on 348 + @ <li> 349 + if( g.okRead && g.okHistory ){ 350 + @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> 351 + @ %h(zFile)</a> 352 + }else{ 353 + @ %h(zFile) 354 + } 355 + @ added by %h(zUser) on 353 356 hyperlink_to_date(zDate, "."); 354 357 if( g.okWrTkt && g.okAttach ){ 355 - @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] 358 + @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] 356 359 } 360 + @ </li> 357 361 } 358 362 if( cnt ){ 359 363 @ </ul> 360 364 } 361 365 db_finalize(&q); 362 366 } 363 367 ................................................................................ 436 440 int nValue; 437 441 if( azAppend[i] ){ 438 442 blob_appendf(&tktchng, "J +%s %z\n", azField[i], 439 443 fossilize(azAppend[i], -1)); 440 444 }else{ 441 445 zValue = Th_Fetch(azField[i], &nValue); 442 446 if( zValue ){ 443 - while( nValue>0 && isspace(zValue[nValue-1]) ){ nValue--; } 447 + while( nValue>0 && fossil_isspace(zValue[nValue-1]) ){ nValue--; } 444 448 if( strncmp(zValue, azValue[i], nValue) || strlen(azValue[i])!=nValue ){ 445 449 if( strncmp(azField[i], "private_", 8)==0 ){ 446 450 zValue = db_conceal(zValue, nValue); 447 451 blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue); 448 452 }else{ 449 453 blob_appendf(&tktchng, "J %s %#F\n", azField[i], nValue, zValue); 450 454 } ................................................................................ 460 464 zUuid = db_text(0, "SELECT lower(hex(randomblob(20)))"); 461 465 } 462 466 *(const char**)pUuid = zUuid; 463 467 blob_appendf(&tktchng, "K %s\n", zUuid); 464 468 blob_appendf(&tktchng, "U %F\n", g.zLogin ? g.zLogin : ""); 465 469 md5sum_blob(&tktchng, &cksum); 466 470 blob_appendf(&tktchng, "Z %b\n", &cksum); 467 - if( g.thTrace ){ 471 + if( g.zPath[0]=='d' ){ 472 + /* If called from /debug_tktnew or /debug_tktedit... */ 473 + @ <font color="blue"> 474 + @ <p>Ticket artifact that would have been submitted:</p> 475 + @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote> 476 + @ <hr /></font> 477 + return TH_OK; 478 + }else if( g.thTrace ){ 468 479 Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n" 469 480 "}<br />\n", 470 481 blob_str(&tktchng)); 471 482 }else{ 472 483 rid = content_put(&tktchng, 0, 0); 473 484 if( rid==0 ){ 474 485 fossil_panic("trouble committing ticket: %s", g.zErrMsg); ................................................................................ 504 515 } 505 516 style_header("New Ticket"); 506 517 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW<br />\n", -1); 507 518 ticket_init(); 508 519 getAllTicketFields(); 509 520 initializeVariablesFromDb(); 510 521 initializeVariablesFromCGI(); 511 - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> 522 + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><p> 512 523 login_insert_csrf_secret(); 524 + @ </p> 513 525 zScript = ticket_newpage_code(); 514 526 Th_Store("login", g.zLogin); 515 527 Th_Store("date", db_text(0, "SELECT datetime('now')")); 516 528 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, 517 529 (void*)&zNewUuid, 0); 518 530 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1); 519 531 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){ ................................................................................ 547 559 zName = P("name"); 548 560 if( P("cancel") ){ 549 561 cgi_redirectf("tktview?name=%T", zName); 550 562 } 551 563 style_header("Edit Ticket"); 552 564 if( zName==0 || (nName = strlen(zName))<4 || nName>UUID_SIZE 553 565 || !validate16(zName,nName) ){ 554 - @ <font color="red"><b>Not a valid ticket id: \"%h(zName)\"</b></font> 566 + @ <span class="tktError">Not a valid ticket id: \"%h(zName)\"</span> 555 567 style_footer(); 556 568 return; 557 569 } 558 570 nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'", 559 571 zName); 560 572 if( nRec==0 ){ 561 - @ <font color="red"><b>No such ticket: \"%h(zName)\"</b></font> 573 + @ <span class="tktError">No such ticket: \"%h(zName)\"</span> 562 574 style_footer(); 563 575 return; 564 576 } 565 577 if( nRec>1 ){ 566 - @ <font color="red"><b>%d(nRec) tickets begin with: \"%h(zName)\"</b></font> 578 + @ <span class="tktError">%d(nRec) tickets begin with: 579 + @ \"%h(zName)\"</span> 567 580 style_footer(); 568 581 return; 569 582 } 570 583 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); 571 584 ticket_init(); 572 585 getAllTicketFields(); 573 586 initializeVariablesFromCGI(); 574 587 initializeVariablesFromDb(); 575 - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> 576 - @ <input type="hidden" name="name" value="%s(zName)"> 588 + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><p> 589 + @ <input type="hidden" name="name" value="%s(zName)" /> 577 590 login_insert_csrf_secret(); 591 + @ </p> 578 592 zScript = ticket_editpage_code(); 579 593 Th_Store("login", g.zLogin); 580 594 Th_Store("date", db_text(0, "SELECT datetime('now')")); 581 595 Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); 582 596 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); 583 597 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1); 584 598 if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){ ................................................................................ 617 631 } 618 632 } 619 633 return 0; 620 634 } 621 635 622 636 /* 623 637 ** WEBPAGE: tkttimeline 624 -** URL: /tkttimeline?name=TICKETUUID&y=TYPE 638 +** URL: /tkttimeline?name=TICKETUUID&y=TYPE 625 639 ** 626 640 ** Show the change history for a single ticket in timeline format. 627 641 */ 628 642 void tkttimeline_page(void){ 629 643 Stmt q; 630 644 char *zTitle; 631 645 char *zSQL; ................................................................................ 637 651 638 652 login_check_credentials(); 639 653 if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; } 640 654 zUuid = PD("name",""); 641 655 zType = PD("y","a"); 642 656 if( zType[0]!='c' ){ 643 657 style_submenu_element("Check-ins", "Check-ins", 644 - "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); 658 + "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); 645 659 }else{ 646 660 style_submenu_element("Timeline", "Timeline", 647 661 "%s/tkttimeline?name=%T", g.zTop, zUuid); 648 662 } 649 663 style_submenu_element("History", "History", 650 664 "%s/tkthistory/%s", g.zTop, zUuid); 651 665 style_submenu_element("Status", "Status", ................................................................................ 737 751 " FROM attachment, blob" 738 752 " WHERE target=(SELECT substr(tagname,5) FROM tag WHERE tagid=%d)" 739 753 " AND blob.rid=attachid" 740 754 " ORDER BY 1 DESC", 741 755 tagid, tagid 742 756 ); 743 757 while( db_step(&q)==SQLITE_ROW ){ 744 - Blob content; 745 - Manifest m; 758 + Manifest *pTicket; 746 759 char zShort[12]; 747 760 const char *zDate = db_column_text(&q, 0); 748 761 int rid = db_column_int(&q, 1); 749 762 const char *zChngUuid = db_column_text(&q, 2); 750 763 const char *zFile = db_column_text(&q, 4); 751 764 memcpy(zShort, zChngUuid, 10); 752 765 zShort[10] = 0; ................................................................................ 761 774 @ <p>Add attachment "%h(zFile)" 762 775 } 763 776 @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>] 764 777 @ (rid %d(rid)) by 765 778 hyperlink_to_user(zUser,zDate," on"); 766 779 hyperlink_to_date(zDate, ".</p>"); 767 780 }else{ 768 - content_get(rid, &content); 769 - if( manifest_parse(&m, &content) && m.type==CFTYPE_TICKET ){ 781 + pTicket = manifest_get(rid, CFTYPE_TICKET); 782 + if( pTicket ){ 770 783 @ 771 784 @ <p>Ticket change 772 785 @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>] 773 786 @ (rid %d(rid)) by 774 - hyperlink_to_user(m.zUser,zDate," on"); 787 + hyperlink_to_user(pTicket->zUser,zDate," on"); 775 788 hyperlink_to_date(zDate, ":"); 776 - ticket_output_change_artifact(&m); 777 789 @ </p> 790 + ticket_output_change_artifact(pTicket); 778 791 } 779 - manifest_clear(&m); 792 + manifest_destroy(pTicket); 780 793 } 781 794 } 782 795 db_finalize(&q); 783 796 style_footer(); 784 797 } 785 798 786 799 /* ................................................................................ 818 831 }else{ 819 832 @ <li>Change %h(z) to "%h(blob_str(&val))"</li> 820 833 } 821 834 blob_reset(&val); 822 835 } 823 836 @ </ol> 824 837 } 838 + 839 +/* 840 +** COMMAND: ticket 841 +** Usage: %fossil ticket SUBCOMMAND ... 842 +** 843 +** Run various subcommands to control tickets 844 +** 845 +** %fossil ticket show (REPORTTITLE|REPORTNR) ?TICKETFILTER? ?options? 846 +** 847 +** options can be: 848 +** ?-l|--limit LIMITCHAR? 849 +** ?-q|--quote? 850 +** ?-R|--repository FILE? 851 +** 852 +** Run the ticket report, identified by the report format title 853 +** used in the gui. The data is written as flat file on stdout, 854 +** using "," as separator. The seperator "," can be changed using 855 +** the -l or --limit option. 856 +** If TICKETFILTER is given on the commandline, the query is 857 +** limited with a new WHERE-condition. 858 +** example: Report lists a column # with the uuid 859 +** TICKETFILTER may be [#]='uuuuuuuuu' 860 +** example: Report only lists rows with status not open 861 +** TICKETFILTER: status != 'open' 862 +** If the option -q|--quote is used, the tickets are encoded by 863 +** quoting special chars(space -> \\s, tab -> \\t, newline -> \\n, 864 +** cr -> \\r, formfeed -> \\f, vtab -> \\v, nul -> \\0, \\ -> \\\\). 865 +** Otherwise, the simplified encoding as on the show report raw 866 +** page in the gui is used. 867 +** 868 +** Instead of the report title its possible to use the report 869 +** number. Using the special report number 0 list all columns, 870 +** defined in the ticket table. 871 +** 872 +** %fossil ticket list fields 873 +** 874 +** list all fields, defined for ticket in the fossil repository 875 +** 876 +** %fossil ticket list reports 877 +** 878 +** list all ticket reports, defined in the fossil repository 879 +** 880 +** %fossil ticket set TICKETUUID FIELD VALUE ?FIELD VALUE .. ? ?-q|--quote? 881 +** %fossil ticket change TICKETUUID FIELD VALUE ?FIELD VALUE .. ? ?-q|--quote? 882 +** 883 +** change ticket identified by TICKETUUID and set the value of 884 +** field FIELD to VALUE. Valid field descriptions are: 885 +** status, type, severity, priority, resolution, 886 +** foundin, private_contact, resolution, title or comment 887 +** Field names given above are the ones, defined in a standard 888 +** fossil environment. If you have added, deleted columns, you 889 +** change the all your configured columns. 890 +** You can use more than one field/value pair on the commandline. 891 +** Using -q|--quote enables the special character decoding as 892 +** in "ticket show". So it's possible, to set multiline text or 893 +** text with special characters. 894 +** 895 +** %fossil ticket add FIELD VALUE ?FIELD VALUE .. ? ?-q|--quote? 896 +** 897 +** like set, but create a new ticket with the given values. 898 +** 899 +** The values in set|add are not validated against the definitions 900 +** given in "Ticket Common Script". 901 +*/ 902 +void ticket_cmd(void){ 903 + int n; 904 + 905 + /* do some ints, we want to be inside a checkout */ 906 + db_find_and_open_repository(1); 907 + user_select(); 908 + /* 909 + ** Check that the user exists. 910 + */ 911 + if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ 912 + fossil_fatal("no such user: %s", g.zLogin); 913 + } 914 + 915 + if( g.argc<3 ){ 916 + usage("add|fieldlist|set|show"); 917 + }else{ 918 + n = strlen(g.argv[2]); 919 + if( n==1 && g.argv[2][0]=='s' ){ 920 + /* set/show cannot be distinguished, so show the usage */ 921 + usage("add|fieldlist|set|show"); 922 + }else if( strncmp(g.argv[2],"list",n)==0 ){ 923 + if( g.argc==3 ){ 924 + usage("list fields|reports"); 925 + }else{ 926 + n = strlen(g.argv[3]); 927 + if( !strncmp(g.argv[3],"fields",n) ){ 928 + /* simply show all field names */ 929 + int i; 930 + 931 + /* read all available ticket fields */ 932 + getAllTicketFields(); 933 + for(i=0; i<nField; i++){ 934 + printf("%s\n",azField[i]); 935 + } 936 + }else if( !strncmp(g.argv[3],"reports",n) ){ 937 + rpt_list_reports(); 938 + }else{ 939 + fossil_fatal("unknown ticket list option '%s'!",g.argv[3]); 940 + } 941 + } 942 + }else{ 943 + /* add a new ticket or set fields on existing tickets */ 944 + tTktShowEncoding tktEncoding; 945 + 946 + tktEncoding = find_option("quote","q",0) ? tktFossilize : tktNoTab; 947 + 948 + if( strncmp(g.argv[2],"show",n)==0 ){ 949 + if( g.argc==3 ){ 950 + usage("show REPORTNR"); 951 + }else{ 952 + const char *zRep = 0; 953 + const char *zSep = 0; 954 + const char *zFilterUuid = 0; 955 + 956 + zSep = find_option("limit","l",1); 957 + zRep = g.argv[3]; 958 + if( !strcmp(zRep,"0") ){ 959 + zRep = 0; 960 + } 961 + if( g.argc>4 ){ 962 + zFilterUuid = g.argv[4]; 963 + } 964 + 965 + rptshow( zRep, zSep, zFilterUuid, tktEncoding ); 966 + 967 + } 968 + }else{ 969 + /* add a new ticket or update an existing ticket */ 970 + enum { set,add,err } eCmd = err; 971 + int i = 0; 972 + int rid; 973 + const char *zTktUuid = 0; 974 + Blob tktchng, cksum; 975 + 976 + /* get command type (set/add) and get uuid, if needed for set */ 977 + if( strncmp(g.argv[2],"set",n)==0 || strncmp(g.argv[2],"change",n)==0 ){ 978 + eCmd = set; 979 + if( g.argc==3 ){ 980 + usage("set TICKETUUID"); 981 + } 982 + zTktUuid = db_text(0, 983 + "SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%s*'", g.argv[3] 984 + ); 985 + if( !zTktUuid ){ 986 + fossil_fatal("unknown ticket: '%s'!",g.argv[3]); 987 + } 988 + i=4; 989 + }else if( strncmp(g.argv[2],"add",n)==0 ){ 990 + eCmd = add; 991 + i = 3; 992 + zTktUuid = db_text(0, "SELECT lower(hex(randomblob(20)))"); 993 + } 994 + /* none of set/add, so show the usage! */ 995 + if( eCmd==err ){ 996 + usage("add|fieldlist|set|show"); 997 + } 998 + 999 + /* read all given ticket field/value pairs from command line */ 1000 + if( i==g.argc ){ 1001 + fossil_fatal("empty %s command aborted!",g.argv[2]); 1002 + } 1003 + getAllTicketFields(); 1004 + /* read commandline and assign fields in the azValue array */ 1005 + while( i<g.argc ){ 1006 + char *zFName; 1007 + char *zFValue; 1008 + int j; 1009 + 1010 + zFName = g.argv[i++]; 1011 + if( i==g.argc ){ 1012 + fossil_fatal("missing value for '%s'!",zFName); 1013 + } 1014 + zFValue = g.argv[i++]; 1015 + j = fieldId(zFName); 1016 + if( tktEncoding == tktFossilize ){ 1017 + zFValue=mprintf("%s",zFValue); 1018 + defossilize(zFValue); 1019 + } 1020 + if( j == -1 ){ 1021 + fossil_fatal("unknown field name '%s'!",zFName); 1022 + }else{ 1023 + azValue[j] = zFValue; 1024 + } 1025 + } 1026 + 1027 + /* now add the needed artifacts to the repository */ 1028 + blob_zero(&tktchng); 1029 + { /* add the time to the ticket manifest */ 1030 + char *zDate; 1031 + 1032 + zDate = db_text(0, "SELECT datetime('now')"); 1033 + zDate[10] = 'T'; 1034 + blob_appendf(&tktchng, "D %s\n", zDate); 1035 + free(zDate); 1036 + } 1037 + /* append defined elements */ 1038 + for(i=0; i<nField; i++){ 1039 + char *zValue; 1040 + 1041 + zValue = azValue[i]; 1042 + if( azValue[i] && azValue[i][0] ){ 1043 + if( strncmp(azField[i], "private_", 8)==0 ){ 1044 + zValue = db_conceal(zValue, strlen(zValue)); 1045 + blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue); 1046 + }else{ 1047 + blob_appendf(&tktchng, "J %s %#F\n", 1048 + azField[i], strlen(zValue), zValue); 1049 + } 1050 + if( tktEncoding == tktFossilize ){ 1051 + free(azValue[i]); 1052 + } 1053 + } 1054 + } 1055 + blob_appendf(&tktchng, "K %s\n", zTktUuid); 1056 + blob_appendf(&tktchng, "U %F\n", g.zLogin); 1057 + md5sum_blob(&tktchng, &cksum); 1058 + blob_appendf(&tktchng, "Z %b\n", &cksum); 1059 + rid = content_put(&tktchng, 0, 0); 1060 + if( rid==0 ){ 1061 + fossil_panic("trouble committing ticket: %s", g.zErrMsg); 1062 + } 1063 + manifest_crosslink_begin(); 1064 + manifest_crosslink(rid, &tktchng); 1065 + manifest_crosslink_end(); 1066 + printf("ticket %s succeeded for UID %s\n", 1067 + (eCmd==set?"set":"add"),zTktUuid); 1068 + } 1069 + } 1070 + } 1071 +}
Changes to src/tktsetup.c.
121 121 db_unset(zDbField, 0); 122 122 if( xRebuild ) xRebuild(); 123 123 z = zDfltValue; 124 124 }else if( isSubmit ){ 125 125 char *zErr = 0; 126 126 login_verify_csrf_secret(); 127 127 if( xText && (zErr = xText(z))!=0 ){ 128 - @ <p><font color="red"><b>ERROR: %h(zErr)</b></font></p> 128 + @ <p class="tktsetupError">ERROR: %h(zErr)</p> 129 129 }else{ 130 130 db_set(zDbField, z, 0); 131 131 if( xRebuild ) xRebuild(); 132 132 cgi_redirect("tktsetup"); 133 133 } 134 134 } 135 - @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="POST"> 135 + @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="post"><div> 136 136 login_insert_csrf_secret(); 137 137 @ <p>%s(zDesc)</p> 138 138 @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea> 139 - @ <blockquote> 140 - @ <input type="submit" name="submit" value="Apply Changes"> 141 - @ <input type="submit" name="clear" value="Revert To Default"> 142 - @ <input type="submit" name="setup" value="Cancel"> 143 - @ </blockquote> 144 - @ </form> 145 - @ <hr> 139 + @ <blockquote><p> 140 + @ <input type="submit" name="submit" value="Apply Changes" /> 141 + @ <input type="submit" name="clear" value="Revert To Default" /> 142 + @ <input type="submit" name="setup" value="Cancel" /> 143 + @ </p></blockquote> 144 + @ </div></form> 145 + @ <hr /> 146 146 @ <h2>Default %s(zTitle)</h2> 147 147 @ <blockquote><pre> 148 148 @ %h(zDfltValue) 149 149 @ </pre></blockquote> 150 150 style_footer(); 151 151 } 152 152 153 153 /* 154 154 ** WEBPAGE: tktsetup_tab 155 155 */ 156 156 void tktsetup_tab_page(void){ 157 157 static const char zDesc[] = 158 - @ <p>Enter a valid CREATE TABLE statement for the "ticket" table. The 158 + @ Enter a valid CREATE TABLE statement for the "ticket" table. The 159 159 @ table must contain columns named "tkt_id", "tkt_uuid", and "tkt_mtime" 160 - @ with an unique index on "tkt_uuid" and "tkt_mtime".</p> 160 + @ with an unique index on "tkt_uuid" and "tkt_mtime". 161 161 ; 162 162 tktsetup_generic( 163 163 "Ticket Table Schema", 164 164 "ticket-table", 165 165 zDefaultTicketTable, 166 166 zDesc, 167 167 ticket_schema_check, ................................................................................ 227 227 } 228 228 229 229 /* 230 230 ** WEBPAGE: tktsetup_com 231 231 */ 232 232 void tktsetup_com_page(void){ 233 233 static const char zDesc[] = 234 - @ <p>Enter TH1 script that initializes variables prior to generating 235 - @ any of the ticket view, edit, or creation pages.</p> 234 + @ Enter TH1 script that initializes variables prior to generating 235 + @ any of the ticket view, edit, or creation pages. 236 236 ; 237 237 tktsetup_generic( 238 238 "Ticket Common Script", 239 239 "ticket-common", 240 240 zDefaultTicketCommon, 241 241 zDesc, 242 242 0, ................................................................................ 248 248 static const char zDefaultNew[] = 249 249 @ <th1> 250 250 @ if {[info exists submit]} { 251 251 @ set status Open 252 252 @ submit_ticket 253 253 @ } 254 254 @ </th1> 255 -@ <h1 align="center">Enter A New Ticket</h1> 255 +@ <h1 style="text-align: center;">Enter A New Ticket</h1> 256 256 @ <table cellpadding="5"> 257 257 @ <tr> 258 258 @ <td colspan="2"> 259 -@ Enter a one-line summary of the ticket:<br> 260 -@ <input type="text" name="title" size="60" value="$<title>"> 259 +@ Enter a one-line summary of the ticket:<br /> 260 +@ <input type="text" name="title" size="60" value="$<title>" /> 261 261 @ </td> 262 262 @ </tr> 263 263 @ 264 264 @ <tr> 265 -@ <td align="right">Type: 265 +@ <td style="text-align: center;">Type: 266 266 @ <th1>combobox type $type_choices 1</th1> 267 267 @ </td> 268 268 @ <td>What type of ticket is this?</td> 269 269 @ </tr> 270 270 @ 271 271 @ <tr> 272 -@ <td align="right">Version: 273 -@ <input type="text" name="foundin" size="20" value="$<foundin>"> 272 +@ <td style="text-align: center;">Version: 273 +@ <input type="text" name="foundin" size="20" value="$<foundin>" /> 274 274 @ </td> 275 275 @ <td>In what version or build number do you observe the problem?</td> 276 276 @ </tr> 277 277 @ 278 278 @ <tr> 279 -@ <td align="right">Severity: 279 +@ <td style="text-align: center;">Severity: 280 280 @ <th1>combobox severity $severity_choices 1</th1> 281 281 @ </td> 282 282 @ <td>How debilitating is the problem? How badly does the problem 283 283 @ affect the operation of the product?</td> 284 284 @ </tr> 285 285 @ 286 286 @ <tr> 287 -@ <td align="right">EMail: 288 -@ <input type="text" name="private_contact" value="$<private_contact>" size="30"> 287 +@ <td style="text-align: center;">EMail: 288 +@ <input type="text" name="private_contact" value="$<private_contact>" size="30" /> 289 289 @ </td> 290 -@ <td><u>Not publicly visible</u>. Used by developers to contact you with 291 -@ questions.</td> 290 +@ <td><span style="text-decoration: underline;">Not publicly visible</span>. 291 +@ Used by developers to contact you with questions.</td> 292 292 @ </tr> 293 293 @ 294 294 @ <tr> 295 295 @ <td colspan="2"> 296 296 @ Enter a detailed description of the problem. 297 297 @ For code defects, be sure to provide details on exactly how 298 298 @ the problem can be reproduced. Provide as much detail as 299 299 @ possible. 300 -@ <br> 300 +@ <br /> 301 301 @ <th1>set nline [linecount $comment 50 10]</th1> 302 302 @ <textarea name="comment" cols="80" rows="$nline" 303 -@ wrap="virtual" class="wikiedit">$<comment></textarea><br> 304 -@ <input type="submit" name="preview" value="Preview"> 303 +@ wrap="virtual" class="wikiedit">$<comment></textarea><br /> 304 +@ <input type="submit" name="preview" value="Preview" /></td> 305 305 @ </tr> 306 306 @ 307 307 @ <th1>enable_output [info exists preview]</th1> 308 308 @ <tr><td colspan="2"> 309 -@ Description Preview:<br><hr> 309 +@ Description Preview:<br /><hr /> 310 310 @ <th1>wiki $comment</th1> 311 -@ <hr> 311 +@ <hr /> 312 312 @ </td></tr> 313 313 @ <th1>enable_output 1</th1> 314 314 @ 315 315 @ <tr> 316 -@ <td align="right"> 317 -@ <input type="submit" name="submit" value="Submit"> 316 +@ <td style="text-align: center;"> 317 +@ <input type="submit" name="submit" value="Submit" /> 318 318 @ </td> 319 319 @ <td>After filling in the information above, press this button to create 320 320 @ the new ticket</td> 321 321 @ </tr> 322 322 @ <tr> 323 -@ <td align="right"> 324 -@ <input type="submit" name="cancel" value="Cancel"> 323 +@ <td style="text-align: center;"> 324 +@ <input type="submit" name="cancel" value="Cancel" /> 325 325 @ </td> 326 326 @ <td>Abandon and forget this ticket</td> 327 327 @ </tr> 328 328 @ </table> 329 329 ; 330 330 331 331 /* ................................................................................ 336 336 } 337 337 338 338 /* 339 339 ** WEBPAGE: tktsetup_newpage 340 340 */ 341 341 void tktsetup_newpage_page(void){ 342 342 static const char zDesc[] = 343 - @ <p>Enter HTML with embedded TH1 script that will render the "new ticket" 344 - @ page</p> 343 + @ Enter HTML with embedded TH1 script that will render the "new ticket" 344 + @ page 345 345 ; 346 346 tktsetup_generic( 347 347 "HTML For New Tickets", 348 348 "ticket-newpage", 349 349 zDefaultNew, 350 350 zDesc, 351 351 0, ................................................................................ 352 352 0, 353 353 40 354 354 ); 355 355 } 356 356 357 357 static const char zDefaultView[] = 358 358 @ <table cellpadding="5"> 359 -@ <tr><td align="right">Ticket UUID:</td><td bgcolor="#d0d0d0" colspan="3"> 360 -@ $<tkt_uuid> 361 -@ </td></tr> 362 -@ <tr><td align="right">Title:</td> 363 -@ <td bgcolor="#d0d0d0" colspan="3" valign="top"> 359 +@ <tr><td class="tktDspLabel">Ticket UUID:</td> 360 +@ <td class="tktDspValue" colspan="3">$<tkt_uuid></td></tr> 361 +@ <tr><td class="tktDspLabel">Title:</td> 362 +@ <td class="tktDspValue" colspan="3"> 364 363 @ <th1>wiki $title</th1> 365 364 @ </td></tr> 366 -@ <tr><td align="right">Status:</td><td bgcolor="#d0d0d0"> 365 +@ <tr><td class="tktDspLabel">Status:</td><td class="tktDspValue"> 367 366 @ $<status> 368 367 @ </td> 369 -@ <td align="right">Type:</td><td bgcolor="#d0d0d0"> 368 +@ <td class="tktDspLabel">Type:</td><td class="tktDspValue"> 370 369 @ $<type> 371 370 @ </td></tr> 372 -@ <tr><td align="right">Severity:</td><td bgcolor="#d0d0d0"> 371 +@ <tr><td class="tktDspLabel">Severity:</td><td class="tktDspValue"> 373 372 @ $<severity> 374 373 @ </td> 375 -@ <td align="right">Priority:</td><td bgcolor="#d0d0d0"> 374 +@ <td class="tktDspLabel">Priority:</td><td class="tktDspValue"> 376 375 @ $<priority> 377 376 @ </td></tr> 378 -@ <tr><td align="right">Subsystem:</td><td bgcolor="#d0d0d0"> 377 +@ <tr><td class="tktDspLabel">Subsystem:</td><td class="tktDspValue"> 379 378 @ $<subsystem> 380 379 @ </td> 381 -@ <td align="right">Resolution:</td><td bgcolor="#d0d0d0"> 380 +@ <td class="tktDspLabel">Resolution:</td><td class="tktDspValue"> 382 381 @ $<resolution> 383 382 @ </td></tr> 384 -@ <tr><td align="right">Last Modified:</td><td bgcolor="#d0d0d0"> 383 +@ <tr><td class="tktDspLabel">Last Modified:</td><td class="tktDspValue"> 385 384 @ $<tkt_datetime> 386 385 @ </td> 387 386 @ <th1>enable_output [hascap e]</th1> 388 -@ <td align="right">Contact:</td><td bgcolor="#d0d0d0"> 387 +@ <td class="tktDspLabel">Contact:</td><td class="tktDspValue"> 389 388 @ $<private_contact> 390 389 @ </td> 391 390 @ <th1>enable_output 1</th1> 392 391 @ </tr> 393 -@ <tr><td align="right">Version Found In:</td> 394 -@ <td colspan="3" valign="top" bgcolor="#d0d0d0"> 392 +@ <tr><td class="tktDspLabel">Version Found In:</td> 393 +@ <td colspan="3" valign="top" class="tktDspValue"> 395 394 @ $<foundin> 396 395 @ </td></tr> 397 396 @ <tr><td>Description & Comments:</td></tr> 398 -@ <tr><td colspan="4" bgcolor="#d0d0d0"> 399 -@ <span bgcolor="#d0d0d0"><th1>wiki $comment</th1></span> 397 +@ <tr><td colspan="4" class="tktDspValue"> 398 +@ <th1>wiki $comment</th1> 400 399 @ </td></tr> 401 400 @ </table> 402 401 ; 403 402 404 403 405 404 /* 406 405 ** Return the code used to generate the view ticket page ................................................................................ 410 409 } 411 410 412 411 /* 413 412 ** WEBPAGE: tktsetup_viewpage 414 413 */ 415 414 void tktsetup_viewpage_page(void){ 416 415 static const char zDesc[] = 417 - @ <p>Enter HTML with embedded TH1 script that will render the "view ticket" 418 - @ page</p> 416 + @ Enter HTML with embedded TH1 script that will render the "view ticket" page 419 417 ; 420 418 tktsetup_generic( 421 419 "HTML For Viewing Tickets", 422 420 "ticket-viewpage", 423 421 zDefaultView, 424 422 zDesc, 425 423 0, ................................................................................ 430 428 431 429 static const char zDefaultEdit[] = 432 430 @ <th1> 433 431 @ if {![info exists username]} {set username $login} 434 432 @ if {[info exists submit]} { 435 433 @ if {[info exists cmappnd]} { 436 434 @ if {[string length $cmappnd]>0} { 437 -@ set ctxt "\n\n<hr><i>[htmlize $login]" 435 +@ set ctxt "\n\n<hr /><i>[htmlize $login]" 438 436 @ if {$username ne $login} { 439 437 @ set ctxt "$ctxt claiming to be [htmlize $username]" 440 438 @ } 441 -@ set ctxt "$ctxt added on [date]:</i><br>\n$cmappnd" 439 +@ set ctxt "$ctxt added on [date]:</i><br />\n$cmappnd" 442 440 @ append_field comment $ctxt 443 441 @ } 444 442 @ } 445 443 @ submit_ticket 446 444 @ } 447 445 @ </th1> 448 446 @ <table cellpadding="5"> 449 -@ <tr><td align="right">Title:</td><td> 450 -@ <input type="text" name="title" value="$<title>" size="60"> 447 +@ <tr><td class="tktDspLabel">Title:</td><td> 448 +@ <input type="text" name="title" value="$<title>" size="60" /> 451 449 @ </td></tr> 452 -@ <tr><td align="right">Status:</td><td> 450 +@ <tr><td class="tktDspLabel">Status:</td><td> 453 451 @ <th1>combobox status $status_choices 1</th1> 454 452 @ </td></tr> 455 -@ <tr><td align="right">Type:</td><td> 453 +@ <tr><td class="tktDspLabel">Type:</td><td> 456 454 @ <th1>combobox type $type_choices 1</th1> 457 455 @ </td></tr> 458 -@ <tr><td align="right">Severity:</td><td> 456 +@ <tr><td class="tktDspLabel">Severity:</td><td> 459 457 @ <th1>combobox severity $severity_choices 1</th1> 460 458 @ </td></tr> 461 -@ <tr><td align="right">Priority:</td><td> 459 +@ <tr><td class="tktDspLabel">Priority:</td><td> 462 460 @ <th1>combobox priority $priority_choices 1</th1> 463 461 @ </td></tr> 464 -@ <tr><td align="right">Resolution:</td><td> 462 +@ <tr><td class="tktDspLabel">Resolution:</td><td> 465 463 @ <th1>combobox resolution $resolution_choices 1</th1> 466 464 @ </td></tr> 467 -@ <tr><td align="right">Subsystem:</td><td> 465 +@ <tr><td class="tktDspLabel">Subsystem:</td><td> 468 466 @ <th1>combobox subsystem $subsystem_choices 1</th1> 469 467 @ </td></tr> 470 468 @ <th1>enable_output [hascap e]</th1> 471 -@ <tr><td align="right">Contact:</td><td> 469 +@ <tr><td class="tktDspLabel">Contact:</td><td> 472 470 @ <input type="text" name="private_contact" size="40" 473 -@ value="$<private_contact>"> 471 +@ value="$<private_contact>" /> 474 472 @ </td></tr> 475 473 @ <th1>enable_output 1</th1> 476 -@ <tr><td align="right">Version Found In:</td><td> 477 -@ <input type="text" name="foundin" size="50" value="$<foundin>"> 474 +@ <tr><td class="tktDspLabel">Version Found In:</td><td> 475 +@ <input type="text" name="foundin" size="50" value="$<foundin>" /> 478 476 @ </td></tr> 479 477 @ <tr><td colspan="2"> 480 478 @ <th1> 481 479 @ if {![info exists eall]} {set eall 0} 482 480 @ if {[info exists aonlybtn]} {set eall 0} 483 481 @ if {[info exists eallbtn]} {set eall 1} 484 482 @ if {![hascap w]} {set eall 0} 485 483 @ if {![info exists cmappnd]} {set cmappnd {}} 486 484 @ set nline [linecount $comment 15 10] 487 485 @ enable_output $eall 488 486 @ </th1> 489 -@ Description And Comments:<br> 487 +@ Description And Comments:<br /> 490 488 @ <textarea name="comment" cols="80" rows="$nline" 491 -@ wrap="virtual" class="wikiedit">$<comment></textarea><br> 492 -@ <input type="hidden" name="eall" value="1"> 493 -@ <input type="submit" name="aonlybtn" value="Append Remark"> 494 -@ <input type="submit" name="preview1btn" value="Preview"> 489 +@ wrap="virtual" class="wikiedit">$<comment></textarea><br /> 490 +@ <input type="hidden" name="eall" value="1" /> 491 +@ <input type="submit" name="aonlybtn" value="Append Remark" /> 492 +@ <input type="submit" name="preview1btn" value="Preview" /> 495 493 @ <th1>enable_output [expr {!$eall}]</th1> 496 494 @ Append Remark from 497 -@ <input type="text" name="username" value="$<username>" size="30">:<br> 495 +@ <input type="text" name="username" value="$<username>" size="30" />:<br /> 498 496 @ <textarea name="cmappnd" cols="80" rows="15" 499 -@ wrap="virtual" class="wikiedit">$<cmappnd></textarea><br> 497 +@ wrap="virtual" class="wikiedit">$<cmappnd></textarea><br /> 500 498 @ <th1>enable_output [expr {[hascap w] && !$eall}]</th1> 501 -@ <input type="submit" name="eallbtn" value="Edit All"> 499 +@ <input type="submit" name="eallbtn" value="Edit All" /> 502 500 @ <th1>enable_output [expr {!$eall}]</th1> 503 -@ <input type="submit" name="preview2btn" value="Preview"> 501 +@ <input type="submit" name="preview2btn" value="Preview" /> 504 502 @ <th1>enable_output 1</th1> 505 503 @ </td></tr> 506 504 @ 507 505 @ <th1>enable_output [info exists preview1btn]</th1> 508 506 @ <tr><td colspan="2"> 509 -@ Description Preview:<br><hr> 507 +@ Description Preview:<br /><hr /> 510 508 @ <th1>wiki $comment</th1> 511 -@ <hr> 509 +@ <hr /> 512 510 @ </td></tr> 513 511 @ <th1>enable_output [info exists preview2btn]</th1> 514 512 @ <tr><td colspan="2"> 515 -@ Description Preview:<br><hr> 513 +@ Description Preview:<br /><hr /> 516 514 @ <th1>wiki $cmappnd</th1> 517 -@ <hr> 515 +@ <hr /> 518 516 @ </td></tr> 519 517 @ <th1>enable_output 1</th1> 520 518 @ 521 519 @ <tr><td align="right"></td><td> 522 -@ <input type="submit" name="submit" value="Submit Changes"> 523 -@ <input type="submit" name="cancel" value="Cancel"> 520 +@ <input type="submit" name="submit" value="Submit Changes" /> 521 +@ <input type="submit" name="cancel" value="Cancel" /> 524 522 @ </td></tr> 525 523 @ </table> 526 524 ; 527 525 528 526 /* 529 527 ** Return the code used to generate the edit ticket page 530 528 */ ................................................................................ 533 531 } 534 532 535 533 /* 536 534 ** WEBPAGE: tktsetup_editpage 537 535 */ 538 536 void tktsetup_editpage_page(void){ 539 537 static const char zDesc[] = 540 - @ <p>Enter HTML with embedded TH1 script that will render the "edit ticket" 541 - @ page</p> 538 + @ Enter HTML with embedded TH1 script that will render the "edit ticket" page 542 539 ; 543 540 tktsetup_generic( 544 541 "HTML For Editing Tickets", 545 542 "ticket-editpage", 546 543 zDefaultEdit, 547 544 zDesc, 548 545 0, ................................................................................ 583 580 } 584 581 585 582 /* 586 583 ** WEBPAGE: tktsetup_reportlist 587 584 */ 588 585 void tktsetup_reportlist(void){ 589 586 static const char zDesc[] = 590 - @ <p>Enter HTML with embedded TH1 script that will render the "report list" 591 - @ page</p> 587 + @ Enter HTML with embedded TH1 script that will render the "report list" page 592 588 ; 593 589 tktsetup_generic( 594 590 "HTML For Report List", 595 591 "ticket-reportlist", 596 592 zDefaultReportList, 597 593 zDesc, 598 594 0, ................................................................................ 631 627 } 632 628 633 629 /* 634 630 ** WEBPAGE: tktsetup_rpttplt 635 631 */ 636 632 void tktsetup_rpttplt_page(void){ 637 633 static const char zDesc[] = 638 - @ <p>Enter the default ticket report format template. This is the 634 + @ Enter the default ticket report format template. This is the 639 635 @ the template report format that initially appears when creating a 640 - @ new ticket summary report.</p> 636 + @ new ticket summary report. 641 637 ; 642 638 tktsetup_generic( 643 639 "Default Report Template", 644 640 "ticket-report-template", 645 641 zDefaultReport, 646 642 zDesc, 647 643 0, ................................................................................ 672 668 } 673 669 674 670 /* 675 671 ** WEBPAGE: tktsetup_keytplt 676 672 */ 677 673 void tktsetup_keytplt_page(void){ 678 674 static const char zDesc[] = 679 - @ <p>Enter the default ticket report color-key template. This is the 675 + @ Enter the default ticket report color-key template. This is the 680 676 @ the color-key that initially appears when creating a 681 - @ new ticket summary report.</p> 677 + @ new ticket summary report. 682 678 ; 683 679 tktsetup_generic( 684 680 "Default Report Color-Key Template", 685 681 "ticket-key-template", 686 682 zDefaultKey, 687 683 zDesc, 688 684 0, ................................................................................ 701 697 } 702 698 703 699 if( P("setup") ){ 704 700 cgi_redirect("tktsetup"); 705 701 } 706 702 style_header("Ticket Display On Timelines"); 707 703 db_begin_transaction(); 708 - @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="POST"> 704 + @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="post"><div> 709 705 login_insert_csrf_secret(); 710 706 711 - @ <hr> 707 + @ <hr /> 712 708 entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title"); 713 709 @ <p>An SQL expression in a query against the TICKET table that will 714 710 @ return the title of the ticket for display purposes.</p> 715 711 716 - @ <hr> 712 + @ <hr /> 717 713 entry_attribute("Ticket Status", 40, "ticket-status-column", "s", "status"); 718 714 @ <p>The name of the column in the TICKET table that contains the ticket 719 715 @ status in human-readable form. Case sensitive.</p> 720 716 721 - @ <hr> 717 + @ <hr /> 722 718 entry_attribute("Ticket Closed", 40, "ticket-closed-expr", "c", 723 719 "status='Closed'"); 724 720 @ <p>An SQL expression that evaluates to true in a TICKET table query if 725 721 @ the ticket is closed.</p> 726 722 727 - @ <hr> 723 + @ <hr /> 728 724 @ <p> 729 - @ <input type="submit" name="submit" value="Apply Changes"> 730 - @ <input type="submit" name="setup" value="Cancel"> 725 + @ <input type="submit" name="submit" value="Apply Changes" /> 726 + @ <input type="submit" name="setup" value="Cancel" /> 731 727 @ </p> 732 - @ </form> 728 + @ </div></form> 733 729 db_end_transaction(0); 734 730 style_footer(); 735 731 736 732 }
Changes to src/translate.c.
64 64 } 65 65 } 66 66 67 67 /* 68 68 ** Translate the input stream into the output stream 69 69 */ 70 70 static void trans(FILE *in, FILE *out){ 71 - int i, j, k; /* Loop counters */ 72 - char c1, c2; /* Characters used to start a comment */ 73 - int lastWasEq = 0; /* True if last non-whitespace character was "=" */ 74 - char zLine[2000]; /* A single line of input */ 75 - char zOut[4000]; /* The input line translated into appropriate output */ 71 + int i, j, k; /* Loop counters */ 72 + char c1, c2; /* Characters used to start a comment */ 73 + int lastWasEq = 0; /* True if last non-whitespace character was "=" */ 74 + int lastWasComma = 0; /* True if last non-whitespace character was "," */ 75 + char zLine[2000]; /* A single line of input */ 76 + char zOut[4000]; /* The input line translated into appropriate output */ 76 77 77 78 c1 = c2 = '-'; 78 79 while( fgets(zLine, sizeof(zLine), in) ){ 79 80 for(i=0; zLine[i] && isspace(zLine[i]); i++){} 80 81 if( zLine[i]!='@' ){ 81 82 if( inPrint || inStr ) end_block(out); 82 83 fprintf(out,"%s",zLine); ................................................................................ 83 84 /* 0123456789 12345 */ 84 85 if( strncmp(zLine, "/* @-comment: ", 14)==0 ){ 85 86 c1 = zLine[14]; 86 87 c2 = zLine[15]; 87 88 } 88 89 i += strlen(&zLine[i]); 89 90 while( i>0 && isspace(zLine[i-1]) ){ i--; } 90 - lastWasEq = i>0 && zLine[i-1]=='='; 91 - }else if( lastWasEq ){ 91 + lastWasEq = i>0 && zLine[i-1]=='='; 92 + lastWasComma = i>0 && zLine[i-1]==','; 93 + }else if( lastWasEq || lastWasComma){ 92 94 /* If the last non-whitespace character before the first @ was 93 - ** an "=" then generate a string literal. But skip comments 95 + ** an "="(var init/set) or a ","(const definition in list) then 96 + ** generate a string literal. But skip comments 94 97 ** consisting of all text between c1 and c2 (default "--") 95 98 ** and end of line. 96 99 */ 97 100 int indent, omitline; 98 101 i++; 99 102 if( isspace(zLine[i]) ){ i++; } 100 103 indent = i - 2;
Changes to src/update.c.
22 22 #include "update.h" 23 23 #include <assert.h> 24 24 25 25 /* 26 26 ** Return true if artifact rid is a version 27 27 */ 28 28 int is_a_version(int rid){ 29 - return db_exists("SELECT 1 FROM plink WHERE cid=%d", rid); 29 + return db_exists("SELECT 1 FROM event WHERE objid=%d AND type='ci'", rid); 30 30 } 31 31 32 32 /* 33 33 ** COMMAND: update 34 34 ** 35 35 ** Usage: %fossil update ?VERSION? ?FILES...? 36 36 ** ................................................................................ 109 109 fossil_fatal("Multiple descendants"); 110 110 } 111 111 tid = db_int(0, "SELECT rid FROM leaves, event" 112 112 " WHERE event.objid=leaves.rid" 113 113 " ORDER BY event.mtime DESC"); 114 114 } 115 115 116 + if( tid==vid ) return; /* Nothing to update */ 116 117 db_begin_transaction(); 117 118 vfile_check_signature(vid, 1); 118 119 if( !nochangeFlag ) undo_begin(); 119 120 load_vfile_from_rid(tid); 120 121 121 122 /* 122 123 ** The record.fn field is used to match files against each other. The ................................................................................ 276 277 */ 277 278 if( nochangeFlag ){ 278 279 db_end_transaction(1); /* With --nochange, rollback changes */ 279 280 }else{ 280 281 if( g.argc<=3 ){ 281 282 /* All files updated. Shift the current checkout to the target. */ 282 283 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid); 284 + checkout_set_all_exe(vid); 283 285 manifest_to_disk(tid); 284 286 db_lset_int("checkout", tid); 285 287 }else{ 286 288 /* A subset of files have been checked out. Keep the current 287 289 ** checkout unchanged. */ 288 290 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid); 289 291 } ................................................................................ 299 301 */ 300 302 int historical_version_of_file( 301 303 const char *revision, /* The checkin containing the file */ 302 304 const char *file, /* Full treename of the file */ 303 305 Blob *content, /* Put the content here */ 304 306 int errCode /* Error code if file not found. Panic if 0. */ 305 307 ){ 306 - Blob mfile; 307 - Manifest m; 308 - int i, rid=0; 308 + Manifest *pManifest; 309 + ManifestFile *pFile; 310 + int rid=0; 309 311 310 312 if( revision ){ 311 313 rid = name_to_rid(revision); 312 314 }else{ 313 315 rid = db_lget_int("checkout", 0); 314 316 } 315 317 if( !is_a_version(rid) ){ 316 318 if( errCode>0 ) return errCode; 317 319 fossil_fatal("no such checkin: %s", revision); 318 320 } 319 - content_get(rid, &mfile); 321 + pManifest = manifest_get(rid, CFTYPE_MANIFEST); 320 322 321 - if( manifest_parse(&m, &mfile) ){ 322 - for(i=0; i<m.nFile; i++){ 323 - if( strcmp(m.aFile[i].zName, file)==0 ){ 324 - rid = uuid_to_rid(m.aFile[i].zUuid, 0); 325 - manifest_clear(&m); 323 + if( pManifest ){ 324 + manifest_file_rewind(pManifest); 325 + while( (pFile = manifest_file_next(pManifest,0))!=0 ){ 326 + if( strcmp(pFile->zName, file)==0 ){ 327 + rid = uuid_to_rid(pFile->zUuid, 0); 328 + manifest_destroy(pManifest); 326 329 return content_get(rid, content); 327 330 } 328 331 } 329 - manifest_clear(&m); 332 + manifest_destroy(pManifest); 330 333 if( errCode<=0 ){ 331 334 fossil_fatal("file %s does not exist in checkin: %s", file, revision); 332 335 } 333 336 }else if( errCode<=0 ){ 334 337 fossil_panic("could not parse manifest for checkin: %s", revision); 335 338 } 336 339 return errCode; ................................................................................ 383 386 blob_reset(&fname); 384 387 } 385 388 }else{ 386 389 int vid; 387 390 vid = db_lget_int("checkout", 0); 388 391 vfile_check_signature(vid, 0); 389 392 db_multi_exec( 393 + "DELETE FROM vmerge;" 390 394 "INSERT INTO torevert " 391 395 "SELECT pathname" 392 396 " FROM vfile " 393 - " WHERE chnged OR deleted OR rid=0 OR pathname!=origname" 397 + " WHERE chnged OR deleted OR rid=0 OR pathname!=origname;" 394 398 ); 395 399 } 396 400 blob_zero(&record); 397 401 db_prepare(&q, "SELECT name FROM torevert"); 398 402 while( db_step(&q)==SQLITE_ROW ){ 399 403 zFile = db_column_text(&q, 0); 400 404 if( zRevision!=0 ){
Changes to src/url.c.
15 15 ** 16 16 ******************************************************************************* 17 17 ** 18 18 ** This file contains code for parsing URLs that appear on the command-line 19 19 */ 20 20 #include "config.h" 21 21 #include "url.h" 22 + 23 +/* 24 +** Convert a string to lower-case. 25 +*/ 26 +static void url_tolower(char *z){ 27 + while( *z ){ 28 + *z = fossil_tolower(*z); 29 + z++; 30 + } 31 +} 22 32 23 33 /* 24 34 ** Parse the given URL. Populate variables in the global "g" structure. 25 35 ** 26 36 ** g.urlIsFile True if FILE: 27 37 ** g.urlIsHttps True if HTTPS: 38 +** g.urlIsSsh True if SSH: 28 39 ** g.urlProtocol "http" or "https" or "file" 29 -** g.urlName Hostname for HTTP: or HTTPS:. Filename for FILE: 40 +** g.urlName Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: 30 41 ** g.urlPort TCP port number for HTTP or HTTPS. 31 42 ** g.urlDfltPort Default TCP port number (80 or 443). 32 43 ** g.urlPath Path name for HTTP or HTTPS. 33 44 ** g.urlUser Userid. 34 45 ** g.urlPasswd Password. 35 46 ** g.urlHostname HOST:PORT or just HOST if port is the default. 36 47 ** g.urlCanonical The URL in canonical form, omitting the password 37 48 ** 38 49 ** HTTP url format is: 39 50 ** 40 -** http://userid:password@host:port/path?query#fragment 51 +** http://userid:password@host:port/path 52 +** 53 +** SSH url format is: 54 +** 55 +** ssh://userid:password@host:port/path?fossil=path/to/fossil.exe 41 56 ** 42 57 */ 43 58 void url_parse(const char *zUrl){ 44 59 int i, j, c; 45 60 char *zFile = 0; 46 - if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){ 61 + if( strncmp(zUrl, "http://", 7)==0 62 + || strncmp(zUrl, "https://", 8)==0 63 + || strncmp(zUrl, "ssh://", 6)==0 64 + ){ 47 65 int iStart; 48 66 char *zLogin; 67 + char *zExe; 68 + 49 69 g.urlIsFile = 0; 50 70 if( zUrl[4]=='s' ){ 51 71 g.urlIsHttps = 1; 52 72 g.urlProtocol = "https"; 53 73 g.urlDfltPort = 443; 54 74 iStart = 8; 75 + }else if( zUrl[0]=='s' ){ 76 + g.urlIsSsh = 1; 77 + g.urlProtocol = "ssh"; 78 + g.urlDfltPort = 22; 79 + g.urlFossil = "fossil"; 80 + iStart = 6; 55 81 }else{ 56 82 g.urlIsHttps = 0; 57 83 g.urlProtocol = "http"; 58 84 g.urlDfltPort = 80; 59 85 iStart = 7; 60 86 } 61 87 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!='@'; i++){} 62 88 if( c=='@' ){ 89 + /* Parse up the user-id and password */ 63 90 for(j=iStart; j<i && zUrl[j]!=':'; j++){} 64 91 g.urlUser = mprintf("%.*s", j-iStart, &zUrl[iStart]); 65 92 dehttpize(g.urlUser); 66 93 if( j<i ){ 67 94 g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]); 68 95 dehttpize(g.urlPasswd); 69 96 } 97 + if( g.urlIsSsh && g.urlPasswd ){ 98 + zLogin = mprintf("%t:*@", g.urlUser); 99 + }else{ 100 + zLogin = mprintf("%t@", g.urlUser); 101 + } 70 102 for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){} 71 103 g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]); 72 104 i = j; 73 - zLogin = mprintf("%t@", g.urlUser); 74 105 }else{ 75 106 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){} 76 107 g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]); 77 108 zLogin = mprintf(""); 78 109 } 79 - for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); } 110 + url_tolower(g.urlName); 80 111 if( c==':' ){ 81 112 g.urlPort = 0; 82 113 i++; 83 - while( (c = zUrl[i])!=0 && isdigit(c) ){ 114 + while( (c = zUrl[i])!=0 && fossil_isdigit(c) ){ 84 115 g.urlPort = g.urlPort*10 + c - '0'; 85 116 i++; 86 117 } 87 118 g.urlHostname = mprintf("%s:%d", g.urlName, g.urlPort); 88 119 }else{ 89 120 g.urlPort = g.urlDfltPort; 90 121 g.urlHostname = g.urlName; 91 122 } 92 - g.urlPath = mprintf(&zUrl[i]); 93 123 dehttpize(g.urlName); 124 + g.urlPath = mprintf("%s", &zUrl[i]); 125 + for(i=0; g.urlPath[i] && g.urlPath[i]!='?'; i++){} 126 + if( g.urlPath[i] ){ 127 + g.urlPath[i] = 0; 128 + i++; 129 + } 130 + zExe = mprintf(""); 131 + while( g.urlPath[i]!=0 ){ 132 + char *zName, *zValue; 133 + zName = &g.urlPath[i]; 134 + zValue = zName; 135 + while( g.urlPath[i] && g.urlPath[i]!='=' ){ i++; } 136 + if( g.urlPath[i]=='=' ){ 137 + g.urlPath[i] = 0; 138 + i++; 139 + zValue = &g.urlPath[i]; 140 + while( g.urlPath[i] && g.urlPath[i]!='&' ){ i++; } 141 + } 142 + if( g.urlPath[i] ){ 143 + g.urlPath[i] = 0; 144 + i++; 145 + } 146 + if( strcmp(zName,"fossil")==0 ){ 147 + g.urlFossil = zValue; 148 + dehttpize(g.urlFossil); 149 + zExe = mprintf("?fossil=%T", g.urlFossil); 150 + } 151 + } 152 + 94 153 dehttpize(g.urlPath); 95 154 if( g.urlDfltPort==g.urlPort ){ 96 155 g.urlCanonical = mprintf( 97 - "%s://%s%T%T", 98 - g.urlProtocol, zLogin, g.urlName, g.urlPath 156 + "%s://%s%T%T%s", 157 + g.urlProtocol, zLogin, g.urlName, g.urlPath, zExe 99 158 ); 100 159 }else{ 101 160 g.urlCanonical = mprintf( 102 - "%s://%s%T:%d%T", 103 - g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath 161 + "%s://%s%T:%d%T%s", 162 + g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath, zExe 104 163 ); 105 164 } 165 + if( g.urlIsSsh && g.urlPath[1] ) g.urlPath++; 106 166 free(zLogin); 107 167 }else if( strncmp(zUrl, "file:", 5)==0 ){ 108 168 g.urlIsFile = 1; 109 169 if( zUrl[5]=='/' && zUrl[6]=='/' ){ 110 170 i = 7; 111 171 }else{ 112 172 i = 5; ................................................................................ 148 208 if( g.argc!=3 && g.argc!=4 ){ 149 209 usage("URL"); 150 210 } 151 211 url_parse(g.argv[2]); 152 212 for(i=0; i<2; i++){ 153 213 printf("g.urlIsFile = %d\n", g.urlIsFile); 154 214 printf("g.urlIsHttps = %d\n", g.urlIsHttps); 215 + printf("g.urlIsSsh = %d\n", g.urlIsSsh); 155 216 printf("g.urlProtocol = %s\n", g.urlProtocol); 156 217 printf("g.urlName = %s\n", g.urlName); 157 218 printf("g.urlPort = %d\n", g.urlPort); 158 219 printf("g.urlDfltPort = %d\n", g.urlDfltPort); 159 220 printf("g.urlHostname = %s\n", g.urlHostname); 160 221 printf("g.urlPath = %s\n", g.urlPath); 161 222 printf("g.urlUser = %s\n", g.urlUser); 162 223 printf("g.urlPasswd = %s\n", g.urlPasswd); 163 224 printf("g.urlCanonical = %s\n", g.urlCanonical); 225 + printf("g.urlFossil = %s\n", g.urlFossil); 226 + if( g.urlIsFile || g.urlIsSsh ) break; 164 227 if( i==0 ){ 165 228 printf("********\n"); 166 229 url_enable_proxy("Using proxy: "); 167 230 } 168 231 } 169 232 } 170 233 ................................................................................ 286 349 } 287 350 if( zName2 && strcmp(zName2,p->azName[i])==0 ){ 288 351 zName2 = 0; 289 352 z = zValue2; 290 353 if( z==0 ) continue; 291 354 } 292 355 blob_appendf(&p->url, "%s%s=%T", zSep, p->azName[i], z); 293 - zSep = "&"; 356 + zSep = "&"; 294 357 } 295 358 if( zName1 && zValue1 ){ 296 359 blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1); 297 360 } 298 361 if( zName2 && zValue2 ){ 299 362 blob_appendf(&p->url, "%s%s=%T", zSep, zName2, zValue2); 300 363 }
Changes to src/user.c.
25 25 /* 26 26 ** Strip leading and trailing space from a string and add the string 27 27 ** onto the end of a blob. 28 28 */ 29 29 static void strip_string(Blob *pBlob, char *z){ 30 30 int i; 31 31 blob_reset(pBlob); 32 - while( isspace(*z) ){ z++; } 32 + while( fossil_isspace(*z) ){ z++; } 33 33 for(i=0; z[i]; i++){ 34 34 if( z[i]=='\r' || z[i]=='\n' ){ 35 - while( i>0 && isspace(z[i-1]) ){ i--; } 35 + while( i>0 && fossil_isspace(z[i-1]) ){ i--; } 36 36 z[i] = 0; 37 37 break; 38 38 } 39 39 if( z[i]<' ' ) z[i] = ' '; 40 40 } 41 41 blob_append(pBlob, z, -1); 42 42 } 43 43 44 +#if defined(_WIN32) 44 45 #ifdef __MINGW32__ 46 +#include <conio.h> 47 +#endif 45 48 /* 46 49 ** getpass for Windows 47 50 */ 48 51 static char *getpass(const char *prompt){ 49 52 static char pwd[64]; 50 53 size_t i; 51 54
Changes to src/vfile.c.
17 17 ** 18 18 ** Procedures for managing the VFILE table. 19 19 */ 20 20 #include "config.h" 21 21 #include "vfile.h" 22 22 #include <assert.h> 23 23 #include <sys/types.h> 24 +#if defined(__DMC__) 25 +#include "dirent.h" 26 +#else 24 27 #include <dirent.h> 28 +#endif 25 29 26 30 /* 27 31 ** Given a UUID, return the corresponding record ID. If the UUID 28 32 ** does not exist, then return 0. 29 33 ** 30 34 ** For this routine, the UUID must be exact. For a match against 31 35 ** user input with mixed case, use resolve_uuid(). ................................................................................ 79 83 fossil_panic("bad object id: %d", rid); 80 84 } 81 85 } 82 86 } 83 87 } 84 88 85 89 /* 86 -** Build a catalog of all files in a baseline. 87 -** We scan the baseline file for lines of the form: 88 -** 89 -** F NAME UUID 90 -** 91 -** Each such line makes an entry in the VFILE table. 90 +** Build a catalog of all files in a checkin. 92 91 */ 93 -void vfile_build(int vid, Blob *p){ 92 +void vfile_build(int vid){ 94 93 int rid; 95 - char *zName, *zUuid; 96 94 Stmt ins; 97 - Blob line, token, name, uuid; 98 - int seenHeader = 0; 95 + Manifest *p; 96 + ManifestFile *pFile; 97 + 99 98 db_begin_transaction(); 100 99 vfile_verify_not_phantom(vid, 0, 0); 100 + p = manifest_get(vid, CFTYPE_MANIFEST); 101 + if( p==0 ) return; 101 102 db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid); 102 103 db_prepare(&ins, 103 104 "INSERT INTO vfile(vid,rid,mrid,pathname) " 104 105 " VALUES(:vid,:id,:id,:name)"); 105 106 db_bind_int(&ins, ":vid", vid); 106 - while( blob_line(p, &line) ){ 107 - char *z = blob_buffer(&line); 108 - if( z[0]=='-' ){ 109 - if( seenHeader ) break; 110 - while( blob_line(p, &line)>2 ){} 111 - if( blob_line(p, &line)==0 ) break; 112 - } 113 - seenHeader = 1; 114 - if( z[0]!='F' || z[1]!=' ' ) continue; 115 - blob_token(&line, &token); /* Skip the "F" token */ 116 - if( blob_token(&line, &name)==0 ) break; 117 - if( blob_token(&line, &uuid)==0 ) break; 118 - zName = blob_str(&name); 119 - defossilize(zName); 120 - zUuid = blob_str(&uuid); 121 - rid = uuid_to_rid(zUuid, 0); 122 - vfile_verify_not_phantom(rid, zName, zUuid); 123 - if( rid>0 && file_is_simple_pathname(zName) ){ 124 - db_bind_int(&ins, ":id", rid); 125 - db_bind_text(&ins, ":name", zName); 126 - db_step(&ins); 127 - db_reset(&ins); 128 - } 129 - blob_reset(&name); 130 - blob_reset(&uuid); 107 + manifest_file_rewind(p); 108 + while( (pFile = manifest_file_next(p,0))!=0 ){ 109 + rid = uuid_to_rid(pFile->zUuid, 0); 110 + vfile_verify_not_phantom(rid, pFile->zName, pFile->zUuid); 111 + db_bind_int(&ins, ":id", rid); 112 + db_bind_text(&ins, ":name", pFile->zName); 113 + db_step(&ins); 114 + db_reset(&ins); 131 115 } 132 116 db_finalize(&ins); 117 + manifest_destroy(p); 133 118 db_end_transaction(0); 134 119 } 135 120 136 121 /* 137 122 ** Check the file signature of the disk image for every VFILE of vid. 138 123 ** 139 124 ** Set the VFILE.CHNGED field on every file that has changed. Also ................................................................................ 363 348 md5sum_step_text(" 0\n", -1); 364 349 continue; 365 350 } 366 351 fseek(in, 0L, SEEK_END); 367 352 sprintf(zBuf, " %ld\n", ftell(in)); 368 353 fseek(in, 0L, SEEK_SET); 369 354 md5sum_step_text(zBuf, -1); 355 + /*printf("%s %s %s",md5sum_current_state(),zName,zBuf); fflush(stdout);*/ 370 356 for(;;){ 371 357 int n; 372 358 n = fread(zBuf, 1, sizeof(zBuf), in); 373 359 if( n<=0 ) break; 374 360 md5sum_step_text(zBuf, n); 375 361 } 376 362 fclose(in); ................................................................................ 416 402 while( db_step(&q)==SQLITE_ROW ){ 417 403 const char *zName = db_column_text(&q, 0); 418 404 int rid = db_column_int(&q, 1); 419 405 md5sum_step_text(zName, -1); 420 406 content_get(rid, &file); 421 407 sprintf(zBuf, " %d\n", blob_size(&file)); 422 408 md5sum_step_text(zBuf, -1); 409 + /*printf("%s %s %s",md5sum_current_state(),zName,zBuf); fflush(stdout);*/ 423 410 md5sum_step_blob(&file); 424 411 blob_reset(&file); 425 412 } 426 413 db_finalize(&q); 427 414 md5sum_finish(pOut); 428 415 } 429 416 ................................................................................ 432 419 ** file in manifest vid. The file names are part of the checksum. 433 420 ** Return the resulting checksum in blob pOut. 434 421 ** 435 422 ** If pManOut is not NULL then fill it with the checksum found in the 436 423 ** "R" card near the end of the manifest. 437 424 */ 438 425 void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){ 439 - int i, fid; 440 - Blob file, mfile; 441 - Manifest m; 426 + int fid; 427 + Blob file; 428 + Manifest *pManifest; 429 + ManifestFile *pFile; 442 430 char zBuf[100]; 443 431 444 432 blob_zero(pOut); 445 433 if( pManOut ){ 446 434 blob_zero(pManOut); 447 435 } 448 436 db_must_be_within_tree(); 449 - content_get(vid, &mfile); 450 - if( manifest_parse(&m, &mfile)==0 ){ 437 + pManifest = manifest_get(vid, CFTYPE_MANIFEST); 438 + if( pManifest==0 ){ 451 439 fossil_panic("manifest file (%d) is malformed", vid); 452 440 } 453 - for(i=0; i<m.nFile; i++){ 454 - fid = uuid_to_rid(m.aFile[i].zUuid, 0); 455 - md5sum_step_text(m.aFile[i].zName, -1); 441 + manifest_file_rewind(pManifest); 442 + while( (pFile = manifest_file_next(pManifest,0))!=0 ){ 443 + fid = uuid_to_rid(pFile->zUuid, 0); 444 + md5sum_step_text(pFile->zName, -1); 456 445 content_get(fid, &file); 457 446 sprintf(zBuf, " %d\n", blob_size(&file)); 458 447 md5sum_step_text(zBuf, -1); 459 448 md5sum_step_blob(&file); 460 449 blob_reset(&file); 461 450 } 462 451 if( pManOut ){ 463 - blob_append(pManOut, m.zRepoCksum, -1); 452 + if( pManifest->zRepoCksum ){ 453 + blob_append(pManOut, pManifest->zRepoCksum, -1); 454 + }else{ 455 + blob_zero(pManOut); 456 + } 464 457 } 465 - manifest_clear(&m); 458 + manifest_destroy(pManifest); 466 459 md5sum_finish(pOut); 467 460 } 468 461 469 462 /* 470 463 ** COMMAND: test-agg-cksum 471 464 */ 472 465 void test_agg_cksum_cmd(void){
Changes to src/wiki.c.
46 46 } 47 47 48 48 /* 49 49 ** Output rules for well-formed wiki pages 50 50 */ 51 51 static void well_formed_wiki_name_rules(void){ 52 52 @ <ul> 53 - @ <li> Must not begin or end with a space. 53 + @ <li> Must not begin or end with a space.</li> 54 54 @ <li> Must not contain any control characters, including tab or 55 - @ newline. 56 - @ <li> Must not have two or more spaces in a row internally. 57 - @ <li> Must be between 3 and 100 characters in length. 55 + @ newline.</li> 56 + @ <li> Must not have two or more spaces in a row internally.</li> 57 + @ <li> Must be between 3 and 100 characters in length.</li> 58 58 @ </ul> 59 59 } 60 60 61 61 /* 62 62 ** Check a wiki name. If it is not well-formed, then issue an error 63 63 ** and return true. If it is well-formed, return false. 64 64 */ 65 65 static int check_name(const char *z){ 66 66 if( !wiki_name_is_wellformed((const unsigned char *)z) ){ 67 67 style_header("Wiki Page Name Error"); 68 - @ The wiki name "<b>%h(z)</b>" is not well-formed. Rules for 69 - @ wiki page names: 68 + @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed. 69 + @ Rules for wiki page names: 70 70 well_formed_wiki_name_rules(); 71 71 style_footer(); 72 72 return 1; 73 73 } 74 74 return 0; 75 75 } 76 76 ................................................................................ 77 77 /* 78 78 ** WEBPAGE: home 79 79 ** WEBPAGE: index 80 80 ** WEBPAGE: not_found 81 81 */ 82 82 void home_page(void){ 83 83 char *zPageName = db_get("project-name",0); 84 + char *zIndexPage = db_get("index-page",0); 84 85 login_check_credentials(); 85 86 if( !g.okRdWiki ){ 86 87 cgi_redirectf("%s/login?g=%s/home", g.zBaseURL, g.zBaseURL); 87 88 } 89 + if( zIndexPage ){ 90 + const char *zPathInfo = P("PATH_INFO"); 91 + while( zIndexPage[0]=='/' ) zIndexPage++; 92 + if( strcmp(zIndexPage, zPathInfo)==0 ) zIndexPage = 0; 93 + } 94 + if( zIndexPage ){ 95 + cgi_redirectf("%s/%s", g.zBaseURL, zIndexPage); 96 + } 88 97 if( zPageName ){ 89 98 login_check_credentials(); 90 99 g.zExtra = zPageName; 91 100 cgi_set_parameter_nocopy("name", g.zExtra); 92 101 g.isHome = 1; 93 102 wiki_page(); 94 103 return; ................................................................................ 95 104 } 96 105 style_header("Home"); 97 106 @ <p>This is a stub home-page for the project. 98 107 @ To fill in this page, first go to 99 108 @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a> 100 109 @ and establish a "Project Name". Then create a 101 110 @ wiki page with that name. The content of that wiki page 102 - @ will be displayed in place of this message. 111 + @ will be displayed in place of this message.</p> 103 112 style_footer(); 104 113 } 105 114 106 115 /* 107 116 ** Return true if the given pagename is the name of the sandbox 108 117 */ 109 118 static int is_sandbox(const char *zPagename){ ................................................................................ 116 125 ** URL: /wiki?name=PAGENAME 117 126 */ 118 127 void wiki_page(void){ 119 128 char *zTag; 120 129 int rid = 0; 121 130 int isSandbox; 122 131 Blob wiki; 123 - Manifest m; 132 + Manifest *pWiki = 0; 124 133 const char *zPageName; 125 134 char *zBody = mprintf("%s","<i>Empty Page</i>"); 126 135 Stmt q; 127 136 int cnt = 0; 128 137 129 138 login_check_credentials(); 130 139 if( !g.okRdWiki ){ login_needed(); return; } ................................................................................ 142 151 @ pages. </li> 143 152 @ <li> <a href="%s(g.zBaseURL)/wiki_rules">Formatting rules</a> for 144 153 @ wiki.</li> 145 154 @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a> 146 155 @ to experiment.</li> 147 156 if( g.okNewWiki ){ 148 157 @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li> 158 + if( g.okWrite ){ 159 + @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li> 160 + } 149 161 } 150 162 @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a> 151 163 @ available on this server.</li> 152 - @ <li> <form method="GET" action="%s(g.zBaseURL)/wfind"> 153 - @ Search wiki titles: <input type="text" name="title"/> 154 - @ <input type="submit" /> 155 - @ </li> 164 + @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div> 165 + @ Search wiki titles: <input type="text" name="title"/> 166 + @ <input type="submit" /></div></form> 167 + @ </li> 156 168 @ </ul> 157 169 style_footer(); 158 170 return; 159 171 } 160 172 if( check_name(zPageName) ) return; 161 173 isSandbox = is_sandbox(zPageName); 162 174 if( isSandbox ){ ................................................................................ 165 177 zTag = mprintf("wiki-%s", zPageName); 166 178 rid = db_int(0, 167 179 "SELECT rid FROM tagxref" 168 180 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" 169 181 " ORDER BY mtime DESC", zTag 170 182 ); 171 183 free(zTag); 172 - memset(&m, 0, sizeof(m)); 173 - blob_zero(&m.content); 174 - if( rid ){ 175 - Blob content; 176 - content_get(rid, &content); 177 - manifest_parse(&m, &content); 178 - if( m.type==CFTYPE_WIKI && m.zWiki ){ 179 - while( isspace(m.zWiki[0]) ) m.zWiki++; 180 - if( m.zWiki[0] ) zBody = m.zWiki; 181 - } 184 + pWiki = manifest_get(rid, CFTYPE_WIKI); 185 + if( pWiki ){ 186 + while( fossil_isspace(pWiki->zWiki[0]) ) pWiki->zWiki++; 187 + if( pWiki->zWiki[0] ) zBody = pWiki->zWiki; 182 188 } 183 189 } 184 190 if( !g.isHome ){ 185 191 if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){ 186 192 style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T", 187 193 g.zTop, zPageName); 188 194 } 189 195 if( rid && g.okApndWiki && g.okAttach ){ 190 196 style_submenu_element("Attach", "Add An Attachment", 191 - "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", 197 + "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", 192 198 g.zTop, zPageName, g.zTop, zPageName); 193 199 } 194 200 if( rid && g.okApndWiki ){ 195 201 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", 196 202 g.zTop, zPageName); 197 203 } 198 204 if( g.okHistory ){ ................................................................................ 212 218 " ORDER BY mtime DESC", 213 219 zPageName); 214 220 while( db_step(&q)==SQLITE_ROW ){ 215 221 const char *zDate = db_column_text(&q, 0); 216 222 const char *zFile = db_column_text(&q, 1); 217 223 const char *zUser = db_column_text(&q, 2); 218 224 if( cnt==0 ){ 219 - @ <hr><h2>Attachments:</h2> 225 + @ <hr /><h2>Attachments:</h2> 220 226 @ <ul> 221 227 } 222 228 cnt++; 223 - if( g.okHistory ){ 224 - @ <li><a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> 229 + @ <li> 230 + if( g.okHistory && g.okRead ){ 231 + @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> 232 + @ %h(zFile)</a> 225 233 }else{ 226 - @ <li> 234 + @ <li>%h(zFile) 227 235 } 228 - @ %h(zFile)</a> add by %h(zUser) on 236 + @ added by %h(zUser) on 229 237 hyperlink_to_date(zDate, "."); 230 238 if( g.okWrWiki && g.okAttach ){ 231 - @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] 239 + @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] 232 240 } 241 + @ </li> 233 242 } 234 243 if( cnt ){ 235 244 @ </ul> 236 245 } 237 246 db_finalize(&q); 238 247 239 - if( !isSandbox ){ 240 - manifest_clear(&m); 241 - } 248 + manifest_destroy(pWiki); 242 249 style_footer(); 243 250 } 244 251 245 252 /* 246 253 ** WEBPAGE: wikiedit 247 254 ** URL: /wikiedit?name=PAGENAME 248 255 */ 249 256 void wikiedit_page(void){ 250 257 char *zTag; 251 258 int rid = 0; 252 259 int isSandbox; 253 260 Blob wiki; 254 - Manifest m; 261 + Manifest *pWiki = 0; 255 262 const char *zPageName; 256 263 char *zHtmlPageName; 257 264 int n; 258 265 const char *z; 259 266 char *zBody = (char*)P("w"); 260 267 261 268 if( zBody ){ ................................................................................ 281 288 " ORDER BY mtime DESC", zTag 282 289 ); 283 290 free(zTag); 284 291 if( (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){ 285 292 login_needed(); 286 293 return; 287 294 } 288 - memset(&m, 0, sizeof(m)); 289 - blob_zero(&m.content); 290 - if( rid && zBody==0 ){ 291 - Blob content; 292 - content_get(rid, &content); 293 - manifest_parse(&m, &content); 294 - if( m.type==CFTYPE_WIKI ){ 295 - zBody = m.zWiki; 296 - } 295 + if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){ 296 + zBody = pWiki->zWiki; 297 297 } 298 298 } 299 299 if( P("submit")!=0 && zBody!=0 ){ 300 300 char *zDate; 301 301 Blob cksum; 302 302 int nrid; 303 303 blob_zero(&wiki); ................................................................................ 340 340 zBody = mprintf("<i>Empty Page</i>"); 341 341 } 342 342 zHtmlPageName = mprintf("Edit: %s", zPageName); 343 343 style_header(zHtmlPageName); 344 344 if( P("preview")!=0 ){ 345 345 blob_zero(&wiki); 346 346 blob_append(&wiki, zBody, -1); 347 - @ Preview:<hr> 347 + @ Preview:<hr /> 348 348 wiki_convert(&wiki, 0, 0); 349 - @ <hr> 349 + @ <hr /> 350 350 blob_reset(&wiki); 351 351 } 352 352 for(n=2, z=zBody; z[0]; z++){ 353 353 if( z[0]=='\n' ) n++; 354 354 } 355 355 if( n<20 ) n = 20; 356 356 if( n>40 ) n = 40; 357 - @ <form method="POST" action="%s(g.zBaseURL)/wikiedit"> 357 + @ <form method="post" action="%s(g.zBaseURL)/wikiedit"><div> 358 358 login_insert_csrf_secret(); 359 - @ <input type="hidden" name="name" value="%h(zPageName)"> 359 + @ <input type="hidden" name="name" value="%h(zPageName)" /> 360 360 @ <textarea name="w" class="wikiedit" cols="80" 361 361 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> 362 - @ <br> 363 - @ <input type="submit" name="preview" value="Preview Your Changes"> 364 - @ <input type="submit" name="submit" value="Apply These Changes"> 365 - @ <input type="submit" name="cancel" value="Cancel"> 366 - @ </form> 367 - if( !isSandbox ){ 368 - manifest_clear(&m); 369 - } 362 + @ <br /> 363 + @ <input type="submit" name="preview" value="Preview Your Changes" /> 364 + @ <input type="submit" name="submit" value="Apply These Changes" /> 365 + @ <input type="submit" name="cancel" value="Cancel" /> 366 + @ </div></form> 367 + manifest_destroy(pWiki); 370 368 style_footer(); 371 369 } 372 370 373 371 /* 374 372 ** WEBPAGE: wikinew 375 373 ** URL /wikinew 376 374 ** ................................................................................ 385 383 return; 386 384 } 387 385 zName = PD("name",""); 388 386 if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){ 389 387 cgi_redirectf("wikiedit?name=%T", zName); 390 388 } 391 389 style_header("Create A New Wiki Page"); 392 - @ <p>Rules for wiki page names: 390 + @ <p>Rules for wiki page names:</p> 393 391 well_formed_wiki_name_rules(); 394 - @ </p> 395 - @ <form method="POST" action="%s(g.zBaseURL)/wikinew"> 392 + @ <form method="post" action="%s(g.zBaseURL)/wikinew"> 396 393 @ <p>Name of new wiki page: 397 - @ <input type="text" width="35" name="name" value="%h(zName)"> 398 - @ <input type="submit" value="Create"> 394 + @ <input style="width: 35;" type="text" name="name" value="%h(zName)" /> 395 + @ <input type="submit" value="Create" /> 399 396 @ </p></form> 400 397 if( zName[0] ){ 401 - @ <p><b><font color="red"> 402 - @ "%h(zName)" is not a valid wiki page name!</font></b></p> 398 + @ <p><span class="wikiError"> 399 + @ "%h(zName)" is not a valid wiki page name!</span></p> 403 400 } 404 401 style_footer(); 405 402 } 406 403 407 404 408 405 /* 409 406 ** Append the wiki text for an remark to the end of the given BLOB. ................................................................................ 461 458 return; 462 459 } 463 460 if( P("submit")!=0 && P("r")!=0 && P("u")!=0 ){ 464 461 char *zDate; 465 462 Blob cksum; 466 463 int nrid; 467 464 Blob body; 468 - Blob content; 469 465 Blob wiki; 470 - Manifest m; 466 + Manifest *pWiki = 0; 471 467 472 468 blob_zero(&body); 473 469 if( isSandbox ){ 474 470 blob_appendf(&body, db_get("sandbox","")); 475 471 appendRemark(&body); 476 472 db_set("sandbox", blob_str(&body), 0); 477 473 }else{ 478 474 login_verify_csrf_secret(); 479 - content_get(rid, &content); 480 - manifest_parse(&m, &content); 481 - if( m.type==CFTYPE_WIKI ){ 482 - blob_append(&body, m.zWiki, -1); 475 + pWiki = manifest_get(rid, CFTYPE_WIKI); 476 + if( pWiki ){ 477 + blob_append(&body, pWiki->zWiki, -1); 478 + manifest_destroy(pWiki); 483 479 } 484 - manifest_clear(&m); 485 480 blob_zero(&wiki); 486 481 db_begin_transaction(); 487 482 zDate = db_text(0, "SELECT datetime('now')"); 488 483 zDate[10] = 'T'; 489 484 blob_appendf(&wiki, "D %s\n", zDate); 490 485 blob_appendf(&wiki, "L %F\n", zPageName); 491 486 if( rid ){ ................................................................................ 522 517 appendRemark(&preview); 523 518 @ Preview:<hr> 524 519 wiki_convert(&preview, 0, 0); 525 520 @ <hr> 526 521 blob_reset(&preview); 527 522 } 528 523 zUser = PD("u", g.zLogin); 529 - @ <form method="POST" action="%s(g.zBaseURL)/wikiappend"> 524 + @ <form method="post" action="%s(g.zBaseURL)/wikiappend"> 530 525 login_insert_csrf_secret(); 531 - @ <input type="hidden" name="name" value="%h(zPageName)"> 526 + @ <input type="hidden" name="name" value="%h(zPageName)" /> 532 527 @ Your Name: 533 - @ <input type="text" name="u" size="20" value="%h(zUser)"><br> 534 - @ Comment to append:<br> 528 + @ <input type="text" name="u" size="20" value="%h(zUser)" /><br /> 529 + @ Comment to append:<br /> 535 530 @ <textarea name="r" class="wikiedit" cols="80" 536 531 @ rows="10" wrap="virtual">%h(PD("r",""))</textarea> 537 - @ <br> 538 - @ <input type="submit" name="preview" value="Preview Your Comment"> 539 - @ <input type="submit" name="submit" value="Append Your Changes"> 540 - @ <input type="submit" name="cancel" value="Cancel"> 532 + @ <br /> 533 + @ <input type="submit" name="preview" value="Preview Your Comment" /> 534 + @ <input type="submit" name="submit" value="Append Your Changes" /> 535 + @ <input type="submit" name="cancel" value="Cancel" /> 541 536 @ </form> 542 537 style_footer(); 543 538 } 544 539 545 540 /* 546 541 ** Name of the wiki history page being generated 547 542 */ ................................................................................ 549 544 550 545 /* 551 546 ** Function called to output extra text at the end of each line in 552 547 ** a wiki history listing. 553 548 */ 554 549 static void wiki_history_extra(int rid){ 555 550 if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){ 556 - @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a> 551 + @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a> 557 552 } 558 553 } 559 554 560 555 /* 561 556 ** WEBPAGE: whistory 562 557 ** URL: /whistory?name=PAGENAME 563 558 ** ................................................................................ 596 591 ** 597 592 ** Show the difference between two wiki pages. 598 593 */ 599 594 void wdiff_page(void){ 600 595 char *zTitle; 601 596 int rid1, rid2; 602 597 const char *zPageName; 603 - Blob content1, content2; 604 - Manifest m1, m2; 598 + Manifest *pW1, *pW2 = 0; 605 599 Blob w1, w2, d; 606 600 607 601 login_check_credentials(); 608 602 rid1 = atoi(PD("a","0")); 609 603 if( !g.okHistory ){ login_needed(); return; } 610 604 if( rid1==0 ) fossil_redirect_home(); 611 605 rid2 = atoi(PD("b","0")); ................................................................................ 619 613 "SELECT objid FROM event JOIN tagxref ON objid=rid AND tagxref.tagid=" 620 614 "(SELECT tagid FROM tag WHERE tagname='wiki-%q')" 621 615 " WHERE event.mtime<(SELECT mtime FROM event WHERE objid=%d)" 622 616 " ORDER BY event.mtime DESC LIMIT 1", 623 617 zPageName, rid1 624 618 ); 625 619 } 626 - content_get(rid1, &content1); 627 - manifest_parse(&m1, &content1); 628 - if( m1.type!=CFTYPE_WIKI ) fossil_redirect_home(); 629 - blob_init(&w1, m1.zWiki, -1); 620 + pW1 = manifest_get(rid1, CFTYPE_WIKI); 621 + if( pW1==0 ) fossil_redirect_home(); 622 + blob_init(&w1, pW1->zWiki, -1); 630 623 blob_zero(&w2); 631 - if( rid2 ){ 632 - content_get(rid2, &content2); 633 - manifest_parse(&m2, &content2); 634 - if( m2.type==CFTYPE_WIKI ){ 635 - blob_init(&w2, m2.zWiki, -1); 636 - } 624 + if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){ 625 + blob_init(&w2, pW2->zWiki, -1); 637 626 } 638 627 blob_zero(&d); 639 - text_diff(&w2, &w1, &d, 5); 628 + text_diff(&w2, &w1, &d, 5, 1); 640 629 @ <pre> 641 630 @ %h(blob_str(&d)) 642 631 @ </pre> 632 + manifest_destroy(pW1); 633 + manifest_destroy(pW2); 643 634 style_footer(); 644 635 } 645 636 646 637 /* 647 638 ** WEBPAGE: wcontent 648 639 ** 649 640 ** all=1 Show deleted pages ................................................................................ 729 720 @ <li>Most ordinary HTML works.</li> 730 721 @ <li><verbatim> and <nowiki>.</li> 731 722 @ </ol> 732 723 @ <p>We call the first five rules above "wiki" formatting rules. The 733 724 @ last two rules are the HTML formatting rule.</p> 734 725 @ <h2>Formatting Rule Details</h2> 735 726 @ <ol> 736 - @ <li> <p><b>Paragraphs</b>. Any sequence of one or more blank lines forms 727 + @ <li> <p><span class="wikiruleHead">Paragraphs</span>. Any sequence of one or more blank lines forms 737 728 @ a paragraph break. Centered or right-justified paragraphs are not 738 729 @ supported by wiki markup, but you can do these things if you need them 739 - @ using HTML.</p> 740 - @ <li> <p><b>Bullet Lists</b>. 730 + @ using HTML.</p></li> 731 + @ <li> <p><span class="wikiruleHead">Bullet Lists</span>. 741 732 @ A bullet list item is a line that begins with a single "*" character 742 733 @ surrounded on 743 734 @ both sides by two or more spaces or by a tab. Only a single level 744 - @ of bullet list is supported by wiki. For nested lists, use HTML.</p> 745 - @ <li> <p><b>Enumeration Lists</b>. 735 + @ of bullet list is supported by wiki. For nested lists, use HTML.</p></li> 736 + @ <li> <p><span class="wikiruleHead">Enumeration Lists</span>. 746 737 @ An enumeration list item is a line that begins with a single "#" character 747 738 @ surrounded on both sides by two or more spaces or by a tab. Only a single 748 739 @ level of enumeration list is supported by wiki. For nested lists or for 749 - @ enumerations that count using letters or roman numerials, use HTML.</p> 750 - @ <li> <p><b>Indented Paragraphs</b>. 740 + @ enumerations that count using letters or roman numerials, use HTML.</p></li> 741 + @ <li> <p><span class="wikiruleHead">Indented Paragraphs</span>. 751 742 @ Any paragraph that begins with two or more spaces or a tab and 752 743 @ which is not a bullet or enumeration list item is rendered 753 744 @ indented. Only a single level of indentation is supported by wiki; use 754 - @ HTML for deeper indentation.</p> 755 - @ <li> <p><b>Hyperlinks</b>. 745 + @ HTML for deeper indentation.</p></li> 746 + @ <li> <p><span class="wikiruleHead">Hyperlinks</span>. 756 747 @ Text within square brackets ("[...]") becomes a hyperlink. The 757 748 @ target can be a wiki page name, the artifact ID of a check-in or ticket, 758 749 @ the name of an image, or a URL. By default, the target is displayed 759 750 @ as the text of the hyperlink. But you can specify alternative text 760 751 @ after the target name separated by a "|" character.</p> 761 752 @ <p>You can also link to internal anchor names using [#anchor-name], providing 762 753 @ you have added the necessary "<a name="anchor-name"></a>" 763 - @ tag to your wiki page.</p> 764 - @ <li> <p><b>HTML</b>. 754 + @ tag to your wiki page.</p></li> 755 + @ <li> <p><span class="wikiruleHead">HTML</span>. 765 756 @ The following standard HTML elements may be used: 766 - @ <a> 767 - @ <address> 768 - @ <b> 769 - @ <big> 770 - @ <blockquote> 771 - @ <br> 772 - @ <center> 773 - @ <cite> 774 - @ <code> 775 - @ <dd> 776 - @ <dfn> 777 - @ <div> 778 - @ <dl> 779 - @ <dt> 780 - @ <em> 781 - @ <font> 782 - @ <h1> 783 - @ <h2> 784 - @ <h3> 785 - @ <h4> 786 - @ <h5> 787 - @ <h6> 788 - @ <hr> 789 - @ <img> 790 - @ <i> 791 - @ <kbd> 792 - @ <li> 793 - @ <nobr> 794 - @ <ol> 795 - @ <p> 796 - @ <pre> 797 - @ <s> 798 - @ <samp> 799 - @ <small> 800 - @ <strike> 801 - @ <strong> 802 - @ <sub> 803 - @ <sup> 804 - @ <table> 805 - @ <td> 806 - @ <th> 807 - @ <tr> 808 - @ <tt> 809 - @ <u> 810 - @ <ul> 811 - @ <var>. 812 - @ In addition, there are two non-standard elements available: 757 + show_allowed_wiki_markup(); 758 + @ . There are two non-standard elements available: 813 759 @ <verbatim> and <nowiki>. 814 760 @ No other elements are allowed. All attributes are checked and 815 761 @ only a few benign attributes are allowed on each element. 816 762 @ In particular, any attributes that specify javascript or CSS 817 763 @ are elided.</p></li> 818 - @ <li><p><b>Special Markup.</b> 764 + @ <li><p><span class="wikiruleHead">Special Markup.</span> 819 765 @ The <nowiki> tag disables all wiki formatting rules 820 766 @ through the matching </nowiki> element. 821 767 @ The <verbatim> tag works like <pre> with the addition 822 768 @ that it also disables all wiki and HTML markup 823 - @ through the matching </verbatim>. 769 + @ through the matching </verbatim>.</p></li> 824 770 @ </ol> 825 771 style_footer(); 826 772 } 827 773 828 774 /* 829 775 ** Add a new wiki page to the respository. The page name is 830 776 ** given by the zPageName parameter. isNew must be true to create ................................................................................ 943 889 if( n==0 ){ 944 890 goto wiki_cmd_usage; 945 891 } 946 892 947 893 if( strncmp(g.argv[2],"export",n)==0 ){ 948 894 char const *zPageName; /* Name of the wiki page to export */ 949 895 char const *zFile; /* Name of the output file (0=stdout) */ 950 - int rid; /* Artifact ID of the wiki page */ 951 - int i; /* Loop counter */ 952 - char *zBody = 0; /* Wiki page content */ 953 - Manifest m; /* Parsed wiki page content */ 896 + int rid; /* Artifact ID of the wiki page */ 897 + int i; /* Loop counter */ 898 + char *zBody = 0; /* Wiki page content */ 899 + Manifest *pWiki = 0; /* Parsed wiki page content */ 900 + 954 901 if( (g.argc!=4) && (g.argc!=5) ){ 955 902 usage("export PAGENAME ?FILE?"); 956 903 } 957 904 zPageName = g.argv[3]; 958 905 rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" 959 906 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" 960 907 " ORDER BY x.mtime DESC LIMIT 1", 961 908 zPageName 962 909 ); 963 - if( rid ){ 964 - Blob content; 965 - content_get(rid, &content); 966 - manifest_parse(&m, &content); 967 - if( m.type==CFTYPE_WIKI ){ 968 - zBody = m.zWiki; 969 - } 910 + if( (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){ 911 + zBody = pWiki->zWiki; 970 912 } 971 913 if( zBody==0 ){ 972 914 fossil_fatal("wiki page [%s] not found",zPageName); 973 915 } 974 - for(i=strlen(zBody); i>0 && isspace(zBody[i-1]); i--){} 916 + for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){} 975 917 zFile = (g.argc==4) ? 0 : g.argv[4]; 976 918 if( zFile ){ 977 919 FILE * zF; 978 920 short doClose = 0; 979 921 if( (1 == strlen(zFile)) && ('-'==zFile[0]) ){ 980 922 zF = stdout; 981 923 }else{ ................................................................................ 984 926 } 985 927 if( ! zF ){ 986 928 fossil_fatal("wiki export could not open output file for writing."); 987 929 } 988 930 fprintf(zF,"%.*s\n", i, zBody); 989 931 if( doClose ) fclose(zF); 990 932 }else{ 991 - printf("%.*s\n", i, zBody); 933 + printf("%.*s\n", i, zBody); 992 934 } 935 + manifest_destroy(pWiki); 993 936 return; 994 937 }else 995 938 if( strncmp(g.argv[2],"commit",n)==0 996 939 || strncmp(g.argv[2],"create",n)==0 ){ 997 940 char *zPageName; 998 941 Blob content; 999 942 if( g.argc!=4 && g.argc!=5 ){
Changes to src/wikiformat.c.
148 148 ** Allowed markup. 149 149 ** 150 150 ** Except for MARKUP_INVALID, this must all be in alphabetical order 151 151 ** and in numerical sequence. The first markup type must be zero. 152 152 ** The value for MARKUP_XYZ must correspond to the <xyz> entry 153 153 ** in aAllowedMarkup[]. 154 154 */ 155 -#define MARKUP_INVALID 0 156 -#define MARKUP_A 1 157 -#define MARKUP_ADDRESS 2 158 -#define MARKUP_B 3 159 -#define MARKUP_BIG 4 160 -#define MARKUP_BLOCKQUOTE 5 161 -#define MARKUP_BR 6 162 -#define MARKUP_CENTER 7 163 -#define MARKUP_CITE 8 164 -#define MARKUP_CODE 9 165 -#define MARKUP_DD 10 166 -#define MARKUP_DFN 11 167 -#define MARKUP_DIV 12 168 -#define MARKUP_DL 13 169 -#define MARKUP_DT 14 170 -#define MARKUP_EM 15 171 -#define MARKUP_FONT 16 172 -#define MARKUP_H1 17 173 -#define MARKUP_H2 18 174 -#define MARKUP_H3 19 175 -#define MARKUP_H4 20 176 -#define MARKUP_H5 21 177 -#define MARKUP_H6 22 178 -#define MARKUP_HR 23 179 -#define MARKUP_I 24 180 -#define MARKUP_IMG 25 181 -#define MARKUP_KBD 26 182 -#define MARKUP_LI 27 183 -#define MARKUP_NOBR 28 184 -#define MARKUP_NOWIKI 29 185 -#define MARKUP_OL 30 186 -#define MARKUP_P 31 187 -#define MARKUP_PRE 32 188 -#define MARKUP_S 33 189 -#define MARKUP_SAMP 34 190 -#define MARKUP_SMALL 35 191 -#define MARKUP_STRIKE 36 192 -#define MARKUP_STRONG 37 193 -#define MARKUP_SUB 38 194 -#define MARKUP_SUP 39 195 -#define MARKUP_TABLE 40 196 -#define MARKUP_TD 41 197 -#define MARKUP_TH 42 198 -#define MARKUP_TR 43 199 -#define MARKUP_TT 44 200 -#define MARKUP_U 45 201 -#define MARKUP_UL 46 202 -#define MARKUP_VAR 47 203 -#define MARKUP_VERBATIM 48 155 +#define MARKUP_INVALID 0 156 +#define MARKUP_A 1 157 +#define MARKUP_ADDRESS 2 158 +#define MARKUP_B 3 159 +#define MARKUP_BIG 4 160 +#define MARKUP_BLOCKQUOTE 5 161 +#define MARKUP_BR 6 162 +#define MARKUP_CENTER 7 163 +#define MARKUP_CITE 8 164 +#define MARKUP_CODE 9 165 +#define MARKUP_COL 10 166 +#define MARKUP_COLGROUP 11 167 +#define MARKUP_DD 12 168 +#define MARKUP_DFN 13 169 +#define MARKUP_DIV 14 170 +#define MARKUP_DL 15 171 +#define MARKUP_DT 16 172 +#define MARKUP_EM 17 173 +#define MARKUP_FONT 18 174 +#define MARKUP_H1 19 175 +#define MARKUP_H2 20 176 +#define MARKUP_H3 21 177 +#define MARKUP_H4 22 178 +#define MARKUP_H5 23 179 +#define MARKUP_H6 24 180 +#define MARKUP_HR 25 181 +#define MARKUP_I 26 182 +#define MARKUP_IMG 27 183 +#define MARKUP_KBD 28 184 +#define MARKUP_LI 29 185 +#define MARKUP_NOBR 30 186 +#define MARKUP_NOWIKI 31 187 +#define MARKUP_OL 32 188 +#define MARKUP_P 33 189 +#define MARKUP_PRE 34 190 +#define MARKUP_S 35 191 +#define MARKUP_SAMP 36 192 +#define MARKUP_SMALL 37 193 +#define MARKUP_SPAN 38 194 +#define MARKUP_STRIKE 39 195 +#define MARKUP_STRONG 40 196 +#define MARKUP_SUB 41 197 +#define MARKUP_SUP 42 198 +#define MARKUP_TABLE 43 199 +#define MARKUP_TBODY 44 200 +#define MARKUP_TD 45 201 +#define MARKUP_TFOOT 46 202 +#define MARKUP_TH 47 203 +#define MARKUP_THEAD 48 204 +#define MARKUP_TR 49 205 +#define MARKUP_TT 50 206 +#define MARKUP_U 51 207 +#define MARKUP_UL 52 208 +#define MARKUP_VAR 53 209 +#define MARKUP_VERBATIM 54 204 210 205 211 /* 206 212 ** The various markup is divided into the following types: 207 213 */ 208 214 #define MUTYPE_SINGLE 0x0001 /* <img>, <br>, or <hr> */ 209 215 #define MUTYPE_BLOCK 0x0002 /* Forms a new paragraph. ex: <p>, <h2> */ 210 216 #define MUTYPE_FONT 0x0004 /* Font changes. ex: <b>, <font>, <sub> */ ................................................................................ 239 245 { "b", MARKUP_B, MUTYPE_FONT, 0 }, 240 246 { "big", MARKUP_BIG, MUTYPE_FONT, 0 }, 241 247 { "blockquote", MARKUP_BLOCKQUOTE, MUTYPE_BLOCK, 0 }, 242 248 { "br", MARKUP_BR, MUTYPE_SINGLE, AMSK_CLEAR }, 243 249 { "center", MARKUP_CENTER, MUTYPE_BLOCK, 0 }, 244 250 { "cite", MARKUP_CITE, MUTYPE_FONT, 0 }, 245 251 { "code", MARKUP_CODE, MUTYPE_FONT, 0 }, 252 + { "col", MARKUP_COL, MUTYPE_SINGLE, 253 + AMSK_ALIGN|AMSK_CLASS|AMSK_COLSPAN|AMSK_WIDTH }, 254 + { "colgroup", MARKUP_COLGROUP, MUTYPE_BLOCK, 255 + AMSK_ALIGN|AMSK_CLASS|AMSK_COLSPAN|AMSK_WIDTH}, 246 256 { "dd", MARKUP_DD, MUTYPE_LI, 0 }, 247 257 { "dfn", MARKUP_DFN, MUTYPE_FONT, 0 }, 248 258 { "div", MARKUP_DIV, MUTYPE_BLOCK, AMSK_ID|AMSK_CLASS }, 249 259 { "dl", MARKUP_DL, MUTYPE_LIST, AMSK_COMPACT }, 250 260 { "dt", MARKUP_DT, MUTYPE_LI, 0 }, 251 261 { "em", MARKUP_EM, MUTYPE_FONT, 0 }, 252 262 { "font", MARKUP_FONT, MUTYPE_FONT, ................................................................................ 271 281 { "ol", MARKUP_OL, MUTYPE_LIST, 272 282 AMSK_START|AMSK_TYPE|AMSK_COMPACT }, 273 283 { "p", MARKUP_P, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS }, 274 284 { "pre", MARKUP_PRE, MUTYPE_BLOCK, 0 }, 275 285 { "s", MARKUP_S, MUTYPE_FONT, 0 }, 276 286 { "samp", MARKUP_SAMP, MUTYPE_FONT, 0 }, 277 287 { "small", MARKUP_SMALL, MUTYPE_FONT, 0 }, 288 + { "span", MARKUP_SPAN, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS }, 278 289 { "strike", MARKUP_STRIKE, MUTYPE_FONT, 0 }, 279 290 { "strong", MARKUP_STRONG, MUTYPE_FONT, 0 }, 280 291 { "sub", MARKUP_SUB, MUTYPE_FONT, 0 }, 281 292 { "sup", MARKUP_SUP, MUTYPE_FONT, 0 }, 282 293 { "table", MARKUP_TABLE, MUTYPE_TABLE, 283 294 AMSK_ALIGN|AMSK_BGCOLOR|AMSK_BORDER|AMSK_CELLPADDING| 284 295 AMSK_CELLSPACING|AMSK_HSPACE|AMSK_VSPACE|AMSK_CLASS }, 296 + { "tbody", MARKUP_TBODY, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS }, 285 297 { "td", MARKUP_TD, MUTYPE_TD, 286 298 AMSK_ALIGN|AMSK_BGCOLOR|AMSK_COLSPAN| 287 299 AMSK_ROWSPAN|AMSK_VALIGN|AMSK_CLASS }, 300 + { "tfoot", MARKUP_TFOOT, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS }, 288 301 { "th", MARKUP_TH, MUTYPE_TD, 289 302 AMSK_ALIGN|AMSK_BGCOLOR|AMSK_COLSPAN| 290 303 AMSK_ROWSPAN|AMSK_VALIGN|AMSK_CLASS }, 304 + { "thead", MARKUP_THEAD, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS }, 291 305 { "tr", MARKUP_TR, MUTYPE_TR, 292 306 AMSK_ALIGN|AMSK_BGCOLOR||AMSK_VALIGN|AMSK_CLASS }, 293 307 { "tt", MARKUP_TT, MUTYPE_FONT, 0 }, 294 308 { "u", MARKUP_U, MUTYPE_FONT, 0 }, 295 309 { "ul", MARKUP_UL, MUTYPE_LIST, 296 310 AMSK_TYPE|AMSK_COMPACT }, 297 311 { "var", MARKUP_VAR, MUTYPE_FONT, 0 }, 298 312 { "verbatim", MARKUP_VERBATIM, MUTYPE_SPECIAL, AMSK_ID|AMSK_TYPE }, 299 313 }; 314 + 315 +void show_allowed_wiki_markup( void ){ 316 + int i; /* loop over allowedAttr */ 317 + 318 + for( i=1 ; i<=sizeof(aMarkup)/sizeof(aMarkup[0]) - 1 ; i++ ){ 319 + @ <%s(aMarkup[i].zName)> 320 + } 321 +} 300 322 301 323 /* 302 324 ** Use binary search to locate a tag in the aMarkup[] table. 303 325 */ 304 326 static int findTag(const char *z){ 305 327 int i, c, first, last; 306 328 first = 1; ................................................................................ 319 341 } 320 342 return MARKUP_INVALID; 321 343 } 322 344 323 345 /* 324 346 ** Token types 325 347 */ 326 -#define TOKEN_MARKUP 1 /* <...> */ 327 -#define TOKEN_CHARACTER 2 /* "&" or "<" not part of markup */ 328 -#define TOKEN_LINK 3 /* [...] */ 329 -#define TOKEN_PARAGRAPH 4 /* blank lines */ 330 -#define TOKEN_NEWLINE 5 /* A single "\n" */ 331 -#define TOKEN_BUL_LI 6 /* " * " */ 332 -#define TOKEN_NUM_LI 7 /* " # " */ 333 -#define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */ 334 -#define TOKEN_INDENT 9 /* " " */ 335 -#define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */ 336 -#define TOKEN_TEXT 11 /* None of the above */ 348 +#define TOKEN_MARKUP 1 /* <...> */ 349 +#define TOKEN_CHARACTER 2 /* "&" or "<" not part of markup */ 350 +#define TOKEN_LINK 3 /* [...] */ 351 +#define TOKEN_PARAGRAPH 4 /* blank lines */ 352 +#define TOKEN_NEWLINE 5 /* A single "\n" */ 353 +#define TOKEN_BUL_LI 6 /* " * " */ 354 +#define TOKEN_NUM_LI 7 /* " # " */ 355 +#define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */ 356 +#define TOKEN_INDENT 9 /* " " */ 357 +#define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */ 358 +#define TOKEN_TEXT 11 /* None of the above */ 337 359 338 360 /* 339 361 ** State flags 340 362 */ 341 363 #define AT_NEWLINE 0x001 /* At start of a line */ 342 364 #define AT_PARAGRAPH 0x002 /* At start of a paragraph */ 343 365 #define ALLOW_WIKI 0x004 /* Allow wiki markup */ ................................................................................ 377 399 */ 378 400 static int wikiUsesHtml(void){ 379 401 static int r = -1; 380 402 if( r<0 ) r = db_get_boolean("wiki-use-html", 0); 381 403 return r; 382 404 } 383 405 384 - 385 406 /* 386 407 ** z points to a "<" character. Check to see if this is the start of 387 408 ** a valid markup. If it is, return the total number of characters in 388 409 ** the markup including the initial "<" and the terminating ">". If 389 410 ** it is not well-formed markup, return 0. 390 411 */ 391 412 static int markupLength(const char *z){ 392 413 int n = 1; 393 414 int inparen = 0; 394 415 int c; 395 416 if( z[n]=='/' ){ n++; } 396 - if( !isalpha(z[n]) ) return 0; 397 - while( isalnum(z[n]) ){ n++; } 398 - if( (c = z[n])!='>' && !isspace(c) ) return 0; 417 + if( !fossil_isalpha(z[n]) ) return 0; 418 + while( fossil_isalnum(z[n]) ){ n++; } 419 + c = z[n]; 420 + if( c=='/' && z[n+1]=='>' ){ return n+2; } 421 + if( c!='>' && !fossil_isspace(c) ) return 0; 399 422 while( (c = z[n])!=0 && (c!='>' || inparen) ){ 400 423 if( c==inparen ){ 401 424 inparen = 0; 402 - }else if( c=='"' || c=='\'' ){ 425 + }else if( inparen==0 && (c=='"' || c=='\'') ){ 403 426 inparen = c; 404 427 } 405 428 n++; 406 429 } 407 430 if( z[n]!='>' ) return 0; 408 431 return n+1; 409 432 } ................................................................................ 412 435 ** z points to a "\n" character. Check to see if this newline is 413 436 ** followed by one or more blank lines. If it is, return the number 414 437 ** of characters through the closing "\n". If not, return 0. 415 438 */ 416 439 static int paragraphBreakLength(const char *z){ 417 440 int i, n; 418 441 int nNewline = 1; 419 - for(i=1, n=0; isspace(z[i]); i++){ 442 + for(i=1, n=0; fossil_isspace(z[i]); i++){ 420 443 if( z[i]=='\n' ){ 421 444 nNewline++; 422 445 n = i; 423 446 } 424 447 } 425 448 if( nNewline>=2 ){ 426 449 return n+1; ................................................................................ 457 480 /* 458 481 ** Return true if z[] begins with an HTML character element. 459 482 */ 460 483 static int isElement(const char *z){ 461 484 int i; 462 485 assert( z[0]=='&' ); 463 486 if( z[1]=='#' ){ 464 - for(i=2; isdigit(z[i]); i++){} 487 + for(i=2; fossil_isdigit(z[i]); i++){} 465 488 return i>2 && z[i]==';'; 466 489 }else{ 467 - for(i=1; isalpha(z[i]); i++){} 490 + for(i=1; fossil_isalpha(z[i]); i++){} 468 491 return i>1 && z[i]==';'; 469 492 } 470 493 } 471 494 472 495 /* 473 496 ** Check to see if the z[] string is the beginning of a wiki list item. 474 497 ** If it is, return the length of the bullet text. Otherwise return 0. ................................................................................ 486 509 n++; 487 510 i = 0; 488 511 while( z[n]==' ' || z[n]=='\t' ){ 489 512 if( z[n]=='\t' ) i++; 490 513 i++; 491 514 n++; 492 515 } 493 - if( i<2 || isspace(z[n]) ) return 0; 516 + if( i<2 || fossil_isspace(z[n]) ) return 0; 494 517 return n; 495 518 } 496 519 497 520 /* 498 521 ** Check to see if the z[] string is the beginning of a enumeration value. 499 522 ** If it is, return the length of the bullet text. Otherwise return 0. 500 523 ** ................................................................................ 511 534 i = 0; 512 535 while( z[n]==' ' || z[n]=='\t' ){ 513 536 if( z[n]=='\t' ) i++; 514 537 i++; 515 538 n++; 516 539 } 517 540 if( i<2 ) return 0; 518 - for(i=0; isdigit(z[n]); i++, n++){} 541 + for(i=0; fossil_isdigit(z[n]); i++, n++){} 519 542 if( i==0 ) return 0; 520 543 if( z[n]=='.' ){ 521 544 n++; 522 545 } 523 546 i = 0; 524 547 while( z[n]==' ' || z[n]=='\t' ){ 525 548 if( z[n]=='\t' ) i++; 526 549 i++; 527 550 n++; 528 551 } 529 - if( i<2 || isspace(z[n]) ) return 0; 552 + if( i<2 || fossil_isspace(z[n]) ) return 0; 530 553 return n; 531 554 } 532 555 533 556 /* 534 557 ** Check to see if the z[] string is the beginning of an indented 535 558 ** paragraph. If it is, return the length of the indent. Otherwise 536 559 ** return 0. ................................................................................ 540 563 n = 0; 541 564 i = 0; 542 565 while( z[n]==' ' || z[n]=='\t' ){ 543 566 if( z[n]=='\t' ) i++; 544 567 i++; 545 568 n++; 546 569 } 547 - if( i<2 || isspace(z[n]) ) return 0; 570 + if( i<2 || fossil_isspace(z[n]) ) return 0; 548 571 return n; 549 572 } 550 573 551 574 /* 552 575 ** Check to see if the z[] string is a wiki hyperlink. If it is, 553 576 ** return the length of the hyperlink. Otherwise return 0. 554 577 */ ................................................................................ 587 610 } 588 611 if( (p->state & ALLOW_WIKI)!=0 ){ 589 612 if( z[0]=='\n' ){ 590 613 n = paragraphBreakLength(z); 591 614 if( n>0 ){ 592 615 *pTokenType = TOKEN_PARAGRAPH; 593 616 return n; 594 - }else if( isspace(z[1]) ){ 617 + }else if( fossil_isspace(z[1]) ){ 595 618 *pTokenType = TOKEN_NEWLINE; 596 619 return 1; 597 620 } 598 621 } 599 - if( (p->state & AT_NEWLINE)!=0 && isspace(z[0]) ){ 622 + if( (p->state & AT_NEWLINE)!=0 && fossil_isspace(z[0]) ){ 600 623 n = listItemLength(z, '*'); 601 624 if( n>0 ){ 602 625 *pTokenType = TOKEN_BUL_LI; 603 626 return n; 604 627 } 605 628 n = listItemLength(z, '#'); 606 629 if( n>0 ){ ................................................................................ 609 632 } 610 633 n = enumLength(z); 611 634 if( n>0 ){ 612 635 *pTokenType = TOKEN_ENUM; 613 636 return n; 614 637 } 615 638 } 616 - if( (p->state & AT_PARAGRAPH)!=0 && isspace(z[0]) ){ 639 + if( (p->state & AT_PARAGRAPH)!=0 && fossil_isspace(z[0]) ){ 617 640 n = indentLength(z); 618 641 if( n>0 ){ 619 642 *pTokenType = TOKEN_INDENT; 620 643 return n; 621 644 } 622 645 } 623 646 if( z[0]=='[' && (n = linkLength(z))>0 ){ ................................................................................ 680 703 p->endTag = 1; 681 704 i = 2; 682 705 }else{ 683 706 p->endTag = 0; 684 707 i = 1; 685 708 } 686 709 j = 0; 687 - while( isalnum(z[i]) ){ 688 - if( j<sizeof(zTag)-1 ) zTag[j++] = tolower(z[i]); 710 + while( fossil_isalnum(z[i]) ){ 711 + if( j<sizeof(zTag)-1 ) zTag[j++] = fossil_tolower(z[i]); 689 712 i++; 690 713 } 691 714 zTag[j] = 0; 692 715 p->iCode = findTag(zTag); 693 716 p->iType = aMarkup[p->iCode].iType; 694 717 p->nAttr = 0; 695 - while( isspace(z[i]) ){ i++; } 696 - while( p->nAttr<8 && isalpha(z[i]) ){ 718 + while( fossil_isspace(z[i]) ){ i++; } 719 + while( p->nAttr<8 && fossil_isalpha(z[i]) ){ 697 720 int attrOk; /* True to preserver attribute. False to ignore it */ 698 721 j = 0; 699 - while( isalnum(z[i]) ){ 700 - if( j<sizeof(zTag)-1 ) zTag[j++] = tolower(z[i]); 722 + while( fossil_isalnum(z[i]) ){ 723 + if( j<sizeof(zTag)-1 ) zTag[j++] = fossil_tolower(z[i]); 701 724 i++; 702 725 } 703 726 zTag[j] = 0; 704 727 p->aAttr[p->nAttr].iACode = iACode = findAttr(zTag); 705 728 attrOk = iACode!=0 && (seen & aAttribute[iACode].iMask)==0; 706 - while( isspace(z[i]) ){ z++; } 729 + while( fossil_isspace(z[i]) ){ z++; } 707 730 if( z[i]!='=' ){ 708 731 p->aAttr[p->nAttr].zValue = 0; 709 732 p->aAttr[p->nAttr].cTerm = 0; 710 733 c = 0; 711 734 }else{ 712 735 i++; 713 - while( isspace(z[i]) ){ z++; } 736 + while( fossil_isspace(z[i]) ){ z++; } 714 737 if( z[i]=='"' ){ 715 738 i++; 716 739 zValue = &z[i]; 717 740 while( z[i] && z[i]!='"' ){ i++; } 718 741 }else if( z[i]=='\'' ){ 719 742 i++; 720 743 zValue = &z[i]; 721 744 while( z[i] && z[i]!='\'' ){ i++; } 722 745 }else{ 723 746 zValue = &z[i]; 724 - while( !isspace(z[i]) && z[i]!='>' ){ z++; } 747 + while( !fossil_isspace(z[i]) && z[i]!='>' ){ z++; } 725 748 } 726 749 if( attrOk ){ 727 750 p->aAttr[p->nAttr].zValue = zValue; 728 751 p->aAttr[p->nAttr].cTerm = c = z[i]; 729 752 z[i] = 0; 730 753 } 731 754 i++; 732 755 } 733 756 if( attrOk ){ 734 757 seen |= aAttribute[iACode].iMask; 735 758 p->nAttr++; 736 759 } 737 - while( isspace(z[i]) ){ i++; } 760 + while( fossil_isspace(z[i]) ){ i++; } 738 761 if( z[i]=='>' || (z[i]=='/' && z[i+1]=='>') ) break; 739 762 } 740 763 } 741 764 742 765 /* 743 766 ** Render markup on the given blob. 744 767 */ ................................................................................ 754 777 const char *zVal = p->aAttr[i].zValue; 755 778 if( p->aAttr[i].iACode==ATTR_SRC && zVal[0]=='/' ){ 756 779 blob_appendf(pOut, "=\"%s%s\"", g.zBaseURL, zVal); 757 780 }else{ 758 781 blob_appendf(pOut, "=\"%s\"", zVal); 759 782 } 760 783 } 784 + } 785 + if (p->iType & MUTYPE_SINGLE){ 786 + blob_append(pOut, " /", 2); 761 787 } 762 788 blob_append(pOut, ">", 1); 763 789 } 764 790 } 765 791 766 792 /* 767 793 ** When the markup was parsed, some "\000" may have been inserted. ................................................................................ 810 836 /* 811 837 ** Push a new markup value onto the stack. Enlarge the stack 812 838 ** if necessary. 813 839 */ 814 840 static void pushStackWithId(Renderer *p, int elem, const char *zId, int w){ 815 841 if( p->nStack>=p->nAlloc ){ 816 842 p->nAlloc = p->nAlloc*2 + 100; 817 - p->aStack = realloc(p->aStack, p->nAlloc*sizeof(p->aStack[0])); 818 - if( p->aStack==0 ){ 819 - fossil_panic("out of memory"); 820 - } 843 + p->aStack = fossil_realloc(p->aStack, p->nAlloc*sizeof(p->aStack[0])); 821 844 } 822 845 p->aStack[p->nStack].iCode = elem; 823 846 p->aStack[p->nStack].zId = zId; 824 847 p->aStack[p->nStack].allowWiki = w; 825 848 p->nStack++; 826 849 } 827 850 static void pushStack(Renderer *p, int elem){ ................................................................................ 883 906 return p->aStack[i-1].iCode; 884 907 } 885 908 886 909 /* 887 910 ** Begin a new paragraph if that something that is needed. 888 911 */ 889 912 static void startAutoParagraph(Renderer *p){ 890 - if( p->wantAutoParagraph==0 || p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return; 913 + if( p->wantAutoParagraph==0 ) return; 914 + if( p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return; 891 915 blob_appendf(p->pOut, "<p>", -1); 892 916 pushStack(p, MARKUP_P); 893 917 p->wantAutoParagraph = 0; 894 918 p->inAutoParagraph = 1; 895 919 } 896 920 897 921 /* ................................................................................ 1017 1041 int isClosed = 0; 1018 1042 if( is_ticket(zTarget, &isClosed) ){ 1019 1043 /* Special display processing for tickets. Display the hyperlink 1020 1044 ** as crossed out if the ticket is closed. 1021 1045 */ 1022 1046 if( isClosed ){ 1023 1047 if( g.okHistory ){ 1024 - blob_appendf(p->pOut,"<a href=\"%s/info/%s\"><s>", 1025 - g.zBaseURL, zTarget 1048 + blob_appendf(p->pOut, 1049 + "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">", 1050 + g.zBaseURL, zTarget 1026 1051 ); 1027 - zTerm = "</s></a>"; 1052 + zTerm = "</span></a>"; 1028 1053 }else{ 1029 - blob_appendf(p->pOut,"<s>"); 1030 - zTerm = "</s>"; 1054 + blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">"); 1055 + zTerm = "</span>"; 1031 1056 } 1032 1057 }else{ 1033 1058 if( g.okHistory ){ 1034 1059 blob_appendf(p->pOut,"<a href=\"%s/info/%s\">", 1035 1060 g.zBaseURL, zTarget 1036 1061 ); 1037 1062 }else{ 1038 1063 zTerm = ""; 1039 1064 } 1040 1065 } 1041 1066 }else if( g.okHistory ){ 1042 1067 blob_appendf(p->pOut, "<a href=\"%s/info/%s\">", g.zBaseURL, zTarget); 1043 1068 } 1044 - }else if( strlen(zTarget)>=10 && isdigit(zTarget[0]) && zTarget[4]=='-' 1069 + }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-' 1045 1070 && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){ 1046 1071 blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zBaseURL, zTarget); 1047 1072 }else if( strncmp(zTarget, "wiki:", 5)==0 1048 1073 && wiki_name_is_wellformed((const unsigned char*)zTarget) ){ 1049 1074 zTarget += 5; 1050 1075 blob_appendf(p->pOut, "<a href=\"%s/wiki?name=%T\">", g.zBaseURL, zTarget); 1051 1076 }else if( wiki_name_is_wellformed((const unsigned char *)zTarget) ){ ................................................................................ 1131 1156 if( inlineOnly ){ 1132 1157 blob_append(p->pOut, " • ", -1); 1133 1158 }else{ 1134 1159 if( p->wikiList!=MARKUP_UL ){ 1135 1160 if( p->wikiList ){ 1136 1161 popStackToTag(p, p->wikiList); 1137 1162 } 1163 + endAutoParagraph(p); 1138 1164 pushStack(p, MARKUP_UL); 1139 1165 blob_append(p->pOut, "<ul>", 4); 1140 1166 p->wikiList = MARKUP_UL; 1141 1167 } 1142 1168 popStackToTag(p, MARKUP_LI); 1143 1169 startAutoParagraph(p); 1144 1170 pushStack(p, MARKUP_LI); ................................................................................ 1150 1176 if( inlineOnly ){ 1151 1177 blob_append(p->pOut, " # ", -1); 1152 1178 }else{ 1153 1179 if( p->wikiList!=MARKUP_OL ){ 1154 1180 if( p->wikiList ){ 1155 1181 popStackToTag(p, p->wikiList); 1156 1182 } 1183 + endAutoParagraph(p); 1157 1184 pushStack(p, MARKUP_OL); 1158 1185 blob_append(p->pOut, "<ol>", 4); 1159 1186 p->wikiList = MARKUP_OL; 1160 1187 } 1161 1188 popStackToTag(p, MARKUP_LI); 1162 1189 startAutoParagraph(p); 1163 1190 pushStack(p, MARKUP_LI); ................................................................................ 1169 1196 if( inlineOnly ){ 1170 1197 blob_appendf(p->pOut, " (%d) ", atoi(z)); 1171 1198 }else{ 1172 1199 if( p->wikiList!=MARKUP_OL ){ 1173 1200 if( p->wikiList ){ 1174 1201 popStackToTag(p, p->wikiList); 1175 1202 } 1203 + endAutoParagraph(p); 1176 1204 pushStack(p, MARKUP_OL); 1177 1205 blob_append(p->pOut, "<ol>", 4); 1178 1206 p->wikiList = MARKUP_OL; 1179 1207 } 1180 1208 popStackToTag(p, MARKUP_LI); 1181 1209 startAutoParagraph(p); 1182 1210 pushStack(p, MARKUP_LI); ................................................................................ 1212 1240 1213 1241 startAutoParagraph(p); 1214 1242 zTarget = &z[1]; 1215 1243 for(i=1; z[i] && z[i]!=']'; i++){ 1216 1244 if( z[i]=='|' && zDisplay==0 ){ 1217 1245 zDisplay = &z[i+1]; 1218 1246 z[i] = 0; 1219 - for(j=i-1; j>0 && isspace(z[j]); j--){ z[j] = 0; } 1247 + for(j=i-1; j>0 && fossil_isspace(z[j]); j--){ z[j] = 0; } 1220 1248 } 1221 1249 } 1222 1250 z[i] = 0; 1223 1251 if( zDisplay==0 ){ 1224 1252 zDisplay = zTarget; 1225 1253 }else{ 1226 - while( isspace(*zDisplay) ) zDisplay++; 1254 + while( fossil_isspace(*zDisplay) ) zDisplay++; 1227 1255 } 1228 1256 openHyperlink(p, zTarget, zClose, sizeof(zClose)); 1229 1257 savedState = p->state; 1230 1258 p->state &= ~ALLOW_WIKI; 1231 1259 p->state |= FONT_MARKUP_ONLY; 1232 1260 wiki_render(p, zDisplay); 1233 1261 p->state = savedState; 1234 1262 blob_append(p->pOut, zClose, -1); 1235 1263 break; 1236 1264 } 1237 1265 case TOKEN_TEXT: { 1238 - startAutoParagraph(p); 1266 + int i; 1267 + for(i=0; i<n && fossil_isspace(z[i]); i++){} 1268 + if( i<n ) startAutoParagraph(p); 1239 1269 blob_append(p->pOut, z, n); 1240 1270 break; 1241 1271 } 1242 1272 case TOKEN_RAW: { 1243 1273 blob_append(p->pOut, z, n); 1244 1274 break; 1245 1275 } ................................................................................ 1345 1375 p->zVerbatimId = markup.aAttr[0].zValue; 1346 1376 }else if( markup.aAttr[vAttrIdx].iACode == ATTR_TYPE ){ 1347 1377 blob_appendf(p->pOut, "<pre name='code' class='%s'>", 1348 1378 markup.aAttr[vAttrIdx].zValue); 1349 1379 vAttrDidAppend=1; 1350 1380 } 1351 1381 } 1352 - if( !vAttrDidAppend ) 1382 + if( !vAttrDidAppend ) { 1383 + endAutoParagraph(p); 1353 1384 blob_append(p->pOut, "<pre class='verbatim'>",-1); 1385 + } 1354 1386 p->wantAutoParagraph = 0; 1355 1387 }else 1356 1388 if( markup.iType==MUTYPE_LI ){ 1357 1389 if( backupToType(p, MUTYPE_LIST)==0 ){ 1390 + endAutoParagraph(p); 1358 1391 pushStack(p, MARKUP_UL); 1359 1392 blob_append(p->pOut, "<ul>", 4); 1360 1393 } 1361 1394 pushStack(p, MARKUP_LI); 1362 1395 renderMarkup(p->pOut, &markup); 1363 1396 }else 1364 1397 if( markup.iType==MUTYPE_TR ){ ................................................................................ 1382 1415 startAutoParagraph(p); 1383 1416 renderMarkup(p->pOut, &markup); 1384 1417 pushStack(p, markup.iCode); 1385 1418 }else 1386 1419 { 1387 1420 if( markup.iType==MUTYPE_FONT ){ 1388 1421 startAutoParagraph(p); 1389 - }else if( markup.iType==MUTYPE_BLOCK ){ 1422 + }else if( markup.iType==MUTYPE_BLOCK || markup.iType==MUTYPE_LIST ){ 1390 1423 p->wantAutoParagraph = 0; 1424 + } 1425 + if( markup.iCode==MARKUP_HR 1426 + || markup.iCode==MARKUP_H1 1427 + || markup.iCode==MARKUP_H2 1428 + || markup.iCode==MARKUP_H3 1429 + || markup.iCode==MARKUP_H4 1430 + || markup.iCode==MARKUP_H5 1431 + || markup.iCode==MARKUP_P 1432 + ){ 1433 + endAutoParagraph(p); 1391 1434 } 1392 1435 if( (markup.iType & MUTYPE_STACK )!=0 ){ 1393 1436 pushStack(p, markup.iCode); 1394 1437 } 1395 1438 renderMarkup(p->pOut, &markup); 1396 1439 } 1397 1440 break; ................................................................................ 1473 1516 ** title. 1474 1517 */ 1475 1518 int wiki_find_title(Blob *pIn, Blob *pTitle, Blob *pTail){ 1476 1519 char *z; 1477 1520 int i; 1478 1521 int iStart; 1479 1522 z = skip_bom(blob_str(pIn)); 1480 - for(i=0; isspace(z[i]); i++){} 1523 + for(i=0; fossil_isspace(z[i]); i++){} 1481 1524 if( z[i]!='<' ) return 0; 1482 1525 i++; 1483 1526 if( strncmp(&z[i],"title>", 6)!=0 ) return 0; 1484 1527 iStart = i+6; 1485 1528 for(i=iStart; z[i] && (z[i]!='<' || strncmp(&z[i],"</title>",8)!=0); i++){} 1486 1529 if( z[i]!='<' ) return 0; 1487 1530 blob_init(pTitle, &z[iStart], i-iStart);
Changes to src/winhttp.c.
14 14 ** http://www.hwaci.com/drh/ 15 15 ** 16 16 ******************************************************************************* 17 17 ** 18 18 ** This file implements a very simple (and low-performance) HTTP server 19 19 ** for windows. 20 20 */ 21 -#ifdef __MINGW32__ /* This code is for win32 only */ 22 21 #include "config.h" 22 +#ifdef _WIN32 23 +/* This code is for win32 only */ 23 24 #include "winhttp.h" 24 25 #include <windows.h> 25 26 26 27 /* 27 28 ** The HttpRequest structure holds information about each incoming 28 29 ** HTTP request. 29 30 */ ................................................................................ 103 104 break; 104 105 } 105 106 wanted -= got; 106 107 } 107 108 fclose(out); 108 109 out = 0; 109 110 sprintf(zCmd, "\"%s\" http \"%s\" %s %s %s%s", 110 - g.argv[0], g.zRepositoryName, zRequestFName, zReplyFName, 111 + _pgmptr, g.zRepositoryName, zRequestFName, zReplyFName, 111 112 inet_ntoa(p->addr.sin_addr), p->zNotFound 112 113 ); 113 - portable_system(zCmd); 114 + fossil_system(zCmd); 114 115 in = fopen(zReplyFName, "rb"); 115 116 if( in ){ 116 117 while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){ 117 118 send(p->s, zHdr, got, 0); 118 119 } 119 120 } 120 121 ................................................................................ 131 132 ** Start a listening socket and process incoming HTTP requests on 132 133 ** that socket. 133 134 */ 134 135 void win32_http_server( 135 136 int mnPort, int mxPort, /* Range of allowed TCP port numbers */ 136 137 const char *zBrowser, /* Command to launch browser. (Or NULL) */ 137 138 const char *zStopper, /* Stop server when this file is exists (Or NULL) */ 138 - const char *zNotFound /* The --notfound option, or NULL */ 139 + const char *zNotFound, /* The --notfound option, or NULL */ 140 + int flags /* One or more HTTP_SERVER_ flags */ 139 141 ){ 140 142 WSADATA wd; 141 143 SOCKET s = INVALID_SOCKET; 142 144 SOCKADDR_IN addr; 143 145 int idCnt = 0; 144 146 int iPort = mnPort; 145 147 char *zNotFoundOption; ................................................................................ 156 158 while( iPort<=mxPort ){ 157 159 s = socket(AF_INET, SOCK_STREAM, 0); 158 160 if( s==INVALID_SOCKET ){ 159 161 fossil_fatal("unable to create a socket"); 160 162 } 161 163 addr.sin_family = AF_INET; 162 164 addr.sin_port = htons(iPort); 163 - addr.sin_addr.s_addr = htonl(INADDR_ANY); 165 + if( flags & HTTP_SERVER_LOCALHOST ){ 166 + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 167 + }else{ 168 + addr.sin_addr.s_addr = htonl(INADDR_ANY); 169 + } 164 170 if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ 165 171 closesocket(s); 166 172 iPort++; 167 173 continue; 168 174 } 169 175 if( listen(s, SOMAXCONN)==SOCKET_ERROR ){ 170 176 closesocket(s); ................................................................................ 182 188 } 183 189 } 184 190 zTempPrefix = mprintf("fossil_server_P%d_", iPort); 185 191 printf("Listening for HTTP requests on TCP port %d\n", iPort); 186 192 if( zBrowser ){ 187 193 zBrowser = mprintf(zBrowser, iPort); 188 194 printf("Launch webbrowser: %s\n", zBrowser); 189 - portable_system(zBrowser); 195 + fossil_system(zBrowser); 190 196 } 191 197 printf("Type Ctrl-C to stop the HTTP server\n"); 192 198 for(;;){ 193 199 SOCKET client; 194 200 SOCKADDR_IN client_addr; 195 201 HttpRequest *p; 196 202 int len = sizeof(client_addr); ................................................................................ 199 205 if( zStopper && file_size(zStopper)>=0 ){ 200 206 break; 201 207 } 202 208 if( client==INVALID_SOCKET ){ 203 209 closesocket(s); 204 210 fossil_fatal("error from accept()"); 205 211 } 206 - p = malloc( sizeof(*p) ); 207 - if( p==0 ){ 208 - fossil_fatal("out of memory"); 209 - } 212 + p = fossil_malloc( sizeof(*p) ); 210 213 p->id = ++idCnt; 211 214 p->s = client; 212 215 p->addr = client_addr; 213 216 p->zNotFound = zNotFoundOption; 214 217 _beginthread(win32_process_one_http_request, 0, (void*)p); 215 218 } 216 219 closesocket(s); 217 220 WSACleanup(); 218 221 } 219 222 220 -#endif /* __MINGW32__ -- This code is for win32 only */ 223 +#endif /* _WIN32 -- This code is for win32 only */
Changes to src/xfer.c.
70 70 } 71 71 72 72 /* 73 73 ** Remember that the other side of the connection already has a copy 74 74 ** of the file rid. 75 75 */ 76 76 static void remote_has(int rid){ 77 - if( rid ) db_multi_exec("INSERT OR IGNORE INTO onremote VALUES(%d)", rid); 77 + if( rid ){ 78 + static Stmt q; 79 + db_static_prepare(&q, "INSERT OR IGNORE INTO onremote VALUES(:r)"); 80 + db_bind_int(&q, ":r", rid); 81 + db_step(&q); 82 + db_reset(&q); 83 + } 78 84 } 79 85 80 86 /* 81 87 ** The aToken[0..nToken-1] blob array is a parse of a "file" line 82 88 ** message. This routine finishes parsing that message and does 83 89 ** a record insert of the file. 84 90 ** ................................................................................ 93 99 ** 94 100 ** If any error occurs, write a message into pErr which has already 95 101 ** be initialized to an empty string. 96 102 ** 97 103 ** Any artifact successfully received by this routine is considered to 98 104 ** be public and is therefore removed from the "private" table. 99 105 */ 100 -static void xfer_accept_file(Xfer *pXfer){ 106 +static void xfer_accept_file(Xfer *pXfer, int cloneFlag){ 101 107 int n; 102 108 int rid; 103 109 int srcid = 0; 104 110 Blob content, hash; 105 111 106 112 if( pXfer->nToken<3 107 113 || pXfer->nToken>4 ................................................................................ 112 118 ){ 113 119 blob_appendf(&pXfer->err, "malformed file line"); 114 120 return; 115 121 } 116 122 blob_zero(&content); 117 123 blob_zero(&hash); 118 124 blob_extract(pXfer->pIn, n, &content); 119 - if( uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ 125 + if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ 120 126 /* Ignore files that have been shunned */ 121 127 return; 128 + } 129 + if( cloneFlag ){ 130 + if( pXfer->nToken==4 ){ 131 + srcid = rid_from_uuid(&pXfer->aToken[2], 1); 132 + pXfer->nDeltaRcvd++; 133 + }else{ 134 + srcid = 0; 135 + pXfer->nFileRcvd++; 136 + } 137 + rid = content_put(&content, blob_str(&pXfer->aToken[1]), srcid); 138 + remote_has(rid); 139 + blob_reset(&content); 140 + return; 122 141 } 123 142 if( pXfer->nToken==4 ){ 124 - Blob src; 143 + Blob src, next; 125 144 srcid = rid_from_uuid(&pXfer->aToken[2], 1); 126 145 if( content_get(srcid, &src)==0 ){ 127 146 rid = content_put(&content, blob_str(&pXfer->aToken[1]), srcid); 128 147 pXfer->nDanglingFile++; 129 148 db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); 130 149 content_make_public(rid); 131 150 return; 132 151 } 133 152 pXfer->nDeltaRcvd++; 134 - blob_delta_apply(&src, &content, &content); 153 + blob_delta_apply(&src, &content, &next); 135 154 blob_reset(&src); 155 + blob_reset(&content); 156 + content = next; 136 157 }else{ 137 158 pXfer->nFileRcvd++; 138 159 } 139 160 sha1sum_blob(&content, &hash); 140 161 if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){ 141 162 blob_appendf(&pXfer->err, "content does not match sha1 hash"); 142 163 } ................................................................................ 463 484 464 485 /* 465 486 ** Check to see if the number of unclustered entries is greater than 466 487 ** 100 and if it is, form a new cluster. Unclustered phantoms do not 467 488 ** count toward the 100 total. And phantoms are never added to a new 468 489 ** cluster. 469 490 */ 470 -static void create_cluster(void){ 491 +void create_cluster(void){ 471 492 Blob cluster, cksum; 472 493 Stmt q; 473 494 int nUncl; 495 + int nRow = 0; 474 496 475 497 /* We should not ever get any private artifacts in the unclustered table. 476 498 ** But if we do (because of a bug) now is a good time to delete them. */ 477 499 db_multi_exec( 478 500 "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)" 479 501 ); 480 502 481 - nUncl = db_int(0, "SELECT count(*) FROM unclustered" 503 + nUncl = db_int(0, "SELECT count(*) FROM unclustered /*scan*/" 482 504 " WHERE NOT EXISTS(SELECT 1 FROM phantom" 483 505 " WHERE rid=unclustered.rid)"); 484 - if( nUncl<100 ){ 485 - return; 486 - } 487 - blob_zero(&cluster); 488 - db_prepare(&q, "SELECT uuid FROM unclustered, blob" 489 - " WHERE NOT EXISTS(SELECT 1 FROM phantom" 490 - " WHERE rid=unclustered.rid)" 491 - " AND unclustered.rid=blob.rid" 492 - " AND NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" 493 - " ORDER BY 1"); 494 - while( db_step(&q)==SQLITE_ROW ){ 495 - blob_appendf(&cluster, "M %s\n", db_column_text(&q, 0)); 496 - } 497 - db_finalize(&q); 498 - md5sum_blob(&cluster, &cksum); 499 - blob_appendf(&cluster, "Z %b\n", &cksum); 500 - blob_reset(&cksum); 501 - db_multi_exec("DELETE FROM unclustered"); 502 - content_put(&cluster, 0, 0); 503 - blob_reset(&cluster); 506 + if( nUncl>=100 ){ 507 + blob_zero(&cluster); 508 + db_prepare(&q, "SELECT uuid FROM unclustered, blob" 509 + " WHERE NOT EXISTS(SELECT 1 FROM phantom" 510 + " WHERE rid=unclustered.rid)" 511 + " AND unclustered.rid=blob.rid" 512 + " AND NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" 513 + " ORDER BY 1"); 514 + while( db_step(&q)==SQLITE_ROW ){ 515 + blob_appendf(&cluster, "M %s\n", db_column_text(&q, 0)); 516 + nRow++; 517 + if( nRow>=800 && nUncl>nRow+100 ){ 518 + md5sum_blob(&cluster, &cksum); 519 + blob_appendf(&cluster, "Z %b\n", &cksum); 520 + blob_reset(&cksum); 521 + content_put(&cluster, 0, 0); 522 + blob_reset(&cluster); 523 + nUncl -= nRow; 524 + nRow = 0; 525 + } 526 + } 527 + db_finalize(&q); 528 + db_multi_exec("DELETE FROM unclustered"); 529 + if( nRow>0 ){ 530 + md5sum_blob(&cluster, &cksum); 531 + blob_appendf(&cluster, "Z %b\n", &cksum); 532 + blob_reset(&cksum); 533 + content_put(&cluster, 0, 0); 534 + blob_reset(&cluster); 535 + } 536 + } 504 537 } 505 538 506 539 /* 507 540 ** Send an igot message for every entry in unclustered table. 508 541 ** Return the number of cards sent. 509 542 */ 510 543 static int send_unclustered(Xfer *pXfer){ ................................................................................ 591 624 int nErr = 0; 592 625 Xfer xfer; 593 626 int deltaFlag = 0; 594 627 int isClone = 0; 595 628 int nGimme = 0; 596 629 int size; 597 630 int recvConfig = 0; 631 + char *zNow; 598 632 599 633 if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){ 600 634 fossil_redirect_home(); 601 635 } 602 636 memset(&xfer, 0, sizeof(xfer)); 603 637 blobarray_zero(xfer.aToken, count(xfer.aToken)); 604 638 cgi_set_content_type(g.zContentType); 605 639 blob_zero(&xfer.err); 606 640 xfer.pIn = &g.cgiIn; 607 641 xfer.pOut = cgi_output_blob(); 608 - xfer.mxSend = db_get_int("max-download", 5000000); 642 + xfer.mxSend = db_get_int("max-download", 20000000); 609 643 g.xferPanic = 1; 610 644 611 645 db_begin_transaction(); 612 646 db_multi_exec( 613 647 "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" 614 648 ); 615 649 manifest_crosslink_begin(); ................................................................................ 625 659 if( blob_eq(&xfer.aToken[0], "file") ){ 626 660 if( !isPush ){ 627 661 cgi_reset_content(); 628 662 @ error not\sauthorized\sto\swrite 629 663 nErr++; 630 664 break; 631 665 } 632 - xfer_accept_file(&xfer); 666 + xfer_accept_file(&xfer, 0); 633 667 if( blob_size(&xfer.err) ){ 634 668 cgi_reset_content(); 635 669 @ error %T(blob_str(&xfer.err)) 636 670 nErr++; 637 671 break; 638 672 } 639 673 }else ................................................................................ 711 745 } 712 746 }else{ 713 747 isPush = 1; 714 748 } 715 749 } 716 750 }else 717 751 718 - /* clone 752 + /* clone ?PROTOCOL-VERSION? ?SEQUENCE-NUMBER? 719 753 ** 720 754 ** The client knows nothing. Tell all. 721 755 */ 722 756 if( blob_eq(&xfer.aToken[0], "clone") ){ 757 + int iVers; 723 758 login_check_credentials(); 724 759 if( !g.okClone ){ 725 760 cgi_reset_content(); 726 761 @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x")) 727 762 @ error not\sauthorized\sto\sclone 728 763 nErr++; 729 764 break; 730 765 } 731 - isClone = 1; 732 - isPull = 1; 733 - deltaFlag = 1; 766 + if( xfer.nToken==3 767 + && blob_is_int(&xfer.aToken[1], &iVers) 768 + && iVers>=2 769 + ){ 770 + int seqno, max; 771 + blob_is_int(&xfer.aToken[2], &seqno); 772 + max = db_int(0, "SELECT max(rid) FROM blob"); 773 + while( xfer.mxSend>blob_size(xfer.pOut) && seqno<=max ){ 774 + send_file(&xfer, seqno, 0, 1); 775 + seqno++; 776 + } 777 + if( seqno>=max ) seqno = 0; 778 + @ clone_seqno %d(seqno) 779 + }else{ 780 + isClone = 1; 781 + isPull = 1; 782 + deltaFlag = 1; 783 + } 734 784 @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x")) 735 785 }else 736 786 737 787 /* login USER NONCE SIGNATURE 738 788 ** 739 789 ** Check for a valid login. This has to happen before anything else. 740 790 ** The client can send multiple logins. Permissions are cumulative. ................................................................................ 867 917 create_cluster(); 868 918 send_unclustered(&xfer); 869 919 } 870 920 if( recvConfig ){ 871 921 configure_finalize_receive(); 872 922 } 873 923 manifest_crosslink_end(); 924 + 925 + /* Send the server timestamp last, in case prior processing happened 926 + ** to use up a significant fraction of our time window. 927 + */ 928 + zNow = db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S', 'now')"); 929 + @ # timestamp %s(zNow) 930 + free(zNow); 931 + 874 932 db_end_transaction(0); 875 933 } 876 934 877 935 /* 878 936 ** COMMAND: test-xfer 879 937 ** 880 938 ** This command is used for debugging the server. There is a single ................................................................................ 936 994 int size; /* Size of a config value */ 937 995 int nFileSend = 0; 938 996 int origConfigRcvMask; /* Original value of configRcvMask */ 939 997 int nFileRecv; /* Number of files received */ 940 998 int mxPhantomReq = 200; /* Max number of phantoms to request per comm */ 941 999 const char *zCookie; /* Server cookie */ 942 1000 int nSent, nRcvd; /* Bytes sent and received (after compression) */ 1001 + int cloneSeqno = 1; /* Sequence number for clones */ 943 1002 Blob send; /* Text we are sending to the server */ 944 1003 Blob recv; /* Reply we got back from the server */ 945 1004 Xfer xfer; /* Transfer data */ 1005 + int pctDone; /* Percentage done with a message */ 1006 + int lastPctDone = -1; /* Last displayed pctDone */ 1007 + double rArrivalTime; /* Time at which a message arrived */ 946 1008 const char *zSCode = db_get("server-code", "x"); 947 1009 const char *zPCode = db_get("project-code", 0); 948 1010 949 1011 if( db_get_boolean("dont-push", 0) ) pushFlag = 0; 950 1012 if( pushFlag + pullFlag + cloneFlag == 0 951 1013 && configRcvMask==0 && configSendMask==0 ) return; 952 1014 ................................................................................ 970 1032 blob_zero(&xfer.line); 971 1033 origConfigRcvMask = 0; 972 1034 973 1035 /* 974 1036 ** Always begin with a clone, pull, or push message 975 1037 */ 976 1038 if( cloneFlag ){ 977 - blob_appendf(&send, "clone\n"); 1039 + blob_appendf(&send, "clone 2 %d\n", cloneSeqno); 978 1040 pushFlag = 0; 979 1041 pullFlag = 0; 980 1042 nCardSent++; 981 1043 /* TBD: Request all transferable configuration values */ 1044 + content_enable_dephantomize(0); 982 1045 }else if( pullFlag ){ 983 1046 blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); 984 1047 nCardSent++; 985 1048 } 986 1049 if( pushFlag ){ 987 1050 blob_appendf(&send, "push %s %s\n", zSCode, zPCode); 988 1051 nCardSent++; 989 1052 } 990 1053 manifest_crosslink_begin(); 1054 + transport_global_startup(); 991 1055 fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas"); 992 1056 993 1057 while( go ){ 994 1058 int newPhantom = 0; 995 1059 char *zRandomness; 996 1060 997 1061 /* Send make the most recently received cookie. Let the server ................................................................................ 1001 1065 if( zCookie ){ 1002 1066 blob_appendf(&send, "cookie %s\n", zCookie); 1003 1067 } 1004 1068 1005 1069 /* Generate gimme cards for phantoms and leaf cards 1006 1070 ** for all leaves. 1007 1071 */ 1008 - if( pullFlag || cloneFlag ){ 1072 + if( pullFlag || (cloneFlag && cloneSeqno==1) ){ 1009 1073 request_phantoms(&xfer, mxPhantomReq); 1010 1074 } 1011 1075 if( pushFlag ){ 1012 1076 send_unsent(&xfer); 1013 1077 nCardSent += send_unclustered(&xfer); 1014 1078 } 1015 1079 ................................................................................ 1050 1114 */ 1051 1115 zRandomness = db_text(0, "SELECT hex(randomblob(20))"); 1052 1116 blob_appendf(&send, "# %s\n", zRandomness); 1053 1117 free(zRandomness); 1054 1118 1055 1119 /* Exchange messages with the server */ 1056 1120 nFileSend = xfer.nFileSent + xfer.nDeltaSent; 1057 - fossil_print(zValueFormat, "Send:", 1121 + fossil_print(zValueFormat, "Sent:", 1058 1122 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent, 1059 1123 xfer.nFileSent, xfer.nDeltaSent); 1060 1124 nCardSent = 0; 1061 1125 nCardRcvd = 0; 1062 1126 xfer.nFileSent = 0; 1063 1127 xfer.nDeltaSent = 0; 1064 1128 xfer.nGimmeSent = 0; 1065 1129 xfer.nIGotSent = 0; 1130 + if( !g.cgiOutput && !g.fQuiet ){ 1131 + printf("waiting for server..."); 1132 + } 1066 1133 fflush(stdout); 1067 1134 http_exchange(&send, &recv, cloneFlag==0 || nCycle>0); 1135 + lastPctDone = -1; 1068 1136 blob_reset(&send); 1137 + rArrivalTime = db_double(0.0, "SELECT julianday('now')"); 1069 1138 1070 1139 /* Begin constructing the next message (which might never be 1071 1140 ** sent) by beginning with the pull or push cards 1072 1141 */ 1073 1142 if( pullFlag ){ 1074 1143 blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); 1075 1144 nCardSent++; ................................................................................ 1078 1147 blob_appendf(&send, "push %s %s\n", zSCode, zPCode); 1079 1148 nCardSent++; 1080 1149 } 1081 1150 go = 0; 1082 1151 1083 1152 /* Process the reply that came back from the server */ 1084 1153 while( blob_line(&recv, &xfer.line) ){ 1154 + if( g.fHttpTrace ){ 1155 + printf("\rGOT: %.*s", (int)blob_size(&xfer.line), 1156 + blob_buffer(&xfer.line)); 1157 + } 1085 1158 if( blob_buffer(&xfer.line)[0]=='#' ){ 1159 + const char *zLine = blob_buffer(&xfer.line); 1160 + if( memcmp(zLine, "# timestamp ", 12)==0 ){ 1161 + char zTime[20]; 1162 + double rDiff; 1163 + sqlite3_snprintf(sizeof(zTime), zTime, "%.19s", &zLine[12]); 1164 + rDiff = db_double(9e99, "SELECT julianday('%q') - %.17g", 1165 + zTime, rArrivalTime); 1166 + if( rDiff<0.0 ) rDiff = -rDiff; 1167 + if( rDiff>9e98 ) rDiff = 0.0; 1168 + if( (rDiff*24.0*3600.0)>=60.0 ){ 1169 + fossil_warning("*** time skew *** server time differs by %s", 1170 + db_timespan_name(rDiff)); 1171 + g.clockSkewSeen = 1; 1172 + } 1173 + } 1086 1174 continue; 1087 1175 } 1088 1176 xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); 1089 1177 nCardRcvd++; 1090 - if( !g.cgiOutput && !g.fQuiet ){ 1091 - printf("\r%d", nCardRcvd); 1092 - fflush(stdout); 1178 + if( !g.cgiOutput && !g.fQuiet && recv.nUsed>0 ){ 1179 + pctDone = (recv.iCursor*100)/recv.nUsed; 1180 + if( pctDone!=lastPctDone ){ 1181 + printf("\rprocessed: %d%% ", pctDone); 1182 + lastPctDone = pctDone; 1183 + fflush(stdout); 1184 + } 1093 1185 } 1094 1186 1095 1187 /* file UUID SIZE \n CONTENT 1096 1188 ** file UUID DELTASRC SIZE \n CONTENT 1097 1189 ** 1098 1190 ** Receive a file transmitted from the server. 1099 1191 */ 1100 1192 if( blob_eq(&xfer.aToken[0],"file") ){ 1101 - xfer_accept_file(&xfer); 1193 + xfer_accept_file(&xfer, cloneFlag); 1102 1194 }else 1103 1195 1104 1196 /* gimme UUID 1105 1197 ** 1106 1198 ** Server is requesting a file. If the file is a manifest, assume 1107 1199 ** that the server will also want to know all of the content files 1108 1200 ** associated with the manifest and send those too. ................................................................................ 1154 1246 if( blob_eq_str(&xfer.aToken[1], zSCode, -1) ){ 1155 1247 fossil_fatal("server loop"); 1156 1248 } 1157 1249 if( zPCode==0 ){ 1158 1250 zPCode = mprintf("%b", &xfer.aToken[2]); 1159 1251 db_set("project-code", zPCode, 0); 1160 1252 } 1161 - blob_appendf(&send, "clone\n"); 1253 + blob_appendf(&send, "clone 2 %d\n", cloneSeqno); 1162 1254 nCardSent++; 1163 1255 }else 1164 1256 1165 1257 /* config NAME SIZE \n CONTENT 1166 1258 ** 1167 1259 ** Receive a configuration value from the server. 1168 1260 */ ................................................................................ 1213 1305 ** 1214 1306 ** Each cookie received overwrites the prior cookie from the 1215 1307 ** same server. 1216 1308 */ 1217 1309 if( blob_eq(&xfer.aToken[0], "cookie") && xfer.nToken==2 ){ 1218 1310 db_set("cookie", blob_str(&xfer.aToken[1]), 0); 1219 1311 }else 1312 + 1313 + /* clone_seqno N 1314 + ** 1315 + ** When doing a clone, the server tries to send all of its artifacts 1316 + ** in sequence. This card indicates the sequence number of the next 1317 + ** blob that needs to be sent. If N<=0 that indicates that all blobs 1318 + ** have been sent. 1319 + */ 1320 + if( blob_eq(&xfer.aToken[0], "clone_seqno") && xfer.nToken==2 ){ 1321 + blob_is_int(&xfer.aToken[1], &cloneSeqno); 1322 + }else 1220 1323 1221 1324 /* message MESSAGE 1222 1325 ** 1223 1326 ** Print a message. Similar to "error" but does not stop processing. 1224 1327 ** 1225 1328 ** If the "login failed" message is seen, clear the sync password prior 1226 1329 ** to the next cycle. ................................................................................ 1291 1394 ** there are still phantoms, then go another round. 1292 1395 */ 1293 1396 nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile; 1294 1397 if( (nFileRecv>0 || newPhantom) && db_exists("SELECT 1 FROM phantom") ){ 1295 1398 go = 1; 1296 1399 mxPhantomReq = nFileRecv*2; 1297 1400 if( mxPhantomReq<200 ) mxPhantomReq = 200; 1401 + }else if( cloneFlag && nFileRecv>0 ){ 1402 + go = 1; 1298 1403 } 1299 1404 nCardRcvd = 0; 1300 1405 xfer.nFileRcvd = 0; 1301 1406 xfer.nDeltaRcvd = 0; 1302 1407 xfer.nDanglingFile = 0; 1303 1408 1304 1409 /* If we have one or more files queued to send, then go ................................................................................ 1306 1411 */ 1307 1412 if( xfer.nFileSent+xfer.nDeltaSent>0 ){ 1308 1413 go = 1; 1309 1414 } 1310 1415 1311 1416 /* If this is a clone, the go at least two rounds */ 1312 1417 if( cloneFlag && nCycle==1 ) go = 1; 1418 + 1419 + /* Stop the cycle if the server sends a "clone_seqno 0" card */ 1420 + if( cloneSeqno<=0 ) go = 0; 1313 1421 }; 1314 1422 transport_stats(&nSent, &nRcvd, 1); 1315 1423 fossil_print("Total network traffic: %d bytes sent, %d bytes received\n", 1316 1424 nSent, nRcvd); 1317 1425 transport_close(); 1318 1426 transport_global_shutdown(); 1319 1427 db_multi_exec("DROP TABLE onremote"); 1320 1428 manifest_crosslink_end(); 1429 + content_enable_dephantomize(1); 1321 1430 db_end_transaction(0); 1322 1431 }
Changes to src/zip.c.
100 100 c = zName[i+1]; 101 101 zName[i+1] = 0; 102 102 for(j=0; j<nDir; j++){ 103 103 if( strcmp(zName, azDir[j])==0 ) break; 104 104 } 105 105 if( j>=nDir ){ 106 106 nDir++; 107 - azDir = realloc(azDir, sizeof(azDir[0])*nDir); 107 + azDir = fossil_realloc(azDir, sizeof(azDir[0])*nDir); 108 108 azDir[j] = mprintf("%s", zName); 109 109 zip_add_file(zName, 0); 110 110 } 111 111 zName[i+1] = c; 112 112 } 113 113 } 114 114 } ................................................................................ 311 311 ** added to as part of the zip file. It may be 0 or an empty string, 312 312 ** in which case it is ignored. The intention is to create a zip which 313 313 ** politely expands into a subdir instead of filling your current dir 314 314 ** with source files. For example, pass a UUID or "ProjectName". 315 315 ** 316 316 */ 317 317 void zip_of_baseline(int rid, Blob *pZip, const char *zDir){ 318 - int i; 319 - Blob mfile, file, hash; 320 - Manifest m; 318 + Blob mfile, hash, file; 319 + Manifest *pManifest; 320 + ManifestFile *pFile; 321 321 Blob filename; 322 322 int nPrefix; 323 323 324 324 content_get(rid, &mfile); 325 325 if( blob_size(&mfile)==0 ){ 326 326 blob_zero(pZip); 327 327 return; 328 328 } 329 - blob_zero(&file); 330 329 blob_zero(&hash); 331 - blob_copy(&file, &mfile); 332 330 blob_zero(&filename); 333 331 zip_open(); 334 332 335 333 if( zDir && zDir[0] ){ 336 334 blob_appendf(&filename, "%s/", zDir); 337 335 } 338 336 nPrefix = blob_size(&filename); 339 337 340 - if( manifest_parse(&m, &mfile) ){ 338 + pManifest = manifest_get(rid, CFTYPE_MANIFEST); 339 + if( pManifest ){ 341 340 char *zName; 342 - zip_set_timedate(m.rDate); 343 - blob_append(&filename, "manifest", -1); 344 - zName = blob_str(&filename); 345 - zip_add_folders(zName); 346 - zip_add_file(zName, &file); 347 - sha1sum_blob(&file, &hash); 348 - blob_reset(&file); 349 - blob_append(&hash, "\n", 1); 350 - blob_resize(&filename, nPrefix); 351 - blob_append(&filename, "manifest.uuid", -1); 352 - zName = blob_str(&filename); 353 - zip_add_file(zName, &hash); 354 - blob_reset(&hash); 355 - for(i=0; i<m.nFile; i++){ 356 - int fid = uuid_to_rid(m.aFile[i].zUuid, 0); 341 + zip_set_timedate(pManifest->rDate); 342 + if( db_get_boolean("manifest", 0) ){ 343 + blob_append(&filename, "manifest", -1); 344 + zName = blob_str(&filename); 345 + zip_add_folders(zName); 346 + zip_add_file(zName, &mfile); 347 + sha1sum_blob(&mfile, &hash); 348 + blob_reset(&mfile); 349 + blob_append(&hash, "\n", 1); 350 + blob_resize(&filename, nPrefix); 351 + blob_append(&filename, "manifest.uuid", -1); 352 + zName = blob_str(&filename); 353 + zip_add_file(zName, &hash); 354 + blob_reset(&hash); 355 + } 356 + manifest_file_rewind(pManifest); 357 + while( (pFile = manifest_file_next(pManifest,0))!=0 ){ 358 + int fid = uuid_to_rid(pFile->zUuid, 0); 357 359 if( fid ){ 358 360 content_get(fid, &file); 359 361 blob_resize(&filename, nPrefix); 360 - blob_append(&filename, m.aFile[i].zName, -1); 362 + blob_append(&filename, pFile->zName, -1); 361 363 zName = blob_str(&filename); 362 364 zip_add_folders(zName); 363 365 zip_add_file(zName, &file); 364 366 blob_reset(&file); 365 367 } 366 368 } 367 - manifest_clear(&m); 368 369 }else{ 369 370 blob_reset(&mfile); 370 - blob_reset(&file); 371 371 } 372 + manifest_destroy(pManifest); 372 373 blob_reset(&filename); 373 374 zip_close(pZip); 374 375 } 375 376 376 377 /* 377 378 ** COMMAND: zip 378 379 **
Changes to test/delta1.test.
30 30 # some random changes in "./t2". Then call test-delta on the 31 31 # two files to make sure that deltas between these two files 32 32 # work properly. 33 33 # 34 34 set filelist [glob $testdir/*] 35 35 foreach f $filelist { 36 36 set base [file root [file tail $f]] 37 -puts "base=$base f=$f" 37 +protOut "base=$base f=$f" 38 38 set f1 [read_file $f] 39 39 write_file t1 $f1 40 40 for {set i 0} {$i<100} {incr i} { 41 41 write_file t2 [random_changes $f1 1 1 0 0.1] 42 42 fossil test-delta t1 t2 43 43 test delta-$base-$i-1 {$RESULT=="ok"} 44 44 write_file t2 [random_changes $f1 1 1 0 0.2]
Changes to test/merge1.test.
75 75 111 - This is line one OF the demo program - 1111 76 76 222 - The second line program line in code - 2222 77 77 333 - This is a test of the merging algohm - 3333 78 78 444 - If all goes well, we will be pleased - 4444 79 79 555 - we think it well and other stuff too - 5555 80 80 } 81 81 write_file_indented t23 { 82 - >>>>>>> BEGIN MERGE CONFLICT 82 + <<<<<<< BEGIN MERGE CONFLICT 83 83 111 - This is line ONE of the demo program - 1111 84 84 ============================ 85 85 111 - This is line one OF the demo program - 1111 86 - <<<<<<< END MERGE CONFLICT 86 + >>>>>>> END MERGE CONFLICT 87 87 222 - The second line program line in code - 2222 88 88 333 - This is a test of the merging algohm - 3333 89 89 444 - If all goes well, we will be pleased - 4444 90 90 555 - we think it well and other stuff too - 5555 91 91 } 92 92 write_file_indented t32 { 93 - >>>>>>> BEGIN MERGE CONFLICT 93 + <<<<<<< BEGIN MERGE CONFLICT 94 94 111 - This is line one OF the demo program - 1111 95 95 ============================ 96 96 111 - This is line ONE of the demo program - 1111 97 - <<<<<<< END MERGE CONFLICT 97 + >>>>>>> END MERGE CONFLICT 98 98 222 - The second line program line in code - 2222 99 99 333 - This is a test of the merging algohm - 3333 100 100 444 - If all goes well, we will be pleased - 4444 101 101 555 - we think it well and other stuff too - 5555 102 102 } 103 103 fossil test-3 t1 t3 t2 a32 104 104 test merge1-2.1 {[same_file t32 a32]} ................................................................................ 156 156 write_file_indented t3 { 157 157 222 - The second line program line in code - 2222 158 158 333 - This is a test of the merging algohm - 3333 159 159 444 - If all goes well, we will be pleased - 4444 160 160 555 - we think it well and other stuff too - 5555 161 161 } 162 162 write_file_indented t32 { 163 - >>>>>>> BEGIN MERGE CONFLICT 163 + <<<<<<< BEGIN MERGE CONFLICT 164 164 ============================ 165 165 000 - Zero lines added to the beginning of - 0000 166 166 111 - This is line one of the demo program - 1111 167 - <<<<<<< END MERGE CONFLICT 167 + >>>>>>> END MERGE CONFLICT 168 168 222 - The second line program line in code - 2222 169 169 333 - This is a test of the merging algohm - 3333 170 170 444 - If all goes well, we will be pleased - 4444 171 171 555 - we think it well and other stuff too - 5555 172 172 } 173 173 write_file_indented t23 { 174 - >>>>>>> BEGIN MERGE CONFLICT 174 + <<<<<<< BEGIN MERGE CONFLICT 175 175 000 - Zero lines added to the beginning of - 0000 176 176 111 - This is line one of the demo program - 1111 177 177 ============================ 178 - <<<<<<< END MERGE CONFLICT 178 + >>>>>>> END MERGE CONFLICT 179 179 222 - The second line program line in code - 2222 180 180 333 - This is a test of the merging algohm - 3333 181 181 444 - If all goes well, we will be pleased - 4444 182 182 555 - we think it well and other stuff too - 5555 183 183 } 184 184 fossil test-3 t1 t3 t2 a32 185 185 test merge1-4.1 {[same_file t32 a32]} ................................................................................ 291 291 KLMN 292 292 OPQR 293 293 STUV 294 294 XYZ. 295 295 } 296 296 write_file_indented t23 { 297 297 abcd 298 - >>>>>>> BEGIN MERGE CONFLICT 298 + <<<<<<< BEGIN MERGE CONFLICT 299 299 efgh 2 300 300 ijkl 2 301 301 mnop 2 302 302 qrst 303 303 uvwx 304 304 yzAB 2 305 305 CDEF 2 ................................................................................ 309 309 ijkl 310 310 mnop 3 311 311 qrst 3 312 312 uvwx 3 313 313 yzAB 3 314 314 CDEF 315 315 GHIJ 316 - <<<<<<< END MERGE CONFLICT 316 + >>>>>>> END MERGE CONFLICT 317 317 KLMN 318 318 OPQR 319 319 STUV 320 320 XYZ. 321 321 } 322 322 fossil test-3 t1 t2 t3 a23 323 323 test merge1-7.1 {[same_file t23 a23]} ................................................................................ 352 352 STUV 353 353 XYZ. 354 354 } 355 355 write_file_indented t23 { 356 356 abcd 357 357 efgh 2 358 358 ijkl 2 359 - >>>>>>> BEGIN MERGE CONFLICT 359 + <<<<<<< BEGIN MERGE CONFLICT 360 360 mnop 361 361 qrst 362 362 uvwx 363 363 yzAB 2 364 364 CDEF 2 365 365 GHIJ 2 366 366 ============================ 367 367 mnop 3 368 368 qrst 3 369 369 uvwx 3 370 370 yzAB 3 371 371 CDEF 372 372 GHIJ 373 - <<<<<<< END MERGE CONFLICT 373 + >>>>>>> END MERGE CONFLICT 374 374 KLMN 375 375 OPQR 376 376 STUV 377 377 XYZ. 378 378 } 379 379 fossil test-3 t1 t2 t3 a23 380 380 test merge1-7.2 {[same_file t23 a23]}
Changes to test/merge3.test.
26 26 27 27 proc merge-test {testid basis v1 v2 result} { 28 28 write_file t1 [join [string trim $basis] \n]\n 29 29 write_file t2 [join [string trim $v1] \n]\n 30 30 write_file t3 [join [string trim $v2] \n]\n 31 31 fossil test-3-way-merge t1 t2 t3 t4 32 32 set x [read_file t4] 33 - regsub -all {>>>>>>> BEGIN MERGE CONFLICT} $x {>} x 33 + regsub -all {<<<<<<< BEGIN MERGE CONFLICT} $x {>} x 34 34 regsub -all {============================} $x {=} x 35 - regsub -all {<<<<<<< END MERGE CONFLICT} $x {<} x 35 + regsub -all {>>>>>>> END MERGE CONFLICT} $x {<} x 36 36 set x [split [string trim $x] \n] 37 37 set result [string trim $result] 38 38 if {$x!=$result} { 39 - puts " Expected \[$result\]" 40 - puts " Got \[$x\]" 39 + protOut " Expected \[$result\]" 40 + protOut " Got \[$x\]" 41 41 test merge3-$testid 0 42 42 } else { 43 43 test merge3-$testid 1 44 44 } 45 45 } 46 46 47 47 merge-test 1 {
Changes to test/merge4.test.
27 27 proc merge-test {testid basis v1 v2 result1 result2} { 28 28 write_file t1 [join [string trim $basis] \n]\n 29 29 write_file t2 [join [string trim $v1] \n]\n 30 30 write_file t3 [join [string trim $v2] \n]\n 31 31 fossil test-3-way-merge t1 t2 t3 t4 32 32 fossil test-3-way-merge t1 t3 t2 t5 33 33 set x [read_file t4] 34 - regsub -all {>>>>>>> BEGIN MERGE CONFLICT} $x {>} x 34 + regsub -all {<<<<<<< BEGIN MERGE CONFLICT} $x {>} x 35 35 regsub -all {============================} $x {=} x 36 - regsub -all {<<<<<<< END MERGE CONFLICT} $x {<} x 36 + regsub -all {>>>>>>> END MERGE CONFLICT} $x {<} x 37 37 set x [split [string trim $x] \n] 38 38 set y [read_file t5] 39 - regsub -all {>>>>>>> BEGIN MERGE CONFLICT} $y {>} y 39 + regsub -all {<<<<<<< BEGIN MERGE CONFLICT} $y {>} y 40 40 regsub -all {============================} $y {=} y 41 - regsub -all {<<<<<<< END MERGE CONFLICT} $y {<} y 41 + regsub -all {>>>>>>> END MERGE CONFLICT} $y {<} y 42 42 set y [split [string trim $y] \n] 43 43 set result1 [string trim $result1] 44 44 if {$x!=$result1} { 45 - puts " Expected \[$result1\]" 46 - puts " Got \[$x\]" 45 + protOut " Expected \[$result1\]" 46 + protOut " Got \[$x\]" 47 47 test merge3-$testid 0 48 48 } else { 49 49 set result2 [string trim $result2] 50 50 if {$y!=$result2} { 51 - puts " Expected \[$result2\]" 52 - puts " Got \[$y\]" 51 + protOut " Expected \[$result2\]" 52 + protOut " Got \[$y\]" 53 53 test merge3-$testid 0 54 54 } else { 55 55 test merge3-$testid 1 56 56 } 57 57 } 58 58 } 59 59
Changes to test/tester.tcl.
36 36 set i [lsearch $argv -halt] 37 37 if {$i>=0} { 38 38 set HALT 1 39 39 set argv [lreplace $argv $i $i] 40 40 } else { 41 41 set HALT 0 42 42 } 43 + 44 +set i [lsearch $argv -prot] 45 +if {$i>=0} { 46 + set PROT 1 47 + set argv [lreplace $argv $i $i] 48 +} else { 49 + set PROT 0 50 +} 43 51 44 52 if {[llength $argv]==0} { 45 53 foreach f [lsort [glob $testdir/*.test]] { 46 54 set base [file root [file tail $f]] 47 55 lappend argv $base 48 56 } 49 57 } 58 + 59 +# start protocol 60 +# 61 +proc protInit {cmd} { 62 + if {$::PROT} { 63 + set out [open "prot" w] 64 + fconfigure $out -translation platform 65 + puts $out "starting tests with:$cmd" 66 + close $out 67 + } 68 +} 69 + 70 +# write protocol 71 +# 72 +proc protOut {msg} { 73 + puts "$msg" 74 + if {$::PROT} { 75 + set out [open "prot" a] 76 + fconfigure $out -translation platform 77 + puts $out "$msg" 78 + close $out 79 + } 80 +} 50 81 51 82 # Run the fossil program 52 83 # 53 84 proc fossil {args} { 54 85 global fossilexe 55 86 set cmd $fossilexe 56 87 foreach a $args { 57 88 lappend cmd $a 58 89 } 59 - puts $cmd 90 + protOut $cmd 91 + 60 92 flush stdout 61 93 set rc [catch {eval exec $cmd} result] 62 94 global RESULT CODE 63 95 set CODE $rc 64 96 set RESULT $result 65 97 } 66 98 ................................................................................ 98 130 99 131 # Perform a test 100 132 # 101 133 proc test {name expr} { 102 134 global bad_test 103 135 set r [uplevel 1 [list expr $expr]] 104 136 if {$r} { 105 - puts "test $name OK" 137 + protOut "test $name OK" 106 138 } else { 107 - puts "test $name FAILED!" 139 + protOut "test $name FAILED!" 108 140 lappend bad_test $name 109 141 if {$::HALT} exit 110 142 } 111 143 } 112 144 set bad_test {} 113 145 114 146 # Return a random string N characters long. ................................................................................ 165 197 } 166 198 } 167 199 append out \n$line 168 200 } 169 201 return [string range $out 1 end] 170 202 } 171 203 204 +protInit $fossilexe 172 205 foreach testfile $argv { 173 - puts "***** $testfile ******" 206 + protOut "***** $testfile ******" 174 207 source $testdir/$testfile.test 175 208 } 176 -puts "[llength $bad_test] errors: $bad_test" 209 +protOut "[llength $bad_test] errors: $bad_test"
Added win/Makefile.PellesCGMake.
1 +# ########################################################################### 2 +# 3 +# HowTo 4 +# ----- 5 +# 6 +# This is a Makefile to compile fossil with PellesC from 7 +# http://www.smorgasbordet.com/pellesc/index.htm 8 +# In addition to the Compiler envrionment, you need 9 +# gmake from http://sourceforge.net/projects/unxutils/, Pelles make version 10 +# couldn't handle the complex dependencies in this build 11 +# zlib sources 12 +# Then you do 13 +# 1. create a directory PellesC in the project root directory 14 +# 2. Change the variables PellesCDir/ZLIBSRCDIR to the path of your installation 15 +# 3. open a dos prompt window and change working directory into PellesC (step 1) 16 +# 4. run gmake -f ..\win\Makefile.PellesCGMake 17 +# 18 +# this file is tested with 19 +# PellesC 5.00.13 20 +# gmake 3.80 21 +# zlib sources 1.2.5 22 +# Windows XP SP 2 23 +# and 24 +# PellesC 6.00.4 25 +# gmake 3.80 26 +# zlib sources 1.2.5 27 +# Windows 7 Home Premium 28 +# 29 +# ########################################################################### 30 + 31 +# 32 +PellesCDir=c:\Programme\PellesC 33 + 34 +# Select between 32/64 bit code, default is 32 bit 35 +#TARGETVERSION=64 36 + 37 +ifeq ($(TARGETVERSION),64) 38 +# 64 bit version 39 +TARGETMACHINE_CC=amd64 40 +TARGETMACHINE_LN=amd64 41 +TARGETEXTEND=64 42 +else 43 +# 32 bit version 44 +TARGETMACHINE_CC=x86 45 +TARGETMACHINE_LN=ix86 46 +TARGETEXTEND= 47 +endif 48 + 49 +# define the project directories 50 +B=.. 51 +SRCDIR=$(B)/src/ 52 +WINDIR=$(B)/win/ 53 +ZLIBSRCDIR=../../zlib/ 54 + 55 +# define linker command and options 56 +LINK=$(PellesCDir)/bin/polink.exe 57 +LINKFLAGS=-subsystem:console -machine:$(TARGETMACHINE_LN) /LIBPATH:$(PellesCDir)\lib\win$(TARGETEXTEND) /LIBPATH:$(PellesCDir)\lib kernel32.lib advapi32.lib delayimp$(TARGETEXTEND).lib Wsock32.lib Crtmt$(TARGETEXTEND).lib 58 + 59 +# define standard C-compiler and flags, used to compile 60 +# the fossil binary. Some special definitions follow for 61 +# special files follow 62 +CC=$(PellesCDir)\bin\pocc.exe 63 +DEFINES=-DFOSSIL_I18N=0 -Dstrncasecmp=memicmp -Dstrcasecmp=stricmp 64 +CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES) 65 +INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) 66 + 67 +# define commands for building the windows resource files 68 +RESOURCE=fossil.res 69 +RC=$(PellesCDir)\bin\porc.exe 70 +RCFLAGS=$(INCLUDE) -D__POCC__=1 -D_M_X$(TARGETVERSION) 71 + 72 +# define the special utilities files, needed to generate 73 +# the automatically generated source files 74 +UTILS=translate.exe mkindex.exe makeheaders.exe 75 +UTILS_OBJ=$(UTILS:.exe=.obj) 76 +UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c)) 77 + 78 +# define the sqlite files, which need special flags on compile 79 +SQLITESRC=sqlite3.c 80 +ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) 81 +SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) 82 +SQLITEDEFINES=-DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 83 + 84 +# define the th scripting files, which need special flags on compile 85 +THSRC=th.c th_lang.c 86 +ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf)) 87 +THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj)) 88 + 89 +# define the zlib files, needed by this compile 90 +ZLIBSRC=adler32.c compress.c crc32.c deflate.c gzclose.c gzlib.c gzread.c gzwrite.c infback.c inffast.c inflate.c inftrees.c trees.c uncompr.c zutil.c 91 +ORIGZLIBSRC=$(foreach sf,$(ZLIBSRC),$(ZLIBSRCDIR)$(sf)) 92 +ZLIBOBJ=$(foreach sf,$(ZLIBSRC),$(sf:.c=.obj)) 93 + 94 +# define all fossil sources, using the standard compile and 95 +# source generation. These are all files in SRCDIR, which are not 96 +# mentioned as special files above: 97 +ORIGSRC=$(filter-out $(UTILS_SRC) $(ORIGTHSRC) $(ORIGSQLITESRC),$(wildcard $(SRCDIR)*.c)) 98 +SRC=$(subst $(SRCDIR),,$(ORIGSRC)) 99 +TRANSLATEDSRC=$(SRC:.c=_.c) 100 +TRANSLATEDOBJ=$(TRANSLATEDSRC:.c=.obj) 101 + 102 +# main target file is the application 103 +APPLICATION=fossil.exe 104 + 105 +# ########################################################################### 106 +# define the standard make target 107 +.PHONY: default 108 +default: page_index.h headers $(APPLICATION) 109 + 110 +# ########################################################################### 111 +# symbolic target to generate the source generate utils 112 +.PHONY: utils 113 +utils: $(UTILS) 114 + 115 +# link utils 116 +$(UTILS) version.exe: %.exe: %.obj 117 + $(LINK) $(LINKFLAGS) -out:"$@" $< 118 + 119 +# compiling standard fossil utils 120 +$(UTILS_OBJ): %.obj: $(SRCDIR)%.c 121 + $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 122 + 123 +# compile special windows utils 124 +version.obj: $(WINDIR)version.c 125 + $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 126 + 127 +# ########################################################################### 128 +# generate the translated c-source files 129 +$(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe 130 + translate.exe $< >$@ 131 + 132 +# ########################################################################### 133 +# generate the index source, containing all web references,.. 134 +page_index.h: $(TRANSLATEDSRC) mkindex.exe 135 + mkindex.exe $(TRANSLATEDSRC) >$@ 136 + 137 +# ########################################################################### 138 +# extracting version info from manifest 139 +VERSION.h: version.exe ..\manifest.uuid ..\manifest 140 + version.exe ..\manifest.uuid ..\manifest > $@ 141 + 142 +# ########################################################################### 143 +# generate the simplified headers 144 +headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/th.h VERSION.h 145 + makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/th.h VERSION.h 146 + echo Done >$@ 147 + 148 +# ########################################################################### 149 +# compile C sources with relevant options 150 + 151 +$(TRANSLATEDOBJ): %_.obj: %_.c %.h 152 + $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 153 + 154 +$(SQLITEOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)%.h 155 + $(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@" 156 + 157 +$(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h 158 + $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 159 + 160 +$(ZLIBOBJ): %.obj: $(ZLIBSRCDIR)%.c 161 + $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" 162 + 163 +# ########################################################################### 164 +# create the windows resource with icon and version info 165 +$(RESOURCE): %.res: ../win/%.rc ../win/*.ico 166 + $(RC) $(RCFLAGS) $< -Fo"$@" 167 + 168 +# ########################################################################### 169 +# link the application 170 +$(APPLICATION): $(TRANSLATEDOBJ) $(SQLITEOBJ) $(THOBJ) $(ZLIBOBJ) headers $(RESOURCE) 171 + $(LINK) $(LINKFLAGS) -out:"$@" $(TRANSLATEDOBJ) $(SQLITEOBJ) $(THOBJ) $(ZLIBOBJ) $(RESOURCE) 172 + 173 +# ########################################################################### 174 +# cleanup 175 + 176 +.PHONY: clean 177 +clean: 178 + del /F $(TRANSLATEDOBJ) $(SQLITEOBJ) $(THOBJ) $(ZLIBOBJ) $(UTILS_OBJ) version.obj 179 + del /F $(TRANSLATEDSRC) 180 + del /F *.h headers 181 + del /F $(RESOURCE) 182 + 183 +.PHONY: clobber 184 +clobber: clean 185 + del /F *.exe 186 +
Added win/Makefile.dmc.
1 +# DO NOT EDIT 2 +# 3 +# This file is automatically generated. Instead of editing this 4 +# file, edit "makemake.tcl" then run 5 +# "tclsh src/makemake.tcl dmc > win/Makefile.dmc" 6 +# to regenerate this file. 7 +B = .. 8 +SRCDIR = $B\src 9 +OBJDIR = . 10 +O = .obj 11 +E = .exe 12 + 13 + 14 +# Maybe DMDIR, SSL or INCL needs adjustment 15 +DMDIR = c:\DM 16 +INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(DMDIR)\extra\include 17 + 18 +#SSL = -DFOSSIL_ENABLE_SSL=1 19 +SSL = 20 + 21 +DMCDEF = -Dstrncasecmp=memicmp -Dstrcasecmp=stricmp 22 +I18N = -DFOSSIL_I18N=0 23 + 24 +CFLAGS = -o 25 +BCC = $(DMDIR)\bin\dmc $(CFLAGS) 26 +TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL) 27 +LIBS = $(DMDIR)\extra\lib\ zlib wsock32 28 + 29 +SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c 30 + 31 +OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\shell$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O 32 + 33 +RC=$(DMDIR)\bin\rcc 34 +RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ 35 + 36 +APPNAME = $(OBJDIR)\fossil$(E) 37 + 38 +all: $(APPNAME) 39 + 40 +$(APPNAME) : translate$E mkindex$E headers fossil.res $(OBJ) $(OBJDIR)\link 41 + cd $(OBJDIR) 42 + $(DMDIR)\bin\link @link 43 + 44 +fossil.res: $B\win\fossil.rc 45 + $(RC) $(RCFLAGS) -o$@ $** 46 + 47 +$(OBJDIR)\link: $B\win\Makefile.dmc 48 + +echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 shell th th_lang > $@ 49 + +echo fossil >> $@ 50 + +echo fossil >> $@ 51 + +echo $(LIBS) >> $@ 52 + +echo. >> $@ 53 + +echo fossil >> $@ 54 + 55 + 56 + 57 +translate$E: $(SRCDIR)\translate.c 58 + $(BCC) -o$@ $** 59 + 60 +makeheaders$E: $(SRCDIR)\makeheaders.c 61 + $(BCC) -o$@ $** 62 + 63 +mkindex$E: $(SRCDIR)\mkindex.c 64 + $(BCC) -o$@ $** 65 + 66 +version$E: $B\win\version.c 67 + $(BCC) -o$@ $** 68 + 69 +$(OBJDIR)\shell$O : $(SRCDIR)\shell.c 70 + $(TCC) -o$@ -c -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 $** 71 + 72 +$(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c 73 + $(TCC) -o$@ -c -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 $** 74 + 75 +$(OBJDIR)\th$O : $(SRCDIR)\th.c 76 + $(TCC) -o$@ -c $** 77 + 78 +$(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c 79 + $(TCC) -o$@ -c $** 80 + 81 +VERSION.h : version$E $B\manifest.uuid $B\manifest 82 + +$** > $@ 83 + 84 +page_index.h: mkindex$E $(SRC) 85 + +$** > $@ 86 + 87 +clean: 88 + -del $(OBJDIR)\*.obj 89 + -del *.obj *_.c *.h *.map 90 + 91 +realclean: 92 + -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E 93 + 94 + 95 +$(OBJDIR)\add$O : add_.c add.h 96 + $(TCC) -o$@ -c add_.c 97 + 98 +add_.c : $(SRCDIR)\add.c 99 + +translate$E $** > $@ 100 + 101 +$(OBJDIR)\allrepo$O : allrepo_.c allrepo.h 102 + $(TCC) -o$@ -c allrepo_.c 103 + 104 +allrepo_.c : $(SRCDIR)\allrepo.c 105 + +translate$E $** > $@ 106 + 107 +$(OBJDIR)\attach$O : attach_.c attach.h 108 + $(TCC) -o$@ -c attach_.c 109 + 110 +attach_.c : $(SRCDIR)\attach.c 111 + +translate$E $** > $@ 112 + 113 +$(OBJDIR)\bag$O : bag_.c bag.h 114 + $(TCC) -o$@ -c bag_.c 115 + 116 +bag_.c : $(SRCDIR)\bag.c 117 + +translate$E $** > $@ 118 + 119 +$(OBJDIR)\blob$O : blob_.c blob.h 120 + $(TCC) -o$@ -c blob_.c 121 + 122 +blob_.c : $(SRCDIR)\blob.c 123 + +translate$E $** > $@ 124 + 125 +$(OBJDIR)\branch$O : branch_.c branch.h 126 + $(TCC) -o$@ -c branch_.c 127 + 128 +branch_.c : $(SRCDIR)\branch.c 129 + +translate$E $** > $@ 130 + 131 +$(OBJDIR)\browse$O : browse_.c browse.h 132 + $(TCC) -o$@ -c browse_.c 133 + 134 +browse_.c : $(SRCDIR)\browse.c 135 + +translate$E $** > $@ 136 + 137 +$(OBJDIR)\captcha$O : captcha_.c captcha.h 138 + $(TCC) -o$@ -c captcha_.c 139 + 140 +captcha_.c : $(SRCDIR)\captcha.c 141 + +translate$E $** > $@ 142 + 143 +$(OBJDIR)\cgi$O : cgi_.c cgi.h 144 + $(TCC) -o$@ -c cgi_.c 145 + 146 +cgi_.c : $(SRCDIR)\cgi.c 147 + +translate$E $** > $@ 148 + 149 +$(OBJDIR)\checkin$O : checkin_.c checkin.h 150 + $(TCC) -o$@ -c checkin_.c 151 + 152 +checkin_.c : $(SRCDIR)\checkin.c 153 + +translate$E $** > $@ 154 + 155 +$(OBJDIR)\checkout$O : checkout_.c checkout.h 156 + $(TCC) -o$@ -c checkout_.c 157 + 158 +checkout_.c : $(SRCDIR)\checkout.c 159 + +translate$E $** > $@ 160 + 161 +$(OBJDIR)\clearsign$O : clearsign_.c clearsign.h 162 + $(TCC) -o$@ -c clearsign_.c 163 + 164 +clearsign_.c : $(SRCDIR)\clearsign.c 165 + +translate$E $** > $@ 166 + 167 +$(OBJDIR)\clone$O : clone_.c clone.h 168 + $(TCC) -o$@ -c clone_.c 169 + 170 +clone_.c : $(SRCDIR)\clone.c 171 + +translate$E $** > $@ 172 + 173 +$(OBJDIR)\comformat$O : comformat_.c comformat.h 174 + $(TCC) -o$@ -c comformat_.c 175 + 176 +comformat_.c : $(SRCDIR)\comformat.c 177 + +translate$E $** > $@ 178 + 179 +$(OBJDIR)\configure$O : configure_.c configure.h 180 + $(TCC) -o$@ -c configure_.c 181 + 182 +configure_.c : $(SRCDIR)\configure.c 183 + +translate$E $** > $@ 184 + 185 +$(OBJDIR)\content$O : content_.c content.h 186 + $(TCC) -o$@ -c content_.c 187 + 188 +content_.c : $(SRCDIR)\content.c 189 + +translate$E $** > $@ 190 + 191 +$(OBJDIR)\db$O : db_.c db.h 192 + $(TCC) -o$@ -c db_.c 193 + 194 +db_.c : $(SRCDIR)\db.c 195 + +translate$E $** > $@ 196 + 197 +$(OBJDIR)\delta$O : delta_.c delta.h 198 + $(TCC) -o$@ -c delta_.c 199 + 200 +delta_.c : $(SRCDIR)\delta.c 201 + +translate$E $** > $@ 202 + 203 +$(OBJDIR)\deltacmd$O : deltacmd_.c deltacmd.h 204 + $(TCC) -o$@ -c deltacmd_.c 205 + 206 +deltacmd_.c : $(SRCDIR)\deltacmd.c 207 + +translate$E $** > $@ 208 + 209 +$(OBJDIR)\descendants$O : descendants_.c descendants.h 210 + $(TCC) -o$@ -c descendants_.c 211 + 212 +descendants_.c : $(SRCDIR)\descendants.c 213 + +translate$E $** > $@ 214 + 215 +$(OBJDIR)\diff$O : diff_.c diff.h 216 + $(TCC) -o$@ -c diff_.c 217 + 218 +diff_.c : $(SRCDIR)\diff.c 219 + +translate$E $** > $@ 220 + 221 +$(OBJDIR)\diffcmd$O : diffcmd_.c diffcmd.h 222 + $(TCC) -o$@ -c diffcmd_.c 223 + 224 +diffcmd_.c : $(SRCDIR)\diffcmd.c 225 + +translate$E $** > $@ 226 + 227 +$(OBJDIR)\doc$O : doc_.c doc.h 228 + $(TCC) -o$@ -c doc_.c 229 + 230 +doc_.c : $(SRCDIR)\doc.c 231 + +translate$E $** > $@ 232 + 233 +$(OBJDIR)\event$O : event_.c event.h 234 + $(TCC) -o$@ -c event_.c 235 + 236 +event_.c : $(SRCDIR)\event.c 237 + +translate$E $** > $@ 238 + 239 +$(OBJDIR)\encode$O : encode_.c encode.h 240 + $(TCC) -o$@ -c encode_.c 241 + 242 +encode_.c : $(SRCDIR)\encode.c 243 + +translate$E $** > $@ 244 + 245 +$(OBJDIR)\event$O : event_.c event.h 246 + $(TCC) -o$@ -c event_.c 247 + 248 +event_.c : $(SRCDIR)\event.c 249 + +translate$E $** > $@ 250 + 251 +$(OBJDIR)\file$O : file_.c file.h 252 + $(TCC) -o$@ -c file_.c 253 + 254 +file_.c : $(SRCDIR)\file.c 255 + +translate$E $** > $@ 256 + 257 +$(OBJDIR)\finfo$O : finfo_.c finfo.h 258 + $(TCC) -o$@ -c finfo_.c 259 + 260 +finfo_.c : $(SRCDIR)\finfo.c 261 + +translate$E $** > $@ 262 + 263 +$(OBJDIR)\graph$O : graph_.c graph.h 264 + $(TCC) -o$@ -c graph_.c 265 + 266 +graph_.c : $(SRCDIR)\graph.c 267 + +translate$E $** > $@ 268 + 269 +$(OBJDIR)\http$O : http_.c http.h 270 + $(TCC) -o$@ -c http_.c 271 + 272 +http_.c : $(SRCDIR)\http.c 273 + +translate$E $** > $@ 274 + 275 +$(OBJDIR)\http_socket$O : http_socket_.c http_socket.h 276 + $(TCC) -o$@ -c http_socket_.c 277 + 278 +http_socket_.c : $(SRCDIR)\http_socket.c 279 + +translate$E $** > $@ 280 + 281 +$(OBJDIR)\http_ssl$O : http_ssl_.c http_ssl.h 282 + $(TCC) -o$@ -c http_ssl_.c 283 + 284 +http_ssl_.c : $(SRCDIR)\http_ssl.c 285 + +translate$E $** > $@ 286 + 287 +$(OBJDIR)\http_transport$O : http_transport_.c http_transport.h 288 + $(TCC) -o$@ -c http_transport_.c 289 + 290 +http_transport_.c : $(SRCDIR)\http_transport.c 291 + +translate$E $** > $@ 292 + 293 +$(OBJDIR)\info$O : info_.c info.h 294 + $(TCC) -o$@ -c info_.c 295 + 296 +info_.c : $(SRCDIR)\info.c 297 + +translate$E $** > $@ 298 + 299 +$(OBJDIR)\login$O : login_.c login.h 300 + $(TCC) -o$@ -c login_.c 301 + 302 +login_.c : $(SRCDIR)\login.c 303 + +translate$E $** > $@ 304 + 305 +$(OBJDIR)\main$O : main_.c main.h 306 + $(TCC) -o$@ -c main_.c 307 + 308 +main_.c : $(SRCDIR)\main.c 309 + +translate$E $** > $@ 310 + 311 +$(OBJDIR)\manifest$O : manifest_.c manifest.h 312 + $(TCC) -o$@ -c manifest_.c 313 + 314 +manifest_.c : $(SRCDIR)\manifest.c 315 + +translate$E $** > $@ 316 + 317 +$(OBJDIR)\md5$O : md5_.c md5.h 318 + $(TCC) -o$@ -c md5_.c 319 + 320 +md5_.c : $(SRCDIR)\md5.c 321 + +translate$E $** > $@ 322 + 323 +$(OBJDIR)\merge$O : merge_.c merge.h 324 + $(TCC) -o$@ -c merge_.c 325 + 326 +merge_.c : $(SRCDIR)\merge.c 327 + +translate$E $** > $@ 328 + 329 +$(OBJDIR)\merge3$O : merge3_.c merge3.h 330 + $(TCC) -o$@ -c merge3_.c 331 + 332 +merge3_.c : $(SRCDIR)\merge3.c 333 + +translate$E $** > $@ 334 + 335 +$(OBJDIR)\name$O : name_.c name.h 336 + $(TCC) -o$@ -c name_.c 337 + 338 +name_.c : $(SRCDIR)\name.c 339 + +translate$E $** > $@ 340 + 341 +$(OBJDIR)\pivot$O : pivot_.c pivot.h 342 + $(TCC) -o$@ -c pivot_.c 343 + 344 +pivot_.c : $(SRCDIR)\pivot.c 345 + +translate$E $** > $@ 346 + 347 +$(OBJDIR)\popen$O : popen_.c popen.h 348 + $(TCC) -o$@ -c popen_.c 349 + 350 +popen_.c : $(SRCDIR)\popen.c 351 + +translate$E $** > $@ 352 + 353 +$(OBJDIR)\pqueue$O : pqueue_.c pqueue.h 354 + $(TCC) -o$@ -c pqueue_.c 355 + 356 +pqueue_.c : $(SRCDIR)\pqueue.c 357 + +translate$E $** > $@ 358 + 359 +$(OBJDIR)\printf$O : printf_.c printf.h 360 + $(TCC) -o$@ -c printf_.c 361 + 362 +printf_.c : $(SRCDIR)\printf.c 363 + +translate$E $** > $@ 364 + 365 +$(OBJDIR)\rebuild$O : rebuild_.c rebuild.h 366 + $(TCC) -o$@ -c rebuild_.c 367 + 368 +rebuild_.c : $(SRCDIR)\rebuild.c 369 + +translate$E $** > $@ 370 + 371 +$(OBJDIR)\report$O : report_.c report.h 372 + $(TCC) -o$@ -c report_.c 373 + 374 +report_.c : $(SRCDIR)\report.c 375 + +translate$E $** > $@ 376 + 377 +$(OBJDIR)\rss$O : rss_.c rss.h 378 + $(TCC) -o$@ -c rss_.c 379 + 380 +rss_.c : $(SRCDIR)\rss.c 381 + +translate$E $** > $@ 382 + 383 +$(OBJDIR)\schema$O : schema_.c schema.h 384 + $(TCC) -o$@ -c schema_.c 385 + 386 +schema_.c : $(SRCDIR)\schema.c 387 + +translate$E $** > $@ 388 + 389 +$(OBJDIR)\search$O : search_.c search.h 390 + $(TCC) -o$@ -c search_.c 391 + 392 +search_.c : $(SRCDIR)\search.c 393 + +translate$E $** > $@ 394 + 395 +$(OBJDIR)\setup$O : setup_.c setup.h 396 + $(TCC) -o$@ -c setup_.c 397 + 398 +setup_.c : $(SRCDIR)\setup.c 399 + +translate$E $** > $@ 400 + 401 +$(OBJDIR)\sha1$O : sha1_.c sha1.h 402 + $(TCC) -o$@ -c sha1_.c 403 + 404 +sha1_.c : $(SRCDIR)\sha1.c 405 + +translate$E $** > $@ 406 + 407 +$(OBJDIR)\shun$O : shun_.c shun.h 408 + $(TCC) -o$@ -c shun_.c 409 + 410 +shun_.c : $(SRCDIR)\shun.c 411 + +translate$E $** > $@ 412 + 413 +$(OBJDIR)\skins$O : skins_.c skins.h 414 + $(TCC) -o$@ -c skins_.c 415 + 416 +skins_.c : $(SRCDIR)\skins.c 417 + +translate$E $** > $@ 418 + 419 +$(OBJDIR)\stat$O : stat_.c stat.h 420 + $(TCC) -o$@ -c stat_.c 421 + 422 +stat_.c : $(SRCDIR)\stat.c 423 + +translate$E $** > $@ 424 + 425 +$(OBJDIR)\style$O : style_.c style.h 426 + $(TCC) -o$@ -c style_.c 427 + 428 +style_.c : $(SRCDIR)\style.c 429 + +translate$E $** > $@ 430 + 431 +$(OBJDIR)\sync$O : sync_.c sync.h 432 + $(TCC) -o$@ -c sync_.c 433 + 434 +sync_.c : $(SRCDIR)\sync.c 435 + +translate$E $** > $@ 436 + 437 +$(OBJDIR)\tag$O : tag_.c tag.h 438 + $(TCC) -o$@ -c tag_.c 439 + 440 +tag_.c : $(SRCDIR)\tag.c 441 + +translate$E $** > $@ 442 + 443 +$(OBJDIR)\th_main$O : th_main_.c th_main.h 444 + $(TCC) -o$@ -c th_main_.c 445 + 446 +th_main_.c : $(SRCDIR)\th_main.c 447 + +translate$E $** > $@ 448 + 449 +$(OBJDIR)\timeline$O : timeline_.c timeline.h 450 + $(TCC) -o$@ -c timeline_.c 451 + 452 +timeline_.c : $(SRCDIR)\timeline.c 453 + +translate$E $** > $@ 454 + 455 +$(OBJDIR)\tkt$O : tkt_.c tkt.h 456 + $(TCC) -o$@ -c tkt_.c 457 + 458 +tkt_.c : $(SRCDIR)\tkt.c 459 + +translate$E $** > $@ 460 + 461 +$(OBJDIR)\tktsetup$O : tktsetup_.c tktsetup.h 462 + $(TCC) -o$@ -c tktsetup_.c 463 + 464 +tktsetup_.c : $(SRCDIR)\tktsetup.c 465 + +translate$E $** > $@ 466 + 467 +$(OBJDIR)\undo$O : undo_.c undo.h 468 + $(TCC) -o$@ -c undo_.c 469 + 470 +undo_.c : $(SRCDIR)\undo.c 471 + +translate$E $** > $@ 472 + 473 +$(OBJDIR)\update$O : update_.c update.h 474 + $(TCC) -o$@ -c update_.c 475 + 476 +update_.c : $(SRCDIR)\update.c 477 + +translate$E $** > $@ 478 + 479 +$(OBJDIR)\url$O : url_.c url.h 480 + $(TCC) -o$@ -c url_.c 481 + 482 +url_.c : $(SRCDIR)\url.c 483 + +translate$E $** > $@ 484 + 485 +$(OBJDIR)\user$O : user_.c user.h 486 + $(TCC) -o$@ -c user_.c 487 + 488 +user_.c : $(SRCDIR)\user.c 489 + +translate$E $** > $@ 490 + 491 +$(OBJDIR)\verify$O : verify_.c verify.h 492 + $(TCC) -o$@ -c verify_.c 493 + 494 +verify_.c : $(SRCDIR)\verify.c 495 + +translate$E $** > $@ 496 + 497 +$(OBJDIR)\vfile$O : vfile_.c vfile.h 498 + $(TCC) -o$@ -c vfile_.c 499 + 500 +vfile_.c : $(SRCDIR)\vfile.c 501 + +translate$E $** > $@ 502 + 503 +$(OBJDIR)\wiki$O : wiki_.c wiki.h 504 + $(TCC) -o$@ -c wiki_.c 505 + 506 +wiki_.c : $(SRCDIR)\wiki.c 507 + +translate$E $** > $@ 508 + 509 +$(OBJDIR)\wikiformat$O : wikiformat_.c wikiformat.h 510 + $(TCC) -o$@ -c wikiformat_.c 511 + 512 +wikiformat_.c : $(SRCDIR)\wikiformat.c 513 + +translate$E $** > $@ 514 + 515 +$(OBJDIR)\winhttp$O : winhttp_.c winhttp.h 516 + $(TCC) -o$@ -c winhttp_.c 517 + 518 +winhttp_.c : $(SRCDIR)\winhttp.c 519 + +translate$E $** > $@ 520 + 521 +$(OBJDIR)\xfer$O : xfer_.c xfer.h 522 + $(TCC) -o$@ -c xfer_.c 523 + 524 +xfer_.c : $(SRCDIR)\xfer.c 525 + +translate$E $** > $@ 526 + 527 +$(OBJDIR)\zip$O : zip_.c zip.h 528 + $(TCC) -o$@ -c zip_.c 529 + 530 +zip_.c : $(SRCDIR)\zip.c 531 + +translate$E $** > $@ 532 + 533 +headers: makeheaders$E page_index.h VERSION.h 534 + +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h 535 + @copy /Y nul: headers
Added win/Makefile.msc.
1 +# DO NOT EDIT 2 +# 3 +# This file is automatically generated. Instead of editing this 4 +# file, edit "makemake.tcl" then run 5 +# "tclsh src/makemake.tcl msc > win/Makefile.msc" 6 +# to regenerate this file. 7 +B = .. 8 +SRCDIR = $B\src 9 +OBJDIR = . 10 +O = .obj 11 +E = .exe 12 + 13 +# Maybe MSCDIR, SSL, ZLIB, or INCL needs adjustment 14 +MSCDIR = c:\msc 15 + 16 +# Uncomment below for SSL support 17 +SSL = 18 +SSLLIB = 19 +#SSL = -DFOSSIL_ENABLE_SSL=1 20 +#SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib advapi32.lib 21 + 22 +# zlib options 23 +# When using precompiled from http://zlib.net/zlib125-dll.zip 24 +#ZINCDIR = C:\zlib125-dll\include 25 +#ZLIBDIR = C:\zlib125-dll\lib 26 +#ZLIB = zdll.lib 27 +ZINCDIR = $(MSCDIR)\extra\include 28 +ZLIBDIR = $(MSCDIR)\extra\lib 29 +ZLIB = zlib.lib 30 + 31 +INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR) 32 + 33 +MSCDEF = -Dstrncasecmp=memicmp -Dstrcasecmp=stricmp 34 +I18N = -DFOSSIL_I18N=0 35 + 36 +CFLAGS = -nologo -MT -O2 37 +BCC = $(CC) $(CFLAGS) 38 +TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(I18N) $(SSL) $(INCL) 39 +LIBS = $(ZLIB) ws2_32.lib $(SSLLIB) 40 +LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR) 41 + 42 +SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c 43 + 44 +OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O 45 + 46 + 47 +APPNAME = $(OBJDIR)\fossil$(E) 48 + 49 +all: $(OBJDIR) $(APPNAME) 50 + 51 +$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OBJDIR)\linkopts 52 + cd $(OBJDIR) 53 + link -LINK -OUT:$@ $(LIBDIR) @linkopts 54 + 55 +$(OBJDIR)\linkopts: $B\win\Makefile.msc 56 + echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@ 57 + echo $(LIBS) >> $@ 58 + 59 + 60 + 61 + 62 +$(OBJDIR): 63 + @-mkdir $@ 64 + 65 +translate$E: $(SRCDIR)\translate.c 66 + $(BCC) $** 67 + 68 +makeheaders$E: $(SRCDIR)\makeheaders.c 69 + $(BCC) $** 70 + 71 +mkindex$E: $(SRCDIR)\mkindex.c 72 + $(BCC) $** 73 + 74 +version$E: $B\win\version.c 75 + $(BCC) $** 76 + 77 +$(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c 78 + $(TCC) /Fo$@ -c -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 $** 79 + 80 +$(OBJDIR)\th$O : $(SRCDIR)\th.c 81 + $(TCC) /Fo$@ -c $** 82 + 83 +$(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c 84 + $(TCC) /Fo$@ -c $** 85 + 86 +VERSION.h : version$E $B\manifest.uuid $B\manifest 87 + $** > $@ 88 + 89 +page_index.h: mkindex$E $(SRC) 90 + $** > $@ 91 + 92 +clean: 93 + -del $(OBJDIR)\*.obj 94 + -del *.obj *_.c *.h *.map 95 + -del headers linkopts 96 + 97 +realclean: 98 + -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E 99 + 100 + 101 +$(OBJDIR)\add$O : add_.c add.h 102 + $(TCC) /Fo$@ -c add_.c 103 + 104 +add_.c : $(SRCDIR)\add.c 105 + translate$E $** > $@ 106 + 107 +$(OBJDIR)\allrepo$O : allrepo_.c allrepo.h 108 + $(TCC) /Fo$@ -c allrepo_.c 109 + 110 +allrepo_.c : $(SRCDIR)\allrepo.c 111 + translate$E $** > $@ 112 + 113 +$(OBJDIR)\attach$O : attach_.c attach.h 114 + $(TCC) /Fo$@ -c attach_.c 115 + 116 +attach_.c : $(SRCDIR)\attach.c 117 + translate$E $** > $@ 118 + 119 +$(OBJDIR)\bag$O : bag_.c bag.h 120 + $(TCC) /Fo$@ -c bag_.c 121 + 122 +bag_.c : $(SRCDIR)\bag.c 123 + translate$E $** > $@ 124 + 125 +$(OBJDIR)\blob$O : blob_.c blob.h 126 + $(TCC) /Fo$@ -c blob_.c 127 + 128 +blob_.c : $(SRCDIR)\blob.c 129 + translate$E $** > $@ 130 + 131 +$(OBJDIR)\branch$O : branch_.c branch.h 132 + $(TCC) /Fo$@ -c branch_.c 133 + 134 +branch_.c : $(SRCDIR)\branch.c 135 + translate$E $** > $@ 136 + 137 +$(OBJDIR)\browse$O : browse_.c browse.h 138 + $(TCC) /Fo$@ -c browse_.c 139 + 140 +browse_.c : $(SRCDIR)\browse.c 141 + translate$E $** > $@ 142 + 143 +$(OBJDIR)\captcha$O : captcha_.c captcha.h 144 + $(TCC) /Fo$@ -c captcha_.c 145 + 146 +captcha_.c : $(SRCDIR)\captcha.c 147 + translate$E $** > $@ 148 + 149 +$(OBJDIR)\cgi$O : cgi_.c cgi.h 150 + $(TCC) /Fo$@ -c cgi_.c 151 + 152 +cgi_.c : $(SRCDIR)\cgi.c 153 + translate$E $** > $@ 154 + 155 +$(OBJDIR)\checkin$O : checkin_.c checkin.h 156 + $(TCC) /Fo$@ -c checkin_.c 157 + 158 +checkin_.c : $(SRCDIR)\checkin.c 159 + translate$E $** > $@ 160 + 161 +$(OBJDIR)\checkout$O : checkout_.c checkout.h 162 + $(TCC) /Fo$@ -c checkout_.c 163 + 164 +checkout_.c : $(SRCDIR)\checkout.c 165 + translate$E $** > $@ 166 + 167 +$(OBJDIR)\clearsign$O : clearsign_.c clearsign.h 168 + $(TCC) /Fo$@ -c clearsign_.c 169 + 170 +clearsign_.c : $(SRCDIR)\clearsign.c 171 + translate$E $** > $@ 172 + 173 +$(OBJDIR)\clone$O : clone_.c clone.h 174 + $(TCC) /Fo$@ -c clone_.c 175 + 176 +clone_.c : $(SRCDIR)\clone.c 177 + translate$E $** > $@ 178 + 179 +$(OBJDIR)\comformat$O : comformat_.c comformat.h 180 + $(TCC) /Fo$@ -c comformat_.c 181 + 182 +comformat_.c : $(SRCDIR)\comformat.c 183 + translate$E $** > $@ 184 + 185 +$(OBJDIR)\configure$O : configure_.c configure.h 186 + $(TCC) /Fo$@ -c configure_.c 187 + 188 +configure_.c : $(SRCDIR)\configure.c 189 + translate$E $** > $@ 190 + 191 +$(OBJDIR)\content$O : content_.c content.h 192 + $(TCC) /Fo$@ -c content_.c 193 + 194 +content_.c : $(SRCDIR)\content.c 195 + translate$E $** > $@ 196 + 197 +$(OBJDIR)\db$O : db_.c db.h 198 + $(TCC) /Fo$@ -c db_.c 199 + 200 +db_.c : $(SRCDIR)\db.c 201 + translate$E $** > $@ 202 + 203 +$(OBJDIR)\delta$O : delta_.c delta.h 204 + $(TCC) /Fo$@ -c delta_.c 205 + 206 +delta_.c : $(SRCDIR)\delta.c 207 + translate$E $** > $@ 208 + 209 +$(OBJDIR)\deltacmd$O : deltacmd_.c deltacmd.h 210 + $(TCC) /Fo$@ -c deltacmd_.c 211 + 212 +deltacmd_.c : $(SRCDIR)\deltacmd.c 213 + translate$E $** > $@ 214 + 215 +$(OBJDIR)\descendants$O : descendants_.c descendants.h 216 + $(TCC) /Fo$@ -c descendants_.c 217 + 218 +descendants_.c : $(SRCDIR)\descendants.c 219 + translate$E $** > $@ 220 + 221 +$(OBJDIR)\diff$O : diff_.c diff.h 222 + $(TCC) /Fo$@ -c diff_.c 223 + 224 +diff_.c : $(SRCDIR)\diff.c 225 + translate$E $** > $@ 226 + 227 +$(OBJDIR)\diffcmd$O : diffcmd_.c diffcmd.h 228 + $(TCC) /Fo$@ -c diffcmd_.c 229 + 230 +diffcmd_.c : $(SRCDIR)\diffcmd.c 231 + translate$E $** > $@ 232 + 233 +$(OBJDIR)\doc$O : doc_.c doc.h 234 + $(TCC) /Fo$@ -c doc_.c 235 + 236 +doc_.c : $(SRCDIR)\doc.c 237 + translate$E $** > $@ 238 + 239 +$(OBJDIR)\encode$O : encode_.c encode.h 240 + $(TCC) /Fo$@ -c encode_.c 241 + 242 +encode_.c : $(SRCDIR)\encode.c 243 + translate$E $** > $@ 244 + 245 +$(OBJDIR)\file$O : file_.c file.h 246 + $(TCC) /Fo$@ -c file_.c 247 + 248 +file_.c : $(SRCDIR)\file.c 249 + translate$E $** > $@ 250 + 251 +$(OBJDIR)\finfo$O : finfo_.c finfo.h 252 + $(TCC) /Fo$@ -c finfo_.c 253 + 254 +finfo_.c : $(SRCDIR)\finfo.c 255 + translate$E $** > $@ 256 + 257 +$(OBJDIR)\graph$O : graph_.c graph.h 258 + $(TCC) /Fo$@ -c graph_.c 259 + 260 +graph_.c : $(SRCDIR)\graph.c 261 + translate$E $** > $@ 262 + 263 +$(OBJDIR)\http$O : http_.c http.h 264 + $(TCC) /Fo$@ -c http_.c 265 + 266 +http_.c : $(SRCDIR)\http.c 267 + translate$E $** > $@ 268 + 269 +$(OBJDIR)\http_socket$O : http_socket_.c http_socket.h 270 + $(TCC) /Fo$@ -c http_socket_.c 271 + 272 +http_socket_.c : $(SRCDIR)\http_socket.c 273 + translate$E $** > $@ 274 + 275 +$(OBJDIR)\http_ssl$O : http_ssl_.c http_ssl.h 276 + $(TCC) /Fo$@ -c http_ssl_.c 277 + 278 +http_ssl_.c : $(SRCDIR)\http_ssl.c 279 + translate$E $** > $@ 280 + 281 +$(OBJDIR)\http_transport$O : http_transport_.c http_transport.h 282 + $(TCC) /Fo$@ -c http_transport_.c 283 + 284 +http_transport_.c : $(SRCDIR)\http_transport.c 285 + translate$E $** > $@ 286 + 287 +$(OBJDIR)\info$O : info_.c info.h 288 + $(TCC) /Fo$@ -c info_.c 289 + 290 +info_.c : $(SRCDIR)\info.c 291 + translate$E $** > $@ 292 + 293 +$(OBJDIR)\login$O : login_.c login.h 294 + $(TCC) /Fo$@ -c login_.c 295 + 296 +login_.c : $(SRCDIR)\login.c 297 + translate$E $** > $@ 298 + 299 +$(OBJDIR)\main$O : main_.c main.h 300 + $(TCC) /Fo$@ -c main_.c 301 + 302 +main_.c : $(SRCDIR)\main.c 303 + translate$E $** > $@ 304 + 305 +$(OBJDIR)\manifest$O : manifest_.c manifest.h 306 + $(TCC) /Fo$@ -c manifest_.c 307 + 308 +manifest_.c : $(SRCDIR)\manifest.c 309 + translate$E $** > $@ 310 + 311 +$(OBJDIR)\md5$O : md5_.c md5.h 312 + $(TCC) /Fo$@ -c md5_.c 313 + 314 +md5_.c : $(SRCDIR)\md5.c 315 + translate$E $** > $@ 316 + 317 +$(OBJDIR)\merge$O : merge_.c merge.h 318 + $(TCC) /Fo$@ -c merge_.c 319 + 320 +merge_.c : $(SRCDIR)\merge.c 321 + translate$E $** > $@ 322 + 323 +$(OBJDIR)\merge3$O : merge3_.c merge3.h 324 + $(TCC) /Fo$@ -c merge3_.c 325 + 326 +merge3_.c : $(SRCDIR)\merge3.c 327 + translate$E $** > $@ 328 + 329 +$(OBJDIR)\name$O : name_.c name.h 330 + $(TCC) /Fo$@ -c name_.c 331 + 332 +name_.c : $(SRCDIR)\name.c 333 + translate$E $** > $@ 334 + 335 +$(OBJDIR)\pivot$O : pivot_.c pivot.h 336 + $(TCC) /Fo$@ -c pivot_.c 337 + 338 +pivot_.c : $(SRCDIR)\pivot.c 339 + translate$E $** > $@ 340 + 341 +$(OBJDIR)\popen$O : popen_.c popen.h 342 + $(TCC) /Fo$@ -c popen_.c 343 + 344 +popen_.c : $(SRCDIR)\popen.c 345 + translate$E $** > $@ 346 + 347 +$(OBJDIR)\pqueue$O : pqueue_.c pqueue.h 348 + $(TCC) /Fo$@ -c pqueue_.c 349 + 350 +pqueue_.c : $(SRCDIR)\pqueue.c 351 + translate$E $** > $@ 352 + 353 +$(OBJDIR)\printf$O : printf_.c printf.h 354 + $(TCC) /Fo$@ -c printf_.c 355 + 356 +printf_.c : $(SRCDIR)\printf.c 357 + translate$E $** > $@ 358 + 359 +$(OBJDIR)\rebuild$O : rebuild_.c rebuild.h 360 + $(TCC) /Fo$@ -c rebuild_.c 361 + 362 +rebuild_.c : $(SRCDIR)\rebuild.c 363 + translate$E $** > $@ 364 + 365 +$(OBJDIR)\report$O : report_.c report.h 366 + $(TCC) /Fo$@ -c report_.c 367 + 368 +report_.c : $(SRCDIR)\report.c 369 + translate$E $** > $@ 370 + 371 +$(OBJDIR)\rss$O : rss_.c rss.h 372 + $(TCC) /Fo$@ -c rss_.c 373 + 374 +rss_.c : $(SRCDIR)\rss.c 375 + translate$E $** > $@ 376 + 377 +$(OBJDIR)\schema$O : schema_.c schema.h 378 + $(TCC) /Fo$@ -c schema_.c 379 + 380 +schema_.c : $(SRCDIR)\schema.c 381 + translate$E $** > $@ 382 + 383 +$(OBJDIR)\search$O : search_.c search.h 384 + $(TCC) /Fo$@ -c search_.c 385 + 386 +search_.c : $(SRCDIR)\search.c 387 + translate$E $** > $@ 388 + 389 +$(OBJDIR)\setup$O : setup_.c setup.h 390 + $(TCC) /Fo$@ -c setup_.c 391 + 392 +setup_.c : $(SRCDIR)\setup.c 393 + translate$E $** > $@ 394 + 395 +$(OBJDIR)\sha1$O : sha1_.c sha1.h 396 + $(TCC) /Fo$@ -c sha1_.c 397 + 398 +sha1_.c : $(SRCDIR)\sha1.c 399 + translate$E $** > $@ 400 + 401 +$(OBJDIR)\shun$O : shun_.c shun.h 402 + $(TCC) /Fo$@ -c shun_.c 403 + 404 +shun_.c : $(SRCDIR)\shun.c 405 + translate$E $** > $@ 406 + 407 +$(OBJDIR)\skins$O : skins_.c skins.h 408 + $(TCC) /Fo$@ -c skins_.c 409 + 410 +skins_.c : $(SRCDIR)\skins.c 411 + translate$E $** > $@ 412 + 413 +$(OBJDIR)\stat$O : stat_.c stat.h 414 + $(TCC) /Fo$@ -c stat_.c 415 + 416 +stat_.c : $(SRCDIR)\stat.c 417 + translate$E $** > $@ 418 + 419 +$(OBJDIR)\style$O : style_.c style.h 420 + $(TCC) /Fo$@ -c style_.c 421 + 422 +style_.c : $(SRCDIR)\style.c 423 + translate$E $** > $@ 424 + 425 +$(OBJDIR)\sync$O : sync_.c sync.h 426 + $(TCC) /Fo$@ -c sync_.c 427 + 428 +sync_.c : $(SRCDIR)\sync.c 429 + translate$E $** > $@ 430 + 431 +$(OBJDIR)\tag$O : tag_.c tag.h 432 + $(TCC) /Fo$@ -c tag_.c 433 + 434 +tag_.c : $(SRCDIR)\tag.c 435 + translate$E $** > $@ 436 + 437 +$(OBJDIR)\th_main$O : th_main_.c th_main.h 438 + $(TCC) /Fo$@ -c th_main_.c 439 + 440 +th_main_.c : $(SRCDIR)\th_main.c 441 + translate$E $** > $@ 442 + 443 +$(OBJDIR)\timeline$O : timeline_.c timeline.h 444 + $(TCC) /Fo$@ -c timeline_.c 445 + 446 +timeline_.c : $(SRCDIR)\timeline.c 447 + translate$E $** > $@ 448 + 449 +$(OBJDIR)\tkt$O : tkt_.c tkt.h 450 + $(TCC) /Fo$@ -c tkt_.c 451 + 452 +tkt_.c : $(SRCDIR)\tkt.c 453 + translate$E $** > $@ 454 + 455 +$(OBJDIR)\tktsetup$O : tktsetup_.c tktsetup.h 456 + $(TCC) /Fo$@ -c tktsetup_.c 457 + 458 +tktsetup_.c : $(SRCDIR)\tktsetup.c 459 + translate$E $** > $@ 460 + 461 +$(OBJDIR)\undo$O : undo_.c undo.h 462 + $(TCC) /Fo$@ -c undo_.c 463 + 464 +undo_.c : $(SRCDIR)\undo.c 465 + translate$E $** > $@ 466 + 467 +$(OBJDIR)\update$O : update_.c update.h 468 + $(TCC) /Fo$@ -c update_.c 469 + 470 +update_.c : $(SRCDIR)\update.c 471 + translate$E $** > $@ 472 + 473 +$(OBJDIR)\url$O : url_.c url.h 474 + $(TCC) /Fo$@ -c url_.c 475 + 476 +url_.c : $(SRCDIR)\url.c 477 + translate$E $** > $@ 478 + 479 +$(OBJDIR)\user$O : user_.c user.h 480 + $(TCC) /Fo$@ -c user_.c 481 + 482 +user_.c : $(SRCDIR)\user.c 483 + translate$E $** > $@ 484 + 485 +$(OBJDIR)\verify$O : verify_.c verify.h 486 + $(TCC) /Fo$@ -c verify_.c 487 + 488 +verify_.c : $(SRCDIR)\verify.c 489 + translate$E $** > $@ 490 + 491 +$(OBJDIR)\vfile$O : vfile_.c vfile.h 492 + $(TCC) /Fo$@ -c vfile_.c 493 + 494 +vfile_.c : $(SRCDIR)\vfile.c 495 + translate$E $** > $@ 496 + 497 +$(OBJDIR)\wiki$O : wiki_.c wiki.h 498 + $(TCC) /Fo$@ -c wiki_.c 499 + 500 +wiki_.c : $(SRCDIR)\wiki.c 501 + translate$E $** > $@ 502 + 503 +$(OBJDIR)\wikiformat$O : wikiformat_.c wikiformat.h 504 + $(TCC) /Fo$@ -c wikiformat_.c 505 + 506 +wikiformat_.c : $(SRCDIR)\wikiformat.c 507 + translate$E $** > $@ 508 + 509 +$(OBJDIR)\winhttp$O : winhttp_.c winhttp.h 510 + $(TCC) /Fo$@ -c winhttp_.c 511 + 512 +winhttp_.c : $(SRCDIR)\winhttp.c 513 + translate$E $** > $@ 514 + 515 +$(OBJDIR)\xfer$O : xfer_.c xfer.h 516 + $(TCC) /Fo$@ -c xfer_.c 517 + 518 +xfer_.c : $(SRCDIR)\xfer.c 519 + translate$E $** > $@ 520 + 521 +$(OBJDIR)\zip$O : zip_.c zip.h 522 + $(TCC) /Fo$@ -c zip_.c 523 + 524 +zip_.c : $(SRCDIR)\zip.c 525 + translate$E $** > $@ 526 + 527 +headers: makeheaders$E page_index.h VERSION.h 528 + makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h 529 + @copy /Y nul: headers
Added win/fossil.ico.
cannot compute difference between binary files
Added win/fossil.rc.
1 +#include <windows.h> 2 +#include "VERSION.h" 3 +#define _RC_COMPILE_ 4 +#include "config.h" 5 + 6 +LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_US 7 + 8 +VS_VERSION_INFO VERSIONINFO 9 +FILEVERSION 1,0,0,0 10 +PRODUCTVERSION 1,0,0,0 11 +FILEFLAGSMASK 0x3F 12 +FILEFLAGS 0x0 13 +FILEOS VOS__WINDOWS32 14 +FILETYPE VFT_APP 15 +FILESUBTYPE VFT2_UNKNOWN 16 +BEGIN 17 + BLOCK "StringFileInfo" 18 + BEGIN 19 + BLOCK "040904B0" 20 + BEGIN 21 + VALUE "FileDescription", "distributed source code control system with integrated wiki and ticket-system\0" 22 + VALUE "Comments", "compiler: "COMPILER_NAME"\0" 23 + VALUE "FileVersion", MANIFEST_UUID"("COMPILER_NAME"\0" 24 + VALUE "InternalName", "fossil\0" 25 + VALUE "LegalCopyright", "Copyright (c) "MANIFEST_YEAR" D. Richard Hipp\0" 26 + VALUE "OriginalFilename", "fossil.exe\0" 27 + VALUE "ProductName", "fossil\0" 28 + VALUE "ProductVersion", MANIFEST_VERSION" "MANIFEST_DATE" UTC\0" 29 + END 30 + END 31 + BLOCK "VarFileInfo" 32 + BEGIN 33 + VALUE "Translation", 0x409, 0x4B0 34 + END 35 +END 36 + 37 +8001 ICON "fossil.ico" 38 +
Added win/include/dirent.h.
1 +/***************************************************************************** 2 + * dirent.h - dirent API for Microsoft Visual Studio 3 + * 4 + * Copyright (C) 2006 Toni Ronkko 5 + * 6 + * Permission is hereby granted, free of charge, to any person obtaining 7 + * a copy of this software and associated documentation files (the 8 + * ``Software''), to deal in the Software without restriction, including 9 + * without limitation the rights to use, copy, modify, merge, publish, 10 + * distribute, sublicense, and/or sell copies of the Software, and to 11 + * permit persons to whom the Software is furnished to do so, subject to 12 + * the following conditions: 13 + * 14 + * The above copyright notice and this permission notice shall be included 15 + * in all copies or substantial portions of the Software. 16 + * 17 + * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 + * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 + * OTHER DEALINGS IN THE SOFTWARE. 24 + * 25 + * Dec 15, 2009, John Cunningham 26 + * Added rewinddir member function 27 + * 28 + * Jan 18, 2008, Toni Ronkko 29 + * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string 30 + * between multi-byte and unicode representations. This makes the 31 + * code simpler and also allows the code to be compiled under MingW. Thanks 32 + * to Azriel Fasten for the suggestion. 33 + * 34 + * Mar 4, 2007, Toni Ronkko 35 + * Bug fix: due to the strncpy_s() function this file only compiled in 36 + * Visual Studio 2005. Using the new string functions only when the 37 + * compiler version allows. 38 + * 39 + * Nov 2, 2006, Toni Ronkko 40 + * Major update: removed support for Watcom C, MS-DOS and Turbo C to 41 + * simplify the file, updated the code to compile cleanly on Visual 42 + * Studio 2005 with both unicode and multi-byte character strings, 43 + * removed rewinddir() as it had a bug. 44 + * 45 + * Aug 20, 2006, Toni Ronkko 46 + * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified 47 + * comments by removing SGML tags. 48 + * 49 + * May 14 2002, Toni Ronkko 50 + * Embedded the function definitions directly to the header so that no 51 + * source modules need to be included in the Visual Studio project. Removed 52 + * all the dependencies to other projects so that this very header can be 53 + * used independently. 54 + * 55 + * May 28 1998, Toni Ronkko 56 + * First version. 57 + *****************************************************************************/ 58 +#ifndef DIRENT_H 59 +#define DIRENT_H 60 + 61 +#include <windows.h> 62 +#include <string.h> 63 +#include <assert.h> 64 + 65 + 66 +typedef struct dirent 67 +{ 68 + char d_name[MAX_PATH + 1]; /* current dir entry (multi-byte char string) */ 69 + WIN32_FIND_DATAA data; /* file attributes */ 70 +} dirent; 71 + 72 + 73 +typedef struct DIR 74 +{ 75 + dirent current; /* Current directory entry */ 76 + int cached; /* Indicates un-processed entry in memory */ 77 + HANDLE search_handle; /* File search handle */ 78 + char patt[MAX_PATH + 3]; /* search pattern (3 = pattern + "\\*\0") */ 79 +} DIR; 80 + 81 + 82 +/* Forward declarations */ 83 +static DIR *opendir (const char *dirname); 84 +static struct dirent *readdir (DIR *dirp); 85 +static int closedir (DIR *dirp); 86 +static void rewinddir(DIR* dirp); 87 + 88 + 89 +/* Use the new safe string functions introduced in Visual Studio 2005 */ 90 +#if defined(_MSC_VER) && _MSC_VER >= 1400 91 +# define STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE) 92 +#else 93 +# define STRNCPY(dest,src,size) strncpy((dest),(src),(size)) 94 +#endif 95 + 96 + 97 +/***************************************************************************** 98 + * Open directory stream DIRNAME for read and return a pointer to the 99 + * internal working area that is used to retrieve individual directory 100 + * entries. 101 + */ 102 +static DIR *opendir(const char *dirname) 103 +{ 104 + DIR *dirp; 105 + assert (dirname != NULL); 106 + assert (strlen (dirname) < MAX_PATH); 107 + 108 + /* construct new DIR structure */ 109 + dirp = (DIR*) malloc (sizeof (struct DIR)); 110 + if (dirp != NULL) { 111 + char *p; 112 + 113 + /* take directory name... */ 114 + STRNCPY (dirp->patt, dirname, sizeof(dirp->patt)); 115 + dirp->patt[MAX_PATH] = '\0'; 116 + 117 + /* ... and append search pattern to it */ 118 + p = strchr (dirp->patt, '\0'); 119 + if (dirp->patt < p && *(p-1) != '\\' && *(p-1) != ':') { 120 + *p++ = '\\'; 121 + } 122 + *p++ = '*'; 123 + *p = '\0'; 124 + 125 + /* open stream and retrieve first file */ 126 + dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data); 127 + if (dirp->search_handle == INVALID_HANDLE_VALUE) { 128 + /* invalid search pattern? */ 129 + free (dirp); 130 + return NULL; 131 + } 132 + 133 + /* there is an un-processed directory entry in memory now */ 134 + dirp->cached = 1; 135 + } 136 + 137 + return dirp; 138 +} 139 + 140 + 141 +/***************************************************************************** 142 + * Read a directory entry, and return a pointer to a dirent structure 143 + * containing the name of the entry in d_name field. Individual directory 144 + * entries returned by this very function include regular files, 145 + * sub-directories, pseudo-directories "." and "..", but also volume labels, 146 + * hidden files and system files may be returned. 147 + */ 148 +static struct dirent *readdir(DIR *dirp) 149 +{ 150 + assert (dirp != NULL); 151 + 152 + if (dirp->search_handle == INVALID_HANDLE_VALUE) { 153 + /* directory stream was opened/rewound incorrectly or ended normally */ 154 + return NULL; 155 + } 156 + 157 + /* get next directory entry */ 158 + if (dirp->cached != 0) { 159 + /* a valid directory entry already in memory */ 160 + dirp->cached = 0; 161 + } else { 162 + /* read next directory entry from disk */ 163 + if (FindNextFileA (dirp->search_handle, &dirp->current.data) == FALSE) { 164 + /* the very last file has been processed or an error occured */ 165 + FindClose (dirp->search_handle); 166 + dirp->search_handle = INVALID_HANDLE_VALUE; 167 + return NULL; 168 + } 169 + } 170 + 171 + /* copy as a multibyte character string */ 172 + STRNCPY ( dirp->current.d_name, 173 + dirp->current.data.cFileName, 174 + sizeof(dirp->current.d_name) ); 175 + dirp->current.d_name[MAX_PATH] = '\0'; 176 + 177 + return &dirp->current; 178 +} 179 + 180 + 181 +/***************************************************************************** 182 + * Close directory stream opened by opendir() function. Close of the 183 + * directory stream invalidates the DIR structure as well as any previously 184 + * read directory entry. 185 + */ 186 +static int closedir(DIR *dirp) 187 +{ 188 + assert (dirp != NULL); 189 + 190 + /* release search handle */ 191 + if (dirp->search_handle != INVALID_HANDLE_VALUE) { 192 + FindClose (dirp->search_handle); 193 + dirp->search_handle = INVALID_HANDLE_VALUE; 194 + } 195 + 196 + /* release directory handle */ 197 + free (dirp); 198 + return 0; 199 +} 200 + 201 + 202 +/***************************************************************************** 203 + * Resets the position of the directory stream to which dirp refers to the 204 + * beginning of the directory. It also causes the directory stream to refer 205 + * to the current state of the corresponding directory, as a call to opendir() 206 + * would have done. If dirp does not refer to a directory stream, the effect 207 + * is undefined. 208 + */ 209 +static void rewinddir(DIR* dirp) 210 +{ 211 + /* release search handle */ 212 + if (dirp->search_handle != INVALID_HANDLE_VALUE) { 213 + FindClose (dirp->search_handle); 214 + dirp->search_handle = INVALID_HANDLE_VALUE; 215 + } 216 + 217 + /* open new search handle and retrieve first file */ 218 + dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data); 219 + if (dirp->search_handle == INVALID_HANDLE_VALUE) { 220 + /* invalid search pattern? */ 221 + free (dirp); 222 + return; 223 + } 224 + 225 + /* there is an un-processed directory entry in memory now */ 226 + dirp->cached = 1; 227 +} 228 + 229 + 230 +#endif /*DIRENT_H*/
Added win/include/unistd.h.
1 +#ifndef _UNISTD_H 2 +#define _UNISTD_H 1 3 + 4 +/* This file intended to serve as a drop-in replacement for 5 + * unistd.h on Windows 6 + * Please add functionality as neeeded 7 + */ 8 + 9 +#include <stdlib.h> 10 +#include <io.h> 11 +#define srandom srand 12 +#define random rand 13 +#if defined(__DMC__) 14 +#endif 15 + 16 +#if defined(_WIN32) 17 +#define _CRT_SECURE_NO_WARNINGS 1 18 + 19 +#ifndef F_OK 20 +#define F_OK 0 21 +#endif /* not F_OK */ 22 + 23 +#ifndef X_OK 24 +#define X_OK 1 25 +#endif /* not X_OK */ 26 + 27 +#ifndef R_OK 28 +#define R_OK 2 29 +#endif /* not R_OK */ 30 + 31 +#ifndef W_OK 32 +#define W_OK 4 33 +#endif /* not W_OK */ 34 + 35 +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 36 +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 37 + 38 + 39 + 40 +#endif 41 + 42 +#define access _access 43 +#define ftruncate _chsize 44 + 45 +#define ssize_t int 46 + 47 +#endif /* unistd.h */
Added win/version.c.
1 +#include <stdio.h> 2 + 3 +int main(int argc, char *argv[]){ 4 + FILE *m,*u; 5 + char b[10240]; 6 + u = fopen(argv[1],"r"); 7 + fgets(b, sizeof(b)-1,u); 8 + b[strlen(b)-1] =0; 9 + printf("#define MANIFEST_UUID \"%s\"\n",b); 10 + printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b); 11 + m = fopen(argv[2],"r"); 12 + while(b == fgets(b, sizeof(b)-1,m)){ 13 + if(0 == strncmp("D ",b,2)){ 14 + printf("#define MANIFEST_DATE \"%.10s %.8s\"\n",b+2,b+13); 15 + printf("#define MANIFEST_YEAR \"%.4s\"\n",b+2); 16 + return 0; 17 + } 18 + } 19 + return 1; 20 +}
Changes to www/branching.wiki.
153 153 concerned, there is no difference. The distinction is in the intent. 154 154 In figure 2, the fact that check-in 2 has multiple children is an 155 155 accident that stems from concurrent development. In figure 4, giving 156 156 check-in 2 multiple children is a deliberate act. So, to a good 157 157 approximation, we define forking to be by accident and branching to 158 158 be by intent. Apart from that, they are the same. 159 159 160 +<a name="tags"></a> 160 161 <h2>Tags And Properties</h2> 161 162 162 163 Tags and properties are used in fossil to help express the intent, and 163 164 thus to distinguish between forks and branches. Figure 5 shows the 164 165 same scenario as figure 4 but with tags and properties added: 165 166 166 167 <center><table border=1 cellpadding=10 hspace=10 vspace=10>
Added www/event.wiki.
1 +<title>Events</title> 2 + 3 +<h2>What Is An "Event"?</h2> 4 + 5 +In Fossil, and "event" is a special kind of [./wikitheory.wiki | wiki page] 6 +that is associated with a point in time rather than having a page name. 7 +Each event causes a single entry to appear on the [/timeline | Timeline Page]. 8 +Clicking on the hyperlink of the timeline entry cause a jump to the wiki 9 +content for the event. The wiki content, the timeline entry text, the 10 +time of the event, and the timeline background color can all be edited. 11 + 12 +As with check-ins, wiki, and tickets, all events automatically synchronize 13 +to other repositories. Hence, events can be viewed, created, and edited 14 +off-line. And the complete edit history for events is maintained 15 +for auditing purposes. 16 + 17 +Possible uses for events include: 18 + 19 + * <b>Milestones</b>. Project milestones, such as releases or beta-test 20 + cycles, can be recorded as events. The timeline entry for the event 21 + can be something simple like "Version 1.2.3" perhaps with a bright 22 + color background to draw attention to the entry and the wiki content 23 + can contain release notes, for example. 24 + 25 + * <b>Blog Entries</b>. Blog entries from developers describing the current 26 + state of a project, or rational for various design decisions, or 27 + roadmaps for future development, can be entered as events. 28 + 29 + * <b>Process Checkpoints</b>. For projects that have a formal process, 30 + events can be used to record the completion or the initiation of 31 + various process steps. For example, an event can be used to record 32 + the successful completion of a long-running test, perhaps with 33 + performance results and details of where the test was run and who 34 + ran it recorded in the wiki content. 35 + 36 + * <b>News Articles</b>. Significant occurrences in the lifecycle of 37 + a project can be recorded as news articles using events. Perhaps the 38 + domain name of the canonical website for a project changes, or new 39 + server hardware is obtained. Such happenings are appropriate for 40 + reporting as news. 41 + 42 + * <b>Announcements</b>. Changes to the composition of the development 43 + team or acquisition of new project sponsors can be communicated as 44 + announcements which can be implemented as events. 45 + 46 +No project is required to use events. But events can help many projects 47 +stay better organized and provide a better historical record of the 48 +development progress. 49 + 50 +<h2>Viewing Events</h2> 51 + 52 +Because events are considered a special kind of wiki, 53 +users must have permission to read wiki in order read events. 54 +Enable the "j" permission under the /Setup/Users menu in order 55 +to give specific users or user classes the ability to view wiki 56 +and events. 57 + 58 +Events show up on the timeline. Click on the hyperlink beside the 59 +event title to see the details of the event. 60 + 61 +<h2>Creating And Editing Events</h2> 62 + 63 +There is a hyperlink under the /Wiki menu that can be used to create 64 +new events. And there is a submenu hyperlink on event displays for 65 +editing existing events. 66 + 67 +Users must have check-in privileges (permission "i") in order to 68 +create or edit events. In addition, users must have create-wiki 69 +privilege (permission "f") to create new events and edit-wiki 70 +privilege (permission "k") in order to edit existing events. 71 + 72 +If the first non-whitespace text of the event wiki content is 73 +<title>...</title> then that markup is omitted from 74 +the body of the wiki pages and is instead displayed as the page 75 +title.
Changes to www/fileformat.wiki.
41 41 <ul> 42 42 <li> [#manifest | Manifests] </li> 43 43 <li> [#cluster | Clusters] </li> 44 44 <li> [#ctrl | Control Artifacts] </li> 45 45 <li> [#wikichng | Wiki Pages] </li> 46 46 <li> [#tktchng | Ticket Changes] </li> 47 47 <li> [#attachment | Attachments] </li> 48 +<li> [#event | Events] </li> 48 49 </ul> 49 50 50 -These five artifact types are described in the sequel. 51 +These seven artifact types are described in the sequel. 51 52 52 53 In the current implementation (as of 2009-01-25) the artifacts that 53 54 make up a fossil repository are stored in in as delta- and zlib-compressed 54 55 blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This 55 56 is an implementation detail and might change in a future release. For 56 57 the purpose of this article "file format" means the format of the artifacts, 57 58 not how the artifacts are stored on disk. It is the artifact format that 58 59 is intended to be enduring. The specifics of how artifacts are stored on 59 60 disk, though stable, is not intended to live as long as the 60 61 artifact format. 62 + 63 +All of the artifacts can be extracted from a Fossil repository using 64 +the "fossil deconstruct" command. 61 65 62 66 <a name="manifest"></a> 63 67 <h2>1.0 The Manifest</h2> 64 68 65 69 A manifest defines a check-in or version of the project 66 70 source tree. The manifest contains a list of artifacts for 67 71 each file in the project and the corresponding filenames, as ................................................................................ 89 93 No card may be duplicated. 90 94 The entire manifest may be PGP clear-signed, but otherwise it 91 95 may contain no additional text or data beyond what is described here. 92 96 93 97 Allowed cards in the manifest are as follows: 94 98 95 99 <blockquote> 100 +<b>B</b> <i>baseline-manifest</i><br> 96 101 <b>C</b> <i>checkin-comment</i><br> 97 102 <b>D</b> <i>time-and-date-stamp</i><br> 98 103 <b>F</b> <i>filename</i> <i>SHA1-hash</i> <i>permissions</i> <i>old-name</i><br> 99 104 <b>P</b> <i>SHA1-hash</i>+<br> 100 105 <b>R</b> <i>repository-checksum</i><br> 101 106 <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name <b>*</b> ?value?</i><br> 102 107 <b>U</b> <i>user-login</i><br> 103 108 <b>Z</b> <i>manifest-checksum</i> 104 109 </blockquote> 110 + 111 +A manifest may optionally have a single B-card. The B-card specifies 112 +another manifest that serves as the "baseline" for this manifest. A 113 +manifest that has a B-card is called a delta-manifest and a manifest 114 +that omits the B-card is a baseline-manifest. The other manifest 115 +identified by the argument of the B-card must be a baseline-manifest. 116 +A baseline-manifest records the complete contents of a checkin. 117 +A delta-manifest records only changes from its baseline. 105 118 106 119 A manifest must have exactly one C-card. The sole argument to 107 120 the C-card is a check-in comment that describes the check-in that 108 121 the manifest defines. The check-in comment is text. The following 109 122 escape sequences are applied to the text: 110 123 A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A 111 -newline (ASCII 0x0a) is "\n" (ASCII 0x6C, x6E). A backslash 124 +newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash 112 125 (ASCII 0x5C) is represented as two backslashes "\\". Apart from 113 126 space and newline, no other whitespace characters are allowed in 114 127 the check-in comment. Nor are any unprintable characters allowed 115 128 in the comment. 116 129 117 130 A manifest must have exactly one D-card. The sole argument to 118 131 the D-card is a date-time stamp in the ISO8601 format. The ................................................................................ 119 132 date and time should be in coordinated universal time (UTC). 120 133 The format is: 121 134 122 135 <blockquote> 123 136 <i>YYYY</i><b>-</b><i>MM</i><b>-</b><i>DD</i><b>T</b><i>HH</i><b>:</b><i>MM</i><b>:</b><i>SS</i> 124 137 </blockquote> 125 138 126 -A manifest has zero or more F-cards. Each F-card defines a file 127 -(other than the manifest itself) which is part of the check-in that 128 -the manifest defines. There are two, three, or four arguments. 139 +A manifest has zero or more F-cards. Each F-card identifies a file 140 +that is part of the check-in. There are one, two, three, or four arguments. 129 141 The first argument 130 142 is the pathname of the file in the check-in relative to the root 131 143 of the project file hierarchy. No ".." or "." directories are allowed 132 144 within the filename. Space characters are escaped as in C-card 133 145 comment text. Backslash characters and newlines are not allowed 134 146 within filenames. The directory separator character is a forward 135 147 slash (ASCII 0x2F). The second argument to the F-card is the 136 148 full 40-character lower-case hexadecimal SHA1 hash of the content 137 -artifact. The optional 3rd argument defines any special access 149 +artifact. The second argument is required for baseline manifests 150 +but is optional for delta manifests. When the second argument to the 151 +F-card is omitted, it means that the file has been deleted relative 152 +to the baseline. The optional 3rd argument defines any special access 138 153 permissions associated with the file. The only special code currently 139 154 defined is "x" which means that the file is executable. All files are 140 155 always readable and writable. This can be expressed by "w" permission 141 -if desired but is optional. 156 +if desired but is optional. The file format might be extended with 157 +new permission letters in the future. 142 158 The optional 4th argument is the name of the same file as it existed in 143 159 the parent check-in. If the name of the file is unchanged from its 144 160 parent, then the 4th argument is omitted. 145 161 146 162 A manifest has zero or one P-cards. Most manifests have one P-card. 147 163 The P-card has a varying number of arguments that 148 164 defines other manifests from which the current manifest ................................................................................ 163 179 the manifest itself) in strict sorted lexicographical order, 164 180 take the pathname of the file relative to the root of the 165 181 repository, append a single space (ASCII 0x20), the 166 182 size of the file in ASCII decimal, a single newline 167 183 character (ASCII 0x0A), and the complete text of the file. 168 184 Compute the MD5 checksum of the result. 169 185 170 -A manifest might contain one or more T-cards used to set tags or 171 -properties on the check-in. The format of the T-card is the same as 186 +A manifest might contain one or more T-cards used to set 187 +[./branching.wiki#tags | tags or properties] 188 +on the check-in. The format of the T-card is the same as 172 189 described in <i>Control Artifacts</i> section below, except that the 173 190 second argument is the single characcter "<b>*</b>" instead of an 174 191 artifact ID. The <b>*</b> in place of the artifact ID indicates that 175 192 the tag or property applies to the current artifact. It is not 176 193 possible to encode the current artifact ID as part of an artifact, 177 194 since the act of inserting the artifact ID would change the artifact ID, 178 195 hence a <b>*</b> is used to represent "self". T-cards are typically ................................................................................ 180 197 symbolic name when the check-in is intended to start a new branch. 181 198 182 199 Each manifest has a single U-card. The argument to the U-card is 183 200 the login of the user who created the manifest. The login name 184 201 is encoded using the same character escapes as is used for the 185 202 check-in comment argument to the C-card. 186 203 187 -A manifest has an option Z-card as its last line. The argument 204 +A manifest has an optional Z-card as its last line. The argument 188 205 to the Z-card is a 32-character lowercase hexadecimal MD5 hash 189 206 of all prior lines of the manifest up to and including the newline 190 207 character that immediately precedes the "Z". The Z-card is just 191 208 a sanity check to prove that the manifest is well-formed and 192 209 consistent. 193 210 194 211 A sample manifest from Fossil itself can be seen ................................................................................ 260 277 one or more T cards. No other cards or other text is 261 278 allowed in a control artifact. Control artifacts might be PGP 262 279 clearsigned. 263 280 264 281 The D card and the Z card of a control artifact are the same 265 282 as in a manifest. 266 283 267 -The T card represents a "tag" or property that is applied to 284 +The T card represents a [./branching.wiki#tags | tag or property] 285 +that is applied to 268 286 some other artifact. The T card has two or three values. The 269 287 second argument is the 40 character lowercase artifact ID of the artifact 270 288 to which the tag is to be applied. The 271 289 first value is the tag name. The first character of the tag 272 290 is either "+", "-", or "*". A "+" means the tag should be added 273 291 to the artifact. The "-" means the tag should be removed. 274 292 The "*" character means the tag should be added to the artifact ................................................................................ 322 340 The W card is used to specify the text of the wiki page. The 323 341 argument to the W card is an integer which is the number of bytes 324 342 of text in the wiki page. That text follows the newline character 325 343 that terminates the W card. The wiki text is always followed by one 326 344 extra newline. 327 345 328 346 An example wiki artifact can be seen 329 -[/artifact/7b2f5fd0e0 | here]. 347 +[/artifact?name=7b2f5fd0e0&txt=1 | here]. 330 348 331 349 <a name="tktchng"></a> 332 350 <h2>5.0 Ticket Changes</h2> 333 351 334 352 A ticket-change artifact represents a change to a trouble ticket. 335 353 The following cards are allowed on a ticket change artifact: 336 354 ................................................................................ 373 391 An example ticket-change artifact can be seen 374 392 [/artifact/91f1ec6af053 | here]. 375 393 376 394 <a name="attachment"></a> 377 395 <h2>6.0 Attachments</h2> 378 396 379 397 An attachment artifact associates some other artifact that is the 380 -attachment (the source artifact) with a ticket or wiki page to which 398 +attachment (the source artifact) with a ticket or wiki page or event to which 381 399 the attachment is connected (the target artifact). 382 400 The following cards are allowed on an attachment artifact: 383 401 384 402 <blockquote> 385 -<b>A</b> <i>filename target</i> ?<i>source</i>? 386 -<b>C</b> <i>comment</i><br> 403 +<b>A</b> <i>filename target</i> ?<i>source</i>?<br /> 404 +<b>C</b> <i>comment</i><br /> 387 405 <b>D</b> <i>time-and-date-stamp</i><br /> 388 406 <b>U</b> <i>user-name</i><br /> 389 407 <b>Z</b> <i>checksum</i> 390 408 </blockquote> 391 409 392 410 The A card specifies a filename for the attachment in its first argument. 393 411 The second argument to the A card is the name 394 -of the wiki page or ticket to which the attachment is connected. The 412 +of the wiki page or ticket or event to which the attachment is connected. The 395 413 third argument is either missing or else it is the 40-character artifact 396 414 ID of the attachment itself. A missing third argument means that the 397 415 attachment should be deleted. 398 416 399 417 The C card is an optional comment describing what the attachment is about. 400 418 The C card is optional, but there can only be one. 401 419 ................................................................................ 403 421 was applied. 404 422 405 423 A single U card gives the name of the user to added the attachment. 406 424 If an attachment is added anonymously, then the U card may be omitted. 407 425 408 426 The Z card is the usual checksum over the rest of the attachment artifact. 409 427 428 + 429 +<a name="event"></a> 430 +<h2>7.0 Events</h2> 431 + 432 +An event artifact associates a timeline comment and a page of text 433 +(similar to a wiki page) with a point in time. Events can be used 434 +to record project milestones, release notes, blog entries, process 435 +checkpoints, or news articles. 436 +The following cards are allowed on an event artifact: 437 + 438 +<blockquote> 439 +<b>C</b> <i>comment</i><br> 440 +<b>D</b> <i>time-and-date-stamp</i><br /> 441 +<b>E</b> <i>event-time</i> <i>event-id</i><br /> 442 +<b>P</b> <i>parent-artifact-id</i>+<br /> 443 +<b>T</b> <b>+</b><i>tag-name</i> <b>*</b> <i>value</i><br /> 444 +<b>U</b> <i>user-name</i><br /> 445 +<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br /> 446 +<b>Z</b> <i>checksum</i> 447 +</blockquote> 448 + 449 +The C card contains text that is displayed on the timeline for the 450 +event. Exactly one C card is required on an event artifact. 451 + 452 +A single D card is required to give the date and time when the 453 +event artifact was created. This is different from the time at which 454 +the event occurs. 455 + 456 +A single E card gives the time of the event (the point on the timeline 457 +where the event is displayed) and a unique identifier for the event. 458 +When there are multiple artifacts with the same event-id, the one with 459 +the most recent D card is the only one used. The event-id must be a 460 +40-character lower-case hexadecimal string. 461 + 462 +The option P card specifies a prior event with the same event-id from 463 +which the current event is an edit. The P card is a hint to the system 464 +that it might be space efficient to store one event as a delta of the 465 +other. 466 + 467 +An event might contain one or more T-cards used to set 468 +[./branching.wiki#tags | tags or properties] 469 +on the event. The format of the T-card is the same as 470 +described in [#ctrl | Control Artifacts] section above, except that the 471 +second argument is the single characcter "<b>*</b>" instead of an 472 +artifact ID and the name is always prefaced by "<b>+</b>". 473 +The <b>*</b> in place of the artifact ID indicates that 474 +the tag or property applies to the current artifact. It is not 475 +possible to encode the current artifact ID as part of an artifact, 476 +since the act of inserting the artifact ID would change the artifact ID, 477 +hence a <b>*</b> is used to represent "self". The "<b>+</b>" on the 478 +name means that tags can only be add and they can only be non-propagating 479 +tags. A an event, T cards are normally used to set the background 480 +display color for timelines. 481 + 482 +The optional U card gives name of the user who entered the event. 483 + 484 +A single W card provides wiki text for the document associated with the 485 +event. The format of the W card is exactly the same as for a 486 +[#wikichng | wiki artifact]. 487 + 488 +The Z card is the usual checksum over the rest of the attachment artifact. 489 + 410 490 411 491 <a name="summary"></a> 412 -<h2>7.0 Card Summary</h2> 492 +<h2>8.0 Card Summary</h2> 413 493 414 494 The following table summaries the various kinds of cards that 415 495 appear on Fossil artifacts: 416 496 417 497 <table border=1 width="100%"> 418 498 <tr> 419 499 <th rowspan=2 valign=bottom>Card Format</th> 420 -<th colspan=6>Used By</th> 500 +<th colspan=7>Used By</th> 421 501 </tr> 422 502 <tr> 423 503 <th>Manifest</th> 424 504 <th>Cluster</th> 425 505 <th>Control</th> 426 506 <th>Wiki</th> 427 507 <th>Ticket</th> 428 508 <th>Attachment</th> 509 +<th>Event</th> 429 510 </tr> 430 511 <tr> 431 512 <td><b>A</b> <i>filename target source</i></td> 432 513 <td> </td> 433 514 <td> </td> 434 515 <td> </td> 435 516 <td> </td> 436 517 <td> </td> 437 518 <td align=center><b>X</b></td> 519 +<td> </td> 438 520 </tr> 439 521 <tr> 440 -<td><b>C</b> <i>coment-text</i></td> 522 +<td><b>B</b> <i>baseline</i></td> 523 +<td align=center><b>X</b></td> 524 +<td> </td> 525 +<td> </td> 526 +<td> </td> 527 +<td> </td> 528 +<td> </td> 529 +<td> </td> 530 +</tr> 531 +<tr> 532 +<td><b>C</b> <i>comment-text</i></td> 441 533 <td align=center><b>X</b></td> 442 534 <td> </td> 443 535 <td> </td> 444 536 <td> </td> 445 537 <td> </td> 538 +<td align=center><b>X</b></td> 446 539 <td align=center><b>X</b></td> 447 540 </tr> 448 541 <tr> 449 542 <td><b>D</b> <i>date-time-stamp</i></td> 450 543 <td align=center><b>X</b></td> 451 544 <td align=center> </td> 452 545 <td align=center><b>X</b></td> 453 546 <td align=center><b>X</b></td> 454 547 <td align=center><b>X</b></td> 455 548 <td align=center><b>X</b></td> 549 +<td align=center><b>X</b></td> 550 +</tr> 551 +<tr> 552 +<td><b>E</b> <i>event-time event-id</i></td> 553 +<td align=center> </td> 554 +<td align=center> </td> 555 +<td align=center> </td> 556 +<td align=center> </td> 557 +<td align=center> </td> 558 +<td align=center> </td> 559 +<td align=center><b>X</b></td> 456 560 </tr> 457 561 <tr> 458 562 <td><b>F</b> <i>filename uuid permissions oldname</i></td> 459 563 <td align=center><b>X</b></td> 564 +<td align=center> </td> 460 565 <td align=center> </td> 461 566 <td align=center> </td> 462 567 <td align=center> </td> 463 568 <td align=center> </td> 464 569 <td align=center> </td> 465 570 </tr> 466 571 <tr> ................................................................................ 467 572 <td><b>J</b> <i>name value</i></td> 468 573 <td align=center> </td> 469 574 <td align=center> </td> 470 575 <td align=center> </td> 471 576 <td align=center> </td> 472 577 <td align=center><b>X</b></td> 473 578 <td align=center> </td> 579 +<td align=center> </td> 474 580 </tr> 475 581 <tr> 476 582 <td><b>K</b> <i>ticket-uuid</i></td> 477 583 <td align=center> </td> 478 584 <td align=center> </td> 479 585 <td align=center> </td> 480 586 <td align=center> </td> 481 587 <td align=center><b>X</b></td> 588 +<td align=center> </td> 482 589 <td align=center> </td> 483 590 </tr> 484 591 <tr> 485 592 <td><b>L</b> <i>wiki-title</i></td> 486 593 <td align=center> </td> 487 594 <td align=center> </td> 488 595 <td align=center> </td> 489 596 <td align=center><b>X</b></td> 490 597 <td align=center> </td> 491 598 <td align=center> </td> 599 +<td align=center> </td> 492 600 </tr> 493 601 <tr> 494 602 <td><b>M</b> <i>uuid</i></td> 495 603 <td align=center> </td> 496 604 <td align=center><b>X</b></td> 605 +<td align=center> </td> 497 606 <td align=center> </td> 498 607 <td align=center> </td> 499 608 <td align=center> </td> 500 609 <td align=center> </td> 501 610 </tr> 502 611 <tr> 503 612 <td><b>P</b> <i>uuid ...</i></td> 504 613 <td align=center><b>X</b></td> 505 614 <td align=center> </td> 506 615 <td align=center> </td> 507 616 <td align=center><b>X</b></td> 508 617 <td align=center> </td> 509 618 <td align=center> </td> 619 +<td align=center> </td> 510 620 </tr> 511 621 <tr> 512 622 <td><b>R</b> <i>md5sum</i></td> 513 623 <td align=center><b>X</b></td> 624 +<td align=center> </td> 514 625 <td align=center> </td> 515 626 <td align=center> </td> 516 627 <td align=center> </td> 517 628 <td align=center> </td> 518 629 <td align=center> </td> 519 630 <tr> 520 631 <td><b>T</b> (<b>+</b>|<b>*</b>|<b>-</b>)<i>tagname uuid value</i></td> 521 632 <td align=center><b>X</b></td> 522 633 <td align=center> </td> 523 634 <td align=center><b>X</b></td> 524 635 <td align=center> </td> 525 636 <td align=center> </td> 526 637 <td align=center> </td> 638 +<td align=center><b>X</b></td> 527 639 </tr> 528 640 <tr> 529 641 <td><b>U</b> <i>username</i></td> 530 642 <td align=center><b>X</b></td> 531 643 <td align=center> </td> 644 +<td align=center><b>X</b></td> 532 645 <td align=center><b>X</b></td> 533 646 <td align=center><b>X</b></td> 534 647 <td align=center><b>X</b></td> 535 648 <td align=center><b>X</b></td> 536 649 </tr> 537 650 <tr> 538 651 <td><b>W</b> <i>size</i></td> 539 652 <td align=center> </td> 540 653 <td align=center> </td> 541 654 <td align=center> </td> 542 655 <td align=center><b>X</b></td> 543 656 <td align=center> </td> 544 657 <td align=center> </td> 658 +<td align=center><b>X</b></td> 545 659 </tr> 546 660 <tr> 547 661 <td><b>Z</b> <i>md5sum</i></td> 662 +<td align=center><b>X</b></td> 548 663 <td align=center><b>X</b></td> 549 664 <td align=center><b>X</b></td> 550 665 <td align=center><b>X</b></td> 551 666 <td align=center><b>X</b></td> 552 667 <td align=center><b>X</b></td> 553 668 <td align=center><b>X</b></td> 554 669 </tr> 555 670 </table>
Changes to www/index.wiki.
38 38 39 39 There are plenty of open-source version control systems available on the 40 40 internet these days. What makes Fossil worthy of attention? 41 41 42 42 1. <b>Bug Tracking And Wiki</b> - 43 43 In addition to doing [./concepts.wiki | distributed version control] 44 44 like Git and Mercurial, 45 - Fossil also supports [./bugtheory.wiki | distributed bug tracking] and 46 - [./wikitheory.wiki | distributed wiki] all in a single 45 + Fossil also supports [./bugtheory.wiki | distributed bug tracking], 46 + [./wikitheory.wiki | distributed wiki], and a 47 + [./event.wiki | distributed blog] mechanism all in a single 47 48 integrated package. 48 49 49 50 2. <b>Web Interface</b> - 50 51 Fossil has a built-in and easy-to-use [./webui.wiki | web interface] 51 52 that simplifies project tracking and promotes situational awareness. 52 53 Simply type "fossil ui" from within any check-out and Fossil 53 54 automatically opens your web browser in a page that gives detailed ................................................................................ 86 87 used by the [./selfhost.wiki | self-hosting fossil repositories]. 87 88 88 89 7. <b>Robust & Reliable</b> - 89 90 Fossil stores content using an [./fileformat.wiki | enduring file format] 90 91 in an SQLite database so that transactions are 91 92 atomic even if interrupted by a power loss or system crash. Furthermore, 92 93 automatic [./selfcheck.wiki | self-checks] verify that all aspects of 93 - the repository are consistent prior to each commit. In nearly three years 94 + the repository are consistent prior to each commit. In over three years 94 95 of operation, no work has ever been lost after having been committed to 95 96 a Fossil repository. 96 97 97 98 <hr> 98 99 <h3>Links For Fossil Users:</h3> 99 100 100 101 * [./reviews.wiki | Testimonials] from satisfied fossil users. ................................................................................ 109 110 designed to be readable, searchable, and extensible by people 110 111 not yet born. 111 112 * A tutorial on [./branching.wiki | branching], what it means and how 112 113 to do it using fossil. 113 114 * The [./selfcheck.wiki | automatic self-check] mechanism 114 115 helps insure project integrity. 115 116 * Fossil contains a [./wikitheory.wiki | built-in wiki]. 117 + * An [./event.wiki | Event] is a special kind of wiki page associated 118 + with a point in time rather than a name. 116 119 * There is a 117 120 [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable 118 121 [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org | archives] 119 122 available for discussing fossil issues. 120 123 * [./stats.wiki | Performance statistics] taken from real-world projects 121 124 hosted on fossil. 122 125 * How to [./shunning.wiki | delete content] from a fossil repository.
Changes to www/password.wiki.
58 58 all login for that user. Thus, to lock a user out of the system, 59 59 one has only to set their password to an empty string, using either 60 60 the web interface or direct SQL manipulation of the USER table. 61 61 Note also that the password field is 62 62 essentially ignored for the special users named "anonymous", "developer", 63 63 "reader", and "nobody". It is not possible to authenticate as users 64 64 "developer", "reader", or "nobody" and the authentication protocol 65 -for "anonymous" use one-time captchas not persistent passwords. 65 +for "anonymous" uses one-time captchas not persistent passwords. 66 66 67 67 <h2>Web Interface Authentication</h2> 68 68 69 69 When a user logs into Fossil using the web interface, the login name 70 70 and password are sent in the clear to the server. The server then 71 71 hashes the password and compares it against the value stored in USER.PW. 72 72 If they match, the server sets a cookie on the client to record the 73 73 login. This cookie contains a large amount of high-quality randomness 74 -and is thus impossible to guess. The value of the cookie and the IP 74 +and is thus intractable to guess. The value of the cookie and the IP 75 75 address of the client is stored in the USER.COOKIE and USER.IPADDR fields 76 76 of the USER table on the server. 77 77 The USER.CEXPIRE field holds an expiration date 78 78 for the cookie, encoded as a julian day number. On all subsequent 79 79 HTTP requests, the cookie value is matched against the USER table to 80 80 enable access to the repository. 81 81
Changes to www/qandc.wiki.
61 61 fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>, 62 62 for example. 63 63 Other projects are also adopting fossil. But fossil does not yet have 64 64 the massive user base of git or mercurial. 65 65 </blockquote> 66 66 67 67 <b>Fossil looks like the bug tracker that would be in your 68 -Linksys Router's administration screen.</p> 68 +Linksys Router's administration screen.</b> 69 69 70 70 <blockquote> 71 71 <p>I take a pragmatic approach to software: form follows function. 72 72 To me, it is more important to have a reliable, fast, efficient, 73 73 enduring, and simple DVCS than one that looks pretty.</p> 74 74 75 75 <p>On the other hand, if you have patches that improve the appearance
Changes to www/quickstart.wiki.
230 230 231 231 <p>Or</b> 232 232 233 233 <blockquote> 234 234 <b>fossil ui</b> <i>repository-filename</i> 235 235 </blockquote> 236 236 237 - <p>The difference between these two command is that <b>ui</b> 238 - attempts to automatically start your web browser pointing at the 239 - server whereas <b>server</b> does not. 237 + <p>The <b>ui</b> command is intended for accessing the web interface 238 + from a local desktop. The <b>ui</b> command binds to the loopback IP 239 + address only (and is thus makes the web interface visible only on the 240 + local machine) and it automatically start your web browser pointing at the 241 + server. For cross-machine collaboration, use the <b>server</b> command, 242 + which binds on all IP addresses and does not try to start a web browser. 240 243 You can omit the <i>repository-filename</i> if you are within 241 - a checked-out local tree. This server uses port 8080 by default 242 - but you can specify a different port using the <b>-port</b> command.</p> 244 + a checked-out local tree. The <b>server</b> uses port 8080 by default 245 + but you can specify a different port using the <b>-port</b> option.</p> 243 246 244 247 <p>Command-line servers like this are useful when two people want 245 248 to share a repository on temporary or ad-hoc basis. For a more 246 249 permanent installation, you should use either the CGI server or the 247 250 inetd server. 248 251 <a name="cgiserver"></a> 249 252 To use the CGI server, create a CGI script that
Changes to www/server.wiki.
92 92 If you are using "inetd" to serve your repository, then you simply need to add "/usr/bin/stunnel" (perhaps on a different path, depending on your setup) before the command line to launch Fossil. 93 93 </p> 94 94 <p> 95 95 At this stage, the standalone server (e.g. "fossil server") does not support SSL. 96 96 </p> 97 97 </blockquote> 98 98 99 -<h2>Various security concerns with hosted repositories</h2><blockquote> 99 +<h2>Various security concerns with hosted repositories</h2> 100 + 101 +<blockquote> 102 + 100 103 <p> 101 104 There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data): 102 105 <ul> 103 106 <li>Interception of the Fossil synchronization stream, thereby capturing data, and 104 -</ul>Direct access to the Fossil repository on the server 107 +<li>Direct access to the Fossil repository on the server 108 +</ul> 105 109 </p> 106 110 <p> 107 111 Regarding the first, it is adequate to secure the server using SSL, and disallowing any non-SSL access. The data stream will be encrypted by the HTTPS protocol, rendering the data reasonably secure. The truly paranoid may wish to deploy <i>ssh</i> encrypted tunnels, but that is quite a bit more difficult and cumbersome to set up (particularly for a larger number of users). 108 112 </p> 109 113 <p> 110 114 As far as direct access to the repository, the same steps must be taken as for any other internet-facing data-store. Access passwords to any disk-accessing accounts should be strong (and preferably changed from time to time). However, the data in the repository itself are <i>not</i> encrypted (unless you save encrypted data yourself), and so the system administrators of your server will be able to access your data (as with any hosting service setup). The only workaround in this case is to host the server yourself, in which case you will need to allocate resources to deal with administration issues. 111 115 </p> 112 116 113 117 </blockquote> 114 118 115 119 </nowiki>
Changes to www/wikitheory.wiki.
3 3 Fossil uses [/wiki_rules | wiki markup] for many things: 4 4 5 5 * Stand-alone wiki pages. 6 6 * Description and comments in [./bugtheory.wiki | bug reports]. 7 7 * Check-in comments. 8 8 * [./embeddeddoc.wiki | Embedded documentation] files whose 9 9 name ends in "wiki". 10 + * [./event.wiki | Event descriptions]. 10 11 11 12 The [/wiki_rules | formatting rules] for fossil wiki 12 13 are designed to be simple and intuitive. The idea is that wiki provides 13 14 paragraph breaks, numbered and bulleted lists, and hyperlinking for 14 15 simple documents together with a safe subset of HTML for more complex 15 16 formatting tasks. 16 17