Fossil SCM

fossil-scm / src / db.c
Blame History Raw 5733 lines
1
/*
2
** Copyright (c) 2006 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
** [email protected]
14
** http://www.hwaci.com/drh/
15
**
16
*******************************************************************************
17
**
18
** Code for interfacing to the various databases.
19
**
20
** There are three separate database files that fossil interacts
21
** with:
22
**
23
** (1) The "configdb" database in ~/.fossil or ~/.config/fossil.db
24
** or in %LOCALAPPDATA%/_fossil
25
**
26
** (2) The "repository" database
27
**
28
** (3) A local check-out database named "_FOSSIL_" or ".fslckout"
29
** and located at the root of the local copy of the source tree.
30
**
31
*/
32
#include "config.h"
33
#if defined(_WIN32)
34
# if USE_SEE
35
# include <windows.h>
36
# define GETPID (int)GetCurrentProcessId
37
# endif
38
#else
39
# include <pwd.h>
40
# if USE_SEE
41
# define GETPID getpid
42
# endif
43
#endif
44
#if USE_SEE && !defined(SQLITE_HAS_CODEC)
45
# define SQLITE_HAS_CODEC
46
#endif
47
#if USE_SEE && defined(__linux__)
48
# include <sys/uio.h>
49
#endif
50
#include <sqlite3.h>
51
#include <sys/types.h>
52
#include <sys/stat.h>
53
#include <unistd.h>
54
#include <time.h>
55
56
/* BUGBUG: This (PID_T) does not work inside of INTERFACE block. */
57
#if USE_SEE
58
#if defined(_WIN32)
59
typedef DWORD PID_T;
60
#else
61
typedef pid_t PID_T;
62
#endif
63
#endif
64
65
#include "db.h"
66
67
#if INTERFACE
68
/*
69
** Type definitions used for handling the saved encryption key for SEE.
70
*/
71
#if !defined(_WIN32)
72
typedef void *LPVOID;
73
typedef size_t SIZE_T;
74
#endif
75
76
/*
77
** Operations for db_maybe_handle_saved_encryption_key_for_process, et al.
78
*/
79
#define SEE_KEY_READ ((int)0)
80
#define SEE_KEY_WRITE ((int)1)
81
#define SEE_KEY_ZERO ((int)2)
82
83
/*
84
** An single SQL statement is represented as an instance of the following
85
** structure.
86
*/
87
struct Stmt {
88
Blob sql; /* The SQL for this statement */
89
sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
90
Stmt *pNext, *pPrev; /* List of all unfinalized statements */
91
int nStep; /* Number of sqlite3_step() calls */
92
int rc; /* Error from db_vprepare() */
93
};
94
95
/*
96
** Copy this to initialize a Stmt object to a clean/empty state. This
97
** is useful to help avoid assertions when performing cleanup in some
98
** error handling cases.
99
*/
100
#define empty_Stmt_m {BLOB_INITIALIZER,NULL, NULL, NULL, 0, 0}
101
#endif /* INTERFACE */
102
const struct Stmt empty_Stmt = empty_Stmt_m;
103
104
/*
105
** Call this routine when a database error occurs.
106
** This routine throws a fatal error. It does not return.
107
*/
108
static void db_err(const char *zFormat, ...){
109
va_list ap;
110
char *z;
111
va_start(ap, zFormat);
112
z = vmprintf(zFormat, ap);
113
va_end(ap);
114
#ifdef FOSSIL_ENABLE_JSON
115
if( g.json.isJsonMode!=0 ){
116
/*
117
** Avoid calling into the JSON support subsystem if it
118
** has not yet been initialized, e.g. early SQLite log
119
** messages, etc.
120
*/
121
json_bootstrap_early();
122
json_err( 0, z, 1 );
123
}
124
else
125
#endif /* FOSSIL_ENABLE_JSON */
126
if( g.xferPanic && g.cgiOutput==1 ){
127
cgi_reset_content();
128
@ error Database\serror:\s%F(z)
129
cgi_reply();
130
}
131
if( strstr(z,"attempt to write a readonly database") ){
132
static const char *azDbNames[] = { "repository", "localdb", "configdb" };
133
int i;
134
for(i=0; i<3; i++){
135
if( sqlite3_db_readonly(g.db, azDbNames[i])==1 ){
136
z = mprintf("\"%s\" is readonly.\n%s",
137
sqlite3_db_filename(g.db,azDbNames[i]), z);
138
}
139
}
140
}
141
fossil_fatal("Database error: %s", z);
142
}
143
144
/*
145
** Check a result code. If it is not SQLITE_OK, print the
146
** corresponding error message and exit.
147
*/
148
static void db_check_result(int rc, Stmt *pStmt){
149
if( rc!=SQLITE_OK ){
150
db_err("SQL error (%d,%d: %s) while running [%s]",
151
rc, sqlite3_extended_errcode(g.db),
152
sqlite3_errmsg(g.db), blob_str(&pStmt->sql));
153
}
154
}
155
156
/*
157
** All static variable that a used by only this file are gathered into
158
** the following structure.
159
*/
160
static struct DbLocalData {
161
unsigned protectMask; /* Prevent changes to database */
162
int nBegin; /* Nesting depth of BEGIN */
163
int doRollback; /* True to force a rollback */
164
int nCommitHook; /* Number of commit hooks */
165
int wrTxn; /* Outer-most TNX is a write */
166
Stmt *pAllStmt; /* List of all unfinalized statements */
167
int nPrepare; /* Number of calls to sqlite3_prepare_v2() */
168
int nDeleteOnFail; /* Number of entries in azDeleteOnFail[] */
169
struct sCommitHook {
170
int (*xHook)(void); /* Functions to call at db_end_transaction() */
171
int sequence; /* Call functions in sequence order */
172
} aHook[6];
173
char *azDeleteOnFail[3]; /* Files to delete on a failure */
174
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
175
int nBeforeCommit; /* Number of entries in azBeforeCommit */
176
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
177
const char *zStartFile; /* File in which transaction was started */
178
int iStartLine; /* Line of zStartFile where transaction started */
179
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
180
void *pAuthArg; /* Argument to the authorizer */
181
const char *zAuthName; /* Name of the authorizer */
182
int bProtectTriggers; /* True if protection triggers already exist */
183
int nProtect; /* Slots of aProtect used */
184
unsigned aProtect[12]; /* Saved values of protectMask */
185
int pauseDmlLog; /* Ignore pDmlLog if positive */
186
Blob *pDmlLog; /* Append DML statements here, of not NULL */
187
} db = {
188
PROTECT_USER|PROTECT_CONFIG|PROTECT_BASELINE, /* protectMask */
189
0, 0, 0, 0, 0, 0, 0, {{0}}, {0}, {0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}};
190
191
/*
192
** Arrange for the given file to be deleted on a failure.
193
*/
194
void db_delete_on_failure(const char *zFilename){
195
assert( db.nDeleteOnFail<count(db.azDeleteOnFail) );
196
if( zFilename==0 ) return;
197
db.azDeleteOnFail[db.nDeleteOnFail++] = fossil_strdup(zFilename);
198
}
199
200
/*
201
** Return the transaction nesting depth. 0 means we are currently
202
** not in a transaction.
203
*/
204
int db_transaction_nesting_depth(void){
205
return db.nBegin;
206
}
207
208
/*
209
** Return a pointer to a string that is the code point where the
210
** current transaction was started.
211
*/
212
char *db_transaction_start_point(void){
213
return mprintf("%s:%d", db.zStartFile, db.iStartLine);
214
}
215
216
/*
217
** This routine is called by the SQLite commit-hook mechanism
218
** just prior to each commit. All this routine does is verify
219
** that nBegin really is zero. That insures that transactions
220
** cannot commit by any means other than by calling db_end_transaction()
221
** below.
222
**
223
** This is just a safety and sanity check.
224
*/
225
static int db_verify_at_commit(void *notUsed){
226
if( db.nBegin ){
227
fossil_panic("illegal commit attempt");
228
return 1;
229
}
230
return 0;
231
}
232
233
/*
234
** Silently add the filename and line number as parameter to each
235
** db_begin_transaction call.
236
*/
237
#if INTERFACE
238
#define db_begin_transaction() db_begin_transaction_real(__FILE__,__LINE__)
239
#define db_begin_write() db_begin_write_real(__FILE__,__LINE__)
240
#define db_commit_transaction() db_end_transaction(0)
241
#define db_rollback_transaction() db_end_transaction(1)
242
#endif
243
244
/*
245
** Begin a nested transaction
246
*/
247
void db_begin_transaction_real(const char *zStartFile, int iStartLine){
248
if( db.nBegin==0 ){
249
db_multi_exec("BEGIN");
250
sqlite3_commit_hook(g.db, db_verify_at_commit, 0);
251
db.nPriorChanges = sqlite3_total_changes(g.db);
252
db.doRollback = 0;
253
db.zStartFile = zStartFile;
254
db.iStartLine = iStartLine;
255
db.wrTxn = 0;
256
}
257
db.nBegin++;
258
}
259
/*
260
** Begin a new transaction for writing.
261
*/
262
void db_begin_write_real(const char *zStartFile, int iStartLine){
263
if( db.nBegin==0 ){
264
if( !db_is_writeable("repository") ){
265
db_multi_exec("BEGIN");
266
}else{
267
db_multi_exec("BEGIN IMMEDIATE");
268
sqlite3_commit_hook(g.db, db_verify_at_commit, 0);
269
db.nPriorChanges = sqlite3_total_changes(g.db);
270
db.doRollback = 0;
271
db.zStartFile = zStartFile;
272
db.iStartLine = iStartLine;
273
db.wrTxn = 1;
274
}
275
}else if( !db.wrTxn ){
276
fossil_warning("read txn at %s:%d might cause SQLITE_BUSY "
277
"for the write txn at %s:%d",
278
db.zStartFile, db.iStartLine, zStartFile, iStartLine);
279
}
280
db.nBegin++;
281
}
282
283
/* End a transaction previously started using db_begin_transaction()
284
** or db_begin_write().
285
*/
286
void db_end_transaction(int rollbackFlag){
287
if( g.db==0 ) return;
288
if( db.nBegin<=0 ){
289
fossil_warning("Extra call to db_end_transaction");
290
return;
291
}
292
if( rollbackFlag ){
293
db.doRollback = 1;
294
if( g.fSqlTrace ) fossil_trace("-- ROLLBACK by request\n");
295
}
296
db.nBegin--;
297
if( db.nBegin==0 ){
298
int i;
299
if( db.doRollback==0 && db.nPriorChanges<sqlite3_total_changes(g.db) ){
300
i = 0;
301
db_protect_only(PROTECT_SENSITIVE);
302
while( db.nBeforeCommit ){
303
db.nBeforeCommit--;
304
sqlite3_exec(g.db, db.azBeforeCommit[i], 0, 0, 0);
305
sqlite3_free(db.azBeforeCommit[i]);
306
i++;
307
}
308
leaf_do_pending_checks();
309
db_protect_pop();
310
}
311
for(i=0; db.doRollback==0 && i<db.nCommitHook; i++){
312
int rc = db.aHook[i].xHook();
313
if( rc ){
314
db.doRollback = 1;
315
if( g.fSqlTrace ) fossil_trace("-- ROLLBACK due to aHook[%d]\n", i);
316
}
317
}
318
while( db.pAllStmt ){
319
db_finalize(db.pAllStmt);
320
}
321
db_multi_exec("%s", db.doRollback ? "ROLLBACK" : "COMMIT");
322
db.doRollback = 0;
323
}
324
}
325
326
/*
327
** Force a rollback and shutdown the database
328
*/
329
void db_force_rollback(void){
330
int i;
331
static int busy = 0;
332
sqlite3_stmt *pStmt = 0;
333
if( busy || g.db==0 ) return;
334
busy = 1;
335
undo_rollback();
336
while( (pStmt = sqlite3_next_stmt(g.db,pStmt))!=0 ){
337
sqlite3_reset(pStmt);
338
}
339
while( db.pAllStmt ){
340
db_finalize(db.pAllStmt);
341
}
342
if( db.nBegin ){
343
sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0);
344
db.nBegin = 0;
345
}
346
busy = 0;
347
db_close(0);
348
for(i=0; i<db.nDeleteOnFail; i++){
349
file_delete(db.azDeleteOnFail[i]);
350
}
351
}
352
353
/*
354
** Install a commit hook. Hooks are installed in sequence order.
355
** It is an error to install the same commit hook more than once.
356
**
357
** Each commit hook is called (in order of ascending sequence) at
358
** each commit operation. If any commit hook returns non-zero,
359
** the subsequence commit hooks are omitted and the transaction
360
** rolls back rather than commit. It is the responsibility of the
361
** hooks themselves to issue any error messages.
362
*/
363
void db_commit_hook(int (*x)(void), int sequence){
364
int i;
365
assert( db.nCommitHook < count(db.aHook) );
366
for(i=0; i<db.nCommitHook; i++){
367
assert( x!=db.aHook[i].xHook );
368
if( db.aHook[i].sequence>sequence ){
369
int s = sequence;
370
int (*xS)(void) = x;
371
sequence = db.aHook[i].sequence;
372
x = db.aHook[i].xHook;
373
db.aHook[i].sequence = s;
374
db.aHook[i].xHook = xS;
375
}
376
}
377
db.aHook[db.nCommitHook].sequence = sequence;
378
db.aHook[db.nCommitHook].xHook = x;
379
db.nCommitHook++;
380
}
381
382
#if INTERFACE
383
/*
384
** Flag bits for db_protect() and db_unprotect() indicating which parts
385
** of the databases should be write protected or write enabled, respectively.
386
*/
387
#define PROTECT_USER 0x01 /* USER table */
388
#define PROTECT_CONFIG 0x02 /* CONFIG and GLOBAL_CONFIG tables */
389
#define PROTECT_SENSITIVE 0x04 /* Sensitive and/or global settings */
390
#define PROTECT_READONLY 0x08 /* everything except TEMP tables */
391
#define PROTECT_BASELINE 0x10 /* protection system is working */
392
#define PROTECT_ALL 0x1f /* All of the above */
393
#define PROTECT_NONE 0x00 /* Nothing. Everything is open */
394
#endif /* INTERFACE */
395
396
/*
397
** Enable or disable database write protections.
398
**
399
** db_protext(X) Add protects on X
400
** db_unprotect(X) Remove protections on X
401
** db_protect_only(X) Remove all prior protections then set
402
** protections to only X.
403
**
404
** Each of these routines pushes the previous protection mask onto
405
** a finite-size stack. Each should be followed by a call to
406
** db_protect_pop() to pop the stack and restore the protections that
407
** existed prior to the call. The protection mask stack has a limited
408
** depth, so take care not to nest calls too deeply.
409
**
410
** About Database Write Protection
411
** -------------------------------
412
**
413
** This is *not* a primary means of defending the application from
414
** attack. Fossil should be secure even if this mechanism is disabled.
415
** The purpose of database write protection is to provide an additional
416
** layer of defense in case SQL injection bugs somehow slip into other
417
** parts of the system. In other words, database write protection is
418
** not the primary defense but rather defense in depth.
419
**
420
** This mechanism mostly focuses on the USER table, to prevent an
421
** attacker from giving themselves Admin privilegs, and on the
422
** CONFIG table and especially "sensitive" settings such as
423
** "diff-command" or "editor" that if compromised by an attacker
424
** could lead to an RCE.
425
**
426
** By default, the USER and CONFIG tables are read-only. Various
427
** subsystems that legitimately need to change those tables can
428
** temporarily do so using:
429
**
430
** db_unprotect(PROTECT_xxx);
431
** // make the legitmate changes here
432
** db_protect_pop();
433
**
434
** Code that runs inside of reduced protections should be carefully
435
** reviewed to ensure that it is harmless and not subject to SQL
436
** injection.
437
**
438
** Read-only operations (such as many web pages like /timeline)
439
** can invoke db_protect(PROTECT_ALL) to effectively make the database
440
** read-only. TEMP tables (which are often used for these kinds of
441
** pages) are still writable, however.
442
**
443
** The PROTECT_SENSITIVE protection is a subset of PROTECT_CONFIG
444
** that blocks changes to all of the global_config table, but only
445
** "sensitive" settings in the config table. PROTECT_SENSITIVE
446
** relies on triggers and the protected_setting() SQL function to
447
** prevent changes to sensitive settings.
448
**
449
** PROTECT_READONLY is set for any HTTP request for which the HTTP_REFERER
450
** is not the same origin. This is an additional defense against cross-site-
451
** scripting attacks. As with all of these defenses, this is only an extra
452
** backup layer. Fossil should be proof against XSS attacks even without this.
453
**
454
** Any violation of these security restrictions results in a SECURITY message
455
** in the server log (if enabled). A violation of any of these restrictions
456
** probably indicates a bug in Fossil and should be reported to the
457
** developers.
458
**
459
** Additional Notes
460
** ----------------
461
**
462
** Calls to routines like db_set() and db_unset() temporarily disable
463
** the PROTECT_CONFIG protection. The assumption is that these calls
464
** cannot be invoked by an SQL injection and are thus safe. Make sure
465
** this is the case by always using a string literal as the name argument
466
** to db_set() and db_unset() and friend, not a variable that might
467
** be compromised by an attack.
468
*/
469
void db_protect_only(unsigned flags){
470
if( db.nProtect>=count(db.aProtect)-2 ){
471
fossil_panic("too many db_protect() calls");
472
}
473
db.aProtect[db.nProtect++] = db.protectMask;
474
if( (flags & PROTECT_SENSITIVE)!=0
475
&& db.bProtectTriggers==0
476
&& g.repositoryOpen
477
){
478
/* Create the triggers needed to protect sensitive settings from
479
** being created or modified the first time that PROTECT_SENSITIVE
480
** is enabled. Deleting a sensitive setting is harmless, so there
481
** is not trigger to block deletes. After being created once, the
482
** triggers persist for the life of the database connection. */
483
unsigned savedProtectMask = db.protectMask;
484
db.protectMask = 0;
485
db_multi_exec(
486
"CREATE TEMP TRIGGER protect_1 BEFORE INSERT ON config"
487
" WHEN protected_setting(new.name) BEGIN"
488
" SELECT raise(abort,'not authorized');"
489
"END;\n"
490
"CREATE TEMP TRIGGER protect_2 BEFORE UPDATE ON config"
491
" WHEN protected_setting(new.name) BEGIN"
492
" SELECT raise(abort,'not authorized');"
493
"END;\n"
494
);
495
db.bProtectTriggers = 1;
496
db.protectMask = savedProtectMask;
497
}
498
db.protectMask = flags;
499
}
500
void db_protect(unsigned flags){
501
db_protect_only(db.protectMask | flags);
502
}
503
void db_unprotect(unsigned flags){
504
if( db.nProtect>=count(db.aProtect)-2 ){
505
fossil_panic("too many db_unprotect() calls");
506
}
507
db.aProtect[db.nProtect++] = db.protectMask;
508
db.protectMask &= ~(flags|PROTECT_READONLY);
509
}
510
void db_protect_pop(void){
511
if( db.nProtect<1 ){
512
fossil_panic("too many db_protect_pop() calls");
513
}
514
db.protectMask = db.aProtect[--db.nProtect];
515
}
516
int db_is_protected(unsigned flags){
517
return (db.protectMask & flags)!=0;
518
}
519
520
/*
521
** Verify that the desired database write protections are in place.
522
** Throw a fatal error if not.
523
*/
524
void db_assert_protected(unsigned flags){
525
if( (flags & db.protectMask)!=flags ){
526
fossil_fatal("missing database write protection bits: %02x",
527
flags & ~db.protectMask);
528
}
529
}
530
531
/*
532
** Assert that either all protections are off (including PROTECT_BASELINE
533
** which is usually always enabled), or the setting named in the argument
534
** is no a sensitive setting.
535
**
536
** This assert() is used to verify that the db_set() and db_set_int()
537
** interfaces do not modify a sensitive setting.
538
*/
539
void db_assert_protection_off_or_not_sensitive(const char *zName){
540
if( db.protectMask!=0 && db_setting_is_protected(zName) ){
541
fossil_panic("unauthorized change to protected setting \"%s\"", zName);
542
}
543
}
544
545
/*
546
** Every Fossil database connection automatically registers the following
547
** overarching authenticator callback, and leaves it registered for the
548
** duration of the connection. This authenticator will call any
549
** sub-authenticators that are registered using db_set_authorizer().
550
**
551
** == Testing Notes ==
552
**
553
** Run Fossil as using a command like this:
554
**
555
** ./fossil sql --test --errorlog -
556
**
557
** Then enter SQL commands like one of these:
558
**
559
** SELECT db_protect('user');
560
** SELECT db_protect('config');
561
** SELECT db_protect('sensitive');
562
** SELECT db_protect('readonly');
563
** SELECT db_protect('all');
564
**
565
** Then try to do SQL statements that would violate the constraints and
566
** verify that SECURITY warnings appear in the error log output. See
567
** also the sqlcmd_db_protect() function in sqlcmd.c.
568
*/
569
int db_top_authorizer(
570
void *pNotUsed,
571
int eCode,
572
const char *z0,
573
const char *z1,
574
const char *z2,
575
const char *z3
576
){
577
int rc = SQLITE_OK;
578
switch( eCode ){
579
case SQLITE_INSERT:
580
case SQLITE_UPDATE:
581
case SQLITE_DELETE: {
582
if( (db.protectMask & PROTECT_USER)!=0
583
&& sqlite3_stricmp(z0,"user")==0 ){
584
fossil_errorlog(
585
"SECURITY: authorizer blocks DML on protected USER table\n");
586
rc = SQLITE_DENY;
587
}else if( (db.protectMask & PROTECT_CONFIG)!=0 &&
588
(sqlite3_stricmp(z0,"config")==0 ||
589
sqlite3_stricmp(z0,"global_config")==0) ){
590
fossil_errorlog(
591
"SECURITY: authorizer blocks DML on protected table \"%s\"\n", z0);
592
rc = SQLITE_DENY;
593
}else if( (db.protectMask & PROTECT_SENSITIVE)!=0 &&
594
sqlite3_stricmp(z0,"global_config")==0 ){
595
fossil_errorlog(
596
"SECURITY: authorizer blocks DML on protected GLOBAL_CONFIG table\n");
597
rc = SQLITE_DENY;
598
}else if( (db.protectMask & PROTECT_READONLY)!=0
599
&& (sqlite3_stricmp(z2, "repository")==0
600
|| sqlite3_stricmp(z2,"configdb")==0
601
|| sqlite3_stricmp(z2,"localdb")==0) ){
602
/* The READONLY constraint only applies to persistent database files.
603
** "temp" and "mem1" and other transient databases are not
604
** constrained by READONLY. */
605
fossil_errorlog(
606
"SECURITY: authorizer blocks DML on table \"%s\" due to the "
607
"request coming from a different origin\n", z0);
608
rc = SQLITE_DENY;
609
}
610
break;
611
}
612
case SQLITE_DROP_TEMP_TRIGGER: {
613
/* Do not allow the triggers that enforce PROTECT_SENSITIVE
614
** to be dropped */
615
fossil_errorlog(
616
"SECURITY: authorizer blocks attempt to drop a temporary trigger\n");
617
rc = SQLITE_DENY;
618
break;
619
}
620
}
621
if( db.xAuth && rc==SQLITE_OK ){
622
rc = db.xAuth(db.pAuthArg, eCode, z0, z1, z2, z3);
623
}
624
return rc;
625
}
626
627
/*
628
** Set or unset the query authorizer callback function
629
*/
630
void db_set_authorizer(
631
int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
632
void *pArg,
633
const char *zName /* for tracing */
634
){
635
if( db.xAuth ){
636
fossil_panic("multiple active db_set_authorizer() calls");
637
}
638
db.xAuth = xAuth;
639
db.pAuthArg = pArg;
640
db.zAuthName = zName;
641
if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
642
}
643
void db_clear_authorizer(void){
644
if( db.zAuthName && g.fSqlTrace ){
645
fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
646
}
647
db.xAuth = 0;
648
db.pAuthArg = 0;
649
db.zAuthName = 0;
650
}
651
652
#if INTERFACE
653
/*
654
** Possible flags to db_vprepare
655
*/
656
#define DB_PREPARE_IGNORE_ERROR 0x001 /* Suppress errors */
657
#define DB_PREPARE_PERSISTENT 0x002 /* Stmt will stick around for a while */
658
#endif
659
660
/*
661
** If zSql is a DML statement, append it db.pDmlLog.
662
*/
663
static void db_append_dml(const char *zSql){
664
size_t nSql;
665
if( db.pDmlLog==0 ) return;
666
if( db.pauseDmlLog ) return;
667
if( zSql==0 ) return;
668
nSql = strlen(zSql);
669
while( nSql>0 && fossil_isspace(zSql[0]) ){ nSql--; zSql++; }
670
while( nSql>0 && fossil_isspace(zSql[nSql-1]) ) nSql--;
671
if( nSql<6 ) return;
672
if( fossil_strnicmp(zSql, "SELECT", 6)==0 ) return;
673
if( fossil_strnicmp(zSql, "PRAGMA", 6)==0 ) return;
674
blob_append(db.pDmlLog, zSql, nSql);
675
if( zSql[nSql-1]!=';' ) blob_append_char(db.pDmlLog, ';');
676
blob_append_char(db.pDmlLog, '\n');
677
}
678
679
/*
680
** Set the Blob to which DML statement text should be appended. Set it
681
** to zero to stop appending DML statement text.
682
*/
683
void db_append_dml_to_blob(Blob *pBlob){
684
db.pDmlLog = pBlob;
685
}
686
687
/*
688
** Pause or unpause the DML log
689
*/
690
void db_pause_dml_log(void){ db.pauseDmlLog++; }
691
void db_unpause_dml_log(void){ db.pauseDmlLog--; }
692
693
/*
694
** Prepare a Stmt. Assume that the Stmt is previously uninitialized.
695
** If the input string contains multiple SQL statements, only the first
696
** one is processed. All statements beyond the first are silently ignored.
697
*/
698
int db_vprepare(Stmt *pStmt, int flags, const char *zFormat, va_list ap){
699
int rc;
700
int prepFlags = 0;
701
char *zSql;
702
const char *zExtra = 0;
703
blob_zero(&pStmt->sql);
704
blob_vappendf(&pStmt->sql, zFormat, ap);
705
va_end(ap);
706
zSql = blob_str(&pStmt->sql);
707
db.nPrepare++;
708
db_append_dml(zSql);
709
if( flags & DB_PREPARE_PERSISTENT ){
710
prepFlags = SQLITE_PREPARE_PERSISTENT;
711
}
712
rc = sqlite3_prepare_v3(g.db, zSql, -1, prepFlags, &pStmt->pStmt, &zExtra);
713
if( rc!=0 && (flags & DB_PREPARE_IGNORE_ERROR)==0 ){
714
db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
715
}else if( zExtra && !fossil_all_whitespace(zExtra) ){
716
db_err("surplus text follows SQL: \"%s\"", zExtra);
717
}
718
pStmt->pNext = db.pAllStmt;
719
pStmt->pPrev = 0;
720
if( db.pAllStmt ) db.pAllStmt->pPrev = pStmt;
721
db.pAllStmt = pStmt;
722
pStmt->nStep = 0;
723
pStmt->rc = rc;
724
return rc;
725
}
726
int db_prepare(Stmt *pStmt, const char *zFormat, ...){
727
int rc;
728
va_list ap;
729
va_start(ap, zFormat);
730
rc = db_vprepare(pStmt, 0, zFormat, ap);
731
va_end(ap);
732
return rc;
733
}
734
int db_prepare_ignore_error(Stmt *pStmt, const char *zFormat, ...){
735
int rc;
736
va_list ap;
737
va_start(ap, zFormat);
738
rc = db_vprepare(pStmt, DB_PREPARE_IGNORE_ERROR, zFormat, ap);
739
va_end(ap);
740
return rc;
741
}
742
743
/* This variant of db_prepare() checks to see if the statement has
744
** already been prepared, and if it has it becomes a no-op.
745
*/
746
int db_static_prepare(Stmt *pStmt, const char *zFormat, ...){
747
int rc = SQLITE_OK;
748
if( blob_size(&pStmt->sql)==0 ){
749
va_list ap;
750
va_start(ap, zFormat);
751
rc = db_vprepare(pStmt, DB_PREPARE_PERSISTENT, zFormat, ap);
752
va_end(ap);
753
}
754
return rc;
755
}
756
757
/* Return TRUE if static Stmt object pStmt has been initialized.
758
*/
759
int db_static_stmt_is_init(Stmt *pStmt){
760
return blob_size(&pStmt->sql)>0;
761
}
762
763
/* Prepare a statement using text placed inside a Blob
764
** using blob_append_sql().
765
*/
766
int db_prepare_blob(Stmt *pStmt, Blob *pSql){
767
int rc;
768
char *zSql;
769
pStmt->sql = *pSql;
770
blob_init(pSql, 0, 0);
771
zSql = blob_sql_text(&pStmt->sql);
772
db.nPrepare++;
773
rc = sqlite3_prepare_v3(g.db, zSql, -1, 0, &pStmt->pStmt, 0);
774
if( rc!=0 ){
775
db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
776
}
777
pStmt->pNext = pStmt->pPrev = 0;
778
pStmt->nStep = 0;
779
pStmt->rc = rc;
780
return rc;
781
}
782
783
784
/*
785
** Return the index of a bind parameter
786
*/
787
static int paramIdx(Stmt *pStmt, const char *zParamName){
788
int i = sqlite3_bind_parameter_index(pStmt->pStmt, zParamName);
789
if( i==0 ){
790
db_err("no such bind parameter: %s\nSQL: %b", zParamName, &pStmt->sql);
791
}
792
return i;
793
}
794
/*
795
** Bind an integer, string, or Blob value to a named parameter.
796
*/
797
int db_bind_int(Stmt *pStmt, const char *zParamName, int iValue){
798
return sqlite3_bind_int(pStmt->pStmt, paramIdx(pStmt, zParamName), iValue);
799
}
800
int db_bind_int64(Stmt *pStmt, const char *zParamName, i64 iValue){
801
return sqlite3_bind_int64(pStmt->pStmt, paramIdx(pStmt, zParamName), iValue);
802
}
803
int db_bind_double(Stmt *pStmt, const char *zParamName, double rValue){
804
return sqlite3_bind_double(pStmt->pStmt, paramIdx(pStmt, zParamName), rValue);
805
}
806
int db_bind_text(Stmt *pStmt, const char *zParamName, const char *zValue){
807
return sqlite3_bind_text(pStmt->pStmt, paramIdx(pStmt, zParamName), zValue,
808
-1, SQLITE_STATIC);
809
}
810
int db_bind_text16(Stmt *pStmt, const char *zParamName, const char *zValue){
811
return sqlite3_bind_text16(pStmt->pStmt, paramIdx(pStmt, zParamName), zValue,
812
-1, SQLITE_STATIC);
813
}
814
int db_bind_null(Stmt *pStmt, const char *zParamName){
815
return sqlite3_bind_null(pStmt->pStmt, paramIdx(pStmt, zParamName));
816
}
817
int db_bind_blob(Stmt *pStmt, const char *zParamName, Blob *pBlob){
818
return sqlite3_bind_blob(pStmt->pStmt, paramIdx(pStmt, zParamName),
819
blob_buffer(pBlob), blob_size(pBlob), SQLITE_STATIC);
820
}
821
822
/* bind_str() treats a Blob object like a TEXT string and binds it
823
** to the SQL variable. Contrast this to bind_blob() which treats
824
** the Blob object like an SQL BLOB.
825
*/
826
int db_bind_str(Stmt *pStmt, const char *zParamName, Blob *pBlob){
827
return sqlite3_bind_text(pStmt->pStmt, paramIdx(pStmt, zParamName),
828
blob_buffer(pBlob), blob_size(pBlob), SQLITE_STATIC);
829
}
830
831
/*
832
** Step the SQL statement. Return either SQLITE_ROW or an error code
833
** or SQLITE_OK if the statement finishes successfully.
834
*/
835
int db_step(Stmt *pStmt){
836
int rc;
837
if( pStmt->pStmt==0 ) return pStmt->rc;
838
rc = sqlite3_step(pStmt->pStmt);
839
pStmt->nStep++;
840
return rc;
841
}
842
843
/*
844
** Print warnings if a query is inefficient.
845
*/
846
static void db_stats(Stmt *pStmt){
847
#ifdef FOSSIL_DEBUG
848
int c1, c2, c3;
849
const char *zSql = sqlite3_sql(pStmt->pStmt);
850
if( zSql==0 ) return;
851
c1 = sqlite3_stmt_status(pStmt->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, 1);
852
c2 = sqlite3_stmt_status(pStmt->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, 1);
853
c3 = sqlite3_stmt_status(pStmt->pStmt, SQLITE_STMTSTATUS_SORT, 1);
854
if( c1>pStmt->nStep*4 && strstr(zSql,"/*scan*/")==0 ){
855
fossil_warning("%d scan steps for %d rows in [%s]", c1, pStmt->nStep, zSql);
856
}else if( c2 ){
857
fossil_warning("%d automatic index rows in [%s]", c2, zSql);
858
}else if( c3 && strstr(zSql,"/*sort*/")==0 && strstr(zSql,"/*scan*/")==0 ){
859
fossil_warning("sort w/o index in [%s]", zSql);
860
}
861
pStmt->nStep = 0;
862
#endif
863
}
864
865
/*
866
** Reset or finalize a statement.
867
*/
868
int db_reset(Stmt *pStmt){
869
int rc;
870
if( g.fSqlStats ){ db_stats(pStmt); }
871
rc = sqlite3_reset(pStmt->pStmt);
872
db_check_result(rc, pStmt);
873
return rc;
874
}
875
int db_finalize(Stmt *pStmt){
876
int rc;
877
if( pStmt->pNext ){
878
pStmt->pNext->pPrev = pStmt->pPrev;
879
}
880
if( pStmt->pPrev ){
881
pStmt->pPrev->pNext = pStmt->pNext;
882
}else if( db.pAllStmt==pStmt ){
883
db.pAllStmt = pStmt->pNext;
884
}
885
pStmt->pNext = 0;
886
pStmt->pPrev = 0;
887
if( g.fSqlStats ){ db_stats(pStmt); }
888
blob_reset(&pStmt->sql);
889
rc = sqlite3_finalize(pStmt->pStmt);
890
db_check_result(rc, pStmt);
891
pStmt->pStmt = 0;
892
return rc;
893
}
894
895
/*
896
** Return the rowid of the most recent insert
897
*/
898
int db_last_insert_rowid(void){
899
i64 x = sqlite3_last_insert_rowid(g.db);
900
if( x<0 || x>(i64)2147483647 ){
901
fossil_panic("rowid out of range (0..2147483647)");
902
}
903
return (int)x;
904
}
905
906
/*
907
** Return the number of rows that were changed by the most recent
908
** INSERT, UPDATE, or DELETE. Auxiliary changes caused by triggers
909
** or other side effects are not counted.
910
*/
911
int db_changes(void){
912
return sqlite3_changes(g.db);
913
}
914
915
/*
916
** Extract text, integer, or blob values from the N-th column of the
917
** current row.
918
*/
919
int db_column_type(Stmt *pStmt, int N){
920
return sqlite3_column_type(pStmt->pStmt, N);
921
}
922
int db_column_bytes(Stmt *pStmt, int N){
923
return sqlite3_column_bytes(pStmt->pStmt, N);
924
}
925
int db_column_int(Stmt *pStmt, int N){
926
return sqlite3_column_int(pStmt->pStmt, N);
927
}
928
i64 db_column_int64(Stmt *pStmt, int N){
929
return sqlite3_column_int64(pStmt->pStmt, N);
930
}
931
double db_column_double(Stmt *pStmt, int N){
932
return sqlite3_column_double(pStmt->pStmt, N);
933
}
934
const char *db_column_text(Stmt *pStmt, int N){
935
return (char*)sqlite3_column_text(pStmt->pStmt, N);
936
}
937
const char *db_column_raw(Stmt *pStmt, int N){
938
return (const char*)sqlite3_column_blob(pStmt->pStmt, N);
939
}
940
const char *db_column_name(Stmt *pStmt, int N){
941
return (char*)sqlite3_column_name(pStmt->pStmt, N);
942
}
943
int db_column_count(Stmt *pStmt){
944
return sqlite3_column_count(pStmt->pStmt);
945
}
946
char *db_column_malloc(Stmt *pStmt, int N){
947
return fossil_strdup_nn(db_column_text(pStmt, N));
948
}
949
void db_column_blob(Stmt *pStmt, int N, Blob *pBlob){
950
blob_append(pBlob, sqlite3_column_blob(pStmt->pStmt, N),
951
sqlite3_column_bytes(pStmt->pStmt, N));
952
}
953
Blob db_column_text_as_blob(Stmt *pStmt, int N){
954
Blob x;
955
blob_init(&x, (char*)sqlite3_column_text(pStmt->pStmt,N),
956
sqlite3_column_bytes(pStmt->pStmt,N));
957
return x;
958
}
959
960
/*
961
** Initialize a blob to an ephemeral copy of the content of a
962
** column in the current row. The data in the blob will become
963
** invalid when the statement is stepped or reset.
964
*/
965
void db_ephemeral_blob(Stmt *pStmt, int N, Blob *pBlob){
966
blob_init(pBlob, sqlite3_column_blob(pStmt->pStmt, N),
967
sqlite3_column_bytes(pStmt->pStmt, N));
968
}
969
970
/*
971
** Execute a single prepared statement until it finishes.
972
*/
973
int db_exec(Stmt *pStmt){
974
int rc;
975
while( (rc = db_step(pStmt))==SQLITE_ROW ){}
976
rc = db_reset(pStmt);
977
db_check_result(rc, pStmt);
978
return rc;
979
}
980
981
/*
982
** COMMAND: test-db-exec-error
983
** Usage: %fossil test-db-exec-error
984
**
985
** Invoke the db_exec() interface with an erroneous SQL statement
986
** in order to verify the error handling logic.
987
*/
988
void db_test_db_exec_cmd(void){
989
Stmt err;
990
db_find_and_open_repository(0,0);
991
db_prepare(&err, "INSERT INTO repository.config(name) VALUES(NULL);");
992
db_exec(&err);
993
}
994
995
/*
996
** COMMAND: test-db-prepare
997
** Usage: %fossil test-db-prepare ?OPTIONS? SQL-STATEMENT
998
**
999
** Options:
1000
** --auth-report Enable the ticket report query authorizer
1001
** --auth-ticket Enable the ticket schema query authorizer
1002
**
1003
** Invoke db_prepare() on the SQL input. Report any errors encountered.
1004
** This command is used to verify error detection logic in the db_prepare()
1005
** utility routine.
1006
*/
1007
void db_test_db_prepare(void){
1008
const int fAuthReport = find_option("auth-report",0,0)!=0;
1009
const int fAuthSchema = find_option("auth-ticket",0,0)!=0;
1010
char * zReportErr = 0; /* auth-report error string. */
1011
int nSchemaErr = 0; /* Number of auth-ticket errors. */
1012
Stmt err;
1013
1014
if(fAuthReport + fAuthSchema > 1){
1015
fossil_fatal("Only one of --auth-report or --auth-ticket "
1016
"may be used.");
1017
}
1018
db_find_and_open_repository(0,0);
1019
verify_all_options();
1020
if( g.argc!=3 ) usage("?OPTIONS? SQL");
1021
if(fAuthReport){
1022
report_restrict_sql(&zReportErr);
1023
}else if(fAuthSchema){
1024
ticket_restrict_sql(&nSchemaErr);
1025
}
1026
db_prepare(&err, "%s", g.argv[2]/*safe-for-%s*/);
1027
db_finalize(&err);
1028
if(fAuthReport){
1029
report_unrestrict_sql();
1030
if(zReportErr){
1031
fossil_warning("Report authorizer error: %s\n", zReportErr);
1032
fossil_free(zReportErr);
1033
}
1034
}else if(fAuthSchema){
1035
ticket_unrestrict_sql();
1036
if(nSchemaErr){
1037
fossil_warning("Ticket schema authorizer error count: %d\n",
1038
nSchemaErr);
1039
}
1040
}
1041
}
1042
1043
/*
1044
** Print the output of one or more SQL queries on standard output.
1045
** This routine is used for debugging purposes only.
1046
*/
1047
int db_debug(const char *zSql, ...){
1048
Blob sql;
1049
int rc = SQLITE_OK;
1050
va_list ap;
1051
const char *z, *zEnd;
1052
sqlite3_stmt *pStmt;
1053
blob_init(&sql, 0, 0);
1054
va_start(ap, zSql);
1055
blob_vappendf(&sql, zSql, ap);
1056
va_end(ap);
1057
z = blob_str(&sql);
1058
while( rc==SQLITE_OK && z[0] ){
1059
pStmt = 0;
1060
rc = sqlite3_prepare_v2(g.db, z, -1, &pStmt, &zEnd);
1061
if( rc!=SQLITE_OK ) break;
1062
if( pStmt ){
1063
int nRow = 0;
1064
db.nPrepare++;
1065
while( sqlite3_step(pStmt)==SQLITE_ROW ){
1066
int i, n;
1067
if( nRow++ > 0 ) fossil_print("\n");
1068
n = sqlite3_column_count(pStmt);
1069
for(i=0; i<n; i++){
1070
fossil_print("%s = %s\n", sqlite3_column_name(pStmt, i),
1071
sqlite3_column_text(pStmt,i));
1072
}
1073
}
1074
rc = sqlite3_finalize(pStmt);
1075
if( rc ) db_err("%s: {%.*s}", sqlite3_errmsg(g.db), (int)(zEnd-z), z);
1076
}
1077
z = zEnd;
1078
}
1079
blob_reset(&sql);
1080
return rc;
1081
}
1082
1083
/*
1084
** Execute multiple SQL statements. The input text is executed
1085
** directly without any formatting.
1086
*/
1087
int db_exec_sql(const char *z){
1088
int rc = SQLITE_OK;
1089
sqlite3_stmt *pStmt;
1090
const char *zEnd;
1091
while( rc==SQLITE_OK && z[0] ){
1092
pStmt = 0;
1093
rc = sqlite3_prepare_v2(g.db, z, -1, &pStmt, &zEnd);
1094
if( rc ){
1095
db_err("%s: {%s}", sqlite3_errmsg(g.db), z);
1096
}else if( pStmt ){
1097
db.nPrepare++;
1098
db_append_dml(sqlite3_sql(pStmt));
1099
while( sqlite3_step(pStmt)==SQLITE_ROW ){}
1100
rc = sqlite3_finalize(pStmt);
1101
if( rc ) db_err("%s: {%.*s}", sqlite3_errmsg(g.db), (int)(zEnd-z), z);
1102
}
1103
z = zEnd;
1104
}
1105
return rc;
1106
}
1107
1108
/*
1109
** Execute multiple SQL statements using printf-style formatting.
1110
*/
1111
int db_multi_exec(const char *zSql, ...){
1112
Blob sql;
1113
int rc;
1114
va_list ap;
1115
1116
blob_init(&sql, 0, 0);
1117
va_start(ap, zSql);
1118
blob_vappendf(&sql, zSql, ap);
1119
va_end(ap);
1120
rc = db_exec_sql(blob_str(&sql));
1121
blob_reset(&sql);
1122
return rc;
1123
}
1124
1125
/*
1126
** Optionally make the following changes to the database if feasible and
1127
** convenient. Do not start a transaction for these changes, but only
1128
** make these changes if other changes are also being made.
1129
*/
1130
void db_optional_sql(const char *zDb, const char *zSql, ...){
1131
if( db_is_writeable(zDb) && db.nBeforeCommit < count(db.azBeforeCommit) ){
1132
va_list ap;
1133
va_start(ap, zSql);
1134
db.azBeforeCommit[db.nBeforeCommit++] = sqlite3_vmprintf(zSql, ap);
1135
va_end(ap);
1136
}
1137
}
1138
1139
/*
1140
** Execute a query and return a single integer value.
1141
*/
1142
i64 db_int64(i64 iDflt, const char *zSql, ...){
1143
va_list ap;
1144
Stmt s;
1145
i64 rc;
1146
va_start(ap, zSql);
1147
db_vprepare(&s, 0, zSql, ap);
1148
va_end(ap);
1149
if( db_step(&s)!=SQLITE_ROW ){
1150
rc = iDflt;
1151
}else{
1152
rc = db_column_int64(&s, 0);
1153
}
1154
db_finalize(&s);
1155
return rc;
1156
}
1157
int db_int(int iDflt, const char *zSql, ...){
1158
va_list ap;
1159
Stmt s;
1160
int rc;
1161
va_start(ap, zSql);
1162
db_vprepare(&s, 0, zSql, ap);
1163
va_end(ap);
1164
if( db_step(&s)!=SQLITE_ROW ){
1165
rc = iDflt;
1166
}else{
1167
rc = db_column_int(&s, 0);
1168
}
1169
db_finalize(&s);
1170
return rc;
1171
}
1172
1173
/*
1174
** Return TRUE if the query would return 1 or more rows. Return
1175
** FALSE if the query result would be an empty set.
1176
*/
1177
int db_exists(const char *zSql, ...){
1178
va_list ap;
1179
Stmt s;
1180
int rc;
1181
va_start(ap, zSql);
1182
db_vprepare(&s, 0, zSql, ap);
1183
va_end(ap);
1184
if( db_step(&s)!=SQLITE_ROW ){
1185
rc = 0;
1186
}else{
1187
rc = 1;
1188
}
1189
db_finalize(&s);
1190
return rc;
1191
}
1192
1193
1194
/*
1195
** Execute a query and return a floating-point value.
1196
*/
1197
double db_double(double rDflt, const char *zSql, ...){
1198
va_list ap;
1199
Stmt s;
1200
double r;
1201
va_start(ap, zSql);
1202
db_vprepare(&s, 0, zSql, ap);
1203
va_end(ap);
1204
if( db_step(&s)!=SQLITE_ROW ){
1205
r = rDflt;
1206
}else{
1207
r = db_column_double(&s, 0);
1208
}
1209
db_finalize(&s);
1210
return r;
1211
}
1212
1213
/*
1214
** Execute a query and append the first column of the first row
1215
** of the result set to blob given in the first argument.
1216
*/
1217
void db_blob(Blob *pResult, const char *zSql, ...){
1218
va_list ap;
1219
Stmt s;
1220
va_start(ap, zSql);
1221
db_vprepare(&s, 0, zSql, ap);
1222
va_end(ap);
1223
if( db_step(&s)==SQLITE_ROW ){
1224
blob_append(pResult, sqlite3_column_blob(s.pStmt, 0),
1225
sqlite3_column_bytes(s.pStmt, 0));
1226
}
1227
db_finalize(&s);
1228
}
1229
1230
/*
1231
** Execute a query. Return the first column of the first row
1232
** of the result set as a string. Space to hold the string is
1233
** obtained from fossil_strdup() and should be freed using fossil_free().
1234
** If the result set is empty, return a copy of zDefault instead.
1235
*/
1236
char *db_text(const char *zDefault, const char *zSql, ...){
1237
va_list ap;
1238
Stmt s;
1239
char *z;
1240
va_start(ap, zSql);
1241
db_vprepare(&s, 0, zSql, ap);
1242
va_end(ap);
1243
if( db_step(&s)==SQLITE_ROW ){
1244
z = fossil_strdup_nn((const char*)sqlite3_column_text(s.pStmt, 0));
1245
}else{
1246
z = fossil_strdup(zDefault);
1247
}
1248
db_finalize(&s);
1249
return z;
1250
}
1251
1252
/*
1253
** Initialize a new database file with the given schema. If anything
1254
** goes wrong, call db_err() to exit.
1255
**
1256
** If zFilename is NULL, then create an empty repository in an in-memory
1257
** database.
1258
*/
1259
void db_init_database(
1260
const char *zFileName, /* Name of database file to create */
1261
const char *zSchema, /* First part of schema */
1262
... /* Additional SQL to run. Terminate with NULL. */
1263
){
1264
sqlite3 *xdb;
1265
int rc;
1266
const char *zSql;
1267
va_list ap;
1268
1269
xdb = db_open(zFileName ? zFileName : ":memory:");
1270
sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
1271
rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
1272
if( rc!=SQLITE_OK ){
1273
db_err("%s", sqlite3_errmsg(xdb));
1274
}
1275
va_start(ap, zSchema);
1276
while( (zSql = va_arg(ap, const char*))!=0 ){
1277
rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
1278
if( rc!=SQLITE_OK ){
1279
db_err("%s", sqlite3_errmsg(xdb));
1280
}
1281
}
1282
va_end(ap);
1283
sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
1284
if( zFileName || g.db!=0 ){
1285
sqlite3_close(xdb);
1286
}else{
1287
g.db = xdb;
1288
}
1289
}
1290
1291
/*
1292
** Function to return the number of seconds since 1970. This is
1293
** the same as strftime('%s','now') but is more compact.
1294
*/
1295
void db_now_function(
1296
sqlite3_context *context,
1297
int argc,
1298
sqlite3_value **argv
1299
){
1300
sqlite3_result_int64(context, time(0));
1301
}
1302
1303
/*
1304
** Function to return the check-in time for a file.
1305
**
1306
** checkin_mtime(CKINID,RID)
1307
**
1308
** CKINID: The RID for the manifest for a check-in.
1309
** RID: The RID of a file in CKINID for which the check-in time
1310
** is desired.
1311
**
1312
** Returns: The check-in time in seconds since 1970.
1313
*/
1314
void db_checkin_mtime_function(
1315
sqlite3_context *context,
1316
int argc,
1317
sqlite3_value **argv
1318
){
1319
i64 mtime;
1320
int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
1321
sqlite3_value_int(argv[1]), &mtime);
1322
if( rc==0 ){
1323
sqlite3_result_int64(context, mtime);
1324
}
1325
}
1326
1327
/*
1328
** SQL wrapper around the symbolic_name_to_rid() C-language API.
1329
** Examples:
1330
**
1331
** symbolic_name_to_rid('trunk');
1332
** symbolic_name_to_rid('trunk','w');
1333
**
1334
*/
1335
void db_sym2rid_function(
1336
sqlite3_context *context,
1337
int argc,
1338
sqlite3_value **argv
1339
){
1340
const char *arg;
1341
const char *type;
1342
if(1 != argc && 2 != argc){
1343
sqlite3_result_error(context, "Expecting one or two arguments", -1);
1344
return;
1345
}
1346
arg = (const char*)sqlite3_value_text(argv[0]);
1347
if(!arg){
1348
sqlite3_result_error(context, "Expecting a STRING argument", -1);
1349
}else{
1350
int rid;
1351
type = (2==argc) ? (const char*)sqlite3_value_text(argv[1]) : 0;
1352
if(!type) type = "ci";
1353
rid = symbolic_name_to_rid( arg, type );
1354
if(rid<0){
1355
sqlite3_result_error(context, "Symbolic name is ambiguous.", -1);
1356
}else if(0==rid){
1357
sqlite3_result_null(context);
1358
}else{
1359
sqlite3_result_int64(context, rid);
1360
}
1361
}
1362
}
1363
1364
1365
/*
1366
** SETTING: timeline-utc boolean default=on
1367
**
1368
** If the timeline-utc setting is true, then Fossil tries to understand
1369
** and display all time values using UTC. If this setting is false, Fossil
1370
** tries to understand and display time values using the local timezone.
1371
**
1372
** The word "timeline" in the name of this setting is historical.
1373
** This setting applies to all user interfaces of Fossil,
1374
** not just the timeline.
1375
**
1376
** Note that when accessing Fossil using the web interface, the localtime
1377
** used is the localtime on the server, not on the client.
1378
*/
1379
/*
1380
** Return true if Fossil is set to display times as UTC. Return false
1381
** if it wants to display times using the local timezone.
1382
**
1383
** False is returned if display is set to localtime even if the localtime
1384
** happens to be the same as UTC.
1385
*/
1386
int fossil_ui_utctime(void){
1387
if( g.fTimeFormat==0 ){
1388
if( db_get_int("timeline-utc", 1) ){
1389
g.fTimeFormat = 1; /* UTC */
1390
}else{
1391
g.fTimeFormat = 2; /* Localtime */
1392
}
1393
}
1394
return g.fTimeFormat==1;
1395
}
1396
1397
/*
1398
** Return true if Fossil is set to display times using the local timezone.
1399
*/
1400
int fossil_ui_localtime(void){
1401
return fossil_ui_utctime()==0;
1402
}
1403
1404
/*
1405
** The toLocal() SQL function returns a string that is an argument to a
1406
** date/time function that is appropriate for modifying the time for display.
1407
** If UTC time display is selected, no modification occurs. If local time
1408
** display is selected, the time is adjusted appropriately.
1409
**
1410
** Example usage:
1411
**
1412
** SELECT datetime('now',toLocal());
1413
*/
1414
void db_tolocal_function(
1415
sqlite3_context *context,
1416
int argc,
1417
sqlite3_value **argv
1418
){
1419
if( fossil_ui_utctime() ){
1420
sqlite3_result_text(context, "0 seconds", -1, SQLITE_STATIC);
1421
}else{
1422
sqlite3_result_text(context, "localtime", -1, SQLITE_STATIC);
1423
}
1424
}
1425
1426
/*
1427
** The fromLocal() SQL function returns a string that is an argument to a
1428
** date/time function that is appropriate to convert an input time to UTC.
1429
** If UTC time display is selected, no modification occurs. If local time
1430
** display is selected, the time is adjusted from local to UTC.
1431
**
1432
** Example usage:
1433
**
1434
** SELECT julianday(:user_input,fromLocal());
1435
*/
1436
void db_fromlocal_function(
1437
sqlite3_context *context,
1438
int argc,
1439
sqlite3_value **argv
1440
){
1441
if( fossil_ui_utctime() ){
1442
sqlite3_result_text(context, "0 seconds", -1, SQLITE_STATIC);
1443
}else{
1444
sqlite3_result_text(context, "utc", -1, SQLITE_STATIC);
1445
}
1446
}
1447
1448
/*
1449
** If the input is a hexadecimal string, convert that string into a BLOB.
1450
** If the input is not a hexadecimal string, return NULL.
1451
*/
1452
void db_hextoblob(
1453
sqlite3_context *context,
1454
int argc,
1455
sqlite3_value **argv
1456
){
1457
const unsigned char *zIn = sqlite3_value_text(argv[0]);
1458
int nIn = sqlite3_value_bytes(argv[0]);
1459
unsigned char *zOut;
1460
if( zIn==0 ) return;
1461
if( nIn&1 ) return;
1462
if( !validate16((const char*)zIn, nIn) ) return;
1463
zOut = sqlite3_malloc64( nIn/2 + 1 );
1464
if( zOut==0 ){
1465
sqlite3_result_error_nomem(context);
1466
return;
1467
}
1468
decode16(zIn, zOut, nIn);
1469
sqlite3_result_blob(context, zOut, nIn/2, sqlite3_free);
1470
}
1471
1472
/*
1473
** Return the XOR-obscured version of the input text. Useful for
1474
** updating authentication strings in Fossil settings. To change
1475
** the password locally stored for sync, for instance:
1476
**
1477
** echo "UPDATE config
1478
** SET value = obscure('monkey123')
1479
** WHERE name = 'last-sync-pw'" |
1480
** fossil sql
1481
**
1482
** Note that user.pw uses a different obscuration algorithm, but
1483
** you don't need to use 'fossil sql' for that anyway. Just call
1484
**
1485
** fossil user pass monkey123
1486
**
1487
** to change the local user entry's password in the same way.
1488
**
1489
** 2022-12-30: If the user-data pointer is not NULL, then operate
1490
** as unobscure() rather than obscure(). The obscure() variant of
1491
** this routine is commonly available. But unobscure is (currently)
1492
** only registered by the "fossil remote config-data --show-passwords"
1493
** command.
1494
*/
1495
void db_obscure(
1496
sqlite3_context *context,
1497
int argc,
1498
sqlite3_value **argv
1499
){
1500
const unsigned char *zIn = sqlite3_value_text(argv[0]);
1501
int nIn = sqlite3_value_bytes(argv[0]);
1502
char *zOut, *zTemp;
1503
if( 0==zIn ) return;
1504
if( 0==(zOut = sqlite3_malloc64( nIn * 2 + 3 )) ){
1505
sqlite3_result_error_nomem(context);
1506
return;
1507
}
1508
if( sqlite3_user_data(context)==0 ){
1509
zTemp = obscure((char*)zIn);
1510
}else{
1511
zTemp = unobscure((char*)zIn);
1512
}
1513
fossil_strcpy(zOut, zTemp);
1514
fossil_free(zTemp);
1515
sqlite3_result_text(context, zOut, strlen(zOut), sqlite3_free);
1516
}
1517
1518
/*
1519
** Return True if zName is a protected (a.k.a. "sensitive") setting.
1520
*/
1521
int db_setting_is_protected(const char *zName){
1522
const Setting *pSetting = zName ? db_find_setting(zName,0) : 0;
1523
return pSetting!=0 && pSetting->sensitive!=0;
1524
}
1525
1526
/*
1527
** Implement the protected_setting(X) SQL function. This function returns
1528
** true if X is the name of a protected (security-sensitive) setting and
1529
** the db.protectSensitive flag is enabled. It returns false otherwise.
1530
*/
1531
LOCAL void db_protected_setting_func(
1532
sqlite3_context *context,
1533
int argc,
1534
sqlite3_value **argv
1535
){
1536
const char *zSetting;
1537
if( (db.protectMask & PROTECT_SENSITIVE)==0 ){
1538
sqlite3_result_int(context, 0);
1539
return;
1540
}
1541
zSetting = (const char*)sqlite3_value_text(argv[0]);
1542
sqlite3_result_int(context, db_setting_is_protected(zSetting));
1543
}
1544
1545
/*
1546
** Copied from SQLite ext/misc/uint.c...
1547
**
1548
** Compare text in lexicographic order, except strings of digits
1549
** compare in numeric order.
1550
**
1551
** This version modified to also ignore case.
1552
*/
1553
static int uintNocaseCollFunc(
1554
void *notUsed,
1555
int nKey1, const void *pKey1,
1556
int nKey2, const void *pKey2
1557
){
1558
const unsigned char *zA = (const unsigned char*)pKey1;
1559
const unsigned char *zB = (const unsigned char*)pKey2;
1560
int i=0, j=0, x;
1561
(void)notUsed;
1562
while( i<nKey1 && j<nKey2 ){
1563
if( fossil_isdigit(zA[i]) && fossil_isdigit(zB[j]) ){
1564
int k;
1565
while( i<nKey1 && zA[i]=='0' ){ i++; }
1566
while( j<nKey2 && zB[j]=='0' ){ j++; }
1567
k = 0;
1568
while( i+k<nKey1 && fossil_isdigit(zA[i+k])
1569
&& j+k<nKey2 && fossil_isdigit(zB[j+k]) ){
1570
k++;
1571
}
1572
if( i+k<nKey1 && fossil_isdigit(zA[i+k]) ){
1573
return +1;
1574
}else if( j+k<nKey2 && fossil_isdigit(zB[j+k]) ){
1575
return -1;
1576
}else{
1577
x = memcmp(zA+i, zB+j, k);
1578
if( x ) return x;
1579
i += k;
1580
j += k;
1581
}
1582
}else
1583
if( zA[i]!=zB[j]
1584
&& (x = fossil_tolower(zA[i]) - fossil_tolower(zB[j]))!=0
1585
){
1586
return x;
1587
}else{
1588
i++;
1589
j++;
1590
}
1591
}
1592
return (nKey1 - i) - (nKey2 - j);
1593
}
1594
1595
1596
/*
1597
** Register the SQL functions that are useful both to the internal
1598
** representation and to the "fossil sql" command.
1599
*/
1600
void db_add_aux_functions(sqlite3 *db){
1601
sqlite3_create_collation(db, "uintnocase", SQLITE_UTF8,0,uintNocaseCollFunc);
1602
sqlite3_create_function(db, "checkin_mtime", 2,
1603
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1604
0, db_checkin_mtime_function, 0, 0);
1605
sqlite3_create_function(db, "symbolic_name_to_rid", 1,
1606
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1607
0, db_sym2rid_function, 0, 0);
1608
sqlite3_create_function(db, "symbolic_name_to_rid", 2,
1609
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1610
0, db_sym2rid_function, 0, 0);
1611
sqlite3_create_function(db, "now", 0,
1612
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
1613
db_now_function, 0, 0);
1614
sqlite3_create_function(db, "toLocal", 0,
1615
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1616
0, db_tolocal_function, 0, 0);
1617
sqlite3_create_function(db, "fromLocal", 0,
1618
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1619
0, db_fromlocal_function, 0, 0);
1620
sqlite3_create_function(db, "hextoblob", 1,
1621
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1622
0, db_hextoblob, 0, 0);
1623
sqlite3_create_function(db, "capunion", 1, SQLITE_UTF8, 0,
1624
0, capability_union_step, capability_union_finalize);
1625
sqlite3_create_function(db, "fullcap", 1, SQLITE_UTF8, 0,
1626
capability_fullcap, 0, 0);
1627
sqlite3_create_function(db, "find_emailaddr", 1, SQLITE_UTF8, 0,
1628
alert_find_emailaddr_func, 0, 0);
1629
sqlite3_create_function(db, "display_name", 1, SQLITE_UTF8, 0,
1630
alert_display_name_func, 0, 0);
1631
sqlite3_create_function(db, "obscure", 1, SQLITE_UTF8, 0,
1632
db_obscure, 0, 0);
1633
sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
1634
db_protected_setting_func, 0, 0);
1635
sqlite3_create_function(db, "win_reserved", 1, SQLITE_UTF8, 0,
1636
db_win_reserved_func,0,0);
1637
sqlite3_create_function(db, "url_nouser", 1, SQLITE_UTF8, 0,
1638
url_nouser_func,0,0);
1639
sqlite3_create_function(db, "chat_msg_from_event", 4,
1640
SQLITE_UTF8 | SQLITE_INNOCUOUS, 0,
1641
chat_msg_from_event, 0, 0);
1642
sqlite3_create_function(db, "inode", 1, SQLITE_UTF8, 0,
1643
file_inode_sql_func,0,0);
1644
sqlite3_create_function(db, "artifact_to_json", 1, SQLITE_UTF8, 0,
1645
artifact_to_json_sql_func,0,0);
1646
1647
}
1648
1649
#if USE_SEE
1650
/*
1651
** This is a pointer to the saved database encryption key string.
1652
*/
1653
static char *zSavedKey = 0;
1654
1655
/*
1656
** This is the size of the saved database encryption key, in bytes.
1657
*/
1658
static size_t savedKeySize = 0;
1659
1660
/*
1661
** This function returns non-zero if there is a saved database encryption
1662
** key available.
1663
*/
1664
int db_have_saved_encryption_key(){
1665
return db_is_valid_saved_encryption_key(zSavedKey, savedKeySize);
1666
}
1667
1668
/*
1669
** This function returns non-zero if the specified database encryption key
1670
** is valid.
1671
*/
1672
int db_is_valid_saved_encryption_key(const char *p, size_t n){
1673
if( p==0 ) return 0;
1674
if( n==0 ) return 0;
1675
if( p[0]==0 ) return 0;
1676
return 1;
1677
}
1678
1679
/*
1680
** This function returns the saved database encryption key -OR- zero if
1681
** no database encryption key is saved.
1682
*/
1683
char *db_get_saved_encryption_key(){
1684
return zSavedKey;
1685
}
1686
1687
/*
1688
** This function returns the size of the saved database encryption key
1689
** -OR- zero if no database encryption key is saved.
1690
*/
1691
size_t db_get_saved_encryption_key_size(){
1692
return savedKeySize;
1693
}
1694
1695
/*
1696
** This function arranges for the saved database encryption key buffer
1697
** to be allocated and then sets up the environment variable to allow
1698
** a child process to initialize it with the actual database encryption
1699
** key.
1700
*/
1701
void db_setup_for_saved_encryption_key(){
1702
void *p = NULL;
1703
size_t n = 0;
1704
size_t pageSize = 0;
1705
Blob pidKey;
1706
1707
assert( !db_have_saved_encryption_key() );
1708
db_unsave_encryption_key();
1709
fossil_get_page_size(&pageSize);
1710
assert( pageSize>0 );
1711
p = fossil_secure_alloc_page(&n);
1712
assert( p!=NULL );
1713
assert( n==pageSize );
1714
blob_zero(&pidKey);
1715
blob_appendf(&pidKey, "%lu:%p:%u", (unsigned long)GETPID(), p, n);
1716
fossil_setenv("FOSSIL_SEE_PID_KEY", blob_str(&pidKey));
1717
zSavedKey = p;
1718
savedKeySize = n;
1719
}
1720
1721
/*
1722
** This function arranges for the database encryption key to be securely
1723
** saved in non-pageable memory (on platforms where this is possible).
1724
*/
1725
static void db_save_encryption_key(
1726
Blob *pKey
1727
){
1728
void *p = NULL;
1729
size_t n = 0;
1730
size_t pageSize = 0;
1731
size_t blobSize = 0;
1732
1733
assert( !db_have_saved_encryption_key() );
1734
blobSize = blob_size(pKey);
1735
if( blobSize==0 ) return;
1736
fossil_get_page_size(&pageSize);
1737
assert( pageSize>0 );
1738
if( blobSize>pageSize ){
1739
fossil_panic("key blob too large: %u versus %u", blobSize, pageSize);
1740
}
1741
p = fossil_secure_alloc_page(&n);
1742
assert( p!=NULL );
1743
assert( n==pageSize );
1744
assert( n>=blobSize );
1745
memcpy(p, blob_str(pKey), blobSize);
1746
zSavedKey = p;
1747
savedKeySize = n;
1748
}
1749
1750
/*
1751
** This function arranges for the saved database encryption key to be
1752
** securely zeroed, unlocked (if necessary), and freed.
1753
*/
1754
void db_unsave_encryption_key(){
1755
fossil_secure_free_page(zSavedKey, savedKeySize);
1756
zSavedKey = NULL;
1757
savedKeySize = 0;
1758
}
1759
1760
/*
1761
** This function sets the saved database encryption key to the specified
1762
** string value, allocating or freeing the underlying memory if needed.
1763
*/
1764
static void db_set_saved_encryption_key(
1765
Blob *pKey
1766
){
1767
if( zSavedKey!=NULL ){
1768
size_t blobSize = blob_size(pKey);
1769
if( blobSize==0 ){
1770
db_unsave_encryption_key();
1771
}else{
1772
if( blobSize>savedKeySize ){
1773
fossil_panic("key blob too large: %u versus %u",
1774
blobSize, savedKeySize);
1775
}
1776
fossil_secure_zero(zSavedKey, savedKeySize);
1777
memcpy(zSavedKey, blob_str(pKey), blobSize);
1778
}
1779
}else{
1780
db_save_encryption_key(pKey);
1781
}
1782
}
1783
1784
/*
1785
** WEBPAGE: setseekey
1786
**
1787
** Sets the sets the saved database encryption key to one that gets passed
1788
** via the "key" query string parameter. If the saved database encryption
1789
** key has already been set, does nothing. This web page does not produce
1790
** any output on success or failure. No permissions are required and none
1791
** are checked (partially due to lack of encrypted database access).
1792
**
1793
** Query parameters:
1794
**
1795
** key The string to set as the saved database encryption
1796
** key.
1797
*/
1798
void db_set_see_key_page(void){
1799
Blob key;
1800
const char *zKey;
1801
if( db_have_saved_encryption_key() ){
1802
fossil_trace("SEE: encryption key was already set\n");
1803
return;
1804
}
1805
zKey = P("key");
1806
blob_init(&key, 0, 0);
1807
if( zKey!=0 ){
1808
PID_T processId;
1809
blob_set(&key, zKey);
1810
db_set_saved_encryption_key(&key);
1811
processId = db_maybe_handle_saved_encryption_key_for_process(
1812
SEE_KEY_WRITE
1813
);
1814
fossil_trace("SEE: set encryption key for process %lu, length %u\n",
1815
(unsigned long)processId, blob_size(&key));
1816
}else{
1817
fossil_trace("SEE: no encryption key specified\n");
1818
}
1819
blob_reset(&key);
1820
}
1821
1822
/*
1823
** WEBPAGE: unsetseekey
1824
**
1825
** Sets the saved database encryption key to zeros in the current and parent
1826
** Fossil processes. This web page does not produce any output on success
1827
** or failure. Setup permission is required.
1828
*/
1829
void db_unset_see_key_page(void){
1830
PID_T processId;
1831
login_check_credentials();
1832
if( !g.perm.Setup ){ login_needed(0); return; }
1833
processId = db_maybe_handle_saved_encryption_key_for_process(
1834
SEE_KEY_ZERO
1835
);
1836
fossil_trace("SEE: unset encryption key for process %lu\n",
1837
(unsigned long)processId);
1838
}
1839
1840
/*
1841
** This function reads the saved database encryption key from the
1842
** specified Fossil parent process. This is only necessary (or
1843
** functional) on Windows or Linux.
1844
*/
1845
static void db_read_saved_encryption_key_from_process(
1846
PID_T processId, /* Identifier for Fossil parent process. */
1847
LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
1848
SIZE_T nSize /* Size of saved key buffer in the parent process. */
1849
){
1850
void *p = NULL;
1851
size_t n = 0;
1852
size_t pageSize = 0;
1853
1854
fossil_get_page_size(&pageSize);
1855
assert( pageSize>0 );
1856
if( nSize>pageSize ){
1857
fossil_panic("key too large: %u versus %u", nSize, pageSize);
1858
}
1859
p = fossil_secure_alloc_page(&n);
1860
assert( p!=NULL );
1861
assert( n==pageSize );
1862
assert( n>=nSize );
1863
{
1864
#if defined(_WIN32)
1865
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId);
1866
if( hProcess!=NULL ){
1867
SIZE_T nRead = 0;
1868
if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){
1869
CloseHandle(hProcess);
1870
if( nRead==nSize ){
1871
db_unsave_encryption_key();
1872
zSavedKey = p;
1873
savedKeySize = n;
1874
}else{
1875
fossil_secure_free_page(p, n);
1876
fossil_panic("bad size read, %u out of %u bytes at %p from pid %lu",
1877
nRead, nSize, pAddress, processId);
1878
}
1879
}else{
1880
CloseHandle(hProcess);
1881
fossil_secure_free_page(p, n);
1882
fossil_panic("failed read, %u bytes at %p from pid %lu: %lu", nSize,
1883
pAddress, processId, GetLastError());
1884
}
1885
}else{
1886
fossil_secure_free_page(p, n);
1887
fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
1888
}
1889
#elif defined(__linux__)
1890
ssize_t nRead;
1891
struct iovec liov = {0};
1892
struct iovec riov = {0};
1893
liov.iov_base = p;
1894
liov.iov_len = n;
1895
riov.iov_base = pAddress;
1896
riov.iov_len = nSize;
1897
nRead = process_vm_readv(processId, &liov, 1, &riov, 1, 0);
1898
if( nRead==nSize ){
1899
db_unsave_encryption_key();
1900
zSavedKey = p;
1901
savedKeySize = n;
1902
}else{
1903
fossil_secure_free_page(p, n);
1904
fossil_panic("bad size read, %zd out of %zu bytes at %p from pid %lu",
1905
nRead, nSize, pAddress, (unsigned long)processId);
1906
}
1907
#else
1908
fossil_secure_free_page(p, n);
1909
fossil_trace("db_read_saved_encryption_key_from_process unsupported");
1910
#endif
1911
}
1912
}
1913
1914
/*
1915
** This function writes the saved database encryption key into the
1916
** specified Fossil parent process. This is only necessary (or
1917
** functional) on Windows or Linux.
1918
*/
1919
static void db_write_saved_encryption_key_to_process(
1920
PID_T processId, /* Identifier for Fossil parent process. */
1921
LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
1922
SIZE_T nSize /* Size of saved key buffer in the parent process. */
1923
){
1924
void *p = db_get_saved_encryption_key();
1925
size_t n = db_get_saved_encryption_key_size();
1926
size_t pageSize = 0;
1927
1928
fossil_get_page_size(&pageSize);
1929
assert( pageSize>0 );
1930
if( nSize>pageSize ){
1931
fossil_panic("key too large: %u versus %u", nSize, pageSize);
1932
}
1933
assert( p!=NULL );
1934
assert( n==pageSize );
1935
assert( n>=nSize );
1936
{
1937
#if defined(_WIN32)
1938
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
1939
FALSE, processId);
1940
if( hProcess!=NULL ){
1941
SIZE_T nWrite = 0;
1942
if( WriteProcessMemory(hProcess, pAddress, p, nSize, &nWrite) ){
1943
CloseHandle(hProcess);
1944
if( nWrite!=nSize ){
1945
fossil_panic("bad size write, %u out of %u bytes at %p from pid %lu",
1946
nWrite, nSize, pAddress, processId);
1947
}
1948
}else{
1949
CloseHandle(hProcess);
1950
fossil_panic("failed write, %u bytes at %p from pid %lu: %lu", nSize,
1951
pAddress, processId, GetLastError());
1952
}
1953
}else{
1954
fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
1955
}
1956
#elif defined(__linux__)
1957
ssize_t nWrite;
1958
struct iovec liov = {0};
1959
struct iovec riov = {0};
1960
liov.iov_base = p;
1961
liov.iov_len = n;
1962
riov.iov_base = pAddress;
1963
riov.iov_len = nSize;
1964
nWrite = process_vm_writev(processId, &liov, 1, &riov, 1, 0);
1965
if( nWrite!=nSize ){
1966
fossil_panic("bad size write, %zd out of %zu bytes at %p from pid %lu",
1967
nWrite, nSize, pAddress, (unsigned long)processId);
1968
}
1969
#else
1970
fossil_trace("db_write_saved_encryption_key_to_process unsupported");
1971
#endif
1972
}
1973
}
1974
1975
/*
1976
** This function zeros the saved database encryption key in the specified
1977
** Fossil parent process. This is only necessary (or functional) on
1978
** Windows or Linux.
1979
*/
1980
static void db_zero_saved_encryption_key_in_process(
1981
PID_T processId, /* Identifier for Fossil parent process. */
1982
LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
1983
SIZE_T nSize /* Size of saved key buffer in the parent process. */
1984
){
1985
void *p = NULL;
1986
size_t n = 0;
1987
size_t pageSize = 0;
1988
1989
fossil_get_page_size(&pageSize);
1990
assert( pageSize>0 );
1991
if( nSize>pageSize ){
1992
fossil_panic("key too large: %u versus %u", nSize, pageSize);
1993
}
1994
p = fossil_secure_alloc_page(&n);
1995
assert( p!=NULL );
1996
assert( n==pageSize );
1997
assert( n>=nSize );
1998
{
1999
#if defined(_WIN32)
2000
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
2001
FALSE, processId);
2002
if( hProcess!=NULL ){
2003
SIZE_T nWrite = 0;
2004
if( WriteProcessMemory(hProcess, pAddress, p, nSize, &nWrite) ){
2005
CloseHandle(hProcess);
2006
fossil_secure_free_page(p, n);
2007
if( nWrite!=nSize ){
2008
fossil_panic("bad size zero, %u out of %u bytes at %p from pid %lu",
2009
nWrite, nSize, pAddress, processId);
2010
}
2011
}else{
2012
CloseHandle(hProcess);
2013
fossil_secure_free_page(p, n);
2014
fossil_panic("failed zero, %u bytes at %p from pid %lu: %lu", nSize,
2015
pAddress, processId, GetLastError());
2016
}
2017
}else{
2018
fossil_secure_free_page(p, n);
2019
fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
2020
}
2021
#elif defined(__linux__)
2022
ssize_t nWrite;
2023
struct iovec liov = {0};
2024
struct iovec riov = {0};
2025
liov.iov_base = p;
2026
liov.iov_len = n;
2027
riov.iov_base = pAddress;
2028
riov.iov_len = nSize;
2029
nWrite = process_vm_writev(processId, &liov, 1, &riov, 1, 0);
2030
if( nWrite!=nSize ){
2031
fossil_secure_free_page(p, n);
2032
fossil_panic("bad size zero, %zd out of %zu bytes at %p from pid %lu",
2033
nWrite, nSize, pAddress, (unsigned long)processId);
2034
}
2035
#else
2036
fossil_secure_free_page(p, n);
2037
fossil_trace("db_zero_saved_encryption_key_in_process unsupported");
2038
#endif
2039
}
2040
}
2041
2042
/*
2043
** This function evaluates the specified TH1 script and attempts to parse
2044
** its result as a colon-delimited triplet containing a process identifier,
2045
** address, and size (in bytes) of the database encryption key. This is
2046
** only necessary (or functional) on Windows or Linux.
2047
*/
2048
static PID_T db_handle_saved_encryption_key_for_process_via_th1(
2049
const char *zConfig, /* The TH1 script to evaluate. */
2050
int eType /* Non-zero to write key to parent process -OR-
2051
* zero to read it from the parent process. */
2052
){
2053
PID_T processId = 0;
2054
int rc;
2055
char *zResult;
2056
char *zPwd = file_getcwd(0, 0);
2057
Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_NEED_CONFIG | TH_INIT_NO_REPO);
2058
rc = Th_Eval(g.interp, 0, zConfig, -1);
2059
zResult = (char*)Th_GetResult(g.interp, 0);
2060
if( rc!=TH_OK ){
2061
fossil_fatal("script for pid key failed: %s", zResult);
2062
}
2063
if( zResult ){
2064
LPVOID pAddress = NULL;
2065
SIZE_T nSize = 0;
2066
parse_pid_key_value(zResult, &processId, &pAddress, &nSize);
2067
if( eType==SEE_KEY_READ ){
2068
db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
2069
}else if( eType==SEE_KEY_WRITE ){
2070
db_write_saved_encryption_key_to_process(processId, pAddress, nSize);
2071
}else if( eType==SEE_KEY_ZERO ){
2072
db_zero_saved_encryption_key_in_process(processId, pAddress, nSize);
2073
}else{
2074
fossil_panic("unsupported SEE key operation %d", eType);
2075
}
2076
}
2077
file_chdir(zPwd, 0);
2078
fossil_free(zPwd);
2079
return processId;
2080
}
2081
2082
/*
2083
** This function sets the saved database encryption key to one that gets
2084
** read from the specified Fossil parent process, if applicable. This is
2085
** only necessary (or functional) on Windows or Linux.
2086
*/
2087
PID_T db_maybe_handle_saved_encryption_key_for_process(int eType){
2088
PID_T processId = 0;
2089
g.zPidKey = find_option("usepidkey",0,1);
2090
if( !g.zPidKey ){
2091
g.zPidKey = fossil_getenv("FOSSIL_SEE_PID_KEY");
2092
}
2093
if( g.zPidKey ){
2094
LPVOID pAddress = NULL;
2095
SIZE_T nSize = 0;
2096
parse_pid_key_value(g.zPidKey, &processId, &pAddress, &nSize);
2097
if( eType==SEE_KEY_READ ){
2098
db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
2099
}else if( eType==SEE_KEY_WRITE ){
2100
db_write_saved_encryption_key_to_process(processId, pAddress, nSize);
2101
}else if( eType==SEE_KEY_ZERO ){
2102
db_zero_saved_encryption_key_in_process(processId, pAddress, nSize);
2103
}else{
2104
fossil_panic("unsupported SEE key operation %d", eType);
2105
}
2106
}else{
2107
const char *zSeeDbConfig = find_option("seedbcfg",0,1);
2108
if( !zSeeDbConfig ){
2109
zSeeDbConfig = fossil_getenv("FOSSIL_SEE_DB_CONFIG");
2110
}
2111
if( zSeeDbConfig ){
2112
processId = db_handle_saved_encryption_key_for_process_via_th1(
2113
zSeeDbConfig, eType
2114
);
2115
}
2116
}
2117
return processId;
2118
}
2119
#endif /* USE_SEE */
2120
2121
/*
2122
** If the database file zDbFile has a name that suggests that it is
2123
** encrypted, then prompt for the database encryption key and return it
2124
** in the blob *pKey. Or, if the encryption key has previously been
2125
** requested, just return a copy of the previous result. The blob in
2126
** *pKey must be initialized.
2127
*/
2128
static void db_maybe_obtain_encryption_key(
2129
const char *zDbFile, /* Name of the database file */
2130
Blob *pKey /* Put the encryption key here */
2131
){
2132
#if USE_SEE
2133
if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
2134
char *zKey = db_get_saved_encryption_key();
2135
if( zKey ){
2136
blob_set(pKey, zKey);
2137
}else{
2138
char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
2139
prompt_for_password(zPrompt, pKey, 0);
2140
fossil_free(zPrompt);
2141
db_set_saved_encryption_key(pKey);
2142
}
2143
}
2144
#endif
2145
}
2146
2147
2148
/*
2149
** Sets the encryption key for the database, if necessary.
2150
*/
2151
void db_maybe_set_encryption_key(sqlite3 *db, const char *zDbName){
2152
Blob key;
2153
blob_init(&key, 0, 0);
2154
db_maybe_obtain_encryption_key(zDbName, &key);
2155
if( blob_size(&key)>0 ){
2156
if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
2157
char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
2158
sqlite3_exec(db, zCmd, 0, 0, 0);
2159
fossil_secure_zero(zCmd, strlen(zCmd));
2160
sqlite3_free(zCmd);
2161
#if USE_SEE
2162
}else{
2163
sqlite3_key(db, blob_str(&key), -1);
2164
#endif
2165
}
2166
}
2167
blob_reset(&key);
2168
}
2169
2170
/*
2171
** Open a database file. Return a pointer to the new database
2172
** connection. An error results in process abort.
2173
*/
2174
LOCAL sqlite3 *db_open(const char *zDbName){
2175
int rc;
2176
sqlite3 *db;
2177
Blob bNameCheck = BLOB_INITIALIZER;
2178
2179
if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
2180
file_canonical_name(zDbName, &bNameCheck, 0)
2181
/* For purposes of the apndvfs check, g.nameOfExe and zDbName must
2182
** both be canonicalized, else chances are very good that they
2183
** will not match even if they're the same file. Details:
2184
** https://fossil-scm.org/forum/forumpost/16880a28aad1a868 */;
2185
if( strcmp(blob_str(&bNameCheck), g.nameOfExe)==0 ){
2186
extern int sqlite3_appendvfs_init(
2187
sqlite3 *, char **, const sqlite3_api_routines *
2188
);
2189
sqlite3_appendvfs_init(0,0,0);
2190
g.zVfsName = "apndvfs";
2191
}
2192
blob_reset(&bNameCheck);
2193
rc = sqlite3_open_v2(
2194
zDbName, &db,
2195
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
2196
g.zVfsName
2197
);
2198
if( rc!=SQLITE_OK ){
2199
db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
2200
}
2201
db_maybe_set_encryption_key(db, zDbName);
2202
sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, 0, &rc);
2203
sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_TRIGGER, 0, &rc);
2204
sqlite3_db_config(db, SQLITE_DBCONFIG_TRUSTED_SCHEMA, 0, &rc);
2205
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 0, &rc);
2206
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 0, &rc);
2207
sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, &rc);
2208
sqlite3_busy_timeout(db, 15000);
2209
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
2210
sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0);
2211
sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
2212
sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
2213
sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
2214
sqlite3_create_function(
2215
db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
2216
);
2217
sqlite3_create_function(
2218
db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
2219
);
2220
if( g.fSqlTrace ) sqlite3_trace_v2(db, SQLITE_TRACE_PROFILE, db_sql_trace, 0);
2221
db_add_aux_functions(db);
2222
re_add_sql_func(db); /* The REGEXP operator */
2223
foci_register(db); /* The "files_of_checkin" virtual table */
2224
sqlite3_set_authorizer(db, db_top_authorizer, db);
2225
db_register_fts5(db) /* in search.c */;
2226
return db;
2227
}
2228
2229
2230
/*
2231
** Detaches the zLabel database.
2232
*/
2233
void db_detach(const char *zLabel){
2234
db_multi_exec("DETACH DATABASE %Q", zLabel);
2235
}
2236
2237
/*
2238
** zDbName is the name of a database file. Attach zDbName using
2239
** the name zLabel.
2240
*/
2241
void db_attach(const char *zDbName, const char *zLabel){
2242
Blob key;
2243
if( db_table_exists(zLabel,"sqlite_schema") ) return;
2244
blob_init(&key, 0, 0);
2245
db_maybe_obtain_encryption_key(zDbName, &key);
2246
if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
2247
char *zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q",
2248
zDbName, zLabel, blob_str(&key));
2249
db_exec_sql(zCmd);
2250
fossil_secure_zero(zCmd, strlen(zCmd));
2251
sqlite3_free(zCmd);
2252
}else{
2253
char *zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY ''",
2254
zDbName, zLabel);
2255
db_exec_sql(zCmd);
2256
sqlite3_free(zCmd);
2257
#if USE_SEE
2258
if( blob_size(&key)>0 ){
2259
sqlite3_key_v2(g.db, zLabel, blob_str(&key), -1);
2260
}
2261
#endif
2262
}
2263
blob_reset(&key);
2264
}
2265
2266
/*
2267
** Change the schema name of the "main" database to zLabel.
2268
** zLabel must be a static string that is unchanged for the life of
2269
** the database connection.
2270
**
2271
** After calling this routine, db_database_slot(zLabel) should
2272
** return 0.
2273
*/
2274
void db_set_main_schemaname(sqlite3 *db, const char *zLabel){
2275
if( sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, zLabel) ){
2276
fossil_panic("Fossil requires a version of SQLite that supports the "
2277
"SQLITE_DBCONFIG_MAINDBNAME interface.");
2278
}
2279
}
2280
2281
/*
2282
** Return the slot number for database zLabel. The first database
2283
** opened is slot 0. The "temp" database is slot 1. Attached databases
2284
** are slots 2 and higher.
2285
**
2286
** Return -1 if zLabel does not match any open database.
2287
*/
2288
int db_database_slot(const char *zLabel){
2289
int iSlot = -1;
2290
int rc;
2291
Stmt q;
2292
if( g.db==0 ) return iSlot;
2293
rc = db_prepare_ignore_error(&q, "PRAGMA database_list");
2294
if( rc==SQLITE_OK ){
2295
while( db_step(&q)==SQLITE_ROW ){
2296
if( fossil_strcmp(db_column_text(&q,1),zLabel)==0 ){
2297
iSlot = db_column_int(&q, 0);
2298
break;
2299
}
2300
}
2301
}
2302
db_finalize(&q);
2303
return iSlot;
2304
}
2305
2306
/*
2307
** zDbName is the name of a database file. If no other database
2308
** file is open, then open this one. If another database file is
2309
** already open, then attach zDbName using the name zLabel.
2310
*/
2311
void db_open_or_attach(const char *zDbName, const char *zLabel){
2312
if( !g.db ){
2313
g.db = db_open(zDbName);
2314
db_set_main_schemaname(g.db, zLabel);
2315
}else{
2316
db_attach(zDbName, zLabel);
2317
}
2318
}
2319
2320
/*
2321
** Close the per-user configuration database file
2322
*/
2323
void db_close_config(){
2324
int iSlot = db_database_slot("configdb");
2325
if( iSlot>0 ){
2326
db_detach("configdb");
2327
}else if( g.dbConfig ){
2328
sqlite3_wal_checkpoint(g.dbConfig, 0);
2329
sqlite3_close(g.dbConfig);
2330
g.dbConfig = 0;
2331
}else if( g.db && 0==iSlot ){
2332
int rc;
2333
sqlite3_wal_checkpoint(g.db, 0);
2334
rc = sqlite3_close(g.db);
2335
if( g.fSqlTrace ) fossil_trace("-- db_close_config(%d)\n", rc);
2336
g.db = 0;
2337
g.repositoryOpen = 0;
2338
g.localOpen = 0;
2339
}else{
2340
return;
2341
}
2342
fossil_free(g.zConfigDbName);
2343
g.zConfigDbName = 0;
2344
}
2345
2346
/*
2347
** Compute the name of the configuration database. If unable to find the
2348
** database, return 0 if isOptional is true, or panic if isOptional is false.
2349
**
2350
** Space to hold the result comes from fossil_malloc().
2351
*/
2352
static char *db_configdb_name(int isOptional){
2353
char *zHome; /* Home directory */
2354
char *zDbName; /* Name of the database file */
2355
2356
2357
/* On Windows, look for these directories, in order:
2358
**
2359
** FOSSIL_HOME
2360
** LOCALAPPDATA
2361
** APPDATA
2362
** USERPROFILE
2363
** HOMEDRIVE HOMEPATH
2364
*/
2365
#if defined(_WIN32) || defined(__CYGWIN__)
2366
zHome = fossil_getenv("FOSSIL_HOME");
2367
if( zHome==0 ){
2368
zHome = fossil_getenv("LOCALAPPDATA");
2369
if( zHome==0 ){
2370
zHome = fossil_getenv("APPDATA");
2371
if( zHome==0 ){
2372
zHome = fossil_getenv("USERPROFILE");
2373
if( zHome==0 ){
2374
char *zDrive = fossil_getenv("HOMEDRIVE");
2375
char *zPath = fossil_getenv("HOMEPATH");
2376
if( zDrive && zPath ) zHome = mprintf("%s%s", zDrive, zPath);
2377
}
2378
}
2379
}
2380
}
2381
zDbName = mprintf("%//_fossil", zHome);
2382
fossil_free(zHome);
2383
return zDbName;
2384
2385
#else /* if unix */
2386
char *zXdgHome;
2387
2388
/* For unix. a 5-step algorithm is used.
2389
** See ../www/tech_overview.wiki for discussion.
2390
**
2391
** Step 1: If FOSSIL_HOME exists -> $FOSSIL_HOME/.fossil
2392
*/
2393
zHome = fossil_getenv("FOSSIL_HOME");
2394
if( zHome!=0 ) return mprintf("%s/.fossil", zHome);
2395
2396
/* Step 2: If HOME exists and file $HOME/.fossil exists -> $HOME/.fossil
2397
*/
2398
zHome = fossil_getenv("HOME");
2399
if( zHome ){
2400
zDbName = mprintf("%s/.fossil", zHome);
2401
if( file_size(zDbName, ExtFILE)>1024*3 ){
2402
return zDbName;
2403
}
2404
fossil_free(zDbName);
2405
}
2406
2407
/* Step 3: if XDG_CONFIG_HOME exists -> $XDG_CONFIG_HOME/fossil.db
2408
*/
2409
zXdgHome = fossil_getenv("XDG_CONFIG_HOME");
2410
if( zXdgHome!=0 ){
2411
return mprintf("%s/fossil.db", zXdgHome);
2412
}
2413
2414
/* The HOME variable is required in order to continue.
2415
*/
2416
if( zHome==0 ){
2417
if( isOptional ) return 0;
2418
fossil_fatal("cannot locate home directory - please set one of the "
2419
"FOSSIL_HOME, XDG_CONFIG_HOME, or HOME environment "
2420
"variables");
2421
}
2422
2423
/* Step 4: If $HOME/.config is a directory -> $HOME/.config/fossil.db
2424
*/
2425
zXdgHome = mprintf("%s/.config", zHome);
2426
if( file_isdir(zXdgHome, ExtFILE)==1 ){
2427
fossil_free(zXdgHome);
2428
return mprintf("%s/.config/fossil.db", zHome);
2429
}
2430
2431
/* Step 5: Otherwise -> $HOME/.fossil
2432
*/
2433
return mprintf("%s/.fossil", zHome);
2434
#endif /* unix */
2435
}
2436
2437
/*
2438
** Open the configuration database. Create the database anew if
2439
** it does not already exist.
2440
**
2441
** If the useAttach flag is 0 (the usual case) then the configuration
2442
** database is opened on a separate database connection g.dbConfig.
2443
** This prevents the database from becoming locked on long check-in or sync
2444
** operations which hold an exclusive transaction. In a few cases, though,
2445
** it is convenient for the database to be attached to the main database
2446
** connection so that we can join between the various databases. In that
2447
** case, invoke this routine with useAttach as 1.
2448
*/
2449
int db_open_config(int useAttach, int isOptional){
2450
char *zDbName;
2451
if( g.zConfigDbName ){
2452
int alreadyAttached = db_database_slot("configdb")>0;
2453
if( useAttach==alreadyAttached ) return 1; /* Already open. */
2454
db_close_config();
2455
}
2456
zDbName = db_configdb_name(isOptional);
2457
if( zDbName==0 ) return 0;
2458
if( file_size(zDbName, ExtFILE)<1024*3 ){
2459
char *zHome = file_dirname(zDbName);
2460
int rc;
2461
if( file_isdir(zHome, ExtFILE)==0 ){
2462
file_mkdir(zHome, ExtFILE, 0);
2463
}
2464
rc = file_access(zHome, W_OK);
2465
if( rc ){
2466
if( isOptional ) return 0;
2467
fossil_fatal("home directory \"%s\" must be writeable", zHome);
2468
}
2469
db_init_database(zDbName, zConfigSchema, (char*)0);
2470
fossil_free(zHome);
2471
}
2472
if( file_access(zDbName, W_OK) ){
2473
if( isOptional ) return 0;
2474
fossil_fatal("configuration file %s must be writeable", zDbName);
2475
}
2476
if( useAttach ){
2477
db_open_or_attach(zDbName, "configdb");
2478
g.dbConfig = 0;
2479
}else{
2480
g.dbConfig = db_open(zDbName);
2481
db_set_main_schemaname(g.dbConfig, "configdb");
2482
}
2483
g.zConfigDbName = zDbName;
2484
return 1;
2485
}
2486
2487
/*
2488
** Return TRUE if zTable exists.
2489
*/
2490
int db_table_exists(
2491
const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */
2492
const char *zTable /* Name of table */
2493
){
2494
return sqlite3_table_column_metadata(g.db, zDb, zTable, 0,
2495
0, 0, 0, 0, 0)==SQLITE_OK;
2496
}
2497
2498
/*
2499
** Return TRUE if zTable exists and contains column zColumn.
2500
** Return FALSE if zTable does not exist or if zTable exists
2501
** but lacks zColumn.
2502
*/
2503
int db_table_has_column(
2504
const char *zDb, /* One of: NULL, "config", "localdb", "repository" */
2505
const char *zTable, /* Name of table */
2506
const char *zColumn /* Name of column in table */
2507
){
2508
return sqlite3_table_column_metadata(g.db, zDb, zTable, zColumn,
2509
0, 0, 0, 0, 0)==SQLITE_OK;
2510
}
2511
2512
/*
2513
** Returns TRUE if zTable exists in the local database but lacks column
2514
** zColumn
2515
*/
2516
static int db_local_table_exists_but_lacks_column(
2517
const char *zTable,
2518
const char *zColumn
2519
){
2520
return db_table_exists("localdb", zTable)
2521
&& !db_table_has_column("localdb", zTable, zColumn);
2522
}
2523
2524
/*
2525
** If zDbName is a valid local database file, open it and return
2526
** true. If it is not a valid local database file, return 0.
2527
*/
2528
static int isValidLocalDb(const char *zDbName){
2529
i64 lsize;
2530
2531
if( file_access(zDbName, F_OK) ) return 0;
2532
lsize = file_size(zDbName, ExtFILE);
2533
if( lsize%1024!=0 || lsize<4096 ) return 0;
2534
db_open_or_attach(zDbName, "localdb");
2535
2536
/* Check to see if the check-out database has the latest schema changes.
2537
** The most recent schema change (2019-01-19) is the addition of the
2538
** vmerge.mhash and vfile.mhash fields. If the schema has the vmerge.mhash
2539
** column, assume everything else is up-to-date.
2540
*/
2541
if( db_table_has_column("localdb","vmerge","mhash") ){
2542
return 1; /* This is a check-out database with the latest schema */
2543
}
2544
2545
/* If there is no vfile table, then assume we have picked up something
2546
** that is not even close to being a valid check-out database */
2547
if( !db_table_exists("localdb","vfile") ){
2548
return 0; /* Not a DB */
2549
}
2550
2551
/* If the "isexe" column is missing from the vfile table, then
2552
** add it now. This code added on 2010-03-06. After all users have
2553
** upgraded, this code can be safely deleted.
2554
*/
2555
if( !db_table_has_column("localdb","vfile","isexe") ){
2556
db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");
2557
}
2558
2559
/* If "islink"/"isLink" columns are missing from tables, then
2560
** add them now. This code added on 2011-01-17 and 2011-08-27.
2561
** After all users have upgraded, this code can be safely deleted.
2562
*/
2563
if( !db_table_has_column("localdb","vfile","isLink") ){
2564
db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
2565
if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){
2566
db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0");
2567
}
2568
if( db_local_table_exists_but_lacks_column("undo", "isLink") ){
2569
db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0");
2570
}
2571
if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
2572
db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
2573
}
2574
}
2575
2576
/* The design of the check-out database changed on 2019-01-19 adding the mhash
2577
** column to vfile and vmerge and changing the UNIQUE index on vmerge into
2578
** a PRIMARY KEY that includes the new mhash column. However, we must have
2579
** the repository database at hand in order to do the migration, so that
2580
** step is deferred. */
2581
return 1;
2582
}
2583
2584
/*
2585
** Locate the root directory of the local repository tree. The root
2586
** directory is found by searching for a file named "_FOSSIL_" or ".fslckout"
2587
** that contains a valid repository database.
2588
**
2589
** For legacy, also look for ".fos". The use of ".fos" is deprecated
2590
** since "fos" has negative connotations in Hungarian, we are told.
2591
**
2592
** If no valid _FOSSIL_ or .fslckout file is found, we move up one level and
2593
** try again. Once the file is found, the g.zLocalRoot variable is set
2594
** to the root of the repository tree and this routine returns 1. If
2595
** no database is found, then this routine return 0.
2596
**
2597
** In db_open_local_v2(), if the bRootOnly flag is true, then only
2598
** look in the CWD for the check-out database. Do not scan upwards in
2599
** the file hierarchy.
2600
**
2601
** This routine always opens the user database regardless of whether or
2602
** not the repository database is found. If the _FOSSIL_ or .fslckout file
2603
** is found, it is attached to the open database connection too.
2604
*/
2605
int db_open_local_v2(const char *zDbName, int bRootOnly){
2606
int i, n;
2607
char zPwd[2000];
2608
static const char *(aDbName[]) = { "_FOSSIL_", ".fslckout", ".fos" };
2609
2610
if( g.localOpen ) return 1;
2611
file_getcwd(zPwd, sizeof(zPwd)-20);
2612
n = strlen(zPwd);
2613
while( n>0 ){
2614
for(i=0; i<count(aDbName); i++){
2615
sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "/%s", aDbName[i]);
2616
if( isValidLocalDb(zPwd) ){
2617
if( db_open_config(0, 1)==0 ){
2618
return 0; /* Configuration could not be opened */
2619
}
2620
/* Found a valid check-out database file */
2621
g.zLocalDbName = fossil_strdup(zPwd);
2622
zPwd[n] = 0;
2623
while( n>0 && zPwd[n-1]=='/' ){
2624
n--;
2625
zPwd[n] = 0;
2626
}
2627
g.zLocalRoot = mprintf("%s/", zPwd);
2628
g.localOpen = 1;
2629
db_open_repository(zDbName);
2630
return 1;
2631
}
2632
}
2633
if( bRootOnly ) break;
2634
n--;
2635
while( n>1 && zPwd[n]!='/' ){ n--; }
2636
while( n>1 && zPwd[n-1]=='/' ){ n--; }
2637
zPwd[n] = 0;
2638
}
2639
2640
/* A check-out database file could not be found */
2641
return 0;
2642
}
2643
int db_open_local(const char *zDbName){
2644
return db_open_local_v2(zDbName, 0);
2645
}
2646
2647
/*
2648
** Get the full pathname to the repository database file. The
2649
** local database (the _FOSSIL_ or .fslckout database) must have already
2650
** been opened before this routine is called.
2651
*/
2652
const char *db_repository_filename(void){
2653
static char *zRepo = 0;
2654
assert( g.localOpen );
2655
assert( g.zLocalRoot );
2656
if( zRepo==0 ){
2657
zRepo = db_lget("repository", 0);
2658
if( zRepo && !file_is_absolute_path(zRepo) ){
2659
char * zFree = zRepo;
2660
zRepo = mprintf("%s%s", g.zLocalRoot, zRepo);
2661
fossil_free(zFree);
2662
zFree = zRepo;
2663
zRepo = file_canonical_name_dup(zFree);
2664
fossil_free(zFree);
2665
}
2666
}
2667
return zRepo;
2668
}
2669
2670
/*
2671
** Returns non-zero if support for symlinks is currently enabled.
2672
*/
2673
int db_allow_symlinks(void){
2674
return g.allowSymlinks;
2675
}
2676
2677
/*
2678
** Return TRUE if the file in the argument seems like it might be an
2679
** SQLite database file that contains a Fossil repository schema.
2680
*/
2681
int db_looks_like_a_repository(const char *zDbName){
2682
sqlite3 *db = 0;
2683
i64 sz;
2684
int rc;
2685
int res = 0;
2686
sqlite3_stmt *pStmt = 0;
2687
2688
sz = file_size(zDbName, ExtFILE);
2689
if( sz<16834 ) return 0;
2690
db = db_open(zDbName);
2691
if( !db ) return 0;
2692
if( !g.zVfsName && sz%512 ) return 0;
2693
rc = sqlite3_prepare_v2(db,
2694
"SELECT count(*) FROM sqlite_schema"
2695
" WHERE name COLLATE nocase IN"
2696
"('blob','delta','rcvfrom','user','config','mlink','plink');",
2697
-1, &pStmt, 0);
2698
if( rc ) goto is_repo_end;
2699
rc = sqlite3_step(pStmt);
2700
if( rc!=SQLITE_ROW ) goto is_repo_end;
2701
if( sqlite3_column_int(pStmt, 0)!=7 ) goto is_repo_end;
2702
res = 1;
2703
2704
is_repo_end:
2705
sqlite3_finalize(pStmt);
2706
sqlite3_close(db);
2707
return res;
2708
}
2709
2710
/*
2711
** COMMAND: test-is-repo
2712
** Usage: %fossil test-is-repo FILENAME...
2713
**
2714
** Test whether the specified files look like a SQLite database
2715
** containing a Fossil repository schema.
2716
*/
2717
void test_is_repo(void){
2718
int i;
2719
verify_all_options();
2720
for(i=2; i<g.argc; i++){
2721
fossil_print("%s: %s\n",
2722
db_looks_like_a_repository(g.argv[i]) ? "yes" : " no",
2723
g.argv[i]
2724
);
2725
}
2726
}
2727
2728
2729
/*
2730
** Open the repository database given by zDbName. If zDbName==NULL then
2731
** get the name from the already open local database.
2732
*/
2733
void db_open_repository(const char *zDbName){
2734
if( g.repositoryOpen ) return;
2735
if( zDbName==0 ){
2736
if( g.localOpen ){
2737
zDbName = db_repository_filename();
2738
}
2739
if( zDbName==0 ){
2740
db_err("unable to find the name of a repository database");
2741
}
2742
}
2743
if( !db_looks_like_a_repository(zDbName) ){
2744
if( file_access(zDbName, F_OK) ){
2745
#ifdef FOSSIL_ENABLE_JSON
2746
g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
2747
#endif
2748
fossil_fatal("repository does not exist or"
2749
" is in an unreadable directory: %s", zDbName);
2750
}else if( file_access(zDbName, R_OK) ){
2751
#ifdef FOSSIL_ENABLE_JSON
2752
g.json.resultCode = FSL_JSON_E_DENIED;
2753
#endif
2754
fossil_fatal("read permission denied for repository %s", zDbName);
2755
}else{
2756
#ifdef FOSSIL_ENABLE_JSON
2757
g.json.resultCode = FSL_JSON_E_DB_NOT_VALID;
2758
#endif
2759
fossil_fatal("not a valid repository: %s", zDbName);
2760
}
2761
}
2762
g.zRepositoryName = fossil_strdup(zDbName);
2763
db_open_or_attach(g.zRepositoryName, "repository");
2764
g.repositoryOpen = 1;
2765
sqlite3_file_control(g.db, "repository", SQLITE_FCNTL_DATA_VERSION,
2766
&g.iRepoDataVers);
2767
2768
/* Cache "allow-symlinks" option, because we'll need it on every stat call */
2769
g.allowSymlinks = db_get_boolean("allow-symlinks",0);
2770
2771
g.zAuxSchema = db_get("aux-schema","");
2772
g.eHashPolicy = db_get_int("hash-policy",-1);
2773
if( g.eHashPolicy<0 ){
2774
g.eHashPolicy = hname_default_policy();
2775
db_set_int("hash-policy", g.eHashPolicy, 0);
2776
}
2777
2778
#if 0 /* No longer automatic. Need to run "fossil rebuild" to migrate */
2779
/* Make a change to the CHECK constraint on the BLOB table for
2780
** version 2.0 and later.
2781
*/
2782
rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */
2783
#endif
2784
2785
/* Additional checks that occur when opening the check-out database */
2786
if( g.localOpen ){
2787
2788
/* If the repository database that was just opened has been
2789
** replaced by a clone of the same project, with different RID
2790
** values, then renumber the RID values stored in various tables
2791
** of the check-out database, so that the repository and check-out
2792
** databases align.
2793
*/
2794
if( !db_fingerprint_ok() ){
2795
if( find_option("no-rid-adjust",0,0)!=0 ){
2796
/* The --no-rid-adjust command-line option bypasses the RID value
2797
** updates. Intended for use during debugging, especially to be
2798
** able to run "fossil sql" after a database swap. */
2799
fossil_print(
2800
"WARNING: repository change detected, but no adjust made.\n"
2801
);
2802
}else if( find_option("rid-renumber-dryrun",0,0)!=0 ){
2803
/* the --rid-renumber-dryrun option shows how RID values would be
2804
** renumbered, but does not actually perform the renumbering.
2805
** This is a debugging-only option. */
2806
vfile_rid_renumbering_event(1);
2807
exit(0);
2808
}else{
2809
char *z;
2810
stash_rid_renumbering_event();
2811
vfile_rid_renumbering_event(0);
2812
undo_reset();
2813
bisect_reset();
2814
z = db_fingerprint(0, 1);
2815
db_lset("fingerprint", z);
2816
fossil_free(z);
2817
fossil_print(
2818
"WARNING: The repository database has been replaced by a clone.\n"
2819
"Bisect history and undo have been lost.\n"
2820
);
2821
}
2822
}
2823
2824
/* Make sure the check-out database schema migration of 2019-01-20
2825
** has occurred.
2826
**
2827
** The 2019-01-19 migration is the addition of the vmerge.mhash and
2828
** vfile.mhash columns and making the vmerge.mhash column part of the
2829
** PRIMARY KEY for vmerge.
2830
*/
2831
if( !db_table_has_column("localdb", "vfile", "mhash") ){
2832
db_multi_exec("ALTER TABLE vfile ADD COLUMN mhash;");
2833
db_multi_exec(
2834
"UPDATE vfile"
2835
" SET mhash=(SELECT uuid FROM blob WHERE blob.rid=vfile.mrid)"
2836
" WHERE mrid!=rid;"
2837
);
2838
if( !db_table_has_column("localdb", "vmerge", "mhash") ){
2839
db_exec_sql("ALTER TABLE vmerge RENAME TO old_vmerge;");
2840
db_exec_sql(zLocalSchemaVmerge);
2841
db_exec_sql(
2842
"INSERT OR IGNORE INTO vmerge(id,merge,mhash)"
2843
" SELECT id, merge, blob.uuid FROM old_vmerge, blob"
2844
" WHERE old_vmerge.merge=blob.rid;"
2845
"DROP TABLE old_vmerge;"
2846
);
2847
}
2848
}
2849
}
2850
}
2851
2852
/*
2853
** Return true if there have been any changes to the repository
2854
** database since it was opened.
2855
**
2856
** Changes to "config" and "localdb" and "temp" do not count.
2857
** This routine only returns true if there have been changes
2858
** to "repository".
2859
*/
2860
int db_repository_has_changed(void){
2861
unsigned int v;
2862
if( !g.repositoryOpen ) return 0;
2863
sqlite3_file_control(g.db, "repository", SQLITE_FCNTL_DATA_VERSION, &v);
2864
return g.iRepoDataVers != v;
2865
}
2866
2867
/*
2868
** Flags for the db_find_and_open_repository() function.
2869
*/
2870
#if INTERFACE
2871
#define OPEN_OK_NOT_FOUND 0x001 /* Do not error out if not found */
2872
#define OPEN_ANY_SCHEMA 0x002 /* Do not error if schema is wrong */
2873
#define OPEN_SUBSTITUTE 0x004 /* Fake in-memory repo if not found */
2874
#endif
2875
2876
/*
2877
** Try to find the repository and open it. Use the -R or --repository
2878
** option to locate the repository. If no such option is available, then
2879
** use the repository of the open check-out if there is one.
2880
**
2881
** Error out if the repository cannot be opened.
2882
*/
2883
void db_find_and_open_repository(int bFlags, int nArgUsed){
2884
const char *zRep = find_repository_option();
2885
if( zRep && file_isdir(zRep, ExtFILE)==1 ){
2886
goto rep_not_found;
2887
}
2888
if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
2889
zRep = g.argv[nArgUsed];
2890
}
2891
if( zRep==0 ){
2892
if( db_open_local(0)==0 ){
2893
goto rep_not_found;
2894
}
2895
zRep = db_repository_filename();
2896
if( zRep==0 ){
2897
goto rep_not_found;
2898
}
2899
}
2900
db_open_repository(zRep);
2901
if( g.repositoryOpen ){
2902
if( (bFlags & OPEN_ANY_SCHEMA)==0 ) db_verify_schema();
2903
return;
2904
}
2905
rep_not_found:
2906
if( bFlags & OPEN_OK_NOT_FOUND ){
2907
/* No errors if the database is not found */
2908
if( bFlags & OPEN_SUBSTITUTE ){
2909
db_create_repository(0);
2910
}
2911
}else{
2912
#ifdef FOSSIL_ENABLE_JSON
2913
g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
2914
#endif
2915
if( nArgUsed==0 ){
2916
fossil_fatal("use --repository or -R to specify the repository database");
2917
}else{
2918
fossil_fatal("specify the repository name as a command-line argument");
2919
}
2920
}
2921
}
2922
2923
/*
2924
** Return TRUE if the schema is out-of-date
2925
*/
2926
int db_schema_is_outofdate(void){
2927
return strcmp(g.zAuxSchema,AUX_SCHEMA_MIN)<0
2928
|| strcmp(g.zAuxSchema,AUX_SCHEMA_MAX)>0;
2929
}
2930
2931
/*
2932
** Return true if the database is writeable
2933
*/
2934
int db_is_writeable(const char *zName){
2935
return g.db!=0 && !sqlite3_db_readonly(g.db, zName);
2936
}
2937
2938
/*
2939
** Verify that the repository schema is correct. If it is not correct,
2940
** issue a fatal error and die.
2941
*/
2942
void db_verify_schema(void){
2943
if( db_schema_is_outofdate() ){
2944
#ifdef FOSSIL_ENABLE_JSON
2945
g.json.resultCode = FSL_JSON_E_DB_NEEDS_REBUILD;
2946
#endif
2947
fossil_warning("incorrect repository schema version: "
2948
"current repository schema version is \"%s\" "
2949
"but need versions between \"%s\" and \"%s\".",
2950
g.zAuxSchema, AUX_SCHEMA_MIN, AUX_SCHEMA_MAX);
2951
fossil_fatal("run \"fossil rebuild\" to fix this problem");
2952
}
2953
}
2954
2955
2956
/*
2957
** COMMAND: test-move-repository
2958
**
2959
** Usage: %fossil test-move-repository PATHNAME
2960
**
2961
** Change the location of the repository database on a local check-out.
2962
** Use this command to avoid having to close and reopen a check-out
2963
** when relocating the repository database.
2964
*/
2965
void move_repo_cmd(void){
2966
Blob repo;
2967
char *zRepo;
2968
if( g.argc!=3 ){
2969
usage("PATHNAME");
2970
}
2971
file_canonical_name(g.argv[2], &repo, 0);
2972
zRepo = blob_str(&repo);
2973
if( file_access(zRepo, F_OK) ){
2974
fossil_fatal("no such file: %s", zRepo);
2975
}
2976
if( db_open_local(zRepo)==0 ){
2977
fossil_fatal("not in a local check-out");
2978
return;
2979
}
2980
db_open_or_attach(zRepo, "test_repo");
2981
db_lset("repository", blob_str(&repo));
2982
db_record_repository_filename(blob_str(&repo));
2983
db_close(1);
2984
}
2985
2986
2987
/*
2988
** Open the local database. If unable, exit with an error.
2989
*/
2990
void db_must_be_within_tree(void){
2991
if( find_repository_option() ){
2992
fossil_fatal("the \"%s\" command only works from within an open check-out",
2993
g.argv[1]);
2994
}
2995
if( db_open_local(0)==0 ){
2996
fossil_fatal("current directory is not within an open check-out");
2997
}
2998
db_open_repository(0);
2999
db_verify_schema();
3000
}
3001
3002
/*
3003
** Close the database connection.
3004
**
3005
** Check for unfinalized statements and report errors if the reportErrors
3006
** argument is true. Ignore unfinalized statements when false.
3007
*/
3008
void db_close(int reportErrors){
3009
sqlite3_stmt *pStmt;
3010
if( g.db==0 ) return;
3011
sqlite3_set_authorizer(g.db, 0, 0);
3012
if( g.fSqlStats ){
3013
int cur, hiwtr;
3014
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
3015
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
3016
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
3017
fprintf(stderr, "-- LOOKASIDE_HIT %10d\n", hiwtr);
3018
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &cur,&hiwtr,0);
3019
fprintf(stderr, "-- LOOKASIDE_MISS_SIZE %10d\n", hiwtr);
3020
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &cur,&hiwtr,0);
3021
fprintf(stderr, "-- LOOKASIDE_MISS_FULL %10d\n", hiwtr);
3022
sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_USED, &cur, &hiwtr, 0);
3023
fprintf(stderr, "-- CACHE_USED %10d\n", cur);
3024
sqlite3_db_status(g.db, SQLITE_DBSTATUS_SCHEMA_USED, &cur, &hiwtr, 0);
3025
fprintf(stderr, "-- SCHEMA_USED %10d\n", cur);
3026
sqlite3_db_status(g.db, SQLITE_DBSTATUS_STMT_USED, &cur, &hiwtr, 0);
3027
fprintf(stderr, "-- STMT_USED %10d\n", cur);
3028
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &cur, &hiwtr, 0);
3029
fprintf(stderr, "-- MEMORY_USED %10d %10d\n", cur, hiwtr);
3030
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &cur, &hiwtr, 0);
3031
fprintf(stderr, "-- MALLOC_SIZE %10d\n", hiwtr);
3032
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &cur, &hiwtr, 0);
3033
fprintf(stderr, "-- MALLOC_COUNT %10d %10d\n", cur, hiwtr);
3034
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &cur, &hiwtr, 0);
3035
fprintf(stderr, "-- PCACHE_OVFLOW %10d %10d\n", cur, hiwtr);
3036
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
3037
}
3038
while( db.pAllStmt ){
3039
db_finalize(db.pAllStmt);
3040
}
3041
if( db.nBegin ){
3042
if( reportErrors ){
3043
fossil_warning("Transaction started at %s:%d never commits",
3044
db.zStartFile, db.iStartLine);
3045
}
3046
db_end_transaction(1);
3047
}
3048
pStmt = 0;
3049
sqlite3_busy_timeout(g.db, 0);
3050
g.dbIgnoreErrors++; /* Stop "database locked" warnings */
3051
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
3052
g.dbIgnoreErrors--;
3053
db_close_config();
3054
3055
/* If the localdb has a lot of unused free space,
3056
** then VACUUM it as we shut down.
3057
*/
3058
if( db_database_slot("localdb")>=0 ){
3059
int nFree = db_int(0, "PRAGMA localdb.freelist_count");
3060
int nTotal = db_int(0, "PRAGMA localdb.page_count");
3061
if( nFree>nTotal/4 ){
3062
db_unprotect(PROTECT_ALL);
3063
db_multi_exec("VACUUM localdb;");
3064
db_protect_pop();
3065
}
3066
}
3067
3068
if( g.db ){
3069
int rc;
3070
sqlite3_wal_checkpoint(g.db, 0);
3071
rc = sqlite3_close(g.db);
3072
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
3073
if( rc==SQLITE_BUSY && reportErrors ){
3074
while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){
3075
fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt));
3076
}
3077
}
3078
g.db = 0;
3079
}
3080
g.repositoryOpen = 0;
3081
g.localOpen = 0;
3082
db.bProtectTriggers = 0;
3083
assert( g.dbConfig==0 );
3084
assert( g.zConfigDbName==0 );
3085
backoffice_run_if_needed();
3086
}
3087
3088
/*
3089
** Close the database as quickly as possible without unnecessary processing.
3090
*/
3091
void db_panic_close(void){
3092
if( g.db ){
3093
int rc;
3094
sqlite3_wal_checkpoint(g.db, 0);
3095
rc = sqlite3_close(g.db);
3096
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
3097
db_clear_authorizer();
3098
}
3099
g.db = 0;
3100
g.repositoryOpen = 0;
3101
g.localOpen = 0;
3102
}
3103
3104
/*
3105
** Create a new empty repository database with the given name.
3106
**
3107
** Only the schema is initialized. The required VAR tables entries
3108
** are not set by this routine and must be set separately in order
3109
** to make the new file a valid database.
3110
*/
3111
void db_create_repository(const char *zFilename){
3112
db_init_database(
3113
zFilename,
3114
zRepositorySchema1,
3115
zRepositorySchemaDefaultReports,
3116
zRepositorySchema2,
3117
(char*)0
3118
);
3119
db_delete_on_failure(zFilename);
3120
}
3121
3122
/*
3123
** Create the default user accounts in the USER table.
3124
*/
3125
void db_create_default_users(int setupUserOnly, const char *zDefaultUser){
3126
const char *zUser = zDefaultUser;
3127
if( zUser==0 ){
3128
zUser = db_get("default-user", 0);
3129
}
3130
if( zUser==0 ){
3131
zUser = fossil_getenv("FOSSIL_USER");
3132
}
3133
if( zUser==0 ){
3134
zUser = fossil_getenv("USER");
3135
}
3136
if( zUser==0 ){
3137
zUser = fossil_getenv("LOGNAME");
3138
}
3139
if( zUser==0 ){
3140
zUser = fossil_getenv("USERNAME");
3141
}
3142
if( zUser==0 ){
3143
zUser = "root";
3144
}
3145
db_unprotect(PROTECT_USER);
3146
db_multi_exec(
3147
"INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser
3148
);
3149
db_multi_exec(
3150
"UPDATE user SET cap='s', pw=%Q"
3151
" WHERE login=%Q", fossil_random_password(10), zUser
3152
);
3153
if( !setupUserOnly ){
3154
db_multi_exec(
3155
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
3156
" VALUES('anonymous',hex(randomblob(8)),'hz','Anon');"
3157
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
3158
" VALUES('nobody','','gjorz','Nobody');"
3159
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
3160
" VALUES('developer','','ei','Dev');"
3161
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
3162
" VALUES('reader','','kptw','Reader');"
3163
);
3164
}
3165
db_protect_pop();
3166
}
3167
3168
/*
3169
** Return a pointer to a string that contains the RHS of an IN operator
3170
** that will select CONFIG table names that are in the list of control
3171
** settings.
3172
*/
3173
const char *db_setting_inop_rhs(){
3174
Blob x;
3175
int i;
3176
int nSetting;
3177
const Setting *aSetting = setting_info(&nSetting);
3178
const char *zSep = "";
3179
3180
blob_zero(&x);
3181
blob_append_sql(&x, "(");
3182
for(i=0; i<nSetting; i++){
3183
blob_append_sql(&x, "%s%Q", zSep/*safe-for-%s*/, aSetting[i].name);
3184
zSep = ",";
3185
}
3186
blob_append_sql(&x, ")");
3187
return blob_sql_text(&x);
3188
}
3189
3190
/*
3191
** Fill an empty repository database with the basic information for a
3192
** repository. This function is shared between 'create_repository_cmd'
3193
** ('new') and 'reconstruct_cmd' ('reconstruct'), both of which create
3194
** new repositories.
3195
**
3196
** The zTemplate parameter determines if the settings for the repository
3197
** should be copied from another repository. If zTemplate is 0 then the
3198
** settings will have their normal default values. If zTemplate is
3199
** non-zero, it is assumed that the caller of this function has already
3200
** attached a database using the label "settingSrc". If not, the call to
3201
** this function will fail.
3202
**
3203
** The zInitialDate parameter determines the date of the initial check-in
3204
** that is automatically created. If zInitialDate is 0 then no initial
3205
** check-in is created. The makeServerCodes flag determines whether or
3206
** not server and project codes are invented for this repository.
3207
*/
3208
void db_initial_setup(
3209
const char *zTemplate, /* Repository from which to copy settings. */
3210
const char *zInitialDate, /* Initial date of repository. (ex: "now") */
3211
const char *zDefaultUser /* Default user for the repository */
3212
){
3213
char *zDate;
3214
Blob hash;
3215
Blob manifest;
3216
3217
db_unprotect(PROTECT_ALL);
3218
db_set("content-schema", CONTENT_SCHEMA, 0);
3219
db_set("aux-schema", AUX_SCHEMA_MAX, 0);
3220
db_set("rebuilt", get_version(), 0);
3221
db_multi_exec(
3222
"INSERT INTO config(name,value,mtime)"
3223
" VALUES('server-code', lower(hex(randomblob(20))),now());"
3224
"INSERT INTO config(name,value,mtime)"
3225
" VALUES('project-code', lower(hex(randomblob(20))),now());"
3226
);
3227
db_create_default_users(0, zDefaultUser);
3228
if( zDefaultUser ) g.zLogin = zDefaultUser;
3229
user_select();
3230
3231
if( zTemplate ){
3232
/*
3233
** Copy all settings from the supplied template repository.
3234
*/
3235
db_multi_exec(
3236
"INSERT OR REPLACE INTO config"
3237
" SELECT name,value,mtime FROM settingSrc.config"
3238
" WHERE (name IN %s OR name IN %s OR name GLOB 'walias:/*')"
3239
" AND name NOT GLOB 'project-*'"
3240
" AND name NOT GLOB 'short-project-*';",
3241
configure_inop_rhs(CONFIGSET_ALL),
3242
db_setting_inop_rhs()
3243
);
3244
g.eHashPolicy = db_get_int("hash-policy", g.eHashPolicy);
3245
db_multi_exec(
3246
"REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;"
3247
);
3248
3249
/*
3250
** Copy the user permissions, contact information, last modified
3251
** time, and photo for all the "system" users from the supplied
3252
** template repository into the one being setup. The other columns
3253
** are not copied because they contain security information or other
3254
** data specific to the other repository. The list of columns copied
3255
** by this SQL statement may need to be revised in the future.
3256
*/
3257
db_multi_exec("UPDATE user SET"
3258
" cap = (SELECT u2.cap FROM settingSrc.user u2"
3259
" WHERE u2.login = user.login),"
3260
" info = (SELECT u2.info FROM settingSrc.user u2"
3261
" WHERE u2.login = user.login),"
3262
" mtime = (SELECT u2.mtime FROM settingSrc.user u2"
3263
" WHERE u2.login = user.login),"
3264
" photo = (SELECT u2.photo FROM settingSrc.user u2"
3265
" WHERE u2.login = user.login)"
3266
" WHERE user.login IN ('anonymous','nobody','developer','reader');"
3267
);
3268
}
3269
db_protect_pop();
3270
3271
if( zInitialDate ){
3272
int rid;
3273
blob_zero(&manifest);
3274
blob_appendf(&manifest, "C initial\\sempty\\scheck-in\n");
3275
zDate = date_in_standard_format(zInitialDate);
3276
blob_appendf(&manifest, "D %s\n", zDate);
3277
md5sum_init();
3278
/* The R-card is necessary here because without it
3279
* fossil versions earlier than versions 1.27 would
3280
* interpret this artifact as a "control". */
3281
blob_appendf(&manifest, "R %s\n", md5sum_finish(0));
3282
blob_appendf(&manifest, "T *branch * trunk\n");
3283
blob_appendf(&manifest, "T *sym-trunk *\n");
3284
blob_appendf(&manifest, "U %F\n", g.zLogin);
3285
md5sum_blob(&manifest, &hash);
3286
blob_appendf(&manifest, "Z %b\n", &hash);
3287
blob_reset(&hash);
3288
rid = content_put(&manifest);
3289
manifest_crosslink(rid, &manifest, MC_NONE);
3290
}
3291
}
3292
3293
/*
3294
** COMMAND: new#
3295
** COMMAND: init
3296
**
3297
** Usage: %fossil new ?OPTIONS? FILENAME
3298
** or: %fossil init ?OPTIONS? FILENAME
3299
**
3300
** Create a repository for a new project in the file named FILENAME.
3301
** This command is distinct from "clone". The "clone" command makes
3302
** a copy of an existing project. This command starts a new project.
3303
**
3304
** By default, your current login name is used to create the default
3305
** admin user. This can be overridden using the -A|--admin-user
3306
** parameter.
3307
**
3308
** By default, all settings will be initialized to their default values.
3309
** This can be overridden using the --template parameter to specify a
3310
** repository file from which to copy the initial settings. When a template
3311
** repository is used, almost all of the settings accessible from the setup
3312
** page, either directly or indirectly, will be copied. Normal users and
3313
** their associated permissions will not be copied; however, the system
3314
** default users "anonymous", "nobody", "reader", "developer", and their
3315
** associated permissions will be copied. In case of SQL errors, rebuild the
3316
** template repository and try again.
3317
**
3318
** Options:
3319
** --template FILE Copy settings from repository file
3320
** -A|--admin-user USERNAME Select given USERNAME as admin user
3321
** --date-override DATETIME Use DATETIME as time of the initial check-in
3322
** --sha1 Use an initial hash policy of "sha1"
3323
** --project-name STRING The name of the project "project name in
3324
** quotes"
3325
** --project-desc STRING The description of the project "project
3326
** description in quotes"
3327
**
3328
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
3329
** year-month-day form, it may be truncated, the "T" may be replaced by
3330
** a space, and it may also name a timezone offset from UTC as "-HH:MM"
3331
** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
3332
** means UTC.
3333
**
3334
** See also: [[clone]]
3335
*/
3336
void create_repository_cmd(void){
3337
char *zPassword;
3338
const char *zTemplate; /* Repository from which to copy settings */
3339
const char *zDate; /* Date of the initial check-in */
3340
const char *zDefaultUser; /* Optional name of the default user */
3341
const char *zProjectName; /* Optional project name of the repo */
3342
const char *zProjectDesc; /* Optional project description "description
3343
** of project in quotes" */
3344
int bUseSha1 = 0; /* True to set the hash-policy to sha1 */
3345
3346
3347
zTemplate = find_option("template",0,1);
3348
zDate = find_option("date-override",0,1);
3349
zDefaultUser = find_option("admin-user","A",1);
3350
bUseSha1 = find_option("sha1",0,0)!=0;
3351
zProjectName = find_option("project-name", 0, 1);
3352
zProjectDesc = find_option("project-desc", 0, 1);
3353
/* We should be done with options.. */
3354
verify_all_options();
3355
3356
if( g.argc!=3 ){
3357
usage("REPOSITORY-NAME");
3358
}
3359
3360
if( -1 != file_size(g.argv[2], ExtFILE) ){
3361
fossil_fatal("file already exists: %s", g.argv[2]);
3362
}
3363
3364
db_create_repository(g.argv[2]);
3365
db_open_repository(g.argv[2]);
3366
db_open_config(0, 0);
3367
if( zTemplate ) db_attach(zTemplate, "settingSrc");
3368
db_begin_transaction();
3369
if( bUseSha1 ){
3370
g.eHashPolicy = HPOLICY_SHA1;
3371
db_set_int("hash-policy", HPOLICY_SHA1, 0);
3372
}
3373
if( zProjectName ) db_set("project-name", zProjectName, 0);
3374
if( zProjectDesc ) db_set("project-description", zProjectDesc, 0);
3375
if( zDate==0 ) zDate = "now";
3376
db_initial_setup(zTemplate, zDate, zDefaultUser);
3377
db_end_transaction(0);
3378
if( zTemplate ) db_detach("settingSrc");
3379
if( zProjectName ) fossil_print("project-name: %s\n", zProjectName);
3380
if( zProjectDesc ) fossil_print("project-description: %s\n", zProjectDesc);
3381
fossil_print("project-id: %s\n", db_get("project-code", 0));
3382
fossil_print("server-id: %s\n", db_get("server-code", 0));
3383
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
3384
fossil_print("admin-user: %s (initial remote-access password is \"%s\")\n",
3385
g.zLogin, zPassword);
3386
hash_user_password(g.zLogin);
3387
}
3388
3389
/*
3390
** SQL functions for debugging.
3391
**
3392
** The print() function writes its arguments on stdout, but only
3393
** if the -sqlprint command-line option is turned on.
3394
*/
3395
void db_sql_print(
3396
sqlite3_context *context,
3397
int argc,
3398
sqlite3_value **argv
3399
){
3400
int i;
3401
if( g.fSqlPrint ){
3402
for(i=0; i<argc; i++){
3403
char c = i==argc-1 ? '\n' : ' ';
3404
fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
3405
}
3406
}
3407
}
3408
3409
/*
3410
** Callback for sqlite3_trace_v2();
3411
*/
3412
int db_sql_trace(unsigned m, void *notUsed, void *pP, void *pX){
3413
sqlite3_stmt *pStmt = (sqlite3_stmt*)pP;
3414
char *zSql;
3415
int n;
3416
const char *zArg = (const char*)pX;
3417
char zEnd[100];
3418
if( m & SQLITE_TRACE_CLOSE ){
3419
/* If we are tracking closes, that means we want to clean up static
3420
** prepared statements. */
3421
while( db.pAllStmt ){
3422
db_finalize(db.pAllStmt);
3423
}
3424
return 0;
3425
}
3426
if( zArg[0]=='-' ) return 0;
3427
if( m & SQLITE_TRACE_PROFILE ){
3428
sqlite3_int64 nNano = *(sqlite3_int64*)pX;
3429
double rMillisec = 0.000001 * nNano;
3430
int nRun = sqlite3_stmt_status(pStmt, SQLITE_STMTSTATUS_RUN, 0);
3431
int nVmStep = sqlite3_stmt_status(pStmt, SQLITE_STMTSTATUS_VM_STEP, 1);
3432
sqlite3_snprintf(sizeof(zEnd),zEnd," /* %.3fms, %r run, %d vm-steps */\n",
3433
rMillisec, nRun, nVmStep);
3434
}else{
3435
zEnd[0] = '\n';
3436
zEnd[1] = 0;
3437
}
3438
zSql = sqlite3_expanded_sql(pStmt);
3439
n = (int)strlen(zSql);
3440
fossil_trace("%s%s%s", zSql, (n>0 && zSql[n-1]==';') ? "" : ";", zEnd);
3441
sqlite3_free(zSql);
3442
return 0;
3443
}
3444
3445
/*
3446
** Implement the user() SQL function. user() takes no arguments and
3447
** returns the user ID of the current user.
3448
*/
3449
LOCAL void db_sql_user(
3450
sqlite3_context *context,
3451
int argc,
3452
sqlite3_value **argv
3453
){
3454
if( g.zLogin!=0 ){
3455
sqlite3_result_text(context, g.zLogin, -1, SQLITE_STATIC);
3456
}
3457
}
3458
3459
/*
3460
** Implement the cgi() SQL function. cgi() takes an argument which is
3461
** a name of CGI query parameter. The value of that parameter is returned,
3462
** if available. Optional second argument will be returned if the first
3463
** doesn't exist as a CGI parameter.
3464
*/
3465
LOCAL void db_sql_cgi(sqlite3_context *context, int argc, sqlite3_value **argv){
3466
const char* zP;
3467
if( argc!=1 && argc!=2 ) return;
3468
zP = P((const char*)sqlite3_value_text(argv[0]));
3469
if( zP ){
3470
sqlite3_result_text(context, zP, -1, SQLITE_STATIC);
3471
}else if( argc==2 ){
3472
zP = (const char*)sqlite3_value_text(argv[1]);
3473
if( zP ) sqlite3_result_text(context, zP, -1, SQLITE_TRANSIENT);
3474
}
3475
}
3476
3477
/*
3478
** SQL function:
3479
**
3480
** is_selected(id)
3481
** if_selected(id, X, Y)
3482
**
3483
** On the commit command, when filenames are specified (in order to do
3484
** a partial commit) the vfile.id values for the named files are loaded
3485
** into the g.aCommitFile[] array. This function looks at that array
3486
** to see if a file is named on the command-line.
3487
**
3488
** In the first form (1 argument) return TRUE if either no files are
3489
** named on the command line (g.aCommitFile is NULL meaning that all
3490
** changes are to be committed) or if id is found in g.aCommitFile[]
3491
** (meaning that id was named on the command-line).
3492
**
3493
** In the second form (3 arguments) return argument X if true and Y
3494
** if false. Except if Y is NULL then always return X.
3495
*/
3496
LOCAL void file_is_selected(
3497
sqlite3_context *context,
3498
int argc,
3499
sqlite3_value **argv
3500
){
3501
int rc = 0;
3502
3503
assert(argc==1 || argc==3);
3504
if( g.aCommitFile ){
3505
int iId = sqlite3_value_int(argv[0]);
3506
int ii;
3507
for(ii=0; g.aCommitFile[ii]; ii++){
3508
if( iId==g.aCommitFile[ii] ){
3509
rc = 1;
3510
break;
3511
}
3512
}
3513
}else{
3514
rc = 1;
3515
}
3516
if( argc==1 ){
3517
sqlite3_result_int(context, rc);
3518
}else{
3519
assert( argc==3 );
3520
assert( rc==0 || rc==1 );
3521
if( sqlite3_value_type(argv[2-rc])==SQLITE_NULL ) rc = 1-rc;
3522
sqlite3_result_value(context, argv[2-rc]);
3523
}
3524
}
3525
3526
/*
3527
** Implementation of the "win_reserved(X)" SQL function, a wrapper
3528
** for file_is_win_reserved(X) which returns true if X is
3529
** a Windows-reserved filename.
3530
*/
3531
LOCAL void db_win_reserved_func(
3532
sqlite3_context *context,
3533
int argc,
3534
sqlite3_value **argv
3535
){
3536
const char * zName = (const char *)sqlite3_value_text(argv[0]);
3537
if( zName!=0 ){
3538
sqlite3_result_int(context, file_is_win_reserved(zName)!=0);
3539
}
3540
}
3541
3542
/*
3543
** Convert the input string into an artifact hash. Make a notation in the
3544
** CONCEALED table so that the hash can be undo using the db_reveal()
3545
** function at some later time.
3546
**
3547
** The value returned is stored in static space and will be overwritten
3548
** on subsequent calls.
3549
**
3550
** If zContent is already a well-formed artifact hash, then return a copy
3551
** of that hash, not a hash of the hash.
3552
**
3553
** The CONCEALED table is meant to obscure email addresses. Every valid
3554
** email address will contain a "@" character and "@" is not valid within
3555
** a SHA1 hash so there is no chance that a valid email address will go
3556
** unconcealed.
3557
*/
3558
char *db_conceal(const char *zContent, int n){
3559
static char zHash[HNAME_MAX+1];
3560
Blob out;
3561
if( hname_validate(zContent, n) ){
3562
memcpy(zHash, zContent, n);
3563
zHash[n] = 0;
3564
}else{
3565
sha1sum_step_text(zContent, n);
3566
sha1sum_finish(&out);
3567
sqlite3_snprintf(sizeof(zHash), zHash, "%s", blob_str(&out));
3568
blob_reset(&out);
3569
db_multi_exec(
3570
"INSERT OR IGNORE INTO concealed(hash,content,mtime)"
3571
" VALUES(%Q,%#Q,now())",
3572
zHash, n, zContent
3573
);
3574
}
3575
return zHash;
3576
}
3577
3578
/*
3579
** Attempt to look up the input in the CONCEALED table. If found,
3580
** and if the okRdAddr permission is enabled then return the
3581
** original value for which the input is a hash. If okRdAddr is
3582
** false or if the lookup fails, return the original string content.
3583
**
3584
** In either case, the string returned is stored in space obtained
3585
** from malloc and should be freed by the calling function.
3586
*/
3587
char *db_reveal(const char *zKey){
3588
char *zOut;
3589
if( g.perm.RdAddr ){
3590
zOut = db_text(0, "SELECT content FROM concealed WHERE hash=%Q", zKey);
3591
}else{
3592
zOut = 0;
3593
}
3594
if( zOut==0 ){
3595
zOut = fossil_strdup_nn(zKey);
3596
}
3597
return zOut;
3598
}
3599
3600
/*
3601
** Return true if the string zVal represents "true" (or "false").
3602
*/
3603
int is_truth(const char *zVal){
3604
static const char *const azOn[] = { "on", "yes", "true" };
3605
int i;
3606
for(i=0; i<count(azOn); i++){
3607
if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
3608
}
3609
return atoi(zVal);
3610
}
3611
int is_false(const char *zVal){
3612
static const char *const azOff[] = { "off", "no", "false", "0" };
3613
int i;
3614
for(i=0; i<count(azOff); i++){
3615
if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
3616
}
3617
return 0;
3618
}
3619
3620
/*
3621
** Swap the g.db and g.dbConfig connections so that the various db_* routines
3622
** work on the configuration database instead of on the repository database.
3623
** Be sure to swap them back after doing the operation.
3624
**
3625
** If the configuration database has already been opened as the main database
3626
** or is attached to the main database, no connection swaps are required so
3627
** this routine is a no-op.
3628
*/
3629
void db_swap_connections(void){
3630
/*
3631
** When swapping the main database connection with the config database
3632
** connection, the config database connection must be open (not simply
3633
** attached); otherwise, the swap would end up leaving the main database
3634
** connection invalid, defeating the very purpose of this routine. This
3635
** same constraint also holds true when restoring the previously swapped
3636
** database connection; otherwise, it means that no swap was performed
3637
** because the main database connection was already pointing to the config
3638
** database.
3639
*/
3640
if( g.dbConfig ){
3641
sqlite3 *dbTemp = g.db;
3642
g.db = g.dbConfig;
3643
g.dbConfig = dbTemp;
3644
}
3645
}
3646
3647
/*
3648
** Try to read a versioned setting string from .fossil-settings/<name>.
3649
**
3650
** Return the text of the string if it is found. Return NULL if not
3651
** found.
3652
**
3653
** If the zNonVersionedSetting parameter is not NULL then it holds the
3654
** non-versioned value for this setting. If both a versioned and a
3655
** non-versioned value exist and are not equal, then a warning message
3656
** might be generated.
3657
**
3658
** zCkin is normally NULL. In that case, the versioned setting is
3659
** take from the local check-out, if a local checkout exists, or from
3660
** check-in named by the g.zOpenRevision global variable. If zCkin is
3661
** not NULL, then zCkin is the name of the specific check-in from which
3662
** versioned setting value is taken. When zCkin is not NULL, the cache
3663
** is bypassed.
3664
*/
3665
char *db_get_versioned(
3666
const char *zName,
3667
char *zNonVersionedSetting,
3668
const char *zCkin
3669
){
3670
char *zVersionedSetting = 0;
3671
int noWarn = 0;
3672
int found = 0;
3673
struct _cacheEntry {
3674
struct _cacheEntry *next;
3675
const char *zName, *zValue;
3676
} *cacheEntry = 0;
3677
static struct _cacheEntry *cache = 0;
3678
3679
if( !g.localOpen && g.zOpenRevision==0 && zCkin==0 ){
3680
return zNonVersionedSetting;
3681
}
3682
3683
/* Look up name in cache */
3684
if( zCkin==0 ){
3685
cacheEntry = cache;
3686
while( cacheEntry!=0 ){
3687
if( fossil_strcmp(cacheEntry->zName, zName)==0 ){
3688
zVersionedSetting = fossil_strdup(cacheEntry->zValue);
3689
break;
3690
}
3691
cacheEntry = cacheEntry->next;
3692
}
3693
}
3694
3695
/* Attempt to read value from file in check-out if there wasn't a cache hit.*/
3696
if( cacheEntry==0 ){
3697
Blob versionedPathname;
3698
Blob setting;
3699
blob_init(&versionedPathname, 0, 0);
3700
blob_init(&setting, 0, 0);
3701
if( !g.localOpen || zCkin!=0 ){
3702
/* Repository is in the process of being opened, but files have not been
3703
* written to disk. Load from the database. */
3704
blob_appendf(&versionedPathname, ".fossil-settings/%s", zName);
3705
if( historical_blob(zCkin ? zCkin : g.zOpenRevision,
3706
blob_str(&versionedPathname),
3707
&setting, 0)
3708
){
3709
found = 1;
3710
}
3711
}else{
3712
blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
3713
g.zLocalRoot, zName);
3714
if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3715
/* File exists, and contains the value for this setting. Load from
3716
** the file. */
3717
const char *zFile = blob_str(&versionedPathname);
3718
if( blob_read_from_file(&setting, zFile, ExtFILE)>=0 ){
3719
found = 1;
3720
}
3721
/* See if there's a no-warn flag */
3722
blob_append(&versionedPathname, ".no-warn", -1);
3723
if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3724
noWarn = 1;
3725
}
3726
}
3727
}
3728
blob_reset(&versionedPathname);
3729
if( found ){
3730
blob_strip_comment_lines(&setting, &setting);
3731
blob_trim(&setting); /* Avoid non-obvious problems with line endings
3732
** on boolean properties */
3733
zVersionedSetting = fossil_strdup(blob_str(&setting));
3734
}
3735
blob_reset(&setting);
3736
3737
/* Store result in cache, which can be the value or 0 if not found */
3738
if( zCkin==0 ){
3739
cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(*cacheEntry));
3740
cacheEntry->next = cache;
3741
cacheEntry->zName = zName;
3742
cacheEntry->zValue = fossil_strdup(zVersionedSetting);
3743
cache = cacheEntry;
3744
}
3745
}
3746
3747
/* Display a warning? */
3748
if( zVersionedSetting!=0
3749
&& zNonVersionedSetting!=0
3750
&& zNonVersionedSetting[0]!='\0'
3751
&& zCkin==0
3752
&& !noWarn
3753
){
3754
/* There's a versioned setting, and a non-versioned setting. Tell
3755
** the user about the conflict */
3756
fossil_warning(
3757
"setting %s has both versioned and non-versioned values: using "
3758
"versioned value from file \"%/.fossil-settings/%s\" (to silence "
3759
"this warning, either create an empty file named "
3760
"\"%/.fossil-settings/%s.no-warn\" in the check-out root, or delete "
3761
"the non-versioned setting with \"fossil unset %s\")", zName,
3762
g.zLocalRoot, zName, g.zLocalRoot, zName, zName
3763
);
3764
}
3765
3766
/* Prefer the versioned setting */
3767
return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting;
3768
}
3769
3770
3771
/*
3772
** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
3773
** repository and local databases.
3774
**
3775
** If no such variable exists, return zDefault. Or, if zName is the name
3776
** of a setting, then the zDefault is ignored and the default value of the
3777
** setting is returned instead. If zName is a versioned setting, then
3778
** versioned value takes priority.
3779
*/
3780
char *db_get(const char *zName, const char *zDefault){
3781
char *z = 0;
3782
const Setting *pSetting = db_find_setting(zName, 0);
3783
if( g.repositoryOpen ){
3784
static Stmt q1;
3785
const char *zRes;
3786
db_static_prepare(&q1, "SELECT value FROM config WHERE name=$n");
3787
db_bind_text(&q1, "$n", zName);
3788
if( db_step(&q1)==SQLITE_ROW && (zRes = db_column_text(&q1,0))!=0 ){
3789
z = fossil_strdup(zRes);
3790
}
3791
db_reset(&q1);
3792
}
3793
if( z==0 && g.zConfigDbName ){
3794
static Stmt q2;
3795
const char *zRes;
3796
db_swap_connections();
3797
db_static_prepare(&q2, "SELECT value FROM global_config WHERE name=$n");
3798
db_swap_connections();
3799
db_bind_text(&q2, "$n", zName);
3800
if( db_step(&q2)==SQLITE_ROW && (zRes = db_column_text(&q2,0))!=0 ){
3801
z = fossil_strdup(zRes);
3802
}
3803
db_reset(&q2);
3804
}
3805
if( pSetting!=0 && pSetting->versionable ){
3806
/* This is a versionable setting, try and get the info from a
3807
** checked-out file */
3808
char * zZ = z;
3809
z = db_get_versioned(zName, z, 0);
3810
if(zZ != z){
3811
fossil_free(zZ);
3812
}
3813
}
3814
if( z==0 ){
3815
if( zDefault==0 && pSetting && pSetting->def[0] ){
3816
z = fossil_strdup(pSetting->def);
3817
}else{
3818
z = fossil_strdup(zDefault);
3819
}
3820
}
3821
return z;
3822
}
3823
char *db_get_mtime(const char *zName, const char *zFormat,
3824
const char *zDefault){
3825
char *z = 0;
3826
if( g.repositoryOpen ){
3827
z = db_text(0, "SELECT mtime FROM config WHERE name=%Q", zName);
3828
}
3829
if( z==0 ){
3830
z = fossil_strdup(zDefault);
3831
}else if( zFormat!=0 ){
3832
z = db_text(0, "SELECT strftime(%Q,%Q,'unixepoch');", zFormat, z);
3833
}
3834
return z;
3835
}
3836
void db_set(const char *zName, const char *zValue, int globalFlag){
3837
const CmdOrPage *pCmd = 0;
3838
db_assert_protection_off_or_not_sensitive(zName);
3839
if( zValue!=0 && zValue[0]==0
3840
&& dispatch_name_search(zName, CMDFLAG_SETTING, &pCmd)==0
3841
&& (pCmd->eCmdFlags & CMDFLAG_KEEPEMPTY)==0
3842
){
3843
/* Changing a setting to an empty string is the same as unsetting it,
3844
** unless that setting has the keep-empty flag. */
3845
db_unset(zName/*works-like:"x"*/, globalFlag);
3846
return;
3847
}
3848
db_unprotect(PROTECT_CONFIG);
3849
db_begin_transaction();
3850
if( globalFlag ){
3851
db_swap_connections();
3852
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
3853
zName, zValue);
3854
db_swap_connections();
3855
}else{
3856
db_multi_exec("REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
3857
zName, zValue);
3858
}
3859
if( globalFlag && g.repositoryOpen ){
3860
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3861
}
3862
db_end_transaction(0);
3863
db_protect_pop();
3864
}
3865
void db_unset(const char *zName, int globalFlag){
3866
db_begin_transaction();
3867
db_unprotect(PROTECT_CONFIG);
3868
if( globalFlag ){
3869
db_swap_connections();
3870
db_multi_exec("DELETE FROM global_config WHERE name=%Q", zName);
3871
db_swap_connections();
3872
}else{
3873
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3874
}
3875
if( globalFlag && g.repositoryOpen ){
3876
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3877
}
3878
db_protect_pop();
3879
db_end_transaction(0);
3880
}
3881
int db_is_global(const char *zName){
3882
int rc = 0;
3883
if( g.zConfigDbName ){
3884
db_swap_connections();
3885
rc = db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName);
3886
db_swap_connections();
3887
}
3888
return rc;
3889
}
3890
int db_get_int(const char *zName, int dflt){
3891
int v = dflt;
3892
int rc;
3893
if( g.repositoryOpen ){
3894
static Stmt q;
3895
db_static_prepare(&q, "SELECT value FROM config WHERE name=$n");
3896
db_bind_text(&q, "$n", zName);
3897
rc = db_step(&q);
3898
if( rc==SQLITE_ROW ){
3899
v = db_column_int(&q, 0);
3900
}
3901
db_reset(&q);
3902
}else{
3903
rc = SQLITE_DONE;
3904
}
3905
if( rc==SQLITE_DONE && g.zConfigDbName ){
3906
static Stmt q2;
3907
db_swap_connections();
3908
db_static_prepare(&q2, "SELECT value FROM global_config WHERE name=$n");
3909
db_swap_connections();
3910
db_bind_text(&q2, "$n", zName);
3911
if( db_step(&q2)==SQLITE_ROW ){
3912
v = db_column_int(&q2, 0);
3913
}
3914
db_reset(&q2);
3915
}
3916
return v;
3917
}
3918
i64 db_large_file_size(void){
3919
/* Return size of the largest file that is not considered oversized */
3920
return strtoll(db_get("large-file-size","20000000"),0,0);
3921
}
3922
void db_set_int(const char *zName, int value, int globalFlag){
3923
db_assert_protection_off_or_not_sensitive(zName);
3924
db_unprotect(PROTECT_CONFIG);
3925
if( globalFlag ){
3926
db_swap_connections();
3927
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
3928
zName, value);
3929
db_swap_connections();
3930
}else{
3931
db_multi_exec("REPLACE INTO config(name,value,mtime) VALUES(%Q,%d,now())",
3932
zName, value);
3933
}
3934
if( globalFlag && g.repositoryOpen ){
3935
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3936
}
3937
db_protect_pop();
3938
}
3939
int db_get_boolean(const char *zName, int dflt){
3940
char *zVal = db_get(zName, dflt ? "on" : "off");
3941
if( is_truth(zVal) ){
3942
dflt = 1;
3943
}else if( is_false(zVal) ){
3944
dflt = 0;
3945
}
3946
fossil_free(zVal);
3947
return dflt;
3948
}
3949
int db_get_versioned_boolean(const char *zName, int dflt){
3950
char *zVal = db_get_versioned(zName, 0, 0);
3951
if( zVal==0 ) return dflt;
3952
if( is_truth(zVal) ) return 1;
3953
if( is_false(zVal) ) return 0;
3954
return dflt;
3955
}
3956
char *db_lget(const char *zName, const char *zDefault){
3957
return db_text(zDefault,
3958
"SELECT value FROM vvar WHERE name=%Q", zName);
3959
}
3960
void db_lset(const char *zName, const char *zValue){
3961
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%Q)", zName, zValue);
3962
}
3963
int db_lget_int(const char *zName, int dflt){
3964
return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
3965
}
3966
int db_lget_boolean(const char *zName, int dflt){
3967
char *zVal = db_lget(zName, dflt ? "on" : "off");
3968
if( is_truth(zVal) ){
3969
dflt = 1;
3970
}else if( is_false(zVal) ){
3971
dflt = 0;
3972
}
3973
fossil_free(zVal);
3974
return dflt;
3975
}
3976
void db_lset_int(const char *zName, int value){
3977
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
3978
}
3979
3980
/* Va-args versions of db_get(), db_set(), and db_unset()
3981
**
3982
** codecheck1.c verifies that the format string for db_set_mprintf()
3983
** and db_unset_mprintf() begins with an ASCII character prefix. We
3984
** don't want that format string to begin with %s or %d as that might
3985
** allow an injection attack to set or overwrite arbitrary settings.
3986
*/
3987
char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){
3988
va_list ap;
3989
char *zName;
3990
char *zResult;
3991
va_start(ap, zFormat);
3992
zName = vmprintf(zFormat, ap);
3993
va_end(ap);
3994
zResult = db_get(zName, zDefault);
3995
fossil_free(zName);
3996
return zResult;
3997
}
3998
void db_set_mprintf(const char *zNew, int iGlobal, const char *zFormat, ...){
3999
va_list ap;
4000
char *zName;
4001
va_start(ap, zFormat);
4002
zName = vmprintf(zFormat, ap);
4003
va_end(ap);
4004
db_set(zName/*works-like:"x"*/, zNew, iGlobal);
4005
fossil_free(zName);
4006
}
4007
void db_unset_mprintf(int iGlobal, const char *zFormat, ...){
4008
va_list ap;
4009
char *zName;
4010
va_start(ap, zFormat);
4011
zName = vmprintf(zFormat, ap);
4012
va_end(ap);
4013
db_unset(zName/*works-like:"x"*/, iGlobal);
4014
fossil_free(zName);
4015
}
4016
4017
/*
4018
** Get a setting that is tailored to subsystem. The return value is
4019
** NULL if the setting does not exist, or a string obtained from mprintf()
4020
** if the setting is available.
4021
**
4022
** The actual setting can be a comma-separated list of values of the form:
4023
**
4024
** * VALUE
4025
** * SUBSYSTEM=VALUE
4026
**
4027
** A VALUE without the SUBSYSTEM= prefix is the default. This routine
4028
** returns the VALUE that with the matching SUBSYSTEM, or the default
4029
** VALUE if there is no match.
4030
*/
4031
char *db_get_for_subsystem(const char *zName, const char *zSubsys){
4032
int nSubsys;
4033
char *zToFree = 0;
4034
char *zCopy;
4035
char *zNext;
4036
char *zResult = 0;
4037
const char *zSetting = db_get(zName, 0);
4038
if( zSetting==0 ) return 0;
4039
zCopy = zToFree = fossil_strdup(zSetting);
4040
if( zSubsys==0 ) zSubsys = "";
4041
nSubsys = (int)strlen(zSubsys);
4042
while( zCopy ){
4043
zNext = strchr(zCopy, ',');
4044
if( zNext ){
4045
zNext[0] = 0;
4046
do{ zNext++; }while( fossil_isspace(zNext[0]) );
4047
if( zNext[0]==0 ) zNext = 0;
4048
}
4049
if( strchr(zCopy,'=')==0 ){
4050
if( zResult==0 ) zResult = zCopy;
4051
}else
4052
if( nSubsys
4053
&& strncmp(zCopy, zSubsys, nSubsys)==0
4054
&& zCopy[nSubsys]=='='
4055
){
4056
zResult = &zCopy[nSubsys+1];
4057
break;
4058
}
4059
zCopy = zNext;
4060
}
4061
if( zResult ) zResult = fossil_strdup(zResult);
4062
fossil_free(zToFree);
4063
return zResult;
4064
}
4065
4066
#if INTERFACE
4067
/* Manifest generation flags */
4068
#define MFESTFLG_RAW 0x01
4069
#define MFESTFLG_UUID 0x02
4070
#define MFESTFLG_TAGS 0x04
4071
#endif /* INTERFACE */
4072
4073
/*
4074
** Get the manifest setting. For backwards compatibility first check if the
4075
** value is a boolean. If it's not a boolean, treat each character as a flag
4076
** to enable a manifest type. This system puts certain boundary conditions on
4077
** which letters can be used to represent flags (any permutation of flags must
4078
** not be able to fully form one of the boolean values).
4079
**
4080
** "manifest" is a versionable setting. But we do not issue a warning
4081
** if there is a conflict. Instead, the value returned is the value for
4082
** the versioned setting if the versioned setting exists, or the ordinary
4083
** setting otherwise.
4084
**
4085
** The argument zCkin is the specific check-in for which we want the
4086
** manifest setting.
4087
*/
4088
int db_get_manifest_setting(const char *zCkin){
4089
int flg;
4090
char *zVal;
4091
4092
/* Look for the versioned setting first */
4093
zVal = db_get_versioned("manifest", 0, zCkin);
4094
4095
if( zVal==0 && g.repositoryOpen ){
4096
/* No versioned setting, look for the repository setting second */
4097
zVal = db_text(0, "SELECT value FROM config WHERE name='manifest'");
4098
}
4099
if( zVal==0 || is_false(zVal) ){
4100
return 0;
4101
}else if( is_truth(zVal) ){
4102
return MFESTFLG_RAW|MFESTFLG_UUID;
4103
}
4104
flg = 0;
4105
while( *zVal ){
4106
switch( *zVal ){
4107
case 'r': flg |= MFESTFLG_RAW; break;
4108
case 'u': flg |= MFESTFLG_UUID; break;
4109
case 't': flg |= MFESTFLG_TAGS; break;
4110
}
4111
zVal++;
4112
}
4113
return flg;
4114
}
4115
4116
/*
4117
** COMMAND: test-manifest-setting
4118
**
4119
** Usage: %fossil test-manifest-setting VERSION VERSION ...
4120
**
4121
** Display the value for the "manifest" setting for various versions
4122
** of the repository.
4123
*/
4124
void test_manfest_setting_cmd(void){
4125
int i;
4126
db_find_and_open_repository(0, 0);
4127
for(i=2; i<g.argc; i++){
4128
int m = db_get_manifest_setting(g.argv[i]);
4129
fossil_print("%s:\n", g.argv[i]);
4130
fossil_print(" flags = 0x%02x\n", m);
4131
if( m & MFESTFLG_RAW ){
4132
fossil_print(" manifest\n");
4133
}
4134
if( m & MFESTFLG_UUID ){
4135
fossil_print(" manifest.uuid\n");
4136
}
4137
if( m & MFESTFLG_TAGS ){
4138
fossil_print(" manifest.tags\n");
4139
}
4140
}
4141
}
4142
4143
4144
/*
4145
** Record the name of a local repository in the global_config() database.
4146
** The repository filename %s is recorded as an entry with a "name" field
4147
** of the following form:
4148
**
4149
** repo:%s
4150
**
4151
** The value field is set to 1.
4152
**
4153
** If running from a local check-out, also record the root of the check-out
4154
** as follows:
4155
**
4156
** ckout:%s
4157
**
4158
** Where %s is the check-out root. The value is the repository file.
4159
*/
4160
void db_record_repository_filename(const char *zName){
4161
char *zRepoSetting;
4162
char *zCkoutSetting;
4163
Blob full;
4164
if( zName==0 ){
4165
if( !g.localOpen ) return;
4166
zName = db_repository_filename();
4167
}
4168
file_canonical_name(zName, &full, 0);
4169
(void)filename_collation(); /* Initialize before connection swap */
4170
db_swap_connections();
4171
zRepoSetting = mprintf("repo:%q", blob_str(&full));
4172
4173
db_unprotect(PROTECT_CONFIG);
4174
db_multi_exec(
4175
"DELETE FROM global_config WHERE name %s = %Q;",
4176
filename_collation(), zRepoSetting
4177
);
4178
db_multi_exec(
4179
"INSERT OR IGNORE INTO global_config(name,value)"
4180
"VALUES(%Q,1);",
4181
zRepoSetting
4182
);
4183
db_protect_pop();
4184
fossil_free(zRepoSetting);
4185
if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
4186
Blob localRoot;
4187
file_canonical_name(g.zLocalRoot, &localRoot, 1);
4188
zCkoutSetting = mprintf("ckout:%q", blob_str(&localRoot));
4189
db_unprotect(PROTECT_CONFIG);
4190
db_multi_exec(
4191
"DELETE FROM global_config WHERE name %s = %Q;",
4192
filename_collation(), zCkoutSetting
4193
);
4194
db_multi_exec(
4195
"REPLACE INTO global_config(name, value)"
4196
"VALUES(%Q,%Q);",
4197
zCkoutSetting, blob_str(&full)
4198
);
4199
db_swap_connections();
4200
db_optional_sql("repository",
4201
"DELETE FROM config WHERE name %s = %Q;",
4202
filename_collation(), zCkoutSetting
4203
);
4204
db_optional_sql("repository",
4205
"REPLACE INTO config(name,value,mtime)"
4206
"VALUES(%Q,1,now());",
4207
zCkoutSetting
4208
);
4209
db_protect_pop();
4210
fossil_free(zCkoutSetting);
4211
blob_reset(&localRoot);
4212
}else{
4213
db_swap_connections();
4214
}
4215
blob_reset(&full);
4216
}
4217
4218
/*
4219
** COMMAND: open
4220
**
4221
** Usage: %fossil open REPOSITORY ?VERSION? ?OPTIONS?
4222
**
4223
** Open a new connection to the repository name REPOSITORY. A check-out
4224
** for the repository is created with its root at the current working
4225
** directory, or in DIR if the "--workdir DIR" is used. If VERSION is
4226
** specified then that version is checked out. Otherwise the most recent
4227
** check-in on the main branch (usually "trunk") is used.
4228
**
4229
** REPOSITORY can be the filename for a repository that already exists on the
4230
** local machine or it can be a URI for a remote repository. If REPOSITORY
4231
** is a URI in one of the formats recognized by the [[clone]] command, the
4232
** remote repo is first cloned, then the clone is opened. The clone will be
4233
** stored in the current directory, or in DIR if the "--repodir DIR" option
4234
** is used. The name of the clone will be taken from the last term of the URI.
4235
** For "http:" and "https:" URIs, you can append an extra term to the end of
4236
** the URI to get any repository name you like. For example:
4237
**
4238
** fossil open https://fossil-scm.org/home/new-name
4239
**
4240
** The base URI for cloning is "https://fossil-scm.org/home". The extra
4241
** "new-name" term means that the cloned repository will be called
4242
** "new-name.fossil".
4243
**
4244
** Options:
4245
** --empty Initialize check-out as being empty, but still connected
4246
** with the local repository. If you commit this check-out,
4247
** it will become a new "initial" commit in the repository.
4248
** -f|--force Continue with the open even if the working directory is
4249
** not empty, or if auto-sync fails.
4250
** --force-missing Force opening a repository with missing content
4251
** -k|--keep Only modify the manifest file(s)
4252
** --nested Allow opening a repository inside an opened check-out
4253
** --nosync Do not auto-sync the repository prior to opening even
4254
** if the autosync setting is on.
4255
** --proxy PROXY Use PROXY as http proxy during sync operation
4256
** --reopen REPO "Reopen" an existing checkout to use a different
4257
** repository file REPO. Useful to reconnect an existing
4258
** checkout to a repository after the original repository
4259
** file is moved. CAUTION: may lose stash and bisect
4260
** history.
4261
** --repodir DIR If REPOSITORY is a URI that will be cloned, store
4262
** the clone in DIR rather than in "."
4263
** --setmtime Set timestamps of all files to match their SCM-side
4264
** times (the timestamp of the last check-in which modified
4265
** them).
4266
** --verbose If passed a URI then this flag is passed on to the clone
4267
** operation, otherwise it has no effect
4268
** --workdir DIR Use DIR as the working directory instead of ".". The DIR
4269
** directory is created if it does not exist.
4270
**
4271
** See also: [[close]], [[clone]]
4272
*/
4273
void cmd_open(void){
4274
int emptyFlag;
4275
int keepFlag;
4276
int forceMissingFlag;
4277
int allowNested;
4278
int setmtimeFlag; /* --setmtime. Set mtimes on files */
4279
int bForce = 0; /* --force. Open even if non-empty dir */
4280
static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
4281
const char *zWorkDir; /* --workdir value */
4282
const char *zRepo = 0; /* Name of the repository file */
4283
const char *zRepoDir = 0; /* --repodir value */
4284
const char *zReopen = 0; /* --reopen REPOFILE */
4285
char *zPwd; /* Initial working directory */
4286
int isUri = 0; /* True if REPOSITORY is a URI */
4287
int nLocal; /* Number of preexisting files in cwd */
4288
int bVerbose = 0; /* --verbose option for clone */
4289
4290
zReopen = find_option("reopen",0,1);
4291
if( 0!=zReopen ){
4292
g.argc = 3;
4293
g.argv[2] = (char*)zReopen;
4294
move_repo_cmd();
4295
return;
4296
}
4297
4298
url_proxy_options();
4299
emptyFlag = find_option("empty",0,0)!=0;
4300
keepFlag = find_option("keep","k",0)!=0;
4301
forceMissingFlag = find_option("force-missing",0,0)!=0;
4302
allowNested = find_option("nested",0,0)!=0;
4303
setmtimeFlag = find_option("setmtime",0,0)!=0;
4304
zWorkDir = find_option("workdir",0,1);
4305
zRepoDir = find_option("repodir",0,1);
4306
bForce = find_option("force","f",0)!=0;
4307
if( find_option("nosync",0,0) ) g.fNoSync = 1;
4308
bVerbose = find_option("verbose",0,0)!=0;
4309
zPwd = file_getcwd(0,0);
4310
4311
/* We should be done with options.. */
4312
verify_all_options();
4313
4314
if( g.argc!=3 && g.argc!=4 ){
4315
usage("REPOSITORY-FILENAME ?VERSION?");
4316
}
4317
zRepo = g.argv[2];
4318
if( sqlite3_strglob("http://*", zRepo)==0
4319
|| sqlite3_strglob("https://*", zRepo)==0
4320
|| sqlite3_strglob("ssh:*", zRepo)==0
4321
|| sqlite3_strglob("file:*", zRepo)==0
4322
){
4323
isUri = 1;
4324
}
4325
4326
/* If --workdir is specified, change to the requested working directory */
4327
if( zWorkDir ){
4328
if( !isUri ){
4329
zRepo = file_canonical_name_dup(zRepo);
4330
}
4331
if( zRepoDir ){
4332
zRepoDir = file_canonical_name_dup(zRepoDir);
4333
}
4334
if( file_isdir(zWorkDir, ExtFILE)!=1 ){
4335
file_mkfolder(zWorkDir, ExtFILE, 0, 0);
4336
if( file_mkdir(zWorkDir, ExtFILE, 0) ){
4337
fossil_fatal("cannot create directory %s", zWorkDir);
4338
}
4339
}
4340
if( file_chdir(zWorkDir, 0) ){
4341
fossil_fatal("unable to make %s the working directory", zWorkDir);
4342
}
4343
}
4344
if( keepFlag==0
4345
&& bForce==0
4346
&& (nLocal = file_directory_list(".", 0, 1, 2, 0))>0
4347
&& (nLocal>1 || isUri || !file_in_cwd(zRepo))
4348
){
4349
fossil_fatal("directory %s is not empty\n"
4350
"use the -f (--force) option to override\n"
4351
"or the -k (--keep) option to keep local files unchanged",
4352
file_getcwd(0,0));
4353
}
4354
4355
if( db_open_local_v2(0, allowNested) ){
4356
fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
4357
}
4358
4359
/* If REPOSITORY looks like a URI, then try to clone it first */
4360
if( isUri ){
4361
char *zNewBase; /* Base name of the cloned repository file */
4362
const char *zUri; /* URI to clone */
4363
int rc; /* Result code from fossil_system() */
4364
Blob cmd; /* Clone command to be run */
4365
char *zCmd; /* String version of the clone command */
4366
4367
zUri = zRepo;
4368
zNewBase = url_to_repo_basename(zUri);
4369
if( zNewBase==0 ){
4370
fossil_fatal("unable to deduce a repository name from the url \"%s\"",
4371
zUri);
4372
}
4373
if( zRepoDir==0 ){
4374
zRepo = mprintf("%s.fossil", zNewBase);
4375
}else{
4376
zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
4377
}
4378
fossil_free(zNewBase);
4379
blob_init(&cmd, 0, 0);
4380
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
4381
blob_append(&cmd, " clone", -1);
4382
if(0!=bVerbose){
4383
blob_append(&cmd, " --verbose", -1);
4384
}
4385
blob_append_escaped_arg(&cmd, zUri, 1);
4386
blob_append_escaped_arg(&cmd, zRepo, 1);
4387
zCmd = blob_str(&cmd);
4388
fossil_print("%s\n", zCmd);
4389
if( zWorkDir ) file_chdir(zPwd, 0);
4390
rc = fossil_system(zCmd);
4391
if( rc ){
4392
fossil_fatal("clone of %s failed", zUri);
4393
}
4394
blob_reset(&cmd);
4395
if( zWorkDir ) file_chdir(zWorkDir, 0);
4396
}else if( zRepoDir ){
4397
fossil_fatal("the --repodir option only makes sense if the REPOSITORY "
4398
"argument is a URI that begins with http:, https:, ssh:, "
4399
"or file:");
4400
}
4401
4402
db_open_config(0,0);
4403
db_open_repository(zRepo);
4404
4405
/* Figure out which revision to open. */
4406
if( !emptyFlag ){
4407
if( g.argc==4 ){
4408
g.zOpenRevision = g.argv[3];
4409
}else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
4410
g.zOpenRevision = fossil_strdup(db_main_branch());
4411
}
4412
if( autosync_loop(SYNC_PULL, !bForce, "open") && !bForce ){
4413
fossil_fatal("unable to auto-sync the repository");
4414
}
4415
}
4416
4417
4418
#if defined(_WIN32) || defined(__CYGWIN__)
4419
# define LOCALDB_NAME "./_FOSSIL_"
4420
#else
4421
# define LOCALDB_NAME "./.fslckout"
4422
#endif
4423
db_init_database(LOCALDB_NAME, zLocalSchema, zLocalSchemaVmerge,
4424
#ifdef FOSSIL_LOCAL_WAL
4425
"COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
4426
#endif
4427
(char*)0);
4428
db_delete_on_failure(LOCALDB_NAME);
4429
db_open_local(0);
4430
db_lset("repository", zRepo);
4431
db_record_repository_filename(zRepo);
4432
db_set_checkout(0, 0); /* manifest files handled by checkout_cmd */
4433
azNewArgv[0] = g.argv[0];
4434
g.argv = azNewArgv;
4435
if( !emptyFlag ){
4436
g.argc = 3;
4437
if( g.zOpenRevision ){
4438
azNewArgv[g.argc-1] = g.zOpenRevision;
4439
}else{
4440
azNewArgv[g.argc-1] = "--latest";
4441
}
4442
if( keepFlag ){
4443
azNewArgv[g.argc++] = "--keep";
4444
}
4445
if( forceMissingFlag ){
4446
azNewArgv[g.argc++] = "--force-missing";
4447
}
4448
checkout_cmd();
4449
}
4450
if( setmtimeFlag ){
4451
int const vid = db_lget_int("checkout", 0);
4452
if(vid!=0){
4453
vfile_check_signature(vid, CKSIG_SETMTIME);
4454
}
4455
}
4456
g.argc = 2;
4457
info_cmd();
4458
}
4459
4460
/*
4461
** Return true if pSetting has its default value assuming its
4462
** current value is zVal.
4463
*/
4464
int setting_has_default_value(const Setting *pSetting, const char *zVal){
4465
if( zVal==0 ) return 1;
4466
if( pSetting->def==0 ) return 0;
4467
if( pSetting->width==0 ){
4468
return is_false(pSetting->def)==is_false(zVal);
4469
}
4470
if( fossil_strcmp(pSetting->def, zVal)==0 ) return 1;
4471
if( is_false(zVal) && is_false(pSetting->def) ) return 1;
4472
if( is_truth(zVal) && is_truth(pSetting->def) ) return 1;
4473
return 0;
4474
}
4475
4476
/*
4477
** Print the current value of a setting identified by the pSetting
4478
** pointer.
4479
**
4480
** Only show the value, not the setting name, if valueOnly is true.
4481
**
4482
** Show nothing if bIfChng is true and the setting is not currently set
4483
** or is set to its default value.
4484
*/
4485
void print_setting(const Setting *pSetting, int valueOnly, int bIfChng){
4486
Stmt q;
4487
int versioned = 0;
4488
if( pSetting->versionable && g.localOpen ){
4489
/* Check to see if this is overridden by a versionable settings file */
4490
Blob versionedPathname;
4491
blob_zero(&versionedPathname);
4492
blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
4493
g.zLocalRoot, pSetting->name);
4494
if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
4495
versioned = 1;
4496
}
4497
blob_reset(&versionedPathname);
4498
}
4499
if( valueOnly && versioned ){
4500
const char *zVal = db_get_versioned(pSetting->name, NULL, NULL);
4501
if( !bIfChng || (zVal!=0 && fossil_strcmp(zVal, pSetting->def)!=0) ){
4502
fossil_print("%s\n", db_get_versioned(pSetting->name, NULL, NULL));
4503
}else{
4504
versioned = 0;
4505
}
4506
return;
4507
}
4508
if( g.repositoryOpen ){
4509
db_prepare(&q,
4510
"SELECT '(local)', value FROM config WHERE name=%Q"
4511
" UNION ALL "
4512
"SELECT '(global)', value FROM global_config WHERE name=%Q",
4513
pSetting->name, pSetting->name
4514
);
4515
}else{
4516
db_prepare(&q,
4517
"SELECT '(global)', value FROM global_config WHERE name=%Q",
4518
pSetting->name
4519
);
4520
}
4521
if( db_step(&q)==SQLITE_ROW ){
4522
const char *zVal = db_column_text(&q,1);
4523
if( bIfChng && setting_has_default_value(pSetting,zVal) ){
4524
if( versioned ){
4525
fossil_print("%-24s (versioned)\n", pSetting->name);
4526
versioned = 0;
4527
}
4528
}else if( valueOnly ){
4529
fossil_print("%s\n", db_column_text(&q, 1));
4530
}else{
4531
const char *zVal = (const char*)db_column_text(&q,1);
4532
const char *zName = (const char*)db_column_text(&q,0);
4533
if( zVal==0 ) zVal = "NULL";
4534
if( strchr(zVal,'\n')==0 ){
4535
fossil_print("%-24s %-11s %s\n", pSetting->name, zName, zVal);
4536
}else{
4537
fossil_print("%-24s %-11s\n", pSetting->name, zName);
4538
while( zVal[0] ){
4539
char *zNL = strchr(zVal, '\n');
4540
if( zNL==0 ){
4541
fossil_print(" %s\n", zVal);
4542
break;
4543
}else{
4544
int n = (int)(zNL - zVal);
4545
while( n>0 && fossil_isspace(zVal[n-1]) ){ n--; }
4546
fossil_print(" %.*s\n", n, zVal);
4547
zVal = zNL+1;
4548
}
4549
}
4550
}
4551
}
4552
}else if( bIfChng ){
4553
/* Display nothing */
4554
versioned = 0;
4555
}else if( valueOnly ){
4556
fossil_print("\n");
4557
}else{
4558
fossil_print("%-24s\n", pSetting->name);
4559
}
4560
if( versioned ){
4561
fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
4562
pSetting->name);
4563
}
4564
db_finalize(&q);
4565
}
4566
4567
#if INTERFACE
4568
/*
4569
** Define all settings, which can be controlled via the set/unset
4570
** command.
4571
**
4572
** var is the name of the internal configuration name for db_(un)set.
4573
** If var is 0, the settings name is used.
4574
**
4575
** width is the length for the edit field on the behavior page, 0 is
4576
** used for on/off checkboxes. A negative value indicates that the
4577
** page should not render this setting. Such values may be rendered
4578
** separately/manually on another page, e.g., /setup_access, and are
4579
** exposed via the CLI settings command.
4580
**
4581
** The behaviour page doesn't use a special layout. It lists all
4582
** set-commands and displays the 'set'-help as info.
4583
*/
4584
struct Setting {
4585
const char *name; /* Name of the setting */
4586
const char *var; /* Internal variable name used by db_set() */
4587
int width; /* Width of display. 0 for boolean values and
4588
** negative for values which should not appear
4589
** on the /setup_settings page. */
4590
char versionable; /* Is this setting versionable? */
4591
char forceTextArea; /* Force using a text area for display? */
4592
char sensitive; /* True if this a security-sensitive setting */
4593
const char *def; /* Default value */
4594
};
4595
4596
#endif /* INTERFACE */
4597
4598
/*
4599
** SETTING: access-log boolean default=on
4600
**
4601
** When the access-log setting is enabled, all login attempts (successful
4602
** and unsuccessful) on the web interface are recorded in the "access" table
4603
** of the repository.
4604
*/
4605
/*
4606
** SETTING: admin-log boolean default=on
4607
**
4608
** When the admin-log setting is enabled, configuration changes are recorded
4609
** in the "admin_log" table of the repository.
4610
*/
4611
/*
4612
** SETTING: allow-symlinks boolean default=off sensitive
4613
**
4614
** When allow-symlinks is OFF, Fossil does not see symbolic links
4615
** (a.k.a "symlinks") on disk as a separate class of object. Instead Fossil
4616
** sees the object that the symlink points to. Fossil will only manage files
4617
** and directories, not symlinks. When a symlink is added to a repository,
4618
** the object that the symlink points to is added, not the symlink itself.
4619
**
4620
** When allow-symlinks is ON, Fossil sees symlinks on disk as a separate
4621
** object class that is distinct from files and directories. When a symlink
4622
** is added to a repository, Fossil stores the target filename. In other
4623
** words, Fossil stores the symlink itself, not the object that the symlink
4624
** points to.
4625
**
4626
** Symlinks are not cross-platform. They are not available on all
4627
** operating systems and file systems. Hence the allow-symlinks setting is
4628
** OFF by default, for portability.
4629
*/
4630
/*
4631
** SETTING: auto-captcha boolean default=on variable=autocaptcha
4632
** If enabled, the /login page provides a button that will automatically
4633
** fill in the captcha password. This makes things easier for human users,
4634
** at the expense of also making logins easier for malicious robots.
4635
*/
4636
/*
4637
** SETTING: auto-hyperlink width=16 default=1
4638
**
4639
** If non-zero, enable hyperlinks on web pages even for users that lack
4640
** the "h" privilege as long as the UserAgent string in the HTTP request
4641
** (The HTTP_USER_AGENT cgi variable) looks like it comes from a human and
4642
** not a robot. Details depend on the value of the setting.
4643
**
4644
** (0) Off: No adjustments are made to the 'h' privilege based on
4645
** the user agent.
4646
**
4647
** (1) UserAgent and Javascript: The the href= values of hyperlinks
4648
** initially point to /honeypot and are changed to point to the
4649
** correct target by javascript that runs after the page loads.
4650
** The auto-hyperlink-delay and auto-hyperlink-mouseover settings
4651
** influence that javascript.
4652
**
4653
** (2) UserAgent only: If the HTTP_USER_AGENT looks human
4654
** then generate hyperlinks, otherwise do not.
4655
**
4656
** Better robot exclusion is obtained when this setting is 1 versus 2.
4657
** However, a value of 1 causes the visited/unvisited colors of hyperlinks
4658
** to stop working on Safari-derived web browsers. When this setting is 2,
4659
** the hyperlinks work better on Safari, but more robots are able to sneak
4660
** in.
4661
*/
4662
/*
4663
** SETTING: auto-hyperlink-delay width=16 default=0
4664
**
4665
** When the auto-hyperlink setting is 1, the javascript that runs to set
4666
** the href= attributes of hyperlinks delays by this many milliseconds
4667
** after the page load. Suggested values: 50 to 200.
4668
*/
4669
/*
4670
** SETTING: auto-hyperlink-mouseover boolean default=off
4671
**
4672
** When the auto-hyperlink setting is 1 and this setting is on, the
4673
** javascript that runs to set the href= attributes of hyperlinks waits
4674
** until either a mousedown or mousemove event is seen. This helps
4675
** to distinguish real users from robots. For maximum robot defense,
4676
** the recommended setting is ON.
4677
*/
4678
/*
4679
** SETTING: auto-shun boolean default=on
4680
** If enabled, automatically pull the shunning list
4681
** from a server to which the client autosyncs.
4682
*/
4683
/*
4684
** SETTING: autosync width=16 default=on
4685
** This setting determines when autosync occurs. The setting is a
4686
** string that provides a lot of flexibility for determining when and
4687
** when not to autosync. Examples:
4688
**
4689
** on Always autosync for command where autosync
4690
** makes sense ("commit", "merge", "open", "update")
4691
**
4692
** off Never autosync.
4693
**
4694
** pullonly Only to pull autosyncs
4695
**
4696
** all Sync with all remotes
4697
**
4698
** on,open=off Autosync for most commands, but not for "open"
4699
**
4700
** off,commit=pullonly Do not autosync, except do a pull before each
4701
** "commit", presumably to avoid undesirable
4702
** forks.
4703
**
4704
** The syntax is a comma-separated list of VALUE and COMMAND=VALUE entries.
4705
** A plain VALUE entry is the default that is used if no COMMAND matches.
4706
** Otherwise, the VALUE of the matching command is used.
4707
**
4708
** The "all" value is special in that it applies to the "sync" command in
4709
** addition to "commit", "merge", "open", and "update".
4710
*/
4711
/*
4712
** SETTING: autosync-tries width=16 default=1
4713
** If autosync is enabled setting this to a value greater
4714
** than zero will cause autosync to try no more than this
4715
** number of attempts if there is a sync failure.
4716
*/
4717
/*
4718
** SETTING: backoffice-nodelay boolean default=off
4719
** If backoffice-nodelay is true, then the backoffice processing
4720
** will never invoke sleep(). If it has nothing useful to do,
4721
** it simply exits.
4722
*/
4723
/*
4724
** SETTING: backoffice-disable boolean default=off
4725
** If backoffice-disable is true, then the automatic backoffice
4726
** processing is disabled. Automatic backoffice processing is the
4727
** backoffice work that normally runs after each web page is
4728
** rendered. Backoffice processing that is triggered by the
4729
** "fossil backoffice" command is unaffected by this setting.
4730
**
4731
** Backoffice processing does things such as delivering
4732
** email notifications. So if this setting is true, and if
4733
** there is no cron job periodically running "fossil backoffice",
4734
** email notifications and other work normally done by the
4735
** backoffice will not occur.
4736
*/
4737
/*
4738
** SETTING: backoffice-logfile width=40 sensitive
4739
** If backoffice-logfile is not an empty string and is a valid
4740
** filename, then a one-line message is appended to that file
4741
** every time the backoffice runs. This can be used for debugging,
4742
** to ensure that backoffice is running appropriately.
4743
*/
4744
/*
4745
** SETTING: binary-glob width=40 versionable block-text
4746
** The VALUE of this setting is a list of GLOB patterns matching files
4747
** that should be treated as "binary" for committing and merging
4748
** purposes. Example: *.jpg,*.png The parsing rules are complex;
4749
** see https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4750
*/
4751
#if defined(_WIN32)||defined(__CYGWIN__)||defined(__DARWIN__)
4752
/*
4753
** SETTING: case-sensitive boolean default=off
4754
** If TRUE, the files whose names differ only in case
4755
** are considered distinct. If FALSE files whose names
4756
** differ only in case are the same file. Defaults to
4757
** TRUE for unix and FALSE for Cygwin, Mac and Windows.
4758
*/
4759
#endif
4760
#if !(defined(_WIN32)||defined(__CYGWIN__)||defined(__DARWIN__))
4761
/*
4762
** SETTING: case-sensitive boolean default=on
4763
** If TRUE, the files whose names differ only in case
4764
** are considered distinct. If FALSE files whose names
4765
** differ only in case are the same file. Defaults to
4766
** TRUE for unix and FALSE for Cygwin, Mac and Windows.
4767
*/
4768
#endif
4769
/*
4770
** SETTING: clean-glob width=40 versionable block-text
4771
** The VALUE of this setting is a list of GLOB patterns matching files
4772
** that the "clean" command will delete without prompting or allowing
4773
** undo. Example: *.a,*.o,*.so The parsing rules are complex;
4774
** see https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4775
*/
4776
/*
4777
** SETTING: clearsign boolean default=off
4778
** When enabled, fossil will attempt to sign all commits
4779
** with gpg or ssh. When disabled, commits will be unsigned.
4780
*/
4781
/*
4782
** SETTING: comment-format width=16 default=1
4783
** Set the algorithm for printing timeline comments to the console.
4784
**
4785
** Possible values are:
4786
** 1 Use the original comment printing algorithm:
4787
** * Leading and trailing whitespace is removed
4788
** * Internal whitespace is converted into a single space (0x20)
4789
** * Line breaks occurs at whitespace or hyphens if possible
4790
** This is the recommended value and the default.
4791
**
4792
** Or a bitwise combination of the following flags:
4793
** 2 Trim leading and trailing CR and LF characters.
4794
** 4 Trim leading and trailing white space characters.
4795
** 8 Attempt to break lines on word boundaries.
4796
** 16 Break lines before the original comment embedded in other text.
4797
**
4798
** Note: To preserve line breaks and/or other whitespace within comment text,
4799
** make this setting some integer value that omits the "1" bit.
4800
*/
4801
/*
4802
** SETTING: crlf-glob width=40 versionable block-text
4803
** The VALUE of this setting is a list of GLOB patterns matching files
4804
** in which it is allowed to have CR, CR+LF or mixed line endings,
4805
** suppressing Fossil's normal warning about this. Set it to "*" to
4806
** disable CR+LF checking entirely. Example: *.md,*.txt
4807
** The crnl-glob setting is a compatibility alias.
4808
*/
4809
/*
4810
** SETTING: crnl-glob width=40 versionable block-text
4811
** This is an alias for the crlf-glob setting.
4812
*/
4813
/*
4814
** SETTING: default-perms width=16 default=u sensitive keep-empty
4815
** Permissions given automatically to new users. For more
4816
** information on permissions see the Users page in Server
4817
** Administration of the HTTP UI.
4818
*/
4819
/*
4820
** SETTING: diff-binary boolean default=on
4821
** If enabled, permit files that may be binary
4822
** or that match the "binary-glob" setting to be used with
4823
** external diff programs. If disabled, skip these files.
4824
*/
4825
/*
4826
** SETTING: diff-command width=40 sensitive
4827
** The value is an external command to run when performing a diff.
4828
** If undefined, the internal text diff will be used.
4829
*/
4830
/*
4831
** SETTING: dont-commit boolean default=off
4832
** If enabled, prevent committing to this repository, as an extra precaution
4833
** against accidentally checking in to a repository intended to be read-only.
4834
*/
4835
/*
4836
** SETTING: dont-push boolean default=off
4837
** If enabled, prevent this repository from pushing from client to
4838
** server. This can be used as an extra precaution to prevent
4839
** accidental pushes to a public server from a private clone.
4840
*/
4841
/*
4842
** SETTING: dotfiles boolean versionable default=off
4843
** If enabled, include --dotfiles option for all compatible commands.
4844
*/
4845
/*
4846
** SETTING: editor width=32 sensitive
4847
** The value is an external command that will launch the
4848
** text editor command used for check-in comments.
4849
**
4850
** If this value is not set, then environment variables VISUAL and
4851
** EDITOR are consulted, in that order. If neither of those are set,
4852
** then a search is made for common text editors, including
4853
** "notepad", "nano", "pico", "jove", "edit", "vi", "vim", and "ed".
4854
**
4855
** If this setting is false ("off", "no", "false", or "0") then no
4856
** text editor is used.
4857
*/
4858
/*
4859
** SETTING: empty-dirs width=40 versionable block-text
4860
** The value is a list of pathnames parsed according to the same rules as
4861
** the *-glob settings. On update and checkout commands, if no directory
4862
** exists with that name, an empty directory will be created, even if
4863
** it must create one or more parent directories.
4864
*/
4865
/*
4866
** SETTING: encoding-glob width=40 versionable block-text
4867
** The VALUE of this setting is a list of GLOB patterns matching files that
4868
** the "commit" command will ignore when issuing warnings about text files
4869
** that may use another encoding than ASCII or UTF-8. Set to "*" to disable
4870
** encoding checking. Example: *.md,*.txt The parsing rules are complex;
4871
** see https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4872
*/
4873
#if defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
4874
/*
4875
** SETTING: exec-rel-paths boolean default=on
4876
** When executing certain external commands (e.g. diff and
4877
** gdiff), use relative paths.
4878
*/
4879
#endif
4880
#if !defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
4881
/*
4882
** SETTING: exec-rel-paths boolean default=off
4883
** When executing certain external commands (e.g. diff and
4884
** gdiff), use relative paths.
4885
*/
4886
#endif
4887
4888
/*
4889
** SETTING: fileedit-glob width=40 block-text
4890
** The VALUE of this setting is a list of GLOB patterns matching files
4891
** which are allowed to be edited using the /fileedit page. An empty list
4892
** suppresses the feature. Example: *.md,*.txt The parsing rules are
4893
** complex; see https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4894
** Note that /fileedit cannot edit binary files, so the list should not
4895
** contain any globs for, e.g., images or PDFs.
4896
*/
4897
/*
4898
** SETTING: forbid-delta-manifests boolean default=off
4899
** If enabled on a client, new delta manifests are prohibited on
4900
** commits. If enabled on a server, whenever a client attempts
4901
** to obtain a check-in lock during auto-sync, the server will
4902
** send the "pragma avoid-delta-manifests" statement in its reply,
4903
** which will cause the client to avoid generating a delta
4904
** manifest.
4905
*/
4906
/*
4907
** SETTING: gdiff-command width=40 sensitive
4908
** The value is an external command to run when performing a graphical
4909
** diff. If undefined, a --tk diff is done if commands "tclsh" and "wish"
4910
** are on PATH, or a --by diff is done if "tclsh" or "wish" are unavailable.
4911
*/
4912
/*
4913
** SETTING: gmerge-command width=40 sensitive
4914
** The value is a graphical merge conflict resolver command operating
4915
** on four files. Examples:
4916
**
4917
** kdiff3 "%baseline" "%original" "%merge" -o "%output"
4918
** xxdiff "%original" "%baseline" "%merge" -M "%output"
4919
** meld "%baseline" "%original" "%merge" --output "%output"
4920
*/
4921
/*
4922
** SETTING: hash-digits width=5 default=10
4923
** The number of hexadecimal digits of the SHA3 hash to display.
4924
*/
4925
/*
4926
** SETTING: http-port width=16 default=8080
4927
** The default TCP/IP port number to use by the "server"
4928
** and "ui" commands.
4929
*/
4930
/*
4931
** SETTING: https-login boolean default=off
4932
** If true, then the Fossil web server will redirect unencrypted
4933
** login screen requests to HTTPS.
4934
*/
4935
/*
4936
** SETTING: ignore-glob width=40 versionable block-text
4937
** The VALUE of this setting is a list of GLOB patterns matching files that
4938
** the "add", "addremove", "clean", and "extras" commands will ignore.
4939
** Example: *.log,notes.txt The parsing rules are complex; see
4940
** https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4941
*/
4942
/*
4943
** SETTING: keep-glob width=40 versionable block-text
4944
** The VALUE of this setting is a list of GLOB patterns matching files that
4945
** the "clean" command must not delete. Example: build/precious.exe
4946
** The parsing rules are complex; see
4947
** https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4948
*/
4949
/*
4950
** SETTING: localauth boolean default=off
4951
** If enabled, require that HTTP connections from the loopback
4952
** address (127.0.0.1) be authenticated by password. If false,
4953
** some HTTP requests might be granted full "Setup" user
4954
** privileges without having to present login credentials.
4955
** This mechanism allows the "fossil ui" command to provide
4956
** full access to the repository without requiring the user to
4957
** log in first.
4958
**
4959
** In order for full "Setup" privilege to be granted without a
4960
** login, the following conditions must be met:
4961
**
4962
** (1) This setting ("localauth") must be off
4963
** (2) The HTTP request arrive over the loopback TCP/IP
4964
** address (127.0.01) or else via SSH.
4965
** (3) The request must be HTTP, not HTTPS. (This
4966
** restriction is designed to help prevent accidentally
4967
** providing "Setup" privileges to requests arriving
4968
** over a reverse proxy.)
4969
** (4) The command that launched the fossil server must be
4970
** one of the following:
4971
** (a) "fossil ui"
4972
** (b) "fossil server" with the --localauth option
4973
** (c) "fossil http" with the --localauth option
4974
** (d) CGI with the "localauth" setting in the cgi script.
4975
**
4976
** For maximum security, set "localauth" to 1. However, because
4977
** of the other restrictions (2) through (4), it should be safe
4978
** to leave "localauth" set to 0 in most installations, and
4979
** especially on cloned repositories on workstations. Leaving
4980
** "localauth" at 0 makes the "fossil ui" command more convenient
4981
** to use.
4982
*/
4983
/*
4984
** SETTING: lock-timeout width=25 default=60
4985
** This is the number of seconds that a check-in lock will be held on
4986
** the server before the lock expires. The default is a 60-second delay.
4987
** Set this value to zero to disable the check-in lock mechanism.
4988
**
4989
** This value should be set on the server to which users auto-sync
4990
** their work. This setting has no effect on client repositories. The
4991
** check-in lock mechanism is only effective if all users are auto-syncing
4992
** to the same server.
4993
**
4994
** Check-in locks are an advisory mechanism designed to help prevent
4995
** accidental forks due to a check-in race in installations where many
4996
** users are committing to the same branch and auto-sync is enabled.
4997
** As forks are harmless, there is no danger in disabling this mechanism.
4998
** However, keeping check-in locks turned on can help prevent unnecessary
4999
** confusion.
5000
*/
5001
/*
5002
** SETTING: main-branch width=40 default=trunk
5003
** The value is the primary branch for the project.
5004
*/
5005
/*
5006
** SETTING: manifest width=5 versionable
5007
** If enabled, automatically create files "manifest" and "manifest.uuid"
5008
** in every check-out.
5009
**
5010
** Optionally use combinations of characters 'r' for "manifest",
5011
** 'u' for "manifest.uuid" and 't' for "manifest.tags". The SQLite
5012
** and Fossil repositories both require manifests.
5013
*/
5014
/*
5015
** SETTING: max-loadavg width=25 default=0.0
5016
** Some CPU-intensive web pages (ex: /zip, /tarball, /blame)
5017
** are disallowed if the system load average goes above this
5018
** value. "0.0" means no limit. This only works on unix.
5019
** Only local settings of this value make a difference since
5020
** when running as a web-server, Fossil does not open the
5021
** global configuration database.
5022
*/
5023
/*
5024
** SETTING: max-upload width=25 default=250000
5025
** A limit on the size of uplink HTTP requests.
5026
*/
5027
/*
5028
** SETTING: mimetypes width=40 versionable block-text
5029
** A list of file extension-to-mimetype mappings, one per line. e.g.
5030
** "foo application/x-foo". File extensions are compared
5031
** case-insensitively in the order listed in this setting. A leading
5032
** '.' on file extensions is permitted but not required.
5033
*/
5034
/*
5035
** SETTING: mtime-changes boolean default=on
5036
** Use file modification times (mtimes) to detect when
5037
** files have been modified. If disabled, all managed files
5038
** are hashed to detect changes, which can be slow for large
5039
** projects.
5040
*/
5041
/*
5042
** SETTING: mv-rm-files boolean default=off
5043
** If enabled, the "mv" and "rename" commands will also move
5044
** the associated files within the check-out -AND- the "rm"
5045
** and "delete" commands will also remove the associated
5046
** files from within the check-out.
5047
*/
5048
/*
5049
** SETTING: pgp-command width=40 sensitive
5050
** Command used to clear-sign manifests at check-in.
5051
** Default value is "gpg --clearsign -o".
5052
** For SSH, use e.g. "ssh-keygen -q -Y sign -n fossilscm -f ~/.ssh/id_ed25519"
5053
*/
5054
/*
5055
** SETTING: proxy width=32 default=system
5056
** URL of the HTTP proxy. If undefined or "system", the "http_proxy"
5057
** environment variable is consulted. If "off", a direct HTTP connection is
5058
** used.
5059
*/
5060
/*
5061
** SETTING: redirect-to-https default=0 width=2
5062
** Specifies whether or not to redirect unencrypted "http://" requests to
5063
** encrypted "https://" URIs. A value of 0 (the default) means do not
5064
** redirect, 1 means to redirect only the /login page, and 2
5065
** means to always redirect.
5066
**
5067
** For security, a value of 2 is recommended. The default value is 0
5068
** because not all sites are TLS-capable. But you should definitely enable
5069
** TLS and change this setting to 2 for all public-facing repositories.
5070
*/
5071
/*
5072
** SETTING: relative-paths boolean default=on
5073
** When showing changes and extras, report paths relative
5074
** to the current working directory.
5075
*/
5076
/*
5077
** SETTING: repo-cksum boolean default=on
5078
** Compute checksums over all files in each check-out as a double-check
5079
** of correctness. Disable this on large repositories for a performance
5080
** improvement.
5081
*/
5082
/*
5083
** SETTING: repolist-skin width=2 default=0
5084
** If non-zero then use this repository as the skin for a repository list
5085
** such as created by the one of:
5086
**
5087
** 1) fossil server DIRECTORY --repolist
5088
** 2) fossil ui DIRECTORY --repolist
5089
** 3) fossil http DIRECTORY --repolist
5090
** 4) (The "repolist" option in a CGI script)
5091
** 5) fossil all ui
5092
** 6) fossil all server
5093
**
5094
** All repositories are searched (in lexicographical order) and the first
5095
** repository with a non-zero "repolist-skin" value is used as the skin
5096
** for the repository list page. If none of the repositories on the list
5097
** have a non-zero "repolist-skin" setting then the repository list is
5098
** displayed using unadorned HTML ("skinless"), with the page title taken
5099
** from the FOSSIL_REPOLIST_TITLE environment variable.
5100
**
5101
** If repolist-skin has a value of 2, then the repository is omitted from
5102
** the list in use cases 1 through 4, but not for 5 and 6.
5103
*/
5104
/*
5105
** SETTING: self-pw-reset boolean default=off sensitive
5106
** Allow users to request that an email containing a hyperlink
5107
** to the /resetpw page be sent to their email address of record,
5108
** thus allowing forgetful users to reset their forgotten passwords
5109
** without administrator involvement.
5110
*/
5111
/*
5112
** SETTING: self-register boolean default=off sensitive
5113
** Allow users to register themselves through the HTTP UI.
5114
** This is useful if you want to see other names than
5115
** "Anonymous" in e.g. ticketing system. On the other hand
5116
** users can not be deleted.
5117
*/
5118
/*
5119
** SETTING: ssh-command width=40 sensitive
5120
** The command used to talk to a remote machine with the "ssh://" protocol.
5121
*/
5122
5123
/*
5124
** SETTING: ssl-ca-location width=40 sensitive
5125
** The full pathname to a file containing PEM encoded
5126
** CA root certificates, or a directory of certificates
5127
** with filenames formed from the certificate hashes as
5128
** required by OpenSSL.
5129
**
5130
** If set, this will override the OS default list of
5131
** OpenSSL CAs. If unset, the default list will be used.
5132
** Some platforms may add additional certificates.
5133
** Checking your platform behaviour is required if the
5134
** exact contents of the CA root is critical for your
5135
** application.
5136
**
5137
** This setting is overridden by environment variables
5138
** SSL_CERT_FILE and SSL_CERT_DIR.
5139
*/
5140
/*
5141
** SETTING: ssl-identity width=40 sensitive
5142
** The full pathname to a file containing a certificate
5143
** and private key in PEM format. Create by concatenating
5144
** the certificate and private key files.
5145
**
5146
** This identity will be presented to SSL servers to
5147
** authenticate this client, in addition to the normal
5148
** password authentication.
5149
*/
5150
#ifdef FOSSIL_ENABLE_TCL
5151
/*
5152
** SETTING: tcl boolean default=off sensitive
5153
** If enabled Tcl integration commands will be added to the TH1
5154
** interpreter, allowing arbitrary Tcl expressions and
5155
** scripts to be evaluated from TH1. Additionally, the Tcl
5156
** interpreter will be able to evaluate arbitrary TH1
5157
** expressions and scripts.
5158
*/
5159
/*
5160
** SETTING: tcl-setup width=40 block-text sensitive
5161
** This is the setup script to be evaluated after creating
5162
** and initializing the Tcl interpreter. By default, this
5163
** is empty and no extra setup is performed.
5164
*/
5165
#endif /* FOSSIL_ENABLE_TCL */
5166
/*
5167
** SETTING: tclsh width=80 default=tclsh sensitive
5168
** Name of the external TCL interpreter used for such things
5169
** as running the GUI diff viewer launched by the --tk option
5170
** of the various "diff" commands.
5171
*/
5172
#ifdef FOSSIL_ENABLE_TH1_DOCS
5173
/*
5174
** SETTING: th1-docs boolean default=off sensitive
5175
** If enabled, this allows embedded documentation files to contain
5176
** arbitrary TH1 scripts that are evaluated on the server. If native
5177
** Tcl integration is also enabled, this setting has the
5178
** potential to allow anybody with check-in privileges to
5179
** do almost anything that the associated operating system
5180
** user account could do. Extreme caution should be used
5181
** when enabling this setting.
5182
*/
5183
#endif
5184
#ifdef FOSSIL_ENABLE_TH1_HOOKS
5185
/*
5186
** SETTING: th1-hooks boolean default=off
5187
** If enabled, special TH1 commands will be called before and
5188
** after any Fossil command or web page.
5189
*/
5190
#endif
5191
/*
5192
** SETTING: th1-setup width=40 block-text sensitive
5193
** This is the setup script to be evaluated after creating
5194
** and initializing the TH1 interpreter. By default, this
5195
** is empty and no extra setup is performed.
5196
*/
5197
/*
5198
** SETTING: th1-uri-regexp width=40 block-text
5199
** Specify which URI's are allowed in HTTP requests from
5200
** TH1 scripts. If empty, no HTTP requests are allowed
5201
** whatsoever.
5202
*/
5203
/*
5204
** SETTING: default-csp width=40 block-text keep-empty
5205
**
5206
** The text of the Content Security Policy that is included
5207
** in the Content-Security-Policy: header field of the HTTP
5208
** reply and in the default HTML <head> section that is added when the
5209
** skin header does not specify a <head> section. The text "$nonce"
5210
** is replaced by the random nonce that is created for each web page.
5211
**
5212
** If this setting is an empty string or is omitted, then
5213
** the following default Content Security Policy is used:
5214
**
5215
** default-src 'self' data:;
5216
** script-src 'self' 'nonce-$nonce';
5217
** style-src 'self' 'unsafe-inline';
5218
** img-src * data:;
5219
**
5220
** The default CSP is recommended. The main reason to change
5221
** this setting would be to add CDNs from which it is safe to
5222
** load additional content.
5223
*/
5224
/*
5225
** SETTING: uv-sync boolean default=off
5226
** If true, automatically send unversioned files as part
5227
** of a "fossil clone" or "fossil sync" command. The
5228
** default is false, in which case the -u option is
5229
** needed to clone or sync unversioned files.
5230
*/
5231
/*
5232
** SETTING: web-browser width=30 sensitive
5233
** A shell command used to launch your preferred
5234
** web browser when given a URL as an argument.
5235
** Defaults to "start" on windows, "open" on Mac,
5236
** and "firefox" on Unix.
5237
*/
5238
/*
5239
** SETTING: large-file-size width=10 default=200000000
5240
** Fossil considers any file whose size is greater than this value
5241
** to be a "large file". Fossil might issue warnings if you try to
5242
** "add" or "commit" a "large file". Set this value to 0 or less
5243
** to disable all such warnings.
5244
*/
5245
5246
/*
5247
** Look up a control setting by its name. Return a pointer to the Setting
5248
** object, or NULL if there is no such setting.
5249
**
5250
** If allowPrefix is true, then the Setting returned is the first one for
5251
** which zName is a prefix of the Setting name.
5252
*/
5253
Setting *db_find_setting(const char *zName, int allowPrefix){
5254
int lwr, mid, upr, c;
5255
int n = (int)strlen(zName) + !allowPrefix;
5256
int nSetting;
5257
const Setting *aSetting = setting_info(&nSetting);
5258
lwr = 0;
5259
upr = nSetting - 1;
5260
while( upr>=lwr ){
5261
mid = (upr+lwr)/2;
5262
c = fossil_strncmp(zName, aSetting[mid].name, n);
5263
if( c<0 ){
5264
upr = mid - 1;
5265
}else if( c>0 ){
5266
lwr = mid + 1;
5267
}else{
5268
if( allowPrefix ){
5269
while( mid>lwr && fossil_strncmp(zName, aSetting[mid-1].name, n)==0 ){
5270
mid--;
5271
}
5272
}
5273
return (Setting*)&aSetting[mid];
5274
}
5275
}
5276
return 0;
5277
}
5278
5279
/*
5280
** COMMAND: settings
5281
** COMMAND: unset*
5282
**
5283
** Usage: %fossil settings ?SETTING? ?VALUE? ?OPTIONS?
5284
** or: %fossil unset SETTING ?OPTIONS?
5285
**
5286
** The "settings" command with no arguments lists all settings and their
5287
** values. With just a SETTING name it shows the current value of that setting.
5288
** With a VALUE argument it changes the property for the current repository.
5289
**
5290
** Settings marked as versionable are overridden by the contents of the
5291
** file named .fossil-settings/PROPERTY in the check-out root, if that
5292
** file exists.
5293
**
5294
** The "unset" command clears a setting.
5295
**
5296
** Settings can have both a "local" repository-only value and "global" value
5297
** that applies to all repositories. The local values are stored in the
5298
** "config" table of the repository and the global values are stored in the
5299
** configuration database. If both a local and a global value exists for a
5300
** setting, the local value takes precedence. This command normally operates
5301
** on the local settings. Use the --global option to change global settings.
5302
**
5303
** Options:
5304
** --changed Only show settings if the value differs from the default
5305
** --exact Only consider exact name matches
5306
** --global Set or unset the given property globally instead of
5307
** setting or unsetting it for the open repository only
5308
** --value Only show the value of a given property (implies --exact)
5309
**
5310
** See also: [[configuration]]
5311
*/
5312
void setting_cmd(void){
5313
int i;
5314
int globalFlag = find_option("global","g",0)!=0;
5315
int bIfChng = find_option("changed",0,0)!=0;
5316
int exactFlag = find_option("exact",0,0)!=0;
5317
int valueFlag = find_option("value",0,0)!=0;
5318
/* Undocumented "--test-for-subsystem SUBSYS" option used to test
5319
** the db_get_for_subsystem() interface: */
5320
const char *zSubsys = find_option("test-for-subsystem",0,1);
5321
int unsetFlag = g.argv[1][0]=='u';
5322
int nSetting;
5323
const Setting *aSetting = setting_info(&nSetting);
5324
find_repository_option();
5325
verify_all_options();
5326
db_open_config(1, 0);
5327
if( !globalFlag ){
5328
db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
5329
}
5330
if( !g.repositoryOpen ){
5331
globalFlag = 1;
5332
}
5333
if( unsetFlag && g.argc!=3 ){
5334
usage("PROPERTY ?-global?");
5335
}
5336
if( valueFlag ){
5337
if( g.argc!=3 ){
5338
fossil_fatal("--value is only supported when qurying a given property");
5339
}
5340
}
5341
5342
if( g.argc==2 ){
5343
for(i=0; i<nSetting; i++){
5344
print_setting(&aSetting[i], 0, bIfChng);
5345
}
5346
}else if( g.argc==3 || g.argc==4 ){
5347
const char *zName = g.argv[2];
5348
int n = (int)strlen(zName);
5349
const Setting *pSetting = db_find_setting(zName, !exactFlag);
5350
if( pSetting==0 ){
5351
fossil_fatal("no such setting: %s", zName);
5352
}
5353
if( globalFlag && fossil_strcmp(pSetting->name, "manifest")==0 ){
5354
fossil_fatal("cannot set 'manifest' globally");
5355
}
5356
if( unsetFlag || g.argc==4 ){
5357
int isManifest = fossil_strcmp(pSetting->name, "manifest")==0;
5358
if( n!=(int)strlen(pSetting[0].name) && pSetting[1].name &&
5359
fossil_strncmp(pSetting[1].name, zName, n)==0 ){
5360
Blob x;
5361
int i;
5362
blob_init(&x,0,0);
5363
for(i=0; pSetting[i].name; i++){
5364
if( fossil_strncmp(pSetting[i].name,zName,n)!=0 ) break;
5365
blob_appendf(&x, " %s", pSetting[i].name);
5366
}
5367
fossil_fatal("ambiguous setting \"%s\" - might be:%s",
5368
zName, blob_str(&x));
5369
}
5370
if( globalFlag && isManifest ){
5371
fossil_fatal("cannot set 'manifest' globally");
5372
}
5373
if( unsetFlag ){
5374
db_unset(pSetting->name/*works-like:"x"*/, globalFlag);
5375
}else{
5376
db_protect_only(PROTECT_NONE);
5377
db_set(pSetting->name/*works-like:"x"*/, g.argv[3], globalFlag);
5378
db_protect_pop();
5379
}
5380
if( isManifest && g.localOpen ){
5381
manifest_to_disk(db_lget_int("checkout", 0));
5382
}
5383
}else{
5384
while( pSetting->name ){
5385
if( exactFlag ){
5386
if( fossil_strcmp(pSetting->name,zName)!=0 ) break;
5387
}else{
5388
if( fossil_strncmp(pSetting->name,zName,n)!=0 ) break;
5389
}
5390
if( zSubsys ){
5391
char *zValue = db_get_for_subsystem(pSetting->name, zSubsys);
5392
fossil_print("%s (subsystem %s) ->", pSetting->name, zSubsys);
5393
if( zValue ){
5394
fossil_print(" [%s]", zValue);
5395
fossil_free(zValue);
5396
}
5397
fossil_print("\n");
5398
}else{
5399
print_setting(pSetting, valueFlag, bIfChng);
5400
}
5401
pSetting++;
5402
}
5403
}
5404
}else{
5405
usage("?PROPERTY? ?VALUE? ?-global?");
5406
}
5407
}
5408
5409
/*
5410
** The input in a timespan measured in days. Return a string which
5411
** describes that timespan in units of seconds, minutes, hours, days,
5412
** or years, depending on its duration.
5413
*/
5414
char *db_timespan_name(double rSpan){
5415
if( rSpan<0 ) rSpan = -rSpan;
5416
rSpan *= 24.0*3600.0; /* Convert units to seconds */
5417
if( rSpan<120.0 ){
5418
return sqlite3_mprintf("%.1f seconds", rSpan);
5419
}
5420
rSpan /= 60.0; /* Convert units to minutes */
5421
if( rSpan<90.0 ){
5422
return sqlite3_mprintf("%.1f minutes", rSpan);
5423
}
5424
rSpan /= 60.0; /* Convert units to hours */
5425
if( rSpan<=48.0 ){
5426
return sqlite3_mprintf("%.1f hours", rSpan);
5427
}
5428
rSpan /= 24.0; /* Convert units to days */
5429
if( rSpan<=365.0 ){
5430
return sqlite3_mprintf("%.1f days", rSpan);
5431
}
5432
rSpan /= 356.24; /* Convert units to years */
5433
return sqlite3_mprintf("%.1f years", rSpan);
5434
}
5435
5436
/*
5437
** COMMAND: test-timespan
5438
**
5439
** Usage: %fossil test-timespan TIMESTAMP
5440
**
5441
** Print the approximate span of time from now to TIMESTAMP.
5442
*/
5443
void test_timespan_cmd(void){
5444
double rDiff;
5445
if( g.argc!=3 ) usage("TIMESTAMP");
5446
sqlite3_open(":memory:", &g.db);
5447
rDiff = db_double(0.0, "SELECT julianday('now') - julianday(%Q)", g.argv[2]);
5448
fossil_print("Time differences: %s\n", db_timespan_name(rDiff));
5449
sqlite3_close(g.db);
5450
g.db = 0;
5451
g.repositoryOpen = 0;
5452
g.localOpen = 0;
5453
}
5454
5455
/*
5456
** COMMAND: test-without-rowid
5457
**
5458
** Usage: %fossil test-without-rowid FILENAME...
5459
**
5460
** Change the Fossil repository FILENAME to make use of the WITHOUT ROWID
5461
** optimization. FILENAME can also be the configuration database file
5462
** (~/.fossil or ~/.config/fossil.db) or a local .fslckout or _FOSSIL_ file.
5463
**
5464
** The purpose of this command is for testing the WITHOUT ROWID capabilities
5465
** of SQLite. There is no big advantage to using WITHOUT ROWID in Fossil.
5466
**
5467
** Options:
5468
** -n|--dry-run No changes. Just print what would happen.
5469
*/
5470
void test_without_rowid(void){
5471
int i, j;
5472
Stmt q;
5473
Blob allSql;
5474
int dryRun = find_option("dry-run", "n", 0)!=0;
5475
for(i=2; i<g.argc; i++){
5476
db_open_or_attach(g.argv[i], "main");
5477
blob_init(&allSql, "BEGIN;\n", -1);
5478
db_prepare(&q,
5479
"SELECT name, sql FROM main.sqlite_schema "
5480
" WHERE type='table' AND sql NOT LIKE '%%WITHOUT ROWID%%'"
5481
" AND name IN ('global_config','shun','concealed','config',"
5482
" 'plink','tagxref','backlink','vcache');"
5483
);
5484
while( db_step(&q)==SQLITE_ROW ){
5485
const char *zTName = db_column_text(&q, 0);
5486
const char *zOrigSql = db_column_text(&q, 1);
5487
Blob newSql;
5488
blob_init(&newSql, 0, 0);
5489
for(j=0; zOrigSql[j]; j++){
5490
if( fossil_strnicmp(zOrigSql+j,"unique",6)==0 ){
5491
blob_append(&newSql, zOrigSql, j);
5492
blob_append(&newSql, "PRIMARY KEY", -1);
5493
zOrigSql += j+6;
5494
j = -1;
5495
}
5496
}
5497
blob_append(&newSql, zOrigSql, -1);
5498
blob_append_sql(&allSql,
5499
"ALTER TABLE \"%w\" RENAME TO \"x_%w\";\n"
5500
"%s WITHOUT ROWID;\n"
5501
"INSERT INTO \"%w\" SELECT * FROM \"x_%w\";\n"
5502
"DROP TABLE \"x_%w\";\n",
5503
zTName, zTName, blob_sql_text(&newSql), zTName, zTName, zTName
5504
);
5505
fossil_print("Converting table %s of %s to WITHOUT ROWID.\n",
5506
zTName, g.argv[i]);
5507
blob_reset(&newSql);
5508
}
5509
blob_append_sql(&allSql, "COMMIT;\n");
5510
db_finalize(&q);
5511
if( dryRun ){
5512
fossil_print("SQL that would have been evaluated:\n");
5513
fossil_print("%.78c\n", '-');
5514
fossil_print("%s", blob_sql_text(&allSql));
5515
}else{
5516
db_multi_exec("%s", blob_sql_text(&allSql));
5517
}
5518
blob_reset(&allSql);
5519
db_close(1);
5520
}
5521
}
5522
5523
/*
5524
** Make sure the adminlog table exists. Create it if it does not
5525
*/
5526
void create_admin_log_table(void){
5527
static int once = 0;
5528
if( once ) return;
5529
if( !db_table_exists("repository","admin_log") ){
5530
once = 1;
5531
db_multi_exec(
5532
"CREATE TABLE repository.admin_log(\n"
5533
" id INTEGER PRIMARY KEY,\n"
5534
" time INTEGER, -- Seconds since 1970\n"
5535
" page TEXT, -- path of page\n"
5536
" who TEXT, -- User who made the change\n"
5537
" what TEXT -- What changed\n"
5538
")"
5539
);
5540
}
5541
}
5542
5543
/*
5544
** Write a message into the admin_event table, if admin logging is
5545
** enabled via the admin-log configuration option.
5546
*/
5547
void admin_log(const char *zFormat, ...){
5548
Blob what = empty_blob;
5549
va_list ap;
5550
if( !db_get_boolean("admin-log", 0) ){
5551
/* Potential leak here (on %z params) but
5552
the alternative is to let blob_vappendf()
5553
do it below. */
5554
return;
5555
}
5556
create_admin_log_table();
5557
va_start(ap,zFormat);
5558
blob_vappendf( &what, zFormat, ap );
5559
va_end(ap);
5560
db_multi_exec("INSERT INTO admin_log(time,page,who,what)"
5561
" VALUES(now(), %Q, %Q, %B)",
5562
g.zPath, g.zLogin, &what);
5563
blob_reset(&what);
5564
}
5565
5566
/*
5567
** COMMAND: test-database-names
5568
**
5569
** Print the names of the various database files:
5570
** (1) The main repository database
5571
** (2) The local check-out database
5572
** (3) The global configuration database
5573
*/
5574
void test_database_name_cmd(void){
5575
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
5576
fossil_print("Repository database: %s\n", g.zRepositoryName);
5577
fossil_print("Local database: %s\n", g.zLocalDbName);
5578
fossil_print("Config database: %s\n", g.zConfigDbName);
5579
}
5580
5581
/*
5582
** Compute a "fingerprint" on the repository. A fingerprint is used
5583
** to verify that the repository has not been replaced by a clone
5584
** of the same repository. More precisely, a fingerprint is used to
5585
** verify that the mapping between SHA3 hashes and RID values is unchanged.
5586
**
5587
** The check-out database ("localdb") stores RID values. When associating
5588
** a check-out database against a repository database, it is useful to verify
5589
** the fingerprint so that we know that the RID values in the check-out
5590
** database still correspond to the correct entries in the BLOB table of
5591
** the repository.
5592
**
5593
** The fingerprint is based on the RCVFROM table. When constructing a
5594
** new fingerprint, use the most recent RCVFROM entry. (Set rcvid==0 to
5595
** accomplish this.) When verifying an old fingerprint, use the same
5596
** RCVFROM entry that generated the fingerprint in the first place.
5597
**
5598
** The fingerprint consists of the rcvid, a "/", and the MD5 checksum of
5599
** the remaining fields of the RCVFROM table entry. MD5 is used for this
5600
** because it is 4x faster than SHA3 and 5x faster than SHA1, and there
5601
** are no security concerns - this is just a checksum, not a security
5602
** token.
5603
*/
5604
char *db_fingerprint(int rcvid, int iVersion){
5605
char *z = 0;
5606
Blob sql = BLOB_INITIALIZER;
5607
Stmt q;
5608
if( iVersion==0 ){
5609
/* The original fingerprint algorithm used "quote(mtime)". But this
5610
** could give slightly different answers depending on how the floating-
5611
** point hardware is configured. For example, it gave different
5612
** answers on native Linux versus running under valgrind. */
5613
blob_append_sql(&sql,
5614
"SELECT rcvid, quote(uid), quote(mtime), quote(nonce), quote(ipaddr)"
5615
" FROM rcvfrom"
5616
);
5617
}else{
5618
/* These days, we use "datetime(mtime)" for more consistent answers */
5619
blob_append_sql(&sql,
5620
"SELECT rcvid, quote(uid), datetime(mtime), quote(nonce), quote(ipaddr)"
5621
" FROM rcvfrom"
5622
);
5623
}
5624
if( rcvid<=0 ){
5625
blob_append_sql(&sql, " ORDER BY rcvid DESC LIMIT 1");
5626
}else{
5627
blob_append_sql(&sql, " WHERE rcvid=%d", rcvid);
5628
}
5629
db_prepare_blob(&q, &sql);
5630
blob_reset(&sql);
5631
if( db_step(&q)==SQLITE_ROW ){
5632
int i;
5633
md5sum_init();
5634
for(i=1; i<=4; i++){
5635
md5sum_step_text(db_column_text(&q,i),-1);
5636
}
5637
z = mprintf("%d/%s",db_column_int(&q,0),md5sum_finish(0));
5638
}
5639
db_finalize(&q);
5640
return z;
5641
}
5642
5643
/*
5644
** COMMAND: test-fingerprint
5645
**
5646
** Usage: %fossil test-fingerprint ?RCVID?
5647
**
5648
** Display the repository fingerprint using the supplied RCVID or
5649
** using the latest RCVID if none is given on the command line.
5650
** Show both the legacy and the newer version of the fingerprint,
5651
** and the currently stored fingerprint if there is one.
5652
*/
5653
void test_fingerprint(void){
5654
int rcvid = 0;
5655
db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
5656
if( g.argc==3 ){
5657
rcvid = atoi(g.argv[2]);
5658
}else if( g.argc!=2 ){
5659
fossil_fatal("wrong number of arguments");
5660
}
5661
fossil_print("legacy: %z\n", db_fingerprint(rcvid, 0));
5662
fossil_print("version-1: %z\n", db_fingerprint(rcvid, 1));
5663
if( g.localOpen ){
5664
fossil_print("localdb: %z\n", db_lget("fingerprint","(none)"));
5665
fossil_print("db_fingerprint_ok(): %d\n", db_fingerprint_ok());
5666
}
5667
fossil_print("Fossil version: %s - %.10s %.19s\n",
5668
RELEASE_VERSION, MANIFEST_DATE, MANIFEST_UUID);
5669
}
5670
5671
/*
5672
** Set the value of the "checkout" entry in the VVAR table.
5673
** If bWriteManifest is non-zero then also attempt to write the manifest
5674
** files to disk.
5675
**
5676
** Also set "fingerprint" and "checkout-hash".
5677
*/
5678
void db_set_checkout(int rid, int bWriteManifest){
5679
char *z;
5680
if( bWriteManifest ) manifest_to_disk(rid);
5681
db_lset_int("checkout", rid);
5682
if (rid != 0) {
5683
z = db_text(0,"SELECT uuid FROM blob WHERE rid=%d",rid);
5684
db_lset("checkout-hash", z);
5685
fossil_free(z);
5686
z = db_fingerprint(0, 1);
5687
db_lset("fingerprint", z);
5688
fossil_free(z);
5689
}
5690
}
5691
5692
/*
5693
** Verify that the fingerprint recorded in the "fingerprint" entry
5694
** of the VVAR table matches the fingerprint on the currently
5695
** connected repository. Return true if the fingerprint is ok, and
5696
** return false if the fingerprint does not match.
5697
*/
5698
int db_fingerprint_ok(void){
5699
char *zCkout; /* The fingerprint recorded in the check-out database */
5700
char *zRepo; /* The fingerprint of the repository */
5701
int rc; /* Result */
5702
5703
if( !db_lget_int("checkout", 0) ){
5704
/* We have an empty check-out, fingerprint is still NULL. */
5705
return 2;
5706
}
5707
zCkout = db_text(0,"SELECT value FROM localdb.vvar WHERE name='fingerprint'");
5708
if( zCkout==0 ){
5709
/* This is an older check-out that does not record a fingerprint.
5710
** We have to assume everything is ok */
5711
return 2;
5712
}
5713
zRepo = db_fingerprint(atoi(zCkout), 1);
5714
rc = fossil_strcmp(zCkout,zRepo)==0;
5715
fossil_free(zRepo);
5716
/* If the initial test fails, try again using the older fingerprint
5717
** algorithm */
5718
if( !rc ){
5719
zRepo = db_fingerprint(atoi(zCkout), 0);
5720
rc = fossil_strcmp(zCkout,zRepo)==0;
5721
fossil_free(zRepo);
5722
}
5723
fossil_free(zCkout);
5724
return rc;
5725
}
5726
5727
/*
5728
** Adds the given rid to the UNSENT table.
5729
*/
5730
void db_add_unsent(int rid){
5731
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", rid);
5732
}
5733

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button