Fossil SCM

fossil-scm / src / db.c
Blame History Raw 5741 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
** Its result is either an RID or NULL.
1335
*/
1336
void db_sym2rid_function(
1337
sqlite3_context *context,
1338
int argc,
1339
sqlite3_value **argv
1340
){
1341
const char *arg;
1342
const char *type;
1343
if(1 != argc && 2 != argc){
1344
sqlite3_result_error(context, "Expecting one or two arguments", -1);
1345
return;
1346
}
1347
arg = (const char*)sqlite3_value_text(argv[0]);
1348
if(!arg){
1349
sqlite3_result_error(context, "Expecting a STRING argument", -1);
1350
}else{
1351
int rid;
1352
type = (2==argc) ? (const char*)sqlite3_value_text(argv[1]) : 0;
1353
if(!type) type = "ci";
1354
rid = symbolic_name_to_rid( arg, type );
1355
if(rid<0){
1356
sqlite3_result_error(context, "Symbolic name is ambiguous.", -1);
1357
}else if(0==rid){
1358
sqlite3_result_null(context);
1359
}else{
1360
sqlite3_result_int64(context, rid);
1361
}
1362
}
1363
}
1364
1365
1366
/*
1367
** SETTING: timeline-utc boolean default=on
1368
**
1369
** If the timeline-utc setting is true, then Fossil tries to understand
1370
** and display all time values using UTC. If this setting is false, Fossil
1371
** tries to understand and display time values using the local timezone.
1372
**
1373
** The word "timeline" in the name of this setting is historical.
1374
** This setting applies to all user interfaces of Fossil,
1375
** not just the timeline.
1376
**
1377
** Note that when accessing Fossil using the web interface, the localtime
1378
** used is the localtime on the server, not on the client.
1379
*/
1380
/*
1381
** Return true if Fossil is set to display times as UTC. Return false
1382
** if it wants to display times using the local timezone.
1383
**
1384
** False is returned if display is set to localtime even if the localtime
1385
** happens to be the same as UTC.
1386
*/
1387
int fossil_ui_utctime(void){
1388
if( g.fTimeFormat==0 ){
1389
if( db_get_int("timeline-utc", 1) ){
1390
g.fTimeFormat = 1; /* UTC */
1391
}else{
1392
g.fTimeFormat = 2; /* Localtime */
1393
}
1394
}
1395
return g.fTimeFormat==1;
1396
}
1397
1398
/*
1399
** Return true if Fossil is set to display times using the local timezone.
1400
*/
1401
int fossil_ui_localtime(void){
1402
return fossil_ui_utctime()==0;
1403
}
1404
1405
/*
1406
** The toLocal() SQL function returns a string that is an argument to a
1407
** date/time function that is appropriate for modifying the time for display.
1408
** If UTC time display is selected, no modification occurs. If local time
1409
** display is selected, the time is adjusted appropriately.
1410
**
1411
** Example usage:
1412
**
1413
** SELECT datetime('now',toLocal());
1414
*/
1415
void db_tolocal_function(
1416
sqlite3_context *context,
1417
int argc,
1418
sqlite3_value **argv
1419
){
1420
if( fossil_ui_utctime() ){
1421
sqlite3_result_text(context, "0 seconds", -1, SQLITE_STATIC);
1422
}else{
1423
sqlite3_result_text(context, "localtime", -1, SQLITE_STATIC);
1424
}
1425
}
1426
1427
/*
1428
** The fromLocal() SQL function returns a string that is an argument to a
1429
** date/time function that is appropriate to convert an input time to UTC.
1430
** If UTC time display is selected, no modification occurs. If local time
1431
** display is selected, the time is adjusted from local to UTC.
1432
**
1433
** Example usage:
1434
**
1435
** SELECT julianday(:user_input,fromLocal());
1436
*/
1437
void db_fromlocal_function(
1438
sqlite3_context *context,
1439
int argc,
1440
sqlite3_value **argv
1441
){
1442
if( fossil_ui_utctime() ){
1443
sqlite3_result_text(context, "0 seconds", -1, SQLITE_STATIC);
1444
}else{
1445
sqlite3_result_text(context, "utc", -1, SQLITE_STATIC);
1446
}
1447
}
1448
1449
/*
1450
** If the input is a hexadecimal string, convert that string into a BLOB.
1451
** If the input is not a hexadecimal string, return NULL.
1452
*/
1453
void db_hextoblob(
1454
sqlite3_context *context,
1455
int argc,
1456
sqlite3_value **argv
1457
){
1458
const unsigned char *zIn = sqlite3_value_text(argv[0]);
1459
int nIn = sqlite3_value_bytes(argv[0]);
1460
unsigned char *zOut;
1461
if( zIn==0 ) return;
1462
if( nIn&1 ) return;
1463
if( !validate16((const char*)zIn, nIn) ) return;
1464
zOut = sqlite3_malloc64( nIn/2 + 1 );
1465
if( zOut==0 ){
1466
sqlite3_result_error_nomem(context);
1467
return;
1468
}
1469
decode16(zIn, zOut, nIn);
1470
sqlite3_result_blob(context, zOut, nIn/2, sqlite3_free);
1471
}
1472
1473
/*
1474
** Return the XOR-obscured version of the input text. Useful for
1475
** updating authentication strings in Fossil settings. To change
1476
** the password locally stored for sync, for instance:
1477
**
1478
** echo "UPDATE config
1479
** SET value = obscure('monkey123')
1480
** WHERE name = 'last-sync-pw'" |
1481
** fossil sql
1482
**
1483
** Note that user.pw uses a different obscuration algorithm, but
1484
** you don't need to use 'fossil sql' for that anyway. Just call
1485
**
1486
** fossil user pass monkey123
1487
**
1488
** to change the local user entry's password in the same way.
1489
**
1490
** 2022-12-30: If the user-data pointer is not NULL, then operate
1491
** as unobscure() rather than obscure(). The obscure() variant of
1492
** this routine is commonly available. But unobscure is (currently)
1493
** only registered by the "fossil remote config-data --show-passwords"
1494
** command.
1495
*/
1496
void db_obscure(
1497
sqlite3_context *context,
1498
int argc,
1499
sqlite3_value **argv
1500
){
1501
const unsigned char *zIn = sqlite3_value_text(argv[0]);
1502
int nIn = sqlite3_value_bytes(argv[0]);
1503
char *zOut, *zTemp;
1504
if( 0==zIn ) return;
1505
if( 0==(zOut = sqlite3_malloc64( nIn * 2 + 3 )) ){
1506
sqlite3_result_error_nomem(context);
1507
return;
1508
}
1509
if( sqlite3_user_data(context)==0 ){
1510
zTemp = obscure((char*)zIn);
1511
}else{
1512
zTemp = unobscure((char*)zIn);
1513
}
1514
fossil_strcpy(zOut, zTemp);
1515
fossil_free(zTemp);
1516
sqlite3_result_text(context, zOut, strlen(zOut), sqlite3_free);
1517
}
1518
1519
/*
1520
** Return True if zName is a protected (a.k.a. "sensitive") setting.
1521
*/
1522
int db_setting_is_protected(const char *zName){
1523
const Setting *pSetting = zName ? db_find_setting(zName,0) : 0;
1524
return pSetting!=0 && pSetting->sensitive!=0;
1525
}
1526
1527
/*
1528
** Implement the protected_setting(X) SQL function. This function returns
1529
** true if X is the name of a protected (security-sensitive) setting and
1530
** the db.protectSensitive flag is enabled. It returns false otherwise.
1531
*/
1532
LOCAL void db_protected_setting_func(
1533
sqlite3_context *context,
1534
int argc,
1535
sqlite3_value **argv
1536
){
1537
const char *zSetting;
1538
if( (db.protectMask & PROTECT_SENSITIVE)==0 ){
1539
sqlite3_result_int(context, 0);
1540
return;
1541
}
1542
zSetting = (const char*)sqlite3_value_text(argv[0]);
1543
sqlite3_result_int(context, db_setting_is_protected(zSetting));
1544
}
1545
1546
/*
1547
** Copied from SQLite ext/misc/uint.c...
1548
**
1549
** Compare text in lexicographic order, except strings of digits
1550
** compare in numeric order.
1551
**
1552
** This version modified to also ignore case.
1553
*/
1554
static int uintNocaseCollFunc(
1555
void *notUsed,
1556
int nKey1, const void *pKey1,
1557
int nKey2, const void *pKey2
1558
){
1559
const unsigned char *zA = (const unsigned char*)pKey1;
1560
const unsigned char *zB = (const unsigned char*)pKey2;
1561
int i=0, j=0, x;
1562
(void)notUsed;
1563
while( i<nKey1 && j<nKey2 ){
1564
if( fossil_isdigit(zA[i]) && fossil_isdigit(zB[j]) ){
1565
int k;
1566
while( i<nKey1 && zA[i]=='0' ){ i++; }
1567
while( j<nKey2 && zB[j]=='0' ){ j++; }
1568
k = 0;
1569
while( i+k<nKey1 && fossil_isdigit(zA[i+k])
1570
&& j+k<nKey2 && fossil_isdigit(zB[j+k]) ){
1571
k++;
1572
}
1573
if( i+k<nKey1 && fossil_isdigit(zA[i+k]) ){
1574
return +1;
1575
}else if( j+k<nKey2 && fossil_isdigit(zB[j+k]) ){
1576
return -1;
1577
}else{
1578
x = memcmp(zA+i, zB+j, k);
1579
if( x ) return x;
1580
i += k;
1581
j += k;
1582
}
1583
}else
1584
if( zA[i]!=zB[j]
1585
&& (x = fossil_tolower(zA[i]) - fossil_tolower(zB[j]))!=0
1586
){
1587
return x;
1588
}else{
1589
i++;
1590
j++;
1591
}
1592
}
1593
return (nKey1 - i) - (nKey2 - j);
1594
}
1595
1596
1597
/*
1598
** Register the SQL functions that are useful both to the internal
1599
** representation and to the "fossil sql" command.
1600
*/
1601
void db_add_aux_functions(sqlite3 *db){
1602
sqlite3_create_collation(db, "uintnocase", SQLITE_UTF8,0,uintNocaseCollFunc);
1603
sqlite3_create_function(db, "checkin_mtime", 2,
1604
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1605
0, db_checkin_mtime_function, 0, 0);
1606
sqlite3_create_function(db, "symbolic_name_to_rid", 1,
1607
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1608
0, db_sym2rid_function, 0, 0);
1609
sqlite3_create_function(db, "symbolic_name_to_rid", 2,
1610
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1611
0, db_sym2rid_function, 0, 0);
1612
sqlite3_create_function(db, "now", 0,
1613
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
1614
db_now_function, 0, 0);
1615
sqlite3_create_function(db, "toLocal", 0,
1616
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1617
0, db_tolocal_function, 0, 0);
1618
sqlite3_create_function(db, "fromLocal", 0,
1619
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1620
0, db_fromlocal_function, 0, 0);
1621
sqlite3_create_function(db, "hextoblob", 1,
1622
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
1623
0, db_hextoblob, 0, 0);
1624
sqlite3_create_function(db, "capunion", 1, SQLITE_UTF8, 0,
1625
0, capability_union_step, capability_union_finalize);
1626
sqlite3_create_function(db, "fullcap", 1, SQLITE_UTF8, 0,
1627
capability_fullcap, 0, 0);
1628
sqlite3_create_function(db, "find_emailaddr", 1, SQLITE_UTF8, 0,
1629
alert_find_emailaddr_func, 0, 0);
1630
sqlite3_create_function(db, "display_name", 1, SQLITE_UTF8, 0,
1631
alert_display_name_func, 0, 0);
1632
sqlite3_create_function(db, "obscure", 1, SQLITE_UTF8, 0,
1633
db_obscure, 0, 0);
1634
sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
1635
db_protected_setting_func, 0, 0);
1636
sqlite3_create_function(db, "win_reserved", 1, SQLITE_UTF8, 0,
1637
db_win_reserved_func,0,0);
1638
sqlite3_create_function(db, "url_nouser", 1, SQLITE_UTF8, 0,
1639
url_nouser_func,0,0);
1640
sqlite3_create_function(db, "chat_msg_from_event", 4,
1641
SQLITE_UTF8 | SQLITE_INNOCUOUS, 0,
1642
chat_msg_from_event, 0, 0);
1643
sqlite3_create_function(db, "inode", 1, SQLITE_UTF8, 0,
1644
file_inode_sql_func,0,0);
1645
sqlite3_create_function(db, "artifact_to_json", 1, SQLITE_UTF8, 0,
1646
artifact_to_json_sql_func,0,0);
1647
1648
}
1649
1650
#if USE_SEE
1651
/*
1652
** This is a pointer to the saved database encryption key string.
1653
*/
1654
static char *zSavedKey = 0;
1655
1656
/*
1657
** This is the size of the saved database encryption key, in bytes.
1658
*/
1659
static size_t savedKeySize = 0;
1660
1661
/*
1662
** This function returns non-zero if there is a saved database encryption
1663
** key available.
1664
*/
1665
int db_have_saved_encryption_key(){
1666
return db_is_valid_saved_encryption_key(zSavedKey, savedKeySize);
1667
}
1668
1669
/*
1670
** This function returns non-zero if the specified database encryption key
1671
** is valid.
1672
*/
1673
int db_is_valid_saved_encryption_key(const char *p, size_t n){
1674
if( p==0 ) return 0;
1675
if( n==0 ) return 0;
1676
if( p[0]==0 ) return 0;
1677
return 1;
1678
}
1679
1680
/*
1681
** This function returns the saved database encryption key -OR- zero if
1682
** no database encryption key is saved.
1683
*/
1684
char *db_get_saved_encryption_key(){
1685
return zSavedKey;
1686
}
1687
1688
/*
1689
** This function returns the size of the saved database encryption key
1690
** -OR- zero if no database encryption key is saved.
1691
*/
1692
size_t db_get_saved_encryption_key_size(){
1693
return savedKeySize;
1694
}
1695
1696
/*
1697
** This function arranges for the saved database encryption key buffer
1698
** to be allocated and then sets up the environment variable to allow
1699
** a child process to initialize it with the actual database encryption
1700
** key.
1701
*/
1702
void db_setup_for_saved_encryption_key(){
1703
void *p = NULL;
1704
size_t n = 0;
1705
size_t pageSize = 0;
1706
Blob pidKey;
1707
1708
assert( !db_have_saved_encryption_key() );
1709
db_unsave_encryption_key();
1710
fossil_get_page_size(&pageSize);
1711
assert( pageSize>0 );
1712
p = fossil_secure_alloc_page(&n);
1713
assert( p!=NULL );
1714
assert( n==pageSize );
1715
blob_zero(&pidKey);
1716
blob_appendf(&pidKey, "%lu:%p:%u", (unsigned long)GETPID(), p, n);
1717
fossil_setenv("FOSSIL_SEE_PID_KEY", blob_str(&pidKey));
1718
zSavedKey = p;
1719
savedKeySize = n;
1720
}
1721
1722
/*
1723
** This function arranges for the database encryption key to be securely
1724
** saved in non-pageable memory (on platforms where this is possible).
1725
*/
1726
static void db_save_encryption_key(
1727
Blob *pKey
1728
){
1729
void *p = NULL;
1730
size_t n = 0;
1731
size_t pageSize = 0;
1732
size_t blobSize = 0;
1733
1734
assert( !db_have_saved_encryption_key() );
1735
blobSize = blob_size(pKey);
1736
if( blobSize==0 ) return;
1737
fossil_get_page_size(&pageSize);
1738
assert( pageSize>0 );
1739
if( blobSize>pageSize ){
1740
fossil_panic("key blob too large: %u versus %u", blobSize, pageSize);
1741
}
1742
p = fossil_secure_alloc_page(&n);
1743
assert( p!=NULL );
1744
assert( n==pageSize );
1745
assert( n>=blobSize );
1746
memcpy(p, blob_str(pKey), blobSize);
1747
zSavedKey = p;
1748
savedKeySize = n;
1749
}
1750
1751
/*
1752
** This function arranges for the saved database encryption key to be
1753
** securely zeroed, unlocked (if necessary), and freed.
1754
*/
1755
void db_unsave_encryption_key(){
1756
fossil_secure_free_page(zSavedKey, savedKeySize);
1757
zSavedKey = NULL;
1758
savedKeySize = 0;
1759
}
1760
1761
/*
1762
** This function sets the saved database encryption key to the specified
1763
** string value, allocating or freeing the underlying memory if needed.
1764
*/
1765
static void db_set_saved_encryption_key(
1766
Blob *pKey
1767
){
1768
if( zSavedKey!=NULL ){
1769
size_t blobSize = blob_size(pKey);
1770
if( blobSize==0 ){
1771
db_unsave_encryption_key();
1772
}else{
1773
if( blobSize>savedKeySize ){
1774
fossil_panic("key blob too large: %u versus %u",
1775
blobSize, savedKeySize);
1776
}
1777
fossil_secure_zero(zSavedKey, savedKeySize);
1778
memcpy(zSavedKey, blob_str(pKey), blobSize);
1779
}
1780
}else{
1781
db_save_encryption_key(pKey);
1782
}
1783
}
1784
1785
/*
1786
** WEBPAGE: setseekey
1787
**
1788
** Sets the sets the saved database encryption key to one that gets passed
1789
** via the "key" query string parameter. If the saved database encryption
1790
** key has already been set, does nothing. This web page does not produce
1791
** any output on success or failure. No permissions are required and none
1792
** are checked (partially due to lack of encrypted database access).
1793
**
1794
** Query parameters:
1795
**
1796
** key The string to set as the saved database encryption
1797
** key.
1798
*/
1799
void db_set_see_key_page(void){
1800
Blob key;
1801
const char *zKey;
1802
if( db_have_saved_encryption_key() ){
1803
fossil_trace("SEE: encryption key was already set\n");
1804
return;
1805
}
1806
zKey = P("key");
1807
blob_init(&key, 0, 0);
1808
if( zKey!=0 ){
1809
PID_T processId;
1810
blob_set(&key, zKey);
1811
db_set_saved_encryption_key(&key);
1812
processId = db_maybe_handle_saved_encryption_key_for_process(
1813
SEE_KEY_WRITE
1814
);
1815
fossil_trace("SEE: set encryption key for process %lu, length %u\n",
1816
(unsigned long)processId, blob_size(&key));
1817
}else{
1818
fossil_trace("SEE: no encryption key specified\n");
1819
}
1820
blob_reset(&key);
1821
}
1822
1823
/*
1824
** WEBPAGE: unsetseekey
1825
**
1826
** Sets the saved database encryption key to zeros in the current and parent
1827
** Fossil processes. This web page does not produce any output on success
1828
** or failure. Setup permission is required.
1829
*/
1830
void db_unset_see_key_page(void){
1831
PID_T processId;
1832
login_check_credentials();
1833
if( !g.perm.Setup ){ login_needed(0); return; }
1834
processId = db_maybe_handle_saved_encryption_key_for_process(
1835
SEE_KEY_ZERO
1836
);
1837
fossil_trace("SEE: unset encryption key for process %lu\n",
1838
(unsigned long)processId);
1839
}
1840
1841
/*
1842
** This function reads the saved database encryption key from the
1843
** specified Fossil parent process. This is only necessary (or
1844
** functional) on Windows or Linux.
1845
*/
1846
static void db_read_saved_encryption_key_from_process(
1847
PID_T processId, /* Identifier for Fossil parent process. */
1848
LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
1849
SIZE_T nSize /* Size of saved key buffer in the parent process. */
1850
){
1851
void *p = NULL;
1852
size_t n = 0;
1853
size_t pageSize = 0;
1854
1855
fossil_get_page_size(&pageSize);
1856
assert( pageSize>0 );
1857
if( nSize>pageSize ){
1858
fossil_panic("key too large: %u versus %u", nSize, pageSize);
1859
}
1860
p = fossil_secure_alloc_page(&n);
1861
assert( p!=NULL );
1862
assert( n==pageSize );
1863
assert( n>=nSize );
1864
{
1865
#if defined(_WIN32)
1866
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId);
1867
if( hProcess!=NULL ){
1868
SIZE_T nRead = 0;
1869
if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){
1870
CloseHandle(hProcess);
1871
if( nRead==nSize ){
1872
db_unsave_encryption_key();
1873
zSavedKey = p;
1874
savedKeySize = n;
1875
}else{
1876
fossil_secure_free_page(p, n);
1877
fossil_panic("bad size read, %u out of %u bytes at %p from pid %lu",
1878
nRead, nSize, pAddress, processId);
1879
}
1880
}else{
1881
CloseHandle(hProcess);
1882
fossil_secure_free_page(p, n);
1883
fossil_panic("failed read, %u bytes at %p from pid %lu: %lu", nSize,
1884
pAddress, processId, GetLastError());
1885
}
1886
}else{
1887
fossil_secure_free_page(p, n);
1888
fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
1889
}
1890
#elif defined(__linux__)
1891
ssize_t nRead;
1892
struct iovec liov = {0};
1893
struct iovec riov = {0};
1894
liov.iov_base = p;
1895
liov.iov_len = n;
1896
riov.iov_base = pAddress;
1897
riov.iov_len = nSize;
1898
nRead = process_vm_readv(processId, &liov, 1, &riov, 1, 0);
1899
if( nRead==nSize ){
1900
db_unsave_encryption_key();
1901
zSavedKey = p;
1902
savedKeySize = n;
1903
}else{
1904
fossil_secure_free_page(p, n);
1905
fossil_panic("bad size read, %zd out of %zu bytes at %p from pid %lu",
1906
nRead, nSize, pAddress, (unsigned long)processId);
1907
}
1908
#else
1909
fossil_secure_free_page(p, n);
1910
fossil_trace("db_read_saved_encryption_key_from_process unsupported");
1911
#endif
1912
}
1913
}
1914
1915
/*
1916
** This function writes the saved database encryption key into the
1917
** specified Fossil parent process. This is only necessary (or
1918
** functional) on Windows or Linux.
1919
*/
1920
static void db_write_saved_encryption_key_to_process(
1921
PID_T processId, /* Identifier for Fossil parent process. */
1922
LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
1923
SIZE_T nSize /* Size of saved key buffer in the parent process. */
1924
){
1925
void *p = db_get_saved_encryption_key();
1926
size_t n = db_get_saved_encryption_key_size();
1927
size_t pageSize = 0;
1928
1929
fossil_get_page_size(&pageSize);
1930
assert( pageSize>0 );
1931
if( nSize>pageSize ){
1932
fossil_panic("key too large: %u versus %u", nSize, pageSize);
1933
}
1934
assert( p!=NULL );
1935
assert( n==pageSize );
1936
assert( n>=nSize );
1937
{
1938
#if defined(_WIN32)
1939
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
1940
FALSE, processId);
1941
if( hProcess!=NULL ){
1942
SIZE_T nWrite = 0;
1943
if( WriteProcessMemory(hProcess, pAddress, p, nSize, &nWrite) ){
1944
CloseHandle(hProcess);
1945
if( nWrite!=nSize ){
1946
fossil_panic("bad size write, %u out of %u bytes at %p from pid %lu",
1947
nWrite, nSize, pAddress, processId);
1948
}
1949
}else{
1950
CloseHandle(hProcess);
1951
fossil_panic("failed write, %u bytes at %p from pid %lu: %lu", nSize,
1952
pAddress, processId, GetLastError());
1953
}
1954
}else{
1955
fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
1956
}
1957
#elif defined(__linux__)
1958
ssize_t nWrite;
1959
struct iovec liov = {0};
1960
struct iovec riov = {0};
1961
liov.iov_base = p;
1962
liov.iov_len = n;
1963
riov.iov_base = pAddress;
1964
riov.iov_len = nSize;
1965
nWrite = process_vm_writev(processId, &liov, 1, &riov, 1, 0);
1966
if( nWrite!=nSize ){
1967
fossil_panic("bad size write, %zd out of %zu bytes at %p from pid %lu",
1968
nWrite, nSize, pAddress, (unsigned long)processId);
1969
}
1970
#else
1971
fossil_trace("db_write_saved_encryption_key_to_process unsupported");
1972
#endif
1973
}
1974
}
1975
1976
/*
1977
** This function zeros the saved database encryption key in the specified
1978
** Fossil parent process. This is only necessary (or functional) on
1979
** Windows or Linux.
1980
*/
1981
static void db_zero_saved_encryption_key_in_process(
1982
PID_T processId, /* Identifier for Fossil parent process. */
1983
LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
1984
SIZE_T nSize /* Size of saved key buffer in the parent process. */
1985
){
1986
void *p = NULL;
1987
size_t n = 0;
1988
size_t pageSize = 0;
1989
1990
fossil_get_page_size(&pageSize);
1991
assert( pageSize>0 );
1992
if( nSize>pageSize ){
1993
fossil_panic("key too large: %u versus %u", nSize, pageSize);
1994
}
1995
p = fossil_secure_alloc_page(&n);
1996
assert( p!=NULL );
1997
assert( n==pageSize );
1998
assert( n>=nSize );
1999
{
2000
#if defined(_WIN32)
2001
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
2002
FALSE, processId);
2003
if( hProcess!=NULL ){
2004
SIZE_T nWrite = 0;
2005
if( WriteProcessMemory(hProcess, pAddress, p, nSize, &nWrite) ){
2006
CloseHandle(hProcess);
2007
fossil_secure_free_page(p, n);
2008
if( nWrite!=nSize ){
2009
fossil_panic("bad size zero, %u out of %u bytes at %p from pid %lu",
2010
nWrite, nSize, pAddress, processId);
2011
}
2012
}else{
2013
CloseHandle(hProcess);
2014
fossil_secure_free_page(p, n);
2015
fossil_panic("failed zero, %u bytes at %p from pid %lu: %lu", nSize,
2016
pAddress, processId, GetLastError());
2017
}
2018
}else{
2019
fossil_secure_free_page(p, n);
2020
fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
2021
}
2022
#elif defined(__linux__)
2023
ssize_t nWrite;
2024
struct iovec liov = {0};
2025
struct iovec riov = {0};
2026
liov.iov_base = p;
2027
liov.iov_len = n;
2028
riov.iov_base = pAddress;
2029
riov.iov_len = nSize;
2030
nWrite = process_vm_writev(processId, &liov, 1, &riov, 1, 0);
2031
if( nWrite!=nSize ){
2032
fossil_secure_free_page(p, n);
2033
fossil_panic("bad size zero, %zd out of %zu bytes at %p from pid %lu",
2034
nWrite, nSize, pAddress, (unsigned long)processId);
2035
}
2036
#else
2037
fossil_secure_free_page(p, n);
2038
fossil_trace("db_zero_saved_encryption_key_in_process unsupported");
2039
#endif
2040
}
2041
}
2042
2043
/*
2044
** This function evaluates the specified TH1 script and attempts to parse
2045
** its result as a colon-delimited triplet containing a process identifier,
2046
** address, and size (in bytes) of the database encryption key. This is
2047
** only necessary (or functional) on Windows or Linux.
2048
*/
2049
static PID_T db_handle_saved_encryption_key_for_process_via_th1(
2050
const char *zConfig, /* The TH1 script to evaluate. */
2051
int eType /* Non-zero to write key to parent process -OR-
2052
* zero to read it from the parent process. */
2053
){
2054
PID_T processId = 0;
2055
int rc;
2056
char *zResult;
2057
char *zPwd = file_getcwd(0, 0);
2058
Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_NEED_CONFIG | TH_INIT_NO_REPO);
2059
rc = Th_Eval(g.interp, 0, zConfig, -1);
2060
zResult = (char*)Th_GetResult(g.interp, 0);
2061
if( rc!=TH_OK ){
2062
fossil_fatal("script for pid key failed: %s", zResult);
2063
}
2064
if( zResult ){
2065
LPVOID pAddress = NULL;
2066
SIZE_T nSize = 0;
2067
parse_pid_key_value(zResult, &processId, &pAddress, &nSize);
2068
if( eType==SEE_KEY_READ ){
2069
db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
2070
}else if( eType==SEE_KEY_WRITE ){
2071
db_write_saved_encryption_key_to_process(processId, pAddress, nSize);
2072
}else if( eType==SEE_KEY_ZERO ){
2073
db_zero_saved_encryption_key_in_process(processId, pAddress, nSize);
2074
}else{
2075
fossil_panic("unsupported SEE key operation %d", eType);
2076
}
2077
}
2078
file_chdir(zPwd, 0);
2079
fossil_free(zPwd);
2080
return processId;
2081
}
2082
2083
/*
2084
** This function sets the saved database encryption key to one that gets
2085
** read from the specified Fossil parent process, if applicable. This is
2086
** only necessary (or functional) on Windows or Linux.
2087
*/
2088
PID_T db_maybe_handle_saved_encryption_key_for_process(int eType){
2089
PID_T processId = 0;
2090
g.zPidKey = find_option("usepidkey",0,1);
2091
if( !g.zPidKey ){
2092
g.zPidKey = fossil_getenv("FOSSIL_SEE_PID_KEY");
2093
}
2094
if( g.zPidKey ){
2095
LPVOID pAddress = NULL;
2096
SIZE_T nSize = 0;
2097
parse_pid_key_value(g.zPidKey, &processId, &pAddress, &nSize);
2098
if( eType==SEE_KEY_READ ){
2099
db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
2100
}else if( eType==SEE_KEY_WRITE ){
2101
db_write_saved_encryption_key_to_process(processId, pAddress, nSize);
2102
}else if( eType==SEE_KEY_ZERO ){
2103
db_zero_saved_encryption_key_in_process(processId, pAddress, nSize);
2104
}else{
2105
fossil_panic("unsupported SEE key operation %d", eType);
2106
}
2107
}else{
2108
const char *zSeeDbConfig = find_option("seedbcfg",0,1);
2109
if( !zSeeDbConfig ){
2110
zSeeDbConfig = fossil_getenv("FOSSIL_SEE_DB_CONFIG");
2111
}
2112
if( zSeeDbConfig ){
2113
processId = db_handle_saved_encryption_key_for_process_via_th1(
2114
zSeeDbConfig, eType
2115
);
2116
}
2117
}
2118
return processId;
2119
}
2120
#endif /* USE_SEE */
2121
2122
/*
2123
** If the database file zDbFile has a name that suggests that it is
2124
** encrypted, then prompt for the database encryption key and return it
2125
** in the blob *pKey. Or, if the encryption key has previously been
2126
** requested, just return a copy of the previous result. The blob in
2127
** *pKey must be initialized.
2128
*/
2129
static void db_maybe_obtain_encryption_key(
2130
const char *zDbFile, /* Name of the database file */
2131
Blob *pKey /* Put the encryption key here */
2132
){
2133
#if USE_SEE
2134
if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
2135
char *zKey = db_get_saved_encryption_key();
2136
if( zKey ){
2137
blob_set(pKey, zKey);
2138
}else{
2139
char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
2140
prompt_for_password(zPrompt, pKey, 0);
2141
fossil_free(zPrompt);
2142
db_set_saved_encryption_key(pKey);
2143
}
2144
}
2145
#endif
2146
}
2147
2148
2149
/*
2150
** Sets the encryption key for the database, if necessary.
2151
*/
2152
void db_maybe_set_encryption_key(sqlite3 *db, const char *zDbName){
2153
Blob key;
2154
blob_init(&key, 0, 0);
2155
db_maybe_obtain_encryption_key(zDbName, &key);
2156
if( blob_size(&key)>0 ){
2157
if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
2158
char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
2159
sqlite3_exec(db, zCmd, 0, 0, 0);
2160
fossil_secure_zero(zCmd, strlen(zCmd));
2161
sqlite3_free(zCmd);
2162
#if USE_SEE
2163
}else{
2164
sqlite3_key(db, blob_str(&key), -1);
2165
#endif
2166
}
2167
}
2168
blob_reset(&key);
2169
}
2170
2171
/*
2172
** Open a database file. Return a pointer to the new database
2173
** connection. An error results in process abort.
2174
*/
2175
LOCAL sqlite3 *db_open(const char *zDbName){
2176
int rc;
2177
sqlite3 *db;
2178
Blob bNameCheck = BLOB_INITIALIZER;
2179
2180
if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
2181
file_canonical_name(zDbName, &bNameCheck, 0)
2182
/* For purposes of the apndvfs check, g.nameOfExe and zDbName must
2183
** both be canonicalized, else chances are very good that they
2184
** will not match even if they're the same file. Details:
2185
** https://fossil-scm.org/forum/forumpost/16880a28aad1a868 */;
2186
if( strcmp(blob_str(&bNameCheck), g.nameOfExe)==0 ){
2187
extern int sqlite3_appendvfs_init(
2188
sqlite3 *, char **, const sqlite3_api_routines *
2189
);
2190
sqlite3_appendvfs_init(0,0,0);
2191
g.zVfsName = "apndvfs";
2192
}
2193
blob_reset(&bNameCheck);
2194
rc = sqlite3_open_v2(
2195
zDbName, &db,
2196
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
2197
g.zVfsName
2198
);
2199
if( rc!=SQLITE_OK ){
2200
db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
2201
}
2202
db_maybe_set_encryption_key(db, zDbName);
2203
sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, 0, &rc);
2204
sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_TRIGGER, 0, &rc);
2205
sqlite3_db_config(db, SQLITE_DBCONFIG_TRUSTED_SCHEMA, 0, &rc);
2206
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 0, &rc);
2207
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 0, &rc);
2208
sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, &rc);
2209
sqlite3_busy_timeout(db, 15000);
2210
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
2211
sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0);
2212
sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
2213
sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
2214
sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
2215
sqlite3_create_function(
2216
db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
2217
);
2218
sqlite3_create_function(
2219
db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
2220
);
2221
if( g.fSqlTrace ) sqlite3_trace_v2(db, SQLITE_TRACE_PROFILE, db_sql_trace, 0);
2222
db_add_aux_functions(db);
2223
re_add_sql_func(db); /* The REGEXP operator */
2224
foci_register(db); /* The "files_of_checkin" virtual table */
2225
sqlite3_set_authorizer(db, db_top_authorizer, db);
2226
db_register_fts5(db) /* in search.c */;
2227
return db;
2228
}
2229
2230
2231
/*
2232
** Detaches the zLabel database.
2233
*/
2234
void db_detach(const char *zLabel){
2235
db_multi_exec("DETACH DATABASE %Q", zLabel);
2236
}
2237
2238
/*
2239
** zDbName is the name of a database file. Attach zDbName using
2240
** the name zLabel.
2241
*/
2242
void db_attach(const char *zDbName, const char *zLabel){
2243
Blob key;
2244
if( db_table_exists(zLabel,"sqlite_schema") ) return;
2245
blob_init(&key, 0, 0);
2246
db_maybe_obtain_encryption_key(zDbName, &key);
2247
if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
2248
char *zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q",
2249
zDbName, zLabel, blob_str(&key));
2250
db_exec_sql(zCmd);
2251
fossil_secure_zero(zCmd, strlen(zCmd));
2252
sqlite3_free(zCmd);
2253
}else{
2254
char *zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY ''",
2255
zDbName, zLabel);
2256
db_exec_sql(zCmd);
2257
sqlite3_free(zCmd);
2258
#if USE_SEE
2259
if( blob_size(&key)>0 ){
2260
sqlite3_key_v2(g.db, zLabel, blob_str(&key), -1);
2261
}
2262
#endif
2263
}
2264
blob_reset(&key);
2265
}
2266
2267
/*
2268
** Change the schema name of the "main" database to zLabel.
2269
** zLabel must be a static string that is unchanged for the life of
2270
** the database connection.
2271
**
2272
** After calling this routine, db_database_slot(zLabel) should
2273
** return 0.
2274
*/
2275
void db_set_main_schemaname(sqlite3 *db, const char *zLabel){
2276
if( sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, zLabel) ){
2277
fossil_panic("Fossil requires a version of SQLite that supports the "
2278
"SQLITE_DBCONFIG_MAINDBNAME interface.");
2279
}
2280
}
2281
2282
/*
2283
** Return the slot number for database zLabel. The first database
2284
** opened is slot 0. The "temp" database is slot 1. Attached databases
2285
** are slots 2 and higher.
2286
**
2287
** Return -1 if zLabel does not match any open database.
2288
*/
2289
int db_database_slot(const char *zLabel){
2290
int iSlot = -1;
2291
int rc;
2292
Stmt q;
2293
if( g.db==0 ) return iSlot;
2294
rc = db_prepare_ignore_error(&q, "PRAGMA database_list");
2295
if( rc==SQLITE_OK ){
2296
while( db_step(&q)==SQLITE_ROW ){
2297
if( fossil_strcmp(db_column_text(&q,1),zLabel)==0 ){
2298
iSlot = db_column_int(&q, 0);
2299
break;
2300
}
2301
}
2302
}
2303
db_finalize(&q);
2304
return iSlot;
2305
}
2306
2307
/*
2308
** zDbName is the name of a database file. If no other database
2309
** file is open, then open this one. If another database file is
2310
** already open, then attach zDbName using the name zLabel.
2311
*/
2312
void db_open_or_attach(const char *zDbName, const char *zLabel){
2313
if( !g.db ){
2314
g.db = db_open(zDbName);
2315
db_set_main_schemaname(g.db, zLabel);
2316
}else{
2317
db_attach(zDbName, zLabel);
2318
}
2319
}
2320
2321
/*
2322
** Close the per-user configuration database file
2323
*/
2324
void db_close_config(){
2325
int iSlot = db_database_slot("configdb");
2326
if( iSlot>0 ){
2327
db_detach("configdb");
2328
}else if( g.dbConfig ){
2329
sqlite3_wal_checkpoint(g.dbConfig, 0);
2330
sqlite3_close(g.dbConfig);
2331
g.dbConfig = 0;
2332
}else if( g.db && 0==iSlot ){
2333
int rc;
2334
sqlite3_wal_checkpoint(g.db, 0);
2335
rc = sqlite3_close(g.db);
2336
if( g.fSqlTrace ) fossil_trace("-- db_close_config(%d)\n", rc);
2337
g.db = 0;
2338
g.repositoryOpen = 0;
2339
g.localOpen = 0;
2340
}else{
2341
return;
2342
}
2343
fossil_free(g.zConfigDbName);
2344
g.zConfigDbName = 0;
2345
}
2346
2347
/*
2348
** Compute the name of the configuration database. If unable to find the
2349
** database, return 0 if isOptional is true, or panic if isOptional is false.
2350
**
2351
** Space to hold the result comes from fossil_malloc().
2352
*/
2353
static char *db_configdb_name(int isOptional){
2354
char *zHome; /* Home directory */
2355
char *zDbName; /* Name of the database file */
2356
2357
2358
/* On Windows, look for these directories, in order:
2359
**
2360
** FOSSIL_HOME
2361
** LOCALAPPDATA
2362
** APPDATA
2363
** USERPROFILE
2364
** HOMEDRIVE HOMEPATH
2365
*/
2366
#if defined(_WIN32) || defined(__CYGWIN__)
2367
zHome = fossil_getenv("FOSSIL_HOME");
2368
if( zHome==0 ){
2369
zHome = fossil_getenv("LOCALAPPDATA");
2370
if( zHome==0 ){
2371
zHome = fossil_getenv("APPDATA");
2372
if( zHome==0 ){
2373
zHome = fossil_getenv("USERPROFILE");
2374
if( zHome==0 ){
2375
char *zDrive = fossil_getenv("HOMEDRIVE");
2376
char *zPath = fossil_getenv("HOMEPATH");
2377
if( zDrive && zPath ) zHome = mprintf("%s%s", zDrive, zPath);
2378
}
2379
}
2380
}
2381
}
2382
zDbName = mprintf("%//_fossil", zHome);
2383
fossil_free(zHome);
2384
return zDbName;
2385
2386
#else /* if unix */
2387
char *zXdgHome;
2388
2389
/* For unix. a 5-step algorithm is used.
2390
** See ../www/tech_overview.wiki for discussion.
2391
**
2392
** Step 1: If FOSSIL_HOME exists -> $FOSSIL_HOME/.fossil
2393
*/
2394
zHome = fossil_getenv("FOSSIL_HOME");
2395
if( zHome!=0 ) return mprintf("%s/.fossil", zHome);
2396
2397
/* Step 2: If HOME exists and file $HOME/.fossil exists -> $HOME/.fossil
2398
*/
2399
zHome = fossil_getenv("HOME");
2400
if( zHome ){
2401
zDbName = mprintf("%s/.fossil", zHome);
2402
if( file_size(zDbName, ExtFILE)>1024*3 ){
2403
return zDbName;
2404
}
2405
fossil_free(zDbName);
2406
}
2407
2408
/* Step 3: if XDG_CONFIG_HOME exists -> $XDG_CONFIG_HOME/fossil.db
2409
*/
2410
zXdgHome = fossil_getenv("XDG_CONFIG_HOME");
2411
if( zXdgHome!=0 ){
2412
return mprintf("%s/fossil.db", zXdgHome);
2413
}
2414
2415
/* The HOME variable is required in order to continue.
2416
*/
2417
if( zHome==0 ){
2418
if( isOptional ) return 0;
2419
fossil_fatal("cannot locate home directory - please set one of the "
2420
"FOSSIL_HOME, XDG_CONFIG_HOME, or HOME environment "
2421
"variables");
2422
}
2423
2424
/* Step 4: If $HOME/.config is a directory -> $HOME/.config/fossil.db
2425
*/
2426
zXdgHome = mprintf("%s/.config", zHome);
2427
if( file_isdir(zXdgHome, ExtFILE)==1 ){
2428
fossil_free(zXdgHome);
2429
return mprintf("%s/.config/fossil.db", zHome);
2430
}
2431
2432
/* Step 5: Otherwise -> $HOME/.fossil
2433
*/
2434
return mprintf("%s/.fossil", zHome);
2435
#endif /* unix */
2436
}
2437
2438
/*
2439
** Open the configuration database. Create the database anew if
2440
** it does not already exist.
2441
**
2442
** If the useAttach flag is 0 (the usual case) then the configuration
2443
** database is opened on a separate database connection g.dbConfig.
2444
** This prevents the database from becoming locked on long check-in or sync
2445
** operations which hold an exclusive transaction. In a few cases, though,
2446
** it is convenient for the database to be attached to the main database
2447
** connection so that we can join between the various databases. In that
2448
** case, invoke this routine with useAttach as 1.
2449
*/
2450
int db_open_config(int useAttach, int isOptional){
2451
char *zDbName;
2452
if( g.zConfigDbName ){
2453
int alreadyAttached = db_database_slot("configdb")>0;
2454
if( useAttach==alreadyAttached ) return 1; /* Already open. */
2455
db_close_config();
2456
}
2457
zDbName = db_configdb_name(isOptional);
2458
if( zDbName==0 ) return 0;
2459
if( file_size(zDbName, ExtFILE)<1024*3 ){
2460
char *zHome = file_dirname(zDbName);
2461
int rc;
2462
if( file_isdir(zHome, ExtFILE)==0 ){
2463
file_mkdir(zHome, ExtFILE, 0);
2464
}
2465
rc = file_access(zHome, W_OK);
2466
if( rc ){
2467
if( isOptional ) return 0;
2468
fossil_fatal("home directory \"%s\" must be writeable", zHome);
2469
}
2470
db_init_database(zDbName, zConfigSchema, (char*)0);
2471
fossil_free(zHome);
2472
}
2473
if( file_access(zDbName, W_OK) ){
2474
if( isOptional ) return 0;
2475
fossil_fatal("configuration file %s must be writeable", zDbName);
2476
}
2477
if( useAttach ){
2478
db_open_or_attach(zDbName, "configdb");
2479
g.dbConfig = 0;
2480
}else{
2481
g.dbConfig = db_open(zDbName);
2482
db_set_main_schemaname(g.dbConfig, "configdb");
2483
}
2484
g.zConfigDbName = zDbName;
2485
return 1;
2486
}
2487
2488
/*
2489
** Return TRUE if zTable exists.
2490
*/
2491
int db_table_exists(
2492
const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */
2493
const char *zTable /* Name of table */
2494
){
2495
return sqlite3_table_column_metadata(g.db, zDb, zTable, 0,
2496
0, 0, 0, 0, 0)==SQLITE_OK;
2497
}
2498
2499
/*
2500
** Return TRUE if zTable exists and contains column zColumn.
2501
** Return FALSE if zTable does not exist or if zTable exists
2502
** but lacks zColumn.
2503
*/
2504
int db_table_has_column(
2505
const char *zDb, /* One of: NULL, "config", "localdb", "repository" */
2506
const char *zTable, /* Name of table */
2507
const char *zColumn /* Name of column in table */
2508
){
2509
return sqlite3_table_column_metadata(g.db, zDb, zTable, zColumn,
2510
0, 0, 0, 0, 0)==SQLITE_OK;
2511
}
2512
2513
/*
2514
** Returns TRUE if zTable exists in the local database but lacks column
2515
** zColumn
2516
*/
2517
static int db_local_table_exists_but_lacks_column(
2518
const char *zTable,
2519
const char *zColumn
2520
){
2521
return db_table_exists("localdb", zTable)
2522
&& !db_table_has_column("localdb", zTable, zColumn);
2523
}
2524
2525
/*
2526
** If zDbName is a valid local database file, open it and return
2527
** true. If it is not a valid local database file, return 0.
2528
*/
2529
static int isValidLocalDb(const char *zDbName){
2530
i64 lsize;
2531
2532
if( file_access(zDbName, F_OK) ) return 0;
2533
lsize = file_size(zDbName, ExtFILE);
2534
if( lsize%1024!=0 || lsize<4096 ) return 0;
2535
db_open_or_attach(zDbName, "localdb");
2536
2537
/* Check to see if the check-out database has the latest schema changes.
2538
** The most recent schema change (2019-01-19) is the addition of the
2539
** vmerge.mhash and vfile.mhash fields. If the schema has the vmerge.mhash
2540
** column, assume everything else is up-to-date.
2541
*/
2542
if( db_table_has_column("localdb","vmerge","mhash") ){
2543
return 1; /* This is a check-out database with the latest schema */
2544
}
2545
2546
/* If there is no vfile table, then assume we have picked up something
2547
** that is not even close to being a valid check-out database */
2548
if( !db_table_exists("localdb","vfile") ){
2549
return 0; /* Not a DB */
2550
}
2551
2552
/* If the "isexe" column is missing from the vfile table, then
2553
** add it now. This code added on 2010-03-06. After all users have
2554
** upgraded, this code can be safely deleted.
2555
*/
2556
if( !db_table_has_column("localdb","vfile","isexe") ){
2557
db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");
2558
}
2559
2560
/* If "islink"/"isLink" columns are missing from tables, then
2561
** add them now. This code added on 2011-01-17 and 2011-08-27.
2562
** After all users have upgraded, this code can be safely deleted.
2563
*/
2564
if( !db_table_has_column("localdb","vfile","isLink") ){
2565
db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
2566
if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){
2567
db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0");
2568
}
2569
if( db_local_table_exists_but_lacks_column("undo", "isLink") ){
2570
db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0");
2571
}
2572
if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
2573
db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
2574
}
2575
}
2576
2577
/* The design of the check-out database changed on 2019-01-19 adding the mhash
2578
** column to vfile and vmerge and changing the UNIQUE index on vmerge into
2579
** a PRIMARY KEY that includes the new mhash column. However, we must have
2580
** the repository database at hand in order to do the migration, so that
2581
** step is deferred. */
2582
return 1;
2583
}
2584
2585
/*
2586
** Locate the root directory of the local repository tree. The root
2587
** directory is found by searching for a file named "_FOSSIL_" or ".fslckout"
2588
** that contains a valid repository database.
2589
**
2590
** For legacy, also look for ".fos". The use of ".fos" is deprecated
2591
** since "fos" has negative connotations in Hungarian, we are told.
2592
**
2593
** If no valid _FOSSIL_ or .fslckout file is found, we move up one level and
2594
** try again. Once the file is found, the g.zLocalRoot variable is set
2595
** to the root of the repository tree and this routine returns 1. If
2596
** no database is found, then this routine return 0.
2597
**
2598
** In db_open_local_v2(), if the bRootOnly flag is true, then only
2599
** look in the CWD for the check-out database. Do not scan upwards in
2600
** the file hierarchy.
2601
**
2602
** This routine always opens the user database regardless of whether or
2603
** not the repository database is found. If the _FOSSIL_ or .fslckout file
2604
** is found, it is attached to the open database connection too.
2605
*/
2606
int db_open_local_v2(const char *zDbName, int bRootOnly){
2607
int i, n;
2608
char zPwd[2000];
2609
static const char *(aDbName[]) = { "_FOSSIL_", ".fslckout", ".fos" };
2610
2611
if( g.localOpen ) return 1;
2612
file_getcwd(zPwd, sizeof(zPwd)-20);
2613
n = strlen(zPwd);
2614
while( n>0 ){
2615
for(i=0; i<count(aDbName); i++){
2616
sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "/%s", aDbName[i]);
2617
if( isValidLocalDb(zPwd) ){
2618
if( db_open_config(0, 1)==0 ){
2619
return 0; /* Configuration could not be opened */
2620
}
2621
/* Found a valid check-out database file */
2622
g.zLocalDbName = fossil_strdup(zPwd);
2623
zPwd[n] = 0;
2624
while( n>0 && zPwd[n-1]=='/' ){
2625
n--;
2626
zPwd[n] = 0;
2627
}
2628
g.zLocalRoot = mprintf("%s/", zPwd);
2629
g.localOpen = 1;
2630
db_open_repository(zDbName);
2631
return 1;
2632
}
2633
}
2634
if( bRootOnly ) break;
2635
n--;
2636
while( n>1 && zPwd[n]!='/' ){ n--; }
2637
while( n>1 && zPwd[n-1]=='/' ){ n--; }
2638
zPwd[n] = 0;
2639
}
2640
2641
/* A check-out database file could not be found */
2642
return 0;
2643
}
2644
int db_open_local(const char *zDbName){
2645
return db_open_local_v2(zDbName, 0);
2646
}
2647
2648
/*
2649
** Get the full pathname to the repository database file. The
2650
** local database (the _FOSSIL_ or .fslckout database) must have already
2651
** been opened before this routine is called.
2652
*/
2653
const char *db_repository_filename(void){
2654
static char *zRepo = 0;
2655
assert( g.localOpen );
2656
assert( g.zLocalRoot );
2657
if( zRepo==0 ){
2658
zRepo = db_lget("repository", 0);
2659
if( zRepo && !file_is_absolute_path(zRepo) ){
2660
char * zFree = zRepo;
2661
zRepo = mprintf("%s%s", g.zLocalRoot, zRepo);
2662
fossil_free(zFree);
2663
zFree = zRepo;
2664
zRepo = file_canonical_name_dup(zFree);
2665
fossil_free(zFree);
2666
}
2667
}
2668
return zRepo;
2669
}
2670
2671
/*
2672
** Returns non-zero if support for symlinks is currently enabled.
2673
*/
2674
int db_allow_symlinks(void){
2675
return g.allowSymlinks;
2676
}
2677
2678
/*
2679
** Return TRUE if the file in the argument seems like it might be an
2680
** SQLite database file that contains a Fossil repository schema.
2681
*/
2682
int db_looks_like_a_repository(const char *zDbName){
2683
sqlite3 *db = 0;
2684
i64 sz;
2685
int rc;
2686
int res = 0;
2687
sqlite3_stmt *pStmt = 0;
2688
2689
sz = file_size(zDbName, ExtFILE);
2690
if( sz<16834 ) return 0;
2691
db = db_open(zDbName);
2692
if( !db ) return 0;
2693
if( !g.zVfsName && sz%512 ) return 0;
2694
rc = sqlite3_prepare_v2(db,
2695
"SELECT count(*) FROM sqlite_schema"
2696
" WHERE name COLLATE nocase IN"
2697
"('blob','delta','rcvfrom','user','config','mlink','plink');",
2698
-1, &pStmt, 0);
2699
if( rc ) goto is_repo_end;
2700
rc = sqlite3_step(pStmt);
2701
if( rc!=SQLITE_ROW ) goto is_repo_end;
2702
if( sqlite3_column_int(pStmt, 0)!=7 ) goto is_repo_end;
2703
res = 1;
2704
2705
is_repo_end:
2706
sqlite3_finalize(pStmt);
2707
sqlite3_close(db);
2708
return res;
2709
}
2710
2711
/*
2712
** COMMAND: test-is-repo
2713
** Usage: %fossil test-is-repo FILENAME...
2714
**
2715
** Test whether the specified files look like a SQLite database
2716
** containing a Fossil repository schema.
2717
*/
2718
void test_is_repo(void){
2719
int i;
2720
verify_all_options();
2721
for(i=2; i<g.argc; i++){
2722
fossil_print("%s: %s\n",
2723
db_looks_like_a_repository(g.argv[i]) ? "yes" : " no",
2724
g.argv[i]
2725
);
2726
}
2727
}
2728
2729
2730
/*
2731
** Open the repository database given by zDbName. If zDbName==NULL then
2732
** get the name from the already open local database.
2733
*/
2734
void db_open_repository(const char *zDbName){
2735
if( g.repositoryOpen ) return;
2736
if( zDbName==0 ){
2737
if( g.localOpen ){
2738
zDbName = db_repository_filename();
2739
}
2740
if( zDbName==0 ){
2741
db_err("unable to find the name of a repository database");
2742
}
2743
}
2744
if( !db_looks_like_a_repository(zDbName) ){
2745
if( file_access(zDbName, F_OK) ){
2746
#ifdef FOSSIL_ENABLE_JSON
2747
g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
2748
#endif
2749
fossil_fatal("repository does not exist or"
2750
" is in an unreadable directory: %s", zDbName);
2751
}else if( file_access(zDbName, R_OK) ){
2752
#ifdef FOSSIL_ENABLE_JSON
2753
g.json.resultCode = FSL_JSON_E_DENIED;
2754
#endif
2755
fossil_fatal("read permission denied for repository %s", zDbName);
2756
}else{
2757
#ifdef FOSSIL_ENABLE_JSON
2758
g.json.resultCode = FSL_JSON_E_DB_NOT_VALID;
2759
#endif
2760
fossil_fatal("not a valid repository: %s", zDbName);
2761
}
2762
}
2763
g.zRepositoryName = fossil_strdup(zDbName);
2764
db_open_or_attach(g.zRepositoryName, "repository");
2765
g.repositoryOpen = 1;
2766
{
2767
/* TESTING FIXME set SQL cache size from environment FIXME */
2768
const char *zCS = getenv("FOSSIL_SQLCACHE");
2769
if( zCS!=0 && atoi(zCS)!=0 ){
2770
db_multi_exec("PRAGMA repository.cache_size=%d;", atoi(zCS));
2771
}
2772
}
2773
sqlite3_file_control(g.db, "repository", SQLITE_FCNTL_DATA_VERSION,
2774
&g.iRepoDataVers);
2775
2776
/* Cache "allow-symlinks" option, because we'll need it on every stat call */
2777
g.allowSymlinks = db_get_boolean("allow-symlinks",0);
2778
2779
g.zAuxSchema = db_get("aux-schema","");
2780
g.eHashPolicy = db_get_int("hash-policy",-1);
2781
if( g.eHashPolicy<0 ){
2782
g.eHashPolicy = hname_default_policy();
2783
db_set_int("hash-policy", g.eHashPolicy, 0);
2784
}
2785
2786
#if 0 /* No longer automatic. Need to run "fossil rebuild" to migrate */
2787
/* Make a change to the CHECK constraint on the BLOB table for
2788
** version 2.0 and later.
2789
*/
2790
rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */
2791
#endif
2792
2793
/* Additional checks that occur when opening the check-out database */
2794
if( g.localOpen ){
2795
2796
/* If the repository database that was just opened has been
2797
** replaced by a clone of the same project, with different RID
2798
** values, then renumber the RID values stored in various tables
2799
** of the check-out database, so that the repository and check-out
2800
** databases align.
2801
*/
2802
if( !db_fingerprint_ok() ){
2803
if( find_option("no-rid-adjust",0,0)!=0 ){
2804
/* The --no-rid-adjust command-line option bypasses the RID value
2805
** updates. Intended for use during debugging, especially to be
2806
** able to run "fossil sql" after a database swap. */
2807
fossil_print(
2808
"WARNING: repository change detected, but no adjust made.\n"
2809
);
2810
}else if( find_option("rid-renumber-dryrun",0,0)!=0 ){
2811
/* the --rid-renumber-dryrun option shows how RID values would be
2812
** renumbered, but does not actually perform the renumbering.
2813
** This is a debugging-only option. */
2814
vfile_rid_renumbering_event(1);
2815
exit(0);
2816
}else{
2817
char *z;
2818
stash_rid_renumbering_event();
2819
vfile_rid_renumbering_event(0);
2820
undo_reset();
2821
bisect_reset();
2822
z = db_fingerprint(0, 1);
2823
db_lset("fingerprint", z);
2824
fossil_free(z);
2825
fossil_print(
2826
"WARNING: The repository database has been replaced by a clone.\n"
2827
"Bisect history and undo have been lost.\n"
2828
);
2829
}
2830
}
2831
2832
/* Make sure the check-out database schema migration of 2019-01-20
2833
** has occurred.
2834
**
2835
** The 2019-01-19 migration is the addition of the vmerge.mhash and
2836
** vfile.mhash columns and making the vmerge.mhash column part of the
2837
** PRIMARY KEY for vmerge.
2838
*/
2839
if( !db_table_has_column("localdb", "vfile", "mhash") ){
2840
db_multi_exec("ALTER TABLE vfile ADD COLUMN mhash;");
2841
db_multi_exec(
2842
"UPDATE vfile"
2843
" SET mhash=(SELECT uuid FROM blob WHERE blob.rid=vfile.mrid)"
2844
" WHERE mrid!=rid;"
2845
);
2846
if( !db_table_has_column("localdb", "vmerge", "mhash") ){
2847
db_exec_sql("ALTER TABLE vmerge RENAME TO old_vmerge;");
2848
db_exec_sql(zLocalSchemaVmerge);
2849
db_exec_sql(
2850
"INSERT OR IGNORE INTO vmerge(id,merge,mhash)"
2851
" SELECT id, merge, blob.uuid FROM old_vmerge, blob"
2852
" WHERE old_vmerge.merge=blob.rid;"
2853
"DROP TABLE old_vmerge;"
2854
);
2855
}
2856
}
2857
}
2858
}
2859
2860
/*
2861
** Return true if there have been any changes to the repository
2862
** database since it was opened.
2863
**
2864
** Changes to "config" and "localdb" and "temp" do not count.
2865
** This routine only returns true if there have been changes
2866
** to "repository".
2867
*/
2868
int db_repository_has_changed(void){
2869
unsigned int v;
2870
if( !g.repositoryOpen ) return 0;
2871
sqlite3_file_control(g.db, "repository", SQLITE_FCNTL_DATA_VERSION, &v);
2872
return g.iRepoDataVers != v;
2873
}
2874
2875
/*
2876
** Flags for the db_find_and_open_repository() function.
2877
*/
2878
#if INTERFACE
2879
#define OPEN_OK_NOT_FOUND 0x001 /* Do not error out if not found */
2880
#define OPEN_ANY_SCHEMA 0x002 /* Do not error if schema is wrong */
2881
#define OPEN_SUBSTITUTE 0x004 /* Fake in-memory repo if not found */
2882
#endif
2883
2884
/*
2885
** Try to find the repository and open it. Use the -R or --repository
2886
** option to locate the repository. If no such option is available, then
2887
** use the repository of the open check-out if there is one.
2888
**
2889
** Error out if the repository cannot be opened.
2890
*/
2891
void db_find_and_open_repository(int bFlags, int nArgUsed){
2892
const char *zRep = find_repository_option();
2893
if( zRep && file_isdir(zRep, ExtFILE)==1 ){
2894
goto rep_not_found;
2895
}
2896
if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
2897
zRep = g.argv[nArgUsed];
2898
}
2899
if( zRep==0 ){
2900
if( db_open_local(0)==0 ){
2901
goto rep_not_found;
2902
}
2903
zRep = db_repository_filename();
2904
if( zRep==0 ){
2905
goto rep_not_found;
2906
}
2907
}
2908
db_open_repository(zRep);
2909
if( g.repositoryOpen ){
2910
if( (bFlags & OPEN_ANY_SCHEMA)==0 ) db_verify_schema();
2911
return;
2912
}
2913
rep_not_found:
2914
if( bFlags & OPEN_OK_NOT_FOUND ){
2915
/* No errors if the database is not found */
2916
if( bFlags & OPEN_SUBSTITUTE ){
2917
db_create_repository(0);
2918
}
2919
}else{
2920
#ifdef FOSSIL_ENABLE_JSON
2921
g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
2922
#endif
2923
if( nArgUsed==0 ){
2924
fossil_fatal("use --repository or -R to specify the repository database");
2925
}else{
2926
fossil_fatal("specify the repository name as a command-line argument");
2927
}
2928
}
2929
}
2930
2931
/*
2932
** Return TRUE if the schema is out-of-date
2933
*/
2934
int db_schema_is_outofdate(void){
2935
return strcmp(g.zAuxSchema,AUX_SCHEMA_MIN)<0
2936
|| strcmp(g.zAuxSchema,AUX_SCHEMA_MAX)>0;
2937
}
2938
2939
/*
2940
** Return true if the database is writeable
2941
*/
2942
int db_is_writeable(const char *zName){
2943
return g.db!=0 && !sqlite3_db_readonly(g.db, zName);
2944
}
2945
2946
/*
2947
** Verify that the repository schema is correct. If it is not correct,
2948
** issue a fatal error and die.
2949
*/
2950
void db_verify_schema(void){
2951
if( db_schema_is_outofdate() ){
2952
#ifdef FOSSIL_ENABLE_JSON
2953
g.json.resultCode = FSL_JSON_E_DB_NEEDS_REBUILD;
2954
#endif
2955
fossil_warning("incorrect repository schema version: "
2956
"current repository schema version is \"%s\" "
2957
"but need versions between \"%s\" and \"%s\".",
2958
g.zAuxSchema, AUX_SCHEMA_MIN, AUX_SCHEMA_MAX);
2959
fossil_fatal("run \"fossil rebuild\" to fix this problem");
2960
}
2961
}
2962
2963
2964
/*
2965
** COMMAND: test-move-repository
2966
**
2967
** Usage: %fossil test-move-repository PATHNAME
2968
**
2969
** Change the location of the repository database on a local check-out.
2970
** Use this command to avoid having to close and reopen a check-out
2971
** when relocating the repository database.
2972
*/
2973
void move_repo_cmd(void){
2974
Blob repo;
2975
char *zRepo;
2976
if( g.argc!=3 ){
2977
usage("PATHNAME");
2978
}
2979
file_canonical_name(g.argv[2], &repo, 0);
2980
zRepo = blob_str(&repo);
2981
if( file_access(zRepo, F_OK) ){
2982
fossil_fatal("no such file: %s", zRepo);
2983
}
2984
if( db_open_local(zRepo)==0 ){
2985
fossil_fatal("not in a local check-out");
2986
return;
2987
}
2988
db_open_or_attach(zRepo, "test_repo");
2989
db_lset("repository", blob_str(&repo));
2990
db_record_repository_filename(blob_str(&repo));
2991
db_close(1);
2992
}
2993
2994
2995
/*
2996
** Open the local database. If unable, exit with an error.
2997
*/
2998
void db_must_be_within_tree(void){
2999
if( find_repository_option() ){
3000
fossil_fatal("the \"%s\" command only works from within an open check-out",
3001
g.argv[1]);
3002
}
3003
if( db_open_local(0)==0 ){
3004
fossil_fatal("current directory is not within an open check-out");
3005
}
3006
db_open_repository(0);
3007
db_verify_schema();
3008
}
3009
3010
/*
3011
** Close the database connection.
3012
**
3013
** Check for unfinalized statements and report errors if the reportErrors
3014
** argument is true. Ignore unfinalized statements when false.
3015
*/
3016
void db_close(int reportErrors){
3017
sqlite3_stmt *pStmt;
3018
if( g.db==0 ) return;
3019
sqlite3_set_authorizer(g.db, 0, 0);
3020
if( g.fSqlStats ){
3021
int cur, hiwtr;
3022
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
3023
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
3024
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
3025
fprintf(stderr, "-- LOOKASIDE_HIT %10d\n", hiwtr);
3026
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &cur,&hiwtr,0);
3027
fprintf(stderr, "-- LOOKASIDE_MISS_SIZE %10d\n", hiwtr);
3028
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &cur,&hiwtr,0);
3029
fprintf(stderr, "-- LOOKASIDE_MISS_FULL %10d\n", hiwtr);
3030
sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_USED, &cur, &hiwtr, 0);
3031
fprintf(stderr, "-- CACHE_USED %10d\n", cur);
3032
sqlite3_db_status(g.db, SQLITE_DBSTATUS_SCHEMA_USED, &cur, &hiwtr, 0);
3033
fprintf(stderr, "-- SCHEMA_USED %10d\n", cur);
3034
sqlite3_db_status(g.db, SQLITE_DBSTATUS_STMT_USED, &cur, &hiwtr, 0);
3035
fprintf(stderr, "-- STMT_USED %10d\n", cur);
3036
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &cur, &hiwtr, 0);
3037
fprintf(stderr, "-- MEMORY_USED %10d %10d\n", cur, hiwtr);
3038
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &cur, &hiwtr, 0);
3039
fprintf(stderr, "-- MALLOC_SIZE %10d\n", hiwtr);
3040
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &cur, &hiwtr, 0);
3041
fprintf(stderr, "-- MALLOC_COUNT %10d %10d\n", cur, hiwtr);
3042
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &cur, &hiwtr, 0);
3043
fprintf(stderr, "-- PCACHE_OVFLOW %10d %10d\n", cur, hiwtr);
3044
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
3045
}
3046
while( db.pAllStmt ){
3047
db_finalize(db.pAllStmt);
3048
}
3049
if( db.nBegin ){
3050
if( reportErrors ){
3051
fossil_warning("Transaction started at %s:%d never commits",
3052
db.zStartFile, db.iStartLine);
3053
}
3054
db_end_transaction(1);
3055
}
3056
pStmt = 0;
3057
sqlite3_busy_timeout(g.db, 0);
3058
g.dbIgnoreErrors++; /* Stop "database locked" warnings */
3059
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
3060
g.dbIgnoreErrors--;
3061
db_close_config();
3062
3063
/* If the localdb has a lot of unused free space,
3064
** then VACUUM it as we shut down.
3065
*/
3066
if( db_database_slot("localdb")>=0 ){
3067
int nFree = db_int(0, "PRAGMA localdb.freelist_count");
3068
int nTotal = db_int(0, "PRAGMA localdb.page_count");
3069
if( nFree>nTotal/4 ){
3070
db_unprotect(PROTECT_ALL);
3071
db_multi_exec("VACUUM localdb;");
3072
db_protect_pop();
3073
}
3074
}
3075
3076
if( g.db ){
3077
int rc;
3078
sqlite3_wal_checkpoint(g.db, 0);
3079
rc = sqlite3_close(g.db);
3080
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
3081
if( rc==SQLITE_BUSY && reportErrors ){
3082
while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){
3083
fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt));
3084
}
3085
}
3086
g.db = 0;
3087
}
3088
g.repositoryOpen = 0;
3089
g.localOpen = 0;
3090
db.bProtectTriggers = 0;
3091
assert( g.dbConfig==0 );
3092
assert( g.zConfigDbName==0 );
3093
backoffice_run_if_needed();
3094
}
3095
3096
/*
3097
** Close the database as quickly as possible without unnecessary processing.
3098
*/
3099
void db_panic_close(void){
3100
if( g.db ){
3101
int rc;
3102
sqlite3_wal_checkpoint(g.db, 0);
3103
rc = sqlite3_close(g.db);
3104
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
3105
db_clear_authorizer();
3106
}
3107
g.db = 0;
3108
g.repositoryOpen = 0;
3109
g.localOpen = 0;
3110
}
3111
3112
/*
3113
** Create a new empty repository database with the given name.
3114
**
3115
** Only the schema is initialized. The required VAR tables entries
3116
** are not set by this routine and must be set separately in order
3117
** to make the new file a valid database.
3118
*/
3119
void db_create_repository(const char *zFilename){
3120
db_init_database(
3121
zFilename,
3122
zRepositorySchema1,
3123
zRepositorySchemaDefaultReports,
3124
zRepositorySchema2,
3125
(char*)0
3126
);
3127
db_delete_on_failure(zFilename);
3128
}
3129
3130
/*
3131
** Create the default user accounts in the USER table.
3132
*/
3133
void db_create_default_users(int setupUserOnly, const char *zDefaultUser){
3134
const char *zUser = zDefaultUser;
3135
if( zUser==0 ){
3136
zUser = db_get("default-user", 0);
3137
}
3138
if( zUser==0 ){
3139
zUser = fossil_getenv("FOSSIL_USER");
3140
}
3141
if( zUser==0 ){
3142
zUser = fossil_getenv("USER");
3143
}
3144
if( zUser==0 ){
3145
zUser = fossil_getenv("LOGNAME");
3146
}
3147
if( zUser==0 ){
3148
zUser = fossil_getenv("USERNAME");
3149
}
3150
if( zUser==0 ){
3151
zUser = "root";
3152
}
3153
db_unprotect(PROTECT_USER);
3154
db_multi_exec(
3155
"INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser
3156
);
3157
db_multi_exec(
3158
"UPDATE user SET cap='s', pw=%Q"
3159
" WHERE login=%Q", fossil_random_password(10), zUser
3160
);
3161
if( !setupUserOnly ){
3162
db_multi_exec(
3163
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
3164
" VALUES('anonymous',hex(randomblob(8)),'hz','Anon');"
3165
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
3166
" VALUES('nobody','','gjorz','Nobody');"
3167
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
3168
" VALUES('developer','','ei','Dev');"
3169
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
3170
" VALUES('reader','','kptw','Reader');"
3171
);
3172
}
3173
db_protect_pop();
3174
}
3175
3176
/*
3177
** Return a pointer to a string that contains the RHS of an IN operator
3178
** that will select CONFIG table names that are in the list of control
3179
** settings.
3180
*/
3181
const char *db_setting_inop_rhs(){
3182
Blob x;
3183
int i;
3184
int nSetting;
3185
const Setting *aSetting = setting_info(&nSetting);
3186
const char *zSep = "";
3187
3188
blob_zero(&x);
3189
blob_append_sql(&x, "(");
3190
for(i=0; i<nSetting; i++){
3191
blob_append_sql(&x, "%s%Q", zSep/*safe-for-%s*/, aSetting[i].name);
3192
zSep = ",";
3193
}
3194
blob_append_sql(&x, ")");
3195
return blob_sql_text(&x);
3196
}
3197
3198
/*
3199
** Fill an empty repository database with the basic information for a
3200
** repository. This function is shared between 'create_repository_cmd'
3201
** ('new') and 'reconstruct_cmd' ('reconstruct'), both of which create
3202
** new repositories.
3203
**
3204
** The zTemplate parameter determines if the settings for the repository
3205
** should be copied from another repository. If zTemplate is 0 then the
3206
** settings will have their normal default values. If zTemplate is
3207
** non-zero, it is assumed that the caller of this function has already
3208
** attached a database using the label "settingSrc". If not, the call to
3209
** this function will fail.
3210
**
3211
** The zInitialDate parameter determines the date of the initial check-in
3212
** that is automatically created. If zInitialDate is 0 then no initial
3213
** check-in is created. The makeServerCodes flag determines whether or
3214
** not server and project codes are invented for this repository.
3215
*/
3216
void db_initial_setup(
3217
const char *zTemplate, /* Repository from which to copy settings. */
3218
const char *zInitialDate, /* Initial date of repository. (ex: "now") */
3219
const char *zDefaultUser /* Default user for the repository */
3220
){
3221
char *zDate;
3222
Blob hash;
3223
Blob manifest;
3224
3225
db_unprotect(PROTECT_ALL);
3226
db_set("content-schema", CONTENT_SCHEMA, 0);
3227
db_set("aux-schema", AUX_SCHEMA_MAX, 0);
3228
db_set("rebuilt", get_version(), 0);
3229
db_multi_exec(
3230
"INSERT INTO config(name,value,mtime)"
3231
" VALUES('server-code', lower(hex(randomblob(20))),now());"
3232
"INSERT INTO config(name,value,mtime)"
3233
" VALUES('project-code', lower(hex(randomblob(20))),now());"
3234
);
3235
db_create_default_users(0, zDefaultUser);
3236
if( zDefaultUser ) g.zLogin = zDefaultUser;
3237
user_select();
3238
3239
if( zTemplate ){
3240
/*
3241
** Copy all settings from the supplied template repository.
3242
*/
3243
db_multi_exec(
3244
"INSERT OR REPLACE INTO config"
3245
" SELECT name,value,mtime FROM settingSrc.config"
3246
" WHERE (name IN %s OR name IN %s OR name GLOB 'walias:/*')"
3247
" AND name NOT GLOB 'project-*'"
3248
" AND name NOT GLOB 'short-project-*';",
3249
configure_inop_rhs(CONFIGSET_ALL),
3250
db_setting_inop_rhs()
3251
);
3252
g.eHashPolicy = db_get_int("hash-policy", g.eHashPolicy);
3253
db_multi_exec(
3254
"REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;"
3255
);
3256
3257
/*
3258
** Copy the user permissions, contact information, last modified
3259
** time, and photo for all the "system" users from the supplied
3260
** template repository into the one being setup. The other columns
3261
** are not copied because they contain security information or other
3262
** data specific to the other repository. The list of columns copied
3263
** by this SQL statement may need to be revised in the future.
3264
*/
3265
db_multi_exec("UPDATE user SET"
3266
" cap = (SELECT u2.cap FROM settingSrc.user u2"
3267
" WHERE u2.login = user.login),"
3268
" info = (SELECT u2.info FROM settingSrc.user u2"
3269
" WHERE u2.login = user.login),"
3270
" mtime = (SELECT u2.mtime FROM settingSrc.user u2"
3271
" WHERE u2.login = user.login),"
3272
" photo = (SELECT u2.photo FROM settingSrc.user u2"
3273
" WHERE u2.login = user.login)"
3274
" WHERE user.login IN ('anonymous','nobody','developer','reader');"
3275
);
3276
}
3277
db_protect_pop();
3278
3279
if( zInitialDate ){
3280
int rid;
3281
blob_zero(&manifest);
3282
blob_appendf(&manifest, "C initial\\sempty\\scheck-in\n");
3283
zDate = date_in_standard_format(zInitialDate);
3284
blob_appendf(&manifest, "D %s\n", zDate);
3285
md5sum_init();
3286
/* The R-card is necessary here because without it
3287
* fossil versions earlier than versions 1.27 would
3288
* interpret this artifact as a "control". */
3289
blob_appendf(&manifest, "R %s\n", md5sum_finish(0));
3290
blob_appendf(&manifest, "T *branch * trunk\n");
3291
blob_appendf(&manifest, "T *sym-trunk *\n");
3292
blob_appendf(&manifest, "U %F\n", g.zLogin);
3293
md5sum_blob(&manifest, &hash);
3294
blob_appendf(&manifest, "Z %b\n", &hash);
3295
blob_reset(&hash);
3296
rid = content_put(&manifest);
3297
manifest_crosslink(rid, &manifest, MC_NONE);
3298
}
3299
}
3300
3301
/*
3302
** COMMAND: new#
3303
** COMMAND: init
3304
**
3305
** Usage: %fossil new ?OPTIONS? FILENAME
3306
** or: %fossil init ?OPTIONS? FILENAME
3307
**
3308
** Create a repository for a new project in the file named FILENAME.
3309
** This command is distinct from "clone". The "clone" command makes
3310
** a copy of an existing project. This command starts a new project.
3311
**
3312
** By default, your current login name is used to create the default
3313
** admin user. This can be overridden using the -A|--admin-user
3314
** parameter.
3315
**
3316
** By default, all settings will be initialized to their default values.
3317
** This can be overridden using the --template parameter to specify a
3318
** repository file from which to copy the initial settings. When a template
3319
** repository is used, almost all of the settings accessible from the setup
3320
** page, either directly or indirectly, will be copied. Normal users and
3321
** their associated permissions will not be copied; however, the system
3322
** default users "anonymous", "nobody", "reader", "developer", and their
3323
** associated permissions will be copied. In case of SQL errors, rebuild the
3324
** template repository and try again.
3325
**
3326
** Options:
3327
** --template FILE Copy settings from repository file
3328
** -A|--admin-user USERNAME Select given USERNAME as admin user
3329
** --date-override DATETIME Use DATETIME as time of the initial check-in
3330
** --sha1 Use an initial hash policy of "sha1"
3331
** --project-name STRING The name of the project "project name in
3332
** quotes"
3333
** --project-desc STRING The description of the project "project
3334
** description in quotes"
3335
**
3336
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
3337
** year-month-day form, it may be truncated, the "T" may be replaced by
3338
** a space, and it may also name a timezone offset from UTC as "-HH:MM"
3339
** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
3340
** means UTC.
3341
**
3342
** See also: [[clone]]
3343
*/
3344
void create_repository_cmd(void){
3345
char *zPassword;
3346
const char *zTemplate; /* Repository from which to copy settings */
3347
const char *zDate; /* Date of the initial check-in */
3348
const char *zDefaultUser; /* Optional name of the default user */
3349
const char *zProjectName; /* Optional project name of the repo */
3350
const char *zProjectDesc; /* Optional project description "description
3351
** of project in quotes" */
3352
int bUseSha1 = 0; /* True to set the hash-policy to sha1 */
3353
3354
3355
zTemplate = find_option("template",0,1);
3356
zDate = find_option("date-override",0,1);
3357
zDefaultUser = find_option("admin-user","A",1);
3358
bUseSha1 = find_option("sha1",0,0)!=0;
3359
zProjectName = find_option("project-name", 0, 1);
3360
zProjectDesc = find_option("project-desc", 0, 1);
3361
/* We should be done with options.. */
3362
verify_all_options();
3363
3364
if( g.argc!=3 ){
3365
usage("REPOSITORY-NAME");
3366
}
3367
3368
if( -1 != file_size(g.argv[2], ExtFILE) ){
3369
fossil_fatal("file already exists: %s", g.argv[2]);
3370
}
3371
3372
db_create_repository(g.argv[2]);
3373
db_open_repository(g.argv[2]);
3374
db_open_config(0, 0);
3375
if( zTemplate ) db_attach(zTemplate, "settingSrc");
3376
db_begin_transaction();
3377
if( bUseSha1 ){
3378
g.eHashPolicy = HPOLICY_SHA1;
3379
db_set_int("hash-policy", HPOLICY_SHA1, 0);
3380
}
3381
if( zProjectName ) db_set("project-name", zProjectName, 0);
3382
if( zProjectDesc ) db_set("project-description", zProjectDesc, 0);
3383
if( zDate==0 ) zDate = "now";
3384
db_initial_setup(zTemplate, zDate, zDefaultUser);
3385
db_end_transaction(0);
3386
if( zTemplate ) db_detach("settingSrc");
3387
if( zProjectName ) fossil_print("project-name: %s\n", zProjectName);
3388
if( zProjectDesc ) fossil_print("project-description: %s\n", zProjectDesc);
3389
fossil_print("project-id: %s\n", db_get("project-code", 0));
3390
fossil_print("server-id: %s\n", db_get("server-code", 0));
3391
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
3392
fossil_print("admin-user: %s (initial remote-access password is \"%s\")\n",
3393
g.zLogin, zPassword);
3394
hash_user_password(g.zLogin);
3395
}
3396
3397
/*
3398
** SQL functions for debugging.
3399
**
3400
** The print() function writes its arguments on stdout, but only
3401
** if the -sqlprint command-line option is turned on.
3402
*/
3403
void db_sql_print(
3404
sqlite3_context *context,
3405
int argc,
3406
sqlite3_value **argv
3407
){
3408
int i;
3409
if( g.fSqlPrint ){
3410
for(i=0; i<argc; i++){
3411
char c = i==argc-1 ? '\n' : ' ';
3412
fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
3413
}
3414
}
3415
}
3416
3417
/*
3418
** Callback for sqlite3_trace_v2();
3419
*/
3420
int db_sql_trace(unsigned m, void *notUsed, void *pP, void *pX){
3421
sqlite3_stmt *pStmt = (sqlite3_stmt*)pP;
3422
char *zSql;
3423
int n;
3424
const char *zArg = (const char*)pX;
3425
char zEnd[100];
3426
if( m & SQLITE_TRACE_CLOSE ){
3427
/* If we are tracking closes, that means we want to clean up static
3428
** prepared statements. */
3429
while( db.pAllStmt ){
3430
db_finalize(db.pAllStmt);
3431
}
3432
return 0;
3433
}
3434
if( zArg[0]=='-' ) return 0;
3435
if( m & SQLITE_TRACE_PROFILE ){
3436
sqlite3_int64 nNano = *(sqlite3_int64*)pX;
3437
double rMillisec = 0.000001 * nNano;
3438
int nRun = sqlite3_stmt_status(pStmt, SQLITE_STMTSTATUS_RUN, 0);
3439
int nVmStep = sqlite3_stmt_status(pStmt, SQLITE_STMTSTATUS_VM_STEP, 1);
3440
sqlite3_snprintf(sizeof(zEnd),zEnd," /* %.3fms, %r run, %d vm-steps */\n",
3441
rMillisec, nRun, nVmStep);
3442
}else{
3443
zEnd[0] = '\n';
3444
zEnd[1] = 0;
3445
}
3446
zSql = sqlite3_expanded_sql(pStmt);
3447
n = (int)strlen(zSql);
3448
fossil_trace("%s%s%s", zSql, (n>0 && zSql[n-1]==';') ? "" : ";", zEnd);
3449
sqlite3_free(zSql);
3450
return 0;
3451
}
3452
3453
/*
3454
** Implement the user() SQL function. user() takes no arguments and
3455
** returns the user ID of the current user.
3456
*/
3457
LOCAL void db_sql_user(
3458
sqlite3_context *context,
3459
int argc,
3460
sqlite3_value **argv
3461
){
3462
if( g.zLogin!=0 ){
3463
sqlite3_result_text(context, g.zLogin, -1, SQLITE_STATIC);
3464
}
3465
}
3466
3467
/*
3468
** Implement the cgi() SQL function. cgi() takes an argument which is
3469
** a name of CGI query parameter. The value of that parameter is returned,
3470
** if available. Optional second argument will be returned if the first
3471
** doesn't exist as a CGI parameter.
3472
*/
3473
LOCAL void db_sql_cgi(sqlite3_context *context, int argc, sqlite3_value **argv){
3474
const char* zP;
3475
if( argc!=1 && argc!=2 ) return;
3476
zP = P((const char*)sqlite3_value_text(argv[0]));
3477
if( zP ){
3478
sqlite3_result_text(context, zP, -1, SQLITE_STATIC);
3479
}else if( argc==2 ){
3480
zP = (const char*)sqlite3_value_text(argv[1]);
3481
if( zP ) sqlite3_result_text(context, zP, -1, SQLITE_TRANSIENT);
3482
}
3483
}
3484
3485
/*
3486
** SQL function:
3487
**
3488
** is_selected(id)
3489
** if_selected(id, X, Y)
3490
**
3491
** On the commit command, when filenames are specified (in order to do
3492
** a partial commit) the vfile.id values for the named files are loaded
3493
** into the g.aCommitFile[] array. This function looks at that array
3494
** to see if a file is named on the command-line.
3495
**
3496
** In the first form (1 argument) return TRUE if either no files are
3497
** named on the command line (g.aCommitFile is NULL meaning that all
3498
** changes are to be committed) or if id is found in g.aCommitFile[]
3499
** (meaning that id was named on the command-line).
3500
**
3501
** In the second form (3 arguments) return argument X if true and Y
3502
** if false. Except if Y is NULL then always return X.
3503
*/
3504
LOCAL void file_is_selected(
3505
sqlite3_context *context,
3506
int argc,
3507
sqlite3_value **argv
3508
){
3509
int rc = 0;
3510
3511
assert(argc==1 || argc==3);
3512
if( g.aCommitFile ){
3513
int iId = sqlite3_value_int(argv[0]);
3514
int ii;
3515
for(ii=0; g.aCommitFile[ii]; ii++){
3516
if( iId==g.aCommitFile[ii] ){
3517
rc = 1;
3518
break;
3519
}
3520
}
3521
}else{
3522
rc = 1;
3523
}
3524
if( argc==1 ){
3525
sqlite3_result_int(context, rc);
3526
}else{
3527
assert( argc==3 );
3528
assert( rc==0 || rc==1 );
3529
if( sqlite3_value_type(argv[2-rc])==SQLITE_NULL ) rc = 1-rc;
3530
sqlite3_result_value(context, argv[2-rc]);
3531
}
3532
}
3533
3534
/*
3535
** Implementation of the "win_reserved(X)" SQL function, a wrapper
3536
** for file_is_win_reserved(X) which returns true if X is
3537
** a Windows-reserved filename.
3538
*/
3539
LOCAL void db_win_reserved_func(
3540
sqlite3_context *context,
3541
int argc,
3542
sqlite3_value **argv
3543
){
3544
const char * zName = (const char *)sqlite3_value_text(argv[0]);
3545
if( zName!=0 ){
3546
sqlite3_result_int(context, file_is_win_reserved(zName)!=0);
3547
}
3548
}
3549
3550
/*
3551
** Convert the input string into an artifact hash. Make a notation in the
3552
** CONCEALED table so that the hash can be undo using the db_reveal()
3553
** function at some later time.
3554
**
3555
** The value returned is stored in static space and will be overwritten
3556
** on subsequent calls.
3557
**
3558
** If zContent is already a well-formed artifact hash, then return a copy
3559
** of that hash, not a hash of the hash.
3560
**
3561
** The CONCEALED table is meant to obscure email addresses. Every valid
3562
** email address will contain a "@" character and "@" is not valid within
3563
** a SHA1 hash so there is no chance that a valid email address will go
3564
** unconcealed.
3565
*/
3566
char *db_conceal(const char *zContent, int n){
3567
static char zHash[HNAME_MAX+1];
3568
Blob out;
3569
if( hname_validate(zContent, n) ){
3570
memcpy(zHash, zContent, n);
3571
zHash[n] = 0;
3572
}else{
3573
sha1sum_step_text(zContent, n);
3574
sha1sum_finish(&out);
3575
sqlite3_snprintf(sizeof(zHash), zHash, "%s", blob_str(&out));
3576
blob_reset(&out);
3577
db_multi_exec(
3578
"INSERT OR IGNORE INTO concealed(hash,content,mtime)"
3579
" VALUES(%Q,%#Q,now())",
3580
zHash, n, zContent
3581
);
3582
}
3583
return zHash;
3584
}
3585
3586
/*
3587
** Attempt to look up the input in the CONCEALED table. If found,
3588
** and if the okRdAddr permission is enabled then return the
3589
** original value for which the input is a hash. If g.perm.RdAddr is
3590
** false or if the lookup fails, return the original string content.
3591
**
3592
** In either case, the string returned is stored in space obtained
3593
** from malloc and should be freed by the calling function.
3594
*/
3595
char *db_reveal(const char *zKey){
3596
char *zOut;
3597
if( g.perm.RdAddr ){
3598
zOut = db_text(0, "SELECT content FROM concealed WHERE hash=%Q", zKey);
3599
}else{
3600
zOut = 0;
3601
}
3602
if( zOut==0 ){
3603
zOut = fossil_strdup_nn(zKey);
3604
}
3605
return zOut;
3606
}
3607
3608
/*
3609
** Return true if the string zVal represents "true" (or "false").
3610
*/
3611
int is_truth(const char *zVal){
3612
static const char *const azOn[] = { "on", "yes", "true" };
3613
int i;
3614
for(i=0; i<count(azOn); i++){
3615
if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
3616
}
3617
return atoi(zVal);
3618
}
3619
int is_false(const char *zVal){
3620
static const char *const azOff[] = { "off", "no", "false", "0" };
3621
int i;
3622
for(i=0; i<count(azOff); i++){
3623
if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
3624
}
3625
return 0;
3626
}
3627
3628
/*
3629
** Swap the g.db and g.dbConfig connections so that the various db_* routines
3630
** work on the configuration database instead of on the repository database.
3631
** Be sure to swap them back after doing the operation.
3632
**
3633
** If the configuration database has already been opened as the main database
3634
** or is attached to the main database, no connection swaps are required so
3635
** this routine is a no-op.
3636
*/
3637
void db_swap_connections(void){
3638
/*
3639
** When swapping the main database connection with the config database
3640
** connection, the config database connection must be open (not simply
3641
** attached); otherwise, the swap would end up leaving the main database
3642
** connection invalid, defeating the very purpose of this routine. This
3643
** same constraint also holds true when restoring the previously swapped
3644
** database connection; otherwise, it means that no swap was performed
3645
** because the main database connection was already pointing to the config
3646
** database.
3647
*/
3648
if( g.dbConfig ){
3649
sqlite3 *dbTemp = g.db;
3650
g.db = g.dbConfig;
3651
g.dbConfig = dbTemp;
3652
}
3653
}
3654
3655
/*
3656
** Try to read a versioned setting string from .fossil-settings/<name>.
3657
**
3658
** Return the text of the string if it is found. Return NULL if not
3659
** found.
3660
**
3661
** If the zNonVersionedSetting parameter is not NULL then it holds the
3662
** non-versioned value for this setting. If both a versioned and a
3663
** non-versioned value exist and are not equal, then a warning message
3664
** might be generated.
3665
**
3666
** zCkin is normally NULL. In that case, the versioned setting is
3667
** take from the local check-out, if a local checkout exists, or from
3668
** check-in named by the g.zOpenRevision global variable. If zCkin is
3669
** not NULL, then zCkin is the name of the specific check-in from which
3670
** versioned setting value is taken. When zCkin is not NULL, the cache
3671
** is bypassed.
3672
*/
3673
char *db_get_versioned(
3674
const char *zName,
3675
char *zNonVersionedSetting,
3676
const char *zCkin
3677
){
3678
char *zVersionedSetting = 0;
3679
int noWarn = 0;
3680
int found = 0;
3681
struct _cacheEntry {
3682
struct _cacheEntry *next;
3683
const char *zName, *zValue;
3684
} *cacheEntry = 0;
3685
static struct _cacheEntry *cache = 0;
3686
3687
if( !g.localOpen && g.zOpenRevision==0 && zCkin==0 ){
3688
return zNonVersionedSetting;
3689
}
3690
3691
/* Look up name in cache */
3692
if( zCkin==0 ){
3693
cacheEntry = cache;
3694
while( cacheEntry!=0 ){
3695
if( fossil_strcmp(cacheEntry->zName, zName)==0 ){
3696
zVersionedSetting = fossil_strdup(cacheEntry->zValue);
3697
break;
3698
}
3699
cacheEntry = cacheEntry->next;
3700
}
3701
}
3702
3703
/* Attempt to read value from file in check-out if there wasn't a cache hit.*/
3704
if( cacheEntry==0 ){
3705
Blob versionedPathname;
3706
Blob setting;
3707
blob_init(&versionedPathname, 0, 0);
3708
blob_init(&setting, 0, 0);
3709
if( !g.localOpen || zCkin!=0 ){
3710
/* Repository is in the process of being opened, but files have not been
3711
* written to disk. Load from the database. */
3712
blob_appendf(&versionedPathname, ".fossil-settings/%s", zName);
3713
if( historical_blob(zCkin ? zCkin : g.zOpenRevision,
3714
blob_str(&versionedPathname),
3715
&setting, 0)
3716
){
3717
found = 1;
3718
}
3719
}else{
3720
blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
3721
g.zLocalRoot, zName);
3722
if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3723
/* File exists, and contains the value for this setting. Load from
3724
** the file. */
3725
const char *zFile = blob_str(&versionedPathname);
3726
if( blob_read_from_file(&setting, zFile, ExtFILE)>=0 ){
3727
found = 1;
3728
}
3729
/* See if there's a no-warn flag */
3730
blob_append(&versionedPathname, ".no-warn", -1);
3731
if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3732
noWarn = 1;
3733
}
3734
}
3735
}
3736
blob_reset(&versionedPathname);
3737
if( found ){
3738
blob_strip_comment_lines(&setting, &setting);
3739
blob_trim(&setting); /* Avoid non-obvious problems with line endings
3740
** on boolean properties */
3741
zVersionedSetting = fossil_strdup(blob_str(&setting));
3742
}
3743
blob_reset(&setting);
3744
3745
/* Store result in cache, which can be the value or 0 if not found */
3746
if( zCkin==0 ){
3747
cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(*cacheEntry));
3748
cacheEntry->next = cache;
3749
cacheEntry->zName = zName;
3750
cacheEntry->zValue = fossil_strdup(zVersionedSetting);
3751
cache = cacheEntry;
3752
}
3753
}
3754
3755
/* Display a warning? */
3756
if( zVersionedSetting!=0
3757
&& zNonVersionedSetting!=0
3758
&& zNonVersionedSetting[0]!='\0'
3759
&& zCkin==0
3760
&& !noWarn
3761
){
3762
/* There's a versioned setting, and a non-versioned setting. Tell
3763
** the user about the conflict */
3764
fossil_warning(
3765
"setting %s has both versioned and non-versioned values: using "
3766
"versioned value from file \"%/.fossil-settings/%s\" (to silence "
3767
"this warning, either create an empty file named "
3768
"\"%/.fossil-settings/%s.no-warn\" in the check-out root, or delete "
3769
"the non-versioned setting with \"fossil unset %s\")", zName,
3770
g.zLocalRoot, zName, g.zLocalRoot, zName, zName
3771
);
3772
}
3773
3774
/* Prefer the versioned setting */
3775
return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting;
3776
}
3777
3778
3779
/*
3780
** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
3781
** repository and local databases.
3782
**
3783
** If no such variable exists, return zDefault. Or, if zName is the name
3784
** of a setting, then the zDefault is ignored and the default value of the
3785
** setting is returned instead. If zName is a versioned setting, then
3786
** versioned value takes priority.
3787
*/
3788
char *db_get(const char *zName, const char *zDefault){
3789
char *z = 0;
3790
const Setting *pSetting = db_find_setting(zName, 0);
3791
if( g.repositoryOpen ){
3792
static Stmt q1;
3793
const char *zRes;
3794
db_static_prepare(&q1, "SELECT value FROM config WHERE name=$n");
3795
db_bind_text(&q1, "$n", zName);
3796
if( db_step(&q1)==SQLITE_ROW && (zRes = db_column_text(&q1,0))!=0 ){
3797
z = fossil_strdup(zRes);
3798
}
3799
db_reset(&q1);
3800
}
3801
if( z==0 && g.zConfigDbName ){
3802
static Stmt q2;
3803
const char *zRes;
3804
db_swap_connections();
3805
db_static_prepare(&q2, "SELECT value FROM global_config WHERE name=$n");
3806
db_swap_connections();
3807
db_bind_text(&q2, "$n", zName);
3808
if( db_step(&q2)==SQLITE_ROW && (zRes = db_column_text(&q2,0))!=0 ){
3809
z = fossil_strdup(zRes);
3810
}
3811
db_reset(&q2);
3812
}
3813
if( pSetting!=0 && pSetting->versionable ){
3814
/* This is a versionable setting, try and get the info from a
3815
** checked-out file */
3816
char * zZ = z;
3817
z = db_get_versioned(zName, z, 0);
3818
if(zZ != z){
3819
fossil_free(zZ);
3820
}
3821
}
3822
if( z==0 ){
3823
if( zDefault==0 && pSetting && pSetting->def[0] ){
3824
z = fossil_strdup(pSetting->def);
3825
}else{
3826
z = fossil_strdup(zDefault);
3827
}
3828
}
3829
return z;
3830
}
3831
char *db_get_mtime(const char *zName, const char *zFormat,
3832
const char *zDefault){
3833
char *z = 0;
3834
if( g.repositoryOpen ){
3835
z = db_text(0, "SELECT mtime FROM config WHERE name=%Q", zName);
3836
}
3837
if( z==0 ){
3838
z = fossil_strdup(zDefault);
3839
}else if( zFormat!=0 ){
3840
z = db_text(0, "SELECT strftime(%Q,%Q,'unixepoch');", zFormat, z);
3841
}
3842
return z;
3843
}
3844
void db_set(const char *zName, const char *zValue, int globalFlag){
3845
const CmdOrPage *pCmd = 0;
3846
db_assert_protection_off_or_not_sensitive(zName);
3847
if( zValue!=0 && zValue[0]==0
3848
&& dispatch_name_search(zName, CMDFLAG_SETTING, &pCmd)==0
3849
&& (pCmd->eCmdFlags & CMDFLAG_KEEPEMPTY)==0
3850
){
3851
/* Changing a setting to an empty string is the same as unsetting it,
3852
** unless that setting has the keep-empty flag. */
3853
db_unset(zName/*works-like:"x"*/, globalFlag);
3854
return;
3855
}
3856
db_unprotect(PROTECT_CONFIG);
3857
db_begin_transaction();
3858
if( globalFlag ){
3859
db_swap_connections();
3860
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
3861
zName, zValue);
3862
db_swap_connections();
3863
}else{
3864
db_multi_exec("REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
3865
zName, zValue);
3866
}
3867
if( globalFlag && g.repositoryOpen ){
3868
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3869
}
3870
db_end_transaction(0);
3871
db_protect_pop();
3872
}
3873
void db_unset(const char *zName, int globalFlag){
3874
db_begin_transaction();
3875
db_unprotect(PROTECT_CONFIG);
3876
if( globalFlag ){
3877
db_swap_connections();
3878
db_multi_exec("DELETE FROM global_config WHERE name=%Q", zName);
3879
db_swap_connections();
3880
}else{
3881
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3882
}
3883
if( globalFlag && g.repositoryOpen ){
3884
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3885
}
3886
db_protect_pop();
3887
db_end_transaction(0);
3888
}
3889
int db_is_global(const char *zName){
3890
int rc = 0;
3891
if( g.zConfigDbName ){
3892
db_swap_connections();
3893
rc = db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName);
3894
db_swap_connections();
3895
}
3896
return rc;
3897
}
3898
int db_get_int(const char *zName, int dflt){
3899
int v = dflt;
3900
int rc;
3901
if( g.repositoryOpen ){
3902
static Stmt q;
3903
db_static_prepare(&q, "SELECT value FROM config WHERE name=$n");
3904
db_bind_text(&q, "$n", zName);
3905
rc = db_step(&q);
3906
if( rc==SQLITE_ROW ){
3907
v = db_column_int(&q, 0);
3908
}
3909
db_reset(&q);
3910
}else{
3911
rc = SQLITE_DONE;
3912
}
3913
if( rc==SQLITE_DONE && g.zConfigDbName ){
3914
static Stmt q2;
3915
db_swap_connections();
3916
db_static_prepare(&q2, "SELECT value FROM global_config WHERE name=$n");
3917
db_swap_connections();
3918
db_bind_text(&q2, "$n", zName);
3919
if( db_step(&q2)==SQLITE_ROW ){
3920
v = db_column_int(&q2, 0);
3921
}
3922
db_reset(&q2);
3923
}
3924
return v;
3925
}
3926
i64 db_large_file_size(void){
3927
/* Return size of the largest file that is not considered oversized */
3928
return strtoll(db_get("large-file-size","20000000"),0,0);
3929
}
3930
void db_set_int(const char *zName, int value, int globalFlag){
3931
db_assert_protection_off_or_not_sensitive(zName);
3932
db_unprotect(PROTECT_CONFIG);
3933
if( globalFlag ){
3934
db_swap_connections();
3935
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
3936
zName, value);
3937
db_swap_connections();
3938
}else{
3939
db_multi_exec("REPLACE INTO config(name,value,mtime) VALUES(%Q,%d,now())",
3940
zName, value);
3941
}
3942
if( globalFlag && g.repositoryOpen ){
3943
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3944
}
3945
db_protect_pop();
3946
}
3947
int db_get_boolean(const char *zName, int dflt){
3948
char *zVal = db_get(zName, dflt ? "on" : "off");
3949
if( is_truth(zVal) ){
3950
dflt = 1;
3951
}else if( is_false(zVal) ){
3952
dflt = 0;
3953
}
3954
fossil_free(zVal);
3955
return dflt;
3956
}
3957
int db_get_versioned_boolean(const char *zName, int dflt){
3958
char *zVal = db_get_versioned(zName, 0, 0);
3959
if( zVal==0 ) return dflt;
3960
if( is_truth(zVal) ) return 1;
3961
if( is_false(zVal) ) return 0;
3962
return dflt;
3963
}
3964
char *db_lget(const char *zName, const char *zDefault){
3965
return db_text(zDefault,
3966
"SELECT value FROM vvar WHERE name=%Q", zName);
3967
}
3968
void db_lset(const char *zName, const char *zValue){
3969
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%Q)", zName, zValue);
3970
}
3971
int db_lget_int(const char *zName, int dflt){
3972
return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
3973
}
3974
int db_lget_boolean(const char *zName, int dflt){
3975
char *zVal = db_lget(zName, dflt ? "on" : "off");
3976
if( is_truth(zVal) ){
3977
dflt = 1;
3978
}else if( is_false(zVal) ){
3979
dflt = 0;
3980
}
3981
fossil_free(zVal);
3982
return dflt;
3983
}
3984
void db_lset_int(const char *zName, int value){
3985
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
3986
}
3987
3988
/* Va-args versions of db_get(), db_set(), and db_unset()
3989
**
3990
** codecheck1.c verifies that the format string for db_set_mprintf()
3991
** and db_unset_mprintf() begins with an ASCII character prefix. We
3992
** don't want that format string to begin with %s or %d as that might
3993
** allow an injection attack to set or overwrite arbitrary settings.
3994
*/
3995
char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){
3996
va_list ap;
3997
char *zName;
3998
char *zResult;
3999
va_start(ap, zFormat);
4000
zName = vmprintf(zFormat, ap);
4001
va_end(ap);
4002
zResult = db_get(zName, zDefault);
4003
fossil_free(zName);
4004
return zResult;
4005
}
4006
void db_set_mprintf(const char *zNew, int iGlobal, const char *zFormat, ...){
4007
va_list ap;
4008
char *zName;
4009
va_start(ap, zFormat);
4010
zName = vmprintf(zFormat, ap);
4011
va_end(ap);
4012
db_set(zName/*works-like:"x"*/, zNew, iGlobal);
4013
fossil_free(zName);
4014
}
4015
void db_unset_mprintf(int iGlobal, const char *zFormat, ...){
4016
va_list ap;
4017
char *zName;
4018
va_start(ap, zFormat);
4019
zName = vmprintf(zFormat, ap);
4020
va_end(ap);
4021
db_unset(zName/*works-like:"x"*/, iGlobal);
4022
fossil_free(zName);
4023
}
4024
4025
/*
4026
** Get a setting that is tailored to subsystem. The return value is
4027
** NULL if the setting does not exist, or a string obtained from mprintf()
4028
** if the setting is available.
4029
**
4030
** The actual setting can be a comma-separated list of values of the form:
4031
**
4032
** * VALUE
4033
** * SUBSYSTEM=VALUE
4034
**
4035
** A VALUE without the SUBSYSTEM= prefix is the default. This routine
4036
** returns the VALUE that with the matching SUBSYSTEM, or the default
4037
** VALUE if there is no match.
4038
*/
4039
char *db_get_for_subsystem(const char *zName, const char *zSubsys){
4040
int nSubsys;
4041
char *zToFree = 0;
4042
char *zCopy;
4043
char *zNext;
4044
char *zResult = 0;
4045
const char *zSetting = db_get(zName, 0);
4046
if( zSetting==0 ) return 0;
4047
zCopy = zToFree = fossil_strdup(zSetting);
4048
if( zSubsys==0 ) zSubsys = "";
4049
nSubsys = (int)strlen(zSubsys);
4050
while( zCopy ){
4051
zNext = strchr(zCopy, ',');
4052
if( zNext ){
4053
zNext[0] = 0;
4054
do{ zNext++; }while( fossil_isspace(zNext[0]) );
4055
if( zNext[0]==0 ) zNext = 0;
4056
}
4057
if( strchr(zCopy,'=')==0 ){
4058
if( zResult==0 ) zResult = zCopy;
4059
}else
4060
if( nSubsys
4061
&& strncmp(zCopy, zSubsys, nSubsys)==0
4062
&& zCopy[nSubsys]=='='
4063
){
4064
zResult = &zCopy[nSubsys+1];
4065
break;
4066
}
4067
zCopy = zNext;
4068
}
4069
if( zResult ) zResult = fossil_strdup(zResult);
4070
fossil_free(zToFree);
4071
return zResult;
4072
}
4073
4074
#if INTERFACE
4075
/* Manifest generation flags */
4076
#define MFESTFLG_RAW 0x01
4077
#define MFESTFLG_UUID 0x02
4078
#define MFESTFLG_TAGS 0x04
4079
#endif /* INTERFACE */
4080
4081
/*
4082
** Get the manifest setting. For backwards compatibility first check if the
4083
** value is a boolean. If it's not a boolean, treat each character as a flag
4084
** to enable a manifest type. This system puts certain boundary conditions on
4085
** which letters can be used to represent flags (any permutation of flags must
4086
** not be able to fully form one of the boolean values).
4087
**
4088
** "manifest" is a versionable setting. But we do not issue a warning
4089
** if there is a conflict. Instead, the value returned is the value for
4090
** the versioned setting if the versioned setting exists, or the ordinary
4091
** setting otherwise.
4092
**
4093
** The argument zCkin is the specific check-in for which we want the
4094
** manifest setting.
4095
*/
4096
int db_get_manifest_setting(const char *zCkin){
4097
int flg;
4098
char *zVal;
4099
4100
/* Look for the versioned setting first */
4101
zVal = db_get_versioned("manifest", 0, zCkin);
4102
4103
if( zVal==0 && g.repositoryOpen ){
4104
/* No versioned setting, look for the repository setting second */
4105
zVal = db_text(0, "SELECT value FROM config WHERE name='manifest'");
4106
}
4107
if( zVal==0 || is_false(zVal) ){
4108
return 0;
4109
}else if( is_truth(zVal) ){
4110
return MFESTFLG_RAW|MFESTFLG_UUID;
4111
}
4112
flg = 0;
4113
while( *zVal ){
4114
switch( *zVal ){
4115
case 'r': flg |= MFESTFLG_RAW; break;
4116
case 'u': flg |= MFESTFLG_UUID; break;
4117
case 't': flg |= MFESTFLG_TAGS; break;
4118
}
4119
zVal++;
4120
}
4121
return flg;
4122
}
4123
4124
/*
4125
** COMMAND: test-manifest-setting
4126
**
4127
** Usage: %fossil test-manifest-setting VERSION VERSION ...
4128
**
4129
** Display the value for the "manifest" setting for various versions
4130
** of the repository.
4131
*/
4132
void test_manfest_setting_cmd(void){
4133
int i;
4134
db_find_and_open_repository(0, 0);
4135
for(i=2; i<g.argc; i++){
4136
int m = db_get_manifest_setting(g.argv[i]);
4137
fossil_print("%s:\n", g.argv[i]);
4138
fossil_print(" flags = 0x%02x\n", m);
4139
if( m & MFESTFLG_RAW ){
4140
fossil_print(" manifest\n");
4141
}
4142
if( m & MFESTFLG_UUID ){
4143
fossil_print(" manifest.uuid\n");
4144
}
4145
if( m & MFESTFLG_TAGS ){
4146
fossil_print(" manifest.tags\n");
4147
}
4148
}
4149
}
4150
4151
4152
/*
4153
** Record the name of a local repository in the global_config() database.
4154
** The repository filename %s is recorded as an entry with a "name" field
4155
** of the following form:
4156
**
4157
** repo:%s
4158
**
4159
** The value field is set to 1.
4160
**
4161
** If running from a local check-out, also record the root of the check-out
4162
** as follows:
4163
**
4164
** ckout:%s
4165
**
4166
** Where %s is the check-out root. The value is the repository file.
4167
*/
4168
void db_record_repository_filename(const char *zName){
4169
char *zRepoSetting;
4170
char *zCkoutSetting;
4171
Blob full;
4172
if( zName==0 ){
4173
if( !g.localOpen ) return;
4174
zName = db_repository_filename();
4175
}
4176
file_canonical_name(zName, &full, 0);
4177
(void)filename_collation(); /* Initialize before connection swap */
4178
db_swap_connections();
4179
zRepoSetting = mprintf("repo:%q", blob_str(&full));
4180
4181
db_unprotect(PROTECT_CONFIG);
4182
db_multi_exec(
4183
"DELETE FROM global_config WHERE name %s = %Q;",
4184
filename_collation(), zRepoSetting
4185
);
4186
db_multi_exec(
4187
"INSERT OR IGNORE INTO global_config(name,value)"
4188
"VALUES(%Q,1);",
4189
zRepoSetting
4190
);
4191
db_protect_pop();
4192
fossil_free(zRepoSetting);
4193
if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
4194
Blob localRoot;
4195
file_canonical_name(g.zLocalRoot, &localRoot, 1);
4196
zCkoutSetting = mprintf("ckout:%q", blob_str(&localRoot));
4197
db_unprotect(PROTECT_CONFIG);
4198
db_multi_exec(
4199
"DELETE FROM global_config WHERE name %s = %Q;",
4200
filename_collation(), zCkoutSetting
4201
);
4202
db_multi_exec(
4203
"REPLACE INTO global_config(name, value)"
4204
"VALUES(%Q,%Q);",
4205
zCkoutSetting, blob_str(&full)
4206
);
4207
db_swap_connections();
4208
db_optional_sql("repository",
4209
"DELETE FROM config WHERE name %s = %Q;",
4210
filename_collation(), zCkoutSetting
4211
);
4212
db_optional_sql("repository",
4213
"REPLACE INTO config(name,value,mtime)"
4214
"VALUES(%Q,1,now());",
4215
zCkoutSetting
4216
);
4217
db_protect_pop();
4218
fossil_free(zCkoutSetting);
4219
blob_reset(&localRoot);
4220
}else{
4221
db_swap_connections();
4222
}
4223
blob_reset(&full);
4224
}
4225
4226
/*
4227
** COMMAND: open
4228
**
4229
** Usage: %fossil open REPOSITORY ?VERSION? ?OPTIONS?
4230
**
4231
** Open a new connection to the repository name REPOSITORY. A check-out
4232
** for the repository is created with its root at the current working
4233
** directory, or in DIR if the "--workdir DIR" is used. If VERSION is
4234
** specified then that version is checked out. Otherwise the most recent
4235
** check-in on the main branch (usually "trunk") is used.
4236
**
4237
** REPOSITORY can be the filename for a repository that already exists on the
4238
** local machine or it can be a URI for a remote repository. If REPOSITORY
4239
** is a URI in one of the formats recognized by the [[clone]] command, the
4240
** remote repo is first cloned, then the clone is opened. The clone will be
4241
** stored in the current directory, or in DIR if the "--repodir DIR" option
4242
** is used. The name of the clone will be taken from the last term of the URI.
4243
** For "http:" and "https:" URIs, you can append an extra term to the end of
4244
** the URI to get any repository name you like. For example:
4245
**
4246
** fossil open https://fossil-scm.org/home/new-name
4247
**
4248
** The base URI for cloning is "https://fossil-scm.org/home". The extra
4249
** "new-name" term means that the cloned repository will be called
4250
** "new-name.fossil".
4251
**
4252
** Options:
4253
** --empty Initialize check-out as being empty, but still connected
4254
** with the local repository. If you commit this check-out,
4255
** it will become a new "initial" commit in the repository.
4256
** -f|--force Continue with the open even if the working directory is
4257
** not empty, or if auto-sync fails.
4258
** --force-missing Force opening a repository with missing content
4259
** -k|--keep Only modify the manifest file(s)
4260
** --nested Allow opening a repository inside an opened check-out
4261
** --nosync Do not auto-sync the repository prior to opening even
4262
** if the autosync setting is on.
4263
** --proxy PROXY Use PROXY as http proxy during sync operation
4264
** --reopen REPO "Reopen" an existing checkout to use a different
4265
** repository file REPO. Useful to reconnect an existing
4266
** checkout to a repository after the original repository
4267
** file is moved. CAUTION: may lose stash and bisect
4268
** history.
4269
** --repodir DIR If REPOSITORY is a URI that will be cloned, store
4270
** the clone in DIR rather than in "."
4271
** --setmtime Set timestamps of all files to match their SCM-side
4272
** times (the timestamp of the last check-in which modified
4273
** them).
4274
** --verbose If passed a URI then this flag is passed on to the clone
4275
** operation, otherwise it has no effect
4276
** --workdir DIR Use DIR as the working directory instead of ".". The DIR
4277
** directory is created if it does not exist.
4278
**
4279
** See also: [[close]], [[clone]]
4280
*/
4281
void cmd_open(void){
4282
int emptyFlag;
4283
int keepFlag;
4284
int forceMissingFlag;
4285
int allowNested;
4286
int setmtimeFlag; /* --setmtime. Set mtimes on files */
4287
int bForce = 0; /* --force. Open even if non-empty dir */
4288
static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
4289
const char *zWorkDir; /* --workdir value */
4290
const char *zRepo = 0; /* Name of the repository file */
4291
const char *zRepoDir = 0; /* --repodir value */
4292
const char *zReopen = 0; /* --reopen REPOFILE */
4293
char *zPwd; /* Initial working directory */
4294
int isUri = 0; /* True if REPOSITORY is a URI */
4295
int nLocal; /* Number of preexisting files in cwd */
4296
int bVerbose = 0; /* --verbose option for clone */
4297
4298
zReopen = find_option("reopen",0,1);
4299
if( 0!=zReopen ){
4300
g.argc = 3;
4301
g.argv[2] = (char*)zReopen;
4302
move_repo_cmd();
4303
return;
4304
}
4305
4306
url_proxy_options();
4307
emptyFlag = find_option("empty",0,0)!=0;
4308
keepFlag = find_option("keep","k",0)!=0;
4309
forceMissingFlag = find_option("force-missing",0,0)!=0;
4310
allowNested = find_option("nested",0,0)!=0;
4311
setmtimeFlag = find_option("setmtime",0,0)!=0;
4312
zWorkDir = find_option("workdir",0,1);
4313
zRepoDir = find_option("repodir",0,1);
4314
bForce = find_option("force","f",0)!=0;
4315
if( find_option("nosync",0,0) ) g.fNoSync = 1;
4316
bVerbose = find_option("verbose",0,0)!=0;
4317
zPwd = file_getcwd(0,0);
4318
4319
/* We should be done with options.. */
4320
verify_all_options();
4321
4322
if( g.argc!=3 && g.argc!=4 ){
4323
usage("REPOSITORY-FILENAME ?VERSION?");
4324
}
4325
zRepo = g.argv[2];
4326
if( sqlite3_strglob("http://*", zRepo)==0
4327
|| sqlite3_strglob("https://*", zRepo)==0
4328
|| sqlite3_strglob("ssh:*", zRepo)==0
4329
|| sqlite3_strglob("file:*", zRepo)==0
4330
){
4331
isUri = 1;
4332
}
4333
4334
/* If --workdir is specified, change to the requested working directory */
4335
if( zWorkDir ){
4336
if( !isUri ){
4337
zRepo = file_canonical_name_dup(zRepo);
4338
}
4339
if( zRepoDir ){
4340
zRepoDir = file_canonical_name_dup(zRepoDir);
4341
}
4342
if( file_isdir(zWorkDir, ExtFILE)!=1 ){
4343
file_mkfolder(zWorkDir, ExtFILE, 0, 0);
4344
if( file_mkdir(zWorkDir, ExtFILE, 0) ){
4345
fossil_fatal("cannot create directory %s", zWorkDir);
4346
}
4347
}
4348
if( file_chdir(zWorkDir, 0) ){
4349
fossil_fatal("unable to make %s the working directory", zWorkDir);
4350
}
4351
}
4352
if( keepFlag==0
4353
&& bForce==0
4354
&& (nLocal = file_directory_list(".", 0, 1, 2, 0))>0
4355
&& (nLocal>1 || isUri || !file_in_cwd(zRepo))
4356
){
4357
fossil_fatal("directory %s is not empty\n"
4358
"use the -f (--force) option to override\n"
4359
"or the -k (--keep) option to keep local files unchanged",
4360
file_getcwd(0,0));
4361
}
4362
4363
if( db_open_local_v2(0, allowNested) ){
4364
fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
4365
}
4366
4367
/* If REPOSITORY looks like a URI, then try to clone it first */
4368
if( isUri ){
4369
char *zNewBase; /* Base name of the cloned repository file */
4370
const char *zUri; /* URI to clone */
4371
int rc; /* Result code from fossil_system() */
4372
Blob cmd; /* Clone command to be run */
4373
char *zCmd; /* String version of the clone command */
4374
4375
zUri = zRepo;
4376
zNewBase = url_to_repo_basename(zUri);
4377
if( zNewBase==0 ){
4378
fossil_fatal("unable to deduce a repository name from the url \"%s\"",
4379
zUri);
4380
}
4381
if( zRepoDir==0 ){
4382
zRepo = mprintf("%s.fossil", zNewBase);
4383
}else{
4384
zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
4385
}
4386
fossil_free(zNewBase);
4387
blob_init(&cmd, 0, 0);
4388
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
4389
blob_append(&cmd, " clone", -1);
4390
if(0!=bVerbose){
4391
blob_append(&cmd, " --verbose", -1);
4392
}
4393
blob_append_escaped_arg(&cmd, zUri, 1);
4394
blob_append_escaped_arg(&cmd, zRepo, 1);
4395
zCmd = blob_str(&cmd);
4396
fossil_print("%s\n", zCmd);
4397
if( zWorkDir ) file_chdir(zPwd, 0);
4398
rc = fossil_system(zCmd);
4399
if( rc ){
4400
fossil_fatal("clone of %s failed", zUri);
4401
}
4402
blob_reset(&cmd);
4403
if( zWorkDir ) file_chdir(zWorkDir, 0);
4404
}else if( zRepoDir ){
4405
fossil_fatal("the --repodir option only makes sense if the REPOSITORY "
4406
"argument is a URI that begins with http:, https:, ssh:, "
4407
"or file:");
4408
}
4409
4410
db_open_config(0,0);
4411
db_open_repository(zRepo);
4412
4413
/* Figure out which revision to open. */
4414
if( !emptyFlag ){
4415
if( g.argc==4 ){
4416
g.zOpenRevision = g.argv[3];
4417
}else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
4418
g.zOpenRevision = fossil_strdup(db_main_branch());
4419
}
4420
if( autosync_loop(SYNC_PULL, !bForce, "open") && !bForce ){
4421
fossil_fatal("unable to auto-sync the repository");
4422
}
4423
}
4424
4425
4426
#if defined(_WIN32) || defined(__CYGWIN__)
4427
# define LOCALDB_NAME "./_FOSSIL_"
4428
#else
4429
# define LOCALDB_NAME "./.fslckout"
4430
#endif
4431
db_init_database(LOCALDB_NAME, zLocalSchema, zLocalSchemaVmerge,
4432
#ifdef FOSSIL_LOCAL_WAL
4433
"COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
4434
#endif
4435
(char*)0);
4436
db_delete_on_failure(LOCALDB_NAME);
4437
db_open_local(0);
4438
db_lset("repository", zRepo);
4439
db_record_repository_filename(zRepo);
4440
db_set_checkout(0, 0); /* manifest files handled by checkout_cmd */
4441
azNewArgv[0] = g.argv[0];
4442
g.argv = azNewArgv;
4443
if( !emptyFlag ){
4444
g.argc = 3;
4445
if( g.zOpenRevision ){
4446
azNewArgv[g.argc-1] = g.zOpenRevision;
4447
}else{
4448
azNewArgv[g.argc-1] = "--latest";
4449
}
4450
if( keepFlag ){
4451
azNewArgv[g.argc++] = "--keep";
4452
}
4453
if( forceMissingFlag ){
4454
azNewArgv[g.argc++] = "--force-missing";
4455
}
4456
checkout_cmd();
4457
}
4458
if( setmtimeFlag ){
4459
int const vid = db_lget_int("checkout", 0);
4460
if(vid!=0){
4461
vfile_check_signature(vid, CKSIG_SETMTIME);
4462
}
4463
}
4464
g.argc = 2;
4465
info_cmd();
4466
}
4467
4468
/*
4469
** Return true if pSetting has its default value assuming its
4470
** current value is zVal.
4471
*/
4472
int setting_has_default_value(const Setting *pSetting, const char *zVal){
4473
if( zVal==0 ) return 1;
4474
if( pSetting->def==0 ) return 0;
4475
if( pSetting->width==0 ){
4476
return is_false(pSetting->def)==is_false(zVal);
4477
}
4478
if( fossil_strcmp(pSetting->def, zVal)==0 ) return 1;
4479
if( is_false(zVal) && is_false(pSetting->def) ) return 1;
4480
if( is_truth(zVal) && is_truth(pSetting->def) ) return 1;
4481
return 0;
4482
}
4483
4484
/*
4485
** Print the current value of a setting identified by the pSetting
4486
** pointer.
4487
**
4488
** Only show the value, not the setting name, if valueOnly is true.
4489
**
4490
** Show nothing if bIfChng is true and the setting is not currently set
4491
** or is set to its default value.
4492
*/
4493
void print_setting(const Setting *pSetting, int valueOnly, int bIfChng){
4494
Stmt q;
4495
int versioned = 0;
4496
if( pSetting->versionable && g.localOpen ){
4497
/* Check to see if this is overridden by a versionable settings file */
4498
Blob versionedPathname;
4499
blob_zero(&versionedPathname);
4500
blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
4501
g.zLocalRoot, pSetting->name);
4502
if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
4503
versioned = 1;
4504
}
4505
blob_reset(&versionedPathname);
4506
}
4507
if( valueOnly && versioned ){
4508
const char *zVal = db_get_versioned(pSetting->name, NULL, NULL);
4509
if( !bIfChng || (zVal!=0 && fossil_strcmp(zVal, pSetting->def)!=0) ){
4510
fossil_print("%s\n", db_get_versioned(pSetting->name, NULL, NULL));
4511
}else{
4512
versioned = 0;
4513
}
4514
return;
4515
}
4516
if( g.repositoryOpen ){
4517
db_prepare(&q,
4518
"SELECT '(local)', value FROM config WHERE name=%Q"
4519
" UNION ALL "
4520
"SELECT '(global)', value FROM global_config WHERE name=%Q",
4521
pSetting->name, pSetting->name
4522
);
4523
}else{
4524
db_prepare(&q,
4525
"SELECT '(global)', value FROM global_config WHERE name=%Q",
4526
pSetting->name
4527
);
4528
}
4529
if( db_step(&q)==SQLITE_ROW ){
4530
const char *zVal = db_column_text(&q,1);
4531
if( bIfChng && setting_has_default_value(pSetting,zVal) ){
4532
if( versioned ){
4533
fossil_print("%-24s (versioned)\n", pSetting->name);
4534
versioned = 0;
4535
}
4536
}else if( valueOnly ){
4537
fossil_print("%s\n", db_column_text(&q, 1));
4538
}else{
4539
const char *zVal = (const char*)db_column_text(&q,1);
4540
const char *zName = (const char*)db_column_text(&q,0);
4541
if( zVal==0 ) zVal = "NULL";
4542
if( strchr(zVal,'\n')==0 ){
4543
fossil_print("%-24s %-11s %s\n", pSetting->name, zName, zVal);
4544
}else{
4545
fossil_print("%-24s %-11s\n", pSetting->name, zName);
4546
while( zVal[0] ){
4547
const char *zNL = strchr(zVal, '\n');
4548
if( zNL==0 ){
4549
fossil_print(" %s\n", zVal);
4550
break;
4551
}else{
4552
int n = (int)(zNL - zVal);
4553
while( n>0 && fossil_isspace(zVal[n-1]) ){ n--; }
4554
fossil_print(" %.*s\n", n, zVal);
4555
zVal = zNL+1;
4556
}
4557
}
4558
}
4559
}
4560
}else if( bIfChng ){
4561
/* Display nothing */
4562
versioned = 0;
4563
}else if( valueOnly ){
4564
fossil_print("\n");
4565
}else{
4566
fossil_print("%-24s\n", pSetting->name);
4567
}
4568
if( versioned ){
4569
fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
4570
pSetting->name);
4571
}
4572
db_finalize(&q);
4573
}
4574
4575
#if INTERFACE
4576
/*
4577
** Define all settings, which can be controlled via the set/unset
4578
** command.
4579
**
4580
** var is the name of the internal configuration name for db_(un)set.
4581
** If var is 0, the settings name is used.
4582
**
4583
** width is the length for the edit field on the behavior page, 0 is
4584
** used for on/off checkboxes. A negative value indicates that the
4585
** page should not render this setting. Such values may be rendered
4586
** separately/manually on another page, e.g., /setup_access, and are
4587
** exposed via the CLI settings command.
4588
**
4589
** The behaviour page doesn't use a special layout. It lists all
4590
** set-commands and displays the 'set'-help as info.
4591
*/
4592
struct Setting {
4593
const char *name; /* Name of the setting */
4594
const char *var; /* Internal variable name used by db_set() */
4595
int width; /* Width of display. 0 for boolean values and
4596
** negative for values which should not appear
4597
** on the /setup_settings page. */
4598
char versionable; /* Is this setting versionable? */
4599
char forceTextArea; /* Force using a text area for display? */
4600
char sensitive; /* True if this a security-sensitive setting */
4601
const char *def; /* Default value */
4602
};
4603
4604
#endif /* INTERFACE */
4605
4606
/*
4607
** SETTING: access-log boolean default=on
4608
**
4609
** When the access-log setting is enabled, all login attempts (successful
4610
** and unsuccessful) on the web interface are recorded in the "access" table
4611
** of the repository.
4612
*/
4613
/*
4614
** SETTING: admin-log boolean default=on
4615
**
4616
** When the admin-log setting is enabled, configuration changes are recorded
4617
** in the "admin_log" table of the repository.
4618
*/
4619
/*
4620
** SETTING: allow-symlinks boolean default=off sensitive
4621
**
4622
** When allow-symlinks is OFF, Fossil does not see symbolic links
4623
** (a.k.a "symlinks") on disk as a separate class of object. Instead Fossil
4624
** sees the object that the symlink points to. Fossil will only manage files
4625
** and directories, not symlinks. When a symlink is added to a repository,
4626
** the object that the symlink points to is added, not the symlink itself.
4627
**
4628
** When allow-symlinks is ON, Fossil sees symlinks on disk as a separate
4629
** object class that is distinct from files and directories. When a symlink
4630
** is added to a repository, Fossil stores the target filename. In other
4631
** words, Fossil stores the symlink itself, not the object that the symlink
4632
** points to.
4633
**
4634
** Symlinks are not cross-platform. They are not available on all
4635
** operating systems and file systems. Hence the allow-symlinks setting is
4636
** OFF by default, for portability.
4637
*/
4638
/*
4639
** SETTING: auto-captcha boolean default=on variable=autocaptcha
4640
** If enabled, the /login page provides a button that will automatically
4641
** fill in the captcha password. This makes things easier for human users,
4642
** at the expense of also making logins easier for malicious robots.
4643
*/
4644
/*
4645
** SETTING: auto-hyperlink width=16 default=1
4646
**
4647
** If non-zero, enable hyperlinks on web pages even for users that lack
4648
** the "h" privilege as long as the UserAgent string in the HTTP request
4649
** (The HTTP_USER_AGENT cgi variable) looks like it comes from a human and
4650
** not a robot. Details depend on the value of the setting.
4651
**
4652
** (0) Off: No adjustments are made to the 'h' privilege based on
4653
** the user agent.
4654
**
4655
** (1) UserAgent and Javascript: The the href= values of hyperlinks
4656
** initially point to /honeypot and are changed to point to the
4657
** correct target by javascript that runs after the page loads.
4658
** The auto-hyperlink-delay and auto-hyperlink-mouseover settings
4659
** influence that javascript.
4660
**
4661
** (2) UserAgent only: If the HTTP_USER_AGENT looks human
4662
** then generate hyperlinks, otherwise do not.
4663
**
4664
** Better robot exclusion is obtained when this setting is 1 versus 2.
4665
** However, a value of 1 causes the visited/unvisited colors of hyperlinks
4666
** to stop working on Safari-derived web browsers. When this setting is 2,
4667
** the hyperlinks work better on Safari, but more robots are able to sneak
4668
** in.
4669
*/
4670
/*
4671
** SETTING: auto-hyperlink-delay width=16 default=0
4672
**
4673
** When the auto-hyperlink setting is 1, the javascript that runs to set
4674
** the href= attributes of hyperlinks delays by this many milliseconds
4675
** after the page load. Suggested values: 50 to 200.
4676
*/
4677
/*
4678
** SETTING: auto-hyperlink-mouseover boolean default=off
4679
**
4680
** When the auto-hyperlink setting is 1 and this setting is on, the
4681
** javascript that runs to set the href= attributes of hyperlinks waits
4682
** until either a mousedown or mousemove event is seen. This helps
4683
** to distinguish real users from robots. For maximum robot defense,
4684
** the recommended setting is ON.
4685
*/
4686
/*
4687
** SETTING: auto-shun boolean default=on
4688
** If enabled, automatically pull the shunning list
4689
** from a server to which the client autosyncs.
4690
*/
4691
/*
4692
** SETTING: autosync width=16 default=on
4693
** This setting determines when autosync occurs. The setting is a
4694
** string that provides a lot of flexibility for determining when and
4695
** when not to autosync. Examples:
4696
**
4697
** on Always autosync for command where autosync
4698
** makes sense ("commit", "merge", "open", "update")
4699
**
4700
** off Never autosync.
4701
**
4702
** pullonly Only to pull autosyncs
4703
**
4704
** all Sync with all remotes
4705
**
4706
** on,open=off Autosync for most commands, but not for "open"
4707
**
4708
** off,commit=pullonly Do not autosync, except do a pull before each
4709
** "commit", presumably to avoid undesirable
4710
** forks.
4711
**
4712
** The syntax is a comma-separated list of VALUE and COMMAND=VALUE entries.
4713
** A plain VALUE entry is the default that is used if no COMMAND matches.
4714
** Otherwise, the VALUE of the matching command is used.
4715
**
4716
** The "all" value is special in that it applies to the "sync" command in
4717
** addition to "commit", "merge", "open", and "update".
4718
*/
4719
/*
4720
** SETTING: autosync-tries width=16 default=1
4721
** If autosync is enabled setting this to a value greater
4722
** than zero will cause autosync to try no more than this
4723
** number of attempts if there is a sync failure.
4724
*/
4725
/*
4726
** SETTING: backoffice-nodelay boolean default=off
4727
** If backoffice-nodelay is true, then the backoffice processing
4728
** will never invoke sleep(). If it has nothing useful to do,
4729
** it simply exits.
4730
*/
4731
/*
4732
** SETTING: backoffice-disable boolean default=off
4733
** If backoffice-disable is true, then the automatic backoffice
4734
** processing is disabled. Automatic backoffice processing is the
4735
** backoffice work that normally runs after each web page is
4736
** rendered. Backoffice processing that is triggered by the
4737
** "fossil backoffice" command is unaffected by this setting.
4738
**
4739
** Backoffice processing does things such as delivering
4740
** email notifications. So if this setting is true, and if
4741
** there is no cron job periodically running "fossil backoffice",
4742
** email notifications and other work normally done by the
4743
** backoffice will not occur.
4744
*/
4745
/*
4746
** SETTING: backoffice-logfile width=40 sensitive
4747
** If backoffice-logfile is not an empty string and is a valid
4748
** filename, then a one-line message is appended to that file
4749
** every time the backoffice runs. This can be used for debugging,
4750
** to ensure that backoffice is running appropriately.
4751
*/
4752
/*
4753
** SETTING: binary-glob width=40 versionable block-text
4754
** The VALUE of this setting is a list of GLOB patterns matching files
4755
** that should be treated as "binary" for committing and merging
4756
** purposes. Example: *.jpg,*.png The parsing rules are complex;
4757
** see https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4758
*/
4759
#if defined(_WIN32)||defined(__CYGWIN__)||defined(__DARWIN__)
4760
/*
4761
** SETTING: case-sensitive boolean default=off
4762
** If TRUE, the files whose names differ only in case
4763
** are considered distinct. If FALSE files whose names
4764
** differ only in case are the same file. Defaults to
4765
** TRUE for unix and FALSE for Cygwin, Mac and Windows.
4766
*/
4767
#endif
4768
#if !(defined(_WIN32)||defined(__CYGWIN__)||defined(__DARWIN__))
4769
/*
4770
** SETTING: case-sensitive boolean default=on
4771
** If TRUE, the files whose names differ only in case
4772
** are considered distinct. If FALSE files whose names
4773
** differ only in case are the same file. Defaults to
4774
** TRUE for unix and FALSE for Cygwin, Mac and Windows.
4775
*/
4776
#endif
4777
/*
4778
** SETTING: clean-glob width=40 versionable block-text
4779
** The VALUE of this setting is a list of GLOB patterns matching files
4780
** that the "clean" command will delete without prompting or allowing
4781
** undo. Example: *.a,*.o,*.so The parsing rules are complex;
4782
** see https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4783
*/
4784
/*
4785
** SETTING: clearsign boolean default=off
4786
** When enabled, fossil will attempt to sign all commits
4787
** with gpg or ssh. When disabled, commits will be unsigned.
4788
*/
4789
/*
4790
** SETTING: comment-format width=16 default=1
4791
** Set the algorithm for printing timeline comments to the console.
4792
**
4793
** Possible values are:
4794
** 1 Use the original comment printing algorithm:
4795
** * Leading and trailing whitespace is removed
4796
** * Internal whitespace is converted into a single space (0x20)
4797
** * Line breaks occurs at whitespace or hyphens if possible
4798
** This is the recommended value and the default.
4799
**
4800
** Or a bitwise combination of the following flags:
4801
** 2 Trim leading and trailing CR and LF characters.
4802
** 4 Trim leading and trailing white space characters.
4803
** 8 Attempt to break lines on word boundaries.
4804
** 16 Break lines before the original comment embedded in other text.
4805
**
4806
** Note: To preserve line breaks and/or other whitespace within comment text,
4807
** make this setting some integer value that omits the "1" bit.
4808
*/
4809
/*
4810
** SETTING: crlf-glob width=40 versionable block-text
4811
** The VALUE of this setting is a list of GLOB patterns matching files
4812
** in which it is allowed to have CR, CR+LF or mixed line endings,
4813
** suppressing Fossil's normal warning about this. Set it to "*" to
4814
** disable CR+LF checking entirely. Example: *.md,*.txt
4815
** The crnl-glob setting is a compatibility alias.
4816
*/
4817
/*
4818
** SETTING: crnl-glob width=40 versionable block-text
4819
** This is an alias for the crlf-glob setting.
4820
*/
4821
/*
4822
** SETTING: default-perms width=16 default=u sensitive keep-empty
4823
** Permissions given automatically to new users. For more
4824
** information on permissions see the Users page in Server
4825
** Administration of the HTTP UI.
4826
*/
4827
/*
4828
** SETTING: diff-binary boolean default=on
4829
** If enabled, permit files that may be binary
4830
** or that match the "binary-glob" setting to be used with
4831
** external diff programs. If disabled, skip these files.
4832
*/
4833
/*
4834
** SETTING: diff-command width=40 sensitive
4835
** The value is an external command to run when performing a diff.
4836
** If undefined, the internal text diff will be used.
4837
*/
4838
/*
4839
** SETTING: dont-commit boolean default=off
4840
** If enabled, prevent committing to this repository, as an extra precaution
4841
** against accidentally checking in to a repository intended to be read-only.
4842
*/
4843
/*
4844
** SETTING: dont-push boolean default=off
4845
** If enabled, prevent this repository from pushing from client to
4846
** server. This can be used as an extra precaution to prevent
4847
** accidental pushes to a public server from a private clone.
4848
*/
4849
/*
4850
** SETTING: dotfiles boolean versionable default=off
4851
** If enabled, include --dotfiles option for all compatible commands.
4852
*/
4853
/*
4854
** SETTING: editor width=32 sensitive
4855
** The value is an external command that will launch the
4856
** text editor command used for check-in comments.
4857
**
4858
** If this value is not set, then environment variables VISUAL and
4859
** EDITOR are consulted, in that order. If neither of those are set,
4860
** then a search is made for common text editors, including
4861
** "notepad", "nano", "pico", "jove", "edit", "vi", "vim", and "ed".
4862
**
4863
** If this setting is false ("off", "no", "false", or "0") then no
4864
** text editor is used.
4865
*/
4866
/*
4867
** SETTING: empty-dirs width=40 versionable block-text
4868
** The value is a list of pathnames parsed according to the same rules as
4869
** the *-glob settings. On update and checkout commands, if no directory
4870
** exists with that name, an empty directory will be created, even if
4871
** it must create one or more parent directories.
4872
*/
4873
/*
4874
** SETTING: encoding-glob width=40 versionable block-text
4875
** The VALUE of this setting is a list of GLOB patterns matching files that
4876
** the "commit" command will ignore when issuing warnings about text files
4877
** that may use another encoding than ASCII or UTF-8. Set to "*" to disable
4878
** encoding checking. Example: *.md,*.txt The parsing rules are complex;
4879
** see https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4880
*/
4881
#if defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
4882
/*
4883
** SETTING: exec-rel-paths boolean default=on
4884
** When executing certain external commands (e.g. diff and
4885
** gdiff), use relative paths.
4886
*/
4887
#endif
4888
#if !defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
4889
/*
4890
** SETTING: exec-rel-paths boolean default=off
4891
** When executing certain external commands (e.g. diff and
4892
** gdiff), use relative paths.
4893
*/
4894
#endif
4895
4896
/*
4897
** SETTING: fileedit-glob width=40 block-text
4898
** The VALUE of this setting is a list of GLOB patterns matching files
4899
** which are allowed to be edited using the /fileedit page. An empty list
4900
** suppresses the feature. Example: *.md,*.txt The parsing rules are
4901
** complex; see https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4902
** Note that /fileedit cannot edit binary files, so the list should not
4903
** contain any globs for, e.g., images or PDFs.
4904
*/
4905
/*
4906
** SETTING: forbid-delta-manifests boolean default=on
4907
** If enabled on a client, new delta manifests are prohibited on
4908
** commits. If enabled on a server, whenever a client attempts
4909
** to obtain a check-in lock during auto-sync, the server will
4910
** send the "pragma avoid-delta-manifests" statement in its reply,
4911
** which will cause the client to avoid generating a delta
4912
** manifest.
4913
*/
4914
/*
4915
** SETTING: gdiff-command width=40 sensitive
4916
** The value is an external command to run when performing a graphical
4917
** diff. If undefined, a --tk diff is done if commands "tclsh" and "wish"
4918
** are on PATH, or a --by diff is done if "tclsh" or "wish" are unavailable.
4919
*/
4920
/*
4921
** SETTING: gmerge-command width=40 sensitive
4922
** The value is a graphical merge conflict resolver command operating
4923
** on four files. Examples:
4924
**
4925
** kdiff3 "%baseline" "%original" "%merge" -o "%output"
4926
** xxdiff "%original" "%baseline" "%merge" -M "%output"
4927
** meld "%baseline" "%original" "%merge" --output "%output"
4928
*/
4929
/*
4930
** SETTING: hash-digits width=5 default=10
4931
** The number of hexadecimal digits of the SHA3 hash to display.
4932
*/
4933
/*
4934
** SETTING: http-port width=16 default=8080
4935
** The default TCP/IP port number to use by the "server"
4936
** and "ui" commands.
4937
*/
4938
/*
4939
** SETTING: https-login boolean default=off
4940
** If true, then the Fossil web server will redirect unencrypted
4941
** login screen requests to HTTPS.
4942
*/
4943
/*
4944
** SETTING: ignore-glob width=40 versionable block-text
4945
** The VALUE of this setting is a list of GLOB patterns matching files that
4946
** the "add", "addremove", "clean", and "extras" commands will ignore.
4947
** Example: *.log,notes.txt The parsing rules are complex; see
4948
** https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4949
*/
4950
/*
4951
** SETTING: keep-glob width=40 versionable block-text
4952
** The VALUE of this setting is a list of GLOB patterns matching files that
4953
** the "clean" command must not delete. Example: build/precious.exe
4954
** The parsing rules are complex; see
4955
** https://fossil-scm.org/home/doc/trunk/www/globs.md#syntax
4956
*/
4957
/*
4958
** SETTING: localauth boolean default=off
4959
** If enabled, require that HTTP connections from the loopback
4960
** address (127.0.0.1) be authenticated by password. If false,
4961
** some HTTP requests might be granted full "Setup" user
4962
** privileges without having to present login credentials.
4963
** This mechanism allows the "fossil ui" command to provide
4964
** full access to the repository without requiring the user to
4965
** log in first.
4966
**
4967
** In order for full "Setup" privilege to be granted without a
4968
** login, the following conditions must be met:
4969
**
4970
** (1) This setting ("localauth") must be off
4971
** (2) The HTTP request arrive over the loopback TCP/IP
4972
** address (127.0.01) or else via SSH.
4973
** (3) The request must be HTTP, not HTTPS. (This
4974
** restriction is designed to help prevent accidentally
4975
** providing "Setup" privileges to requests arriving
4976
** over a reverse proxy.)
4977
** (4) The command that launched the fossil server must be
4978
** one of the following:
4979
** (a) "fossil ui"
4980
** (b) "fossil server" with the --localauth option
4981
** (c) "fossil http" with the --localauth option
4982
** (d) CGI with the "localauth" setting in the cgi script.
4983
**
4984
** For maximum security, set "localauth" to 1. However, because
4985
** of the other restrictions (2) through (4), it should be safe
4986
** to leave "localauth" set to 0 in most installations, and
4987
** especially on cloned repositories on workstations. Leaving
4988
** "localauth" at 0 makes the "fossil ui" command more convenient
4989
** to use.
4990
*/
4991
/*
4992
** SETTING: lock-timeout width=25 default=60
4993
** This is the number of seconds that a check-in lock will be held on
4994
** the server before the lock expires. The default is a 60-second delay.
4995
** Set this value to zero to disable the check-in lock mechanism.
4996
**
4997
** This value should be set on the server to which users auto-sync
4998
** their work. This setting has no effect on client repositories. The
4999
** check-in lock mechanism is only effective if all users are auto-syncing
5000
** to the same server.
5001
**
5002
** Check-in locks are an advisory mechanism designed to help prevent
5003
** accidental forks due to a check-in race in installations where many
5004
** users are committing to the same branch and auto-sync is enabled.
5005
** As forks are harmless, there is no danger in disabling this mechanism.
5006
** However, keeping check-in locks turned on can help prevent unnecessary
5007
** confusion.
5008
*/
5009
/*
5010
** SETTING: main-branch width=40 default=trunk
5011
** The value is the primary branch for the project.
5012
*/
5013
/*
5014
** SETTING: manifest width=5 versionable
5015
** If enabled, automatically create files "manifest" and "manifest.uuid"
5016
** in every check-out.
5017
**
5018
** Optionally use combinations of characters 'r' for "manifest",
5019
** 'u' for "manifest.uuid" and 't' for "manifest.tags". The SQLite
5020
** and Fossil repositories both require manifests.
5021
*/
5022
/*
5023
** SETTING: max-loadavg width=25 default=0.0
5024
** Some CPU-intensive web pages (ex: /zip, /tarball, /blame)
5025
** are disallowed if the system load average goes above this
5026
** value. "0.0" means no limit. This only works on unix.
5027
** Only local settings of this value make a difference since
5028
** when running as a web-server, Fossil does not open the
5029
** global configuration database.
5030
*/
5031
/*
5032
** SETTING: max-upload width=25 default=250000
5033
** A limit on the size of uplink HTTP requests.
5034
*/
5035
/*
5036
** SETTING: mimetypes width=40 versionable block-text
5037
** A list of file extension-to-mimetype mappings, one per line. e.g.
5038
** "foo application/x-foo". File extensions are compared
5039
** case-insensitively in the order listed in this setting. A leading
5040
** '.' on file extensions is permitted but not required.
5041
*/
5042
/*
5043
** SETTING: mtime-changes boolean default=on
5044
** Use file modification times (mtimes) to detect when
5045
** files have been modified. If disabled, all managed files
5046
** are hashed to detect changes, which can be slow for large
5047
** projects.
5048
*/
5049
/*
5050
** SETTING: mv-rm-files boolean default=off
5051
** If enabled, the "mv" and "rename" commands will also move
5052
** the associated files within the check-out -AND- the "rm"
5053
** and "delete" commands will also remove the associated
5054
** files from within the check-out.
5055
*/
5056
/*
5057
** SETTING: pgp-command width=40 sensitive
5058
** Command used to clear-sign manifests at check-in.
5059
** Default value is "gpg --clearsign -o".
5060
** For SSH, use e.g. "ssh-keygen -q -Y sign -n fossilscm -f ~/.ssh/id_ed25519"
5061
*/
5062
/*
5063
** SETTING: proxy width=32 default=system
5064
** URL of the HTTP proxy. If undefined or "system", the "http_proxy"
5065
** environment variable is consulted. If "off", a direct HTTP connection is
5066
** used.
5067
*/
5068
/*
5069
** SETTING: redirect-to-https default=0 width=2
5070
** Specifies whether or not to redirect unencrypted "http://" requests to
5071
** encrypted "https://" URIs. A value of 0 (the default) means do not
5072
** redirect, 1 means to redirect only the /login page, and 2
5073
** means to always redirect.
5074
**
5075
** For security, a value of 2 is recommended. The default value is 0
5076
** because not all sites are TLS-capable. But you should definitely enable
5077
** TLS and change this setting to 2 for all public-facing repositories.
5078
*/
5079
/*
5080
** SETTING: relative-paths boolean default=on
5081
** When showing changes and extras, report paths relative
5082
** to the current working directory.
5083
*/
5084
/*
5085
** SETTING: repo-cksum boolean default=on
5086
** Compute checksums over all files in each check-out as a double-check
5087
** of correctness. Disable this on large repositories for a performance
5088
** improvement.
5089
*/
5090
/*
5091
** SETTING: repolist-skin width=2 default=0
5092
** If non-zero then use this repository as the skin for a repository list
5093
** such as created by the one of:
5094
**
5095
** 1) fossil server DIRECTORY --repolist
5096
** 2) fossil ui DIRECTORY --repolist
5097
** 3) fossil http DIRECTORY --repolist
5098
** 4) (The "repolist" option in a CGI script)
5099
** 5) fossil all ui
5100
** 6) fossil all server
5101
**
5102
** All repositories are searched (in lexicographical order) and the first
5103
** repository with a non-zero "repolist-skin" value is used as the skin
5104
** for the repository list page. If none of the repositories on the list
5105
** have a non-zero "repolist-skin" setting then the repository list is
5106
** displayed using unadorned HTML ("skinless"), with the page title taken
5107
** from the FOSSIL_REPOLIST_TITLE environment variable.
5108
**
5109
** If repolist-skin has a value of 2, then the repository is omitted from
5110
** the list in use cases 1 through 4, but not for 5 and 6.
5111
*/
5112
/*
5113
** SETTING: self-pw-reset boolean default=off sensitive
5114
** Allow users to request that an email containing a hyperlink
5115
** to the /resetpw page be sent to their email address of record,
5116
** thus allowing forgetful users to reset their forgotten passwords
5117
** without administrator involvement.
5118
*/
5119
/*
5120
** SETTING: self-register boolean default=off sensitive
5121
** Allow users to register themselves through the HTTP UI.
5122
** This is useful if you want to see other names than
5123
** "Anonymous" in e.g. ticketing system. On the other hand
5124
** users can not be deleted.
5125
*/
5126
/*
5127
** SETTING: ssh-command width=40 sensitive
5128
** The command used to talk to a remote machine with the "ssh://" protocol.
5129
*/
5130
5131
/*
5132
** SETTING: ssl-ca-location width=40 sensitive
5133
** The full pathname to a file containing PEM encoded
5134
** CA root certificates, or a directory of certificates
5135
** with filenames formed from the certificate hashes as
5136
** required by OpenSSL.
5137
**
5138
** If set, this will override the OS default list of
5139
** OpenSSL CAs. If unset, the default list will be used.
5140
** Some platforms may add additional certificates.
5141
** Checking your platform behaviour is required if the
5142
** exact contents of the CA root is critical for your
5143
** application.
5144
**
5145
** This setting is overridden by environment variables
5146
** SSL_CERT_FILE and SSL_CERT_DIR.
5147
*/
5148
/*
5149
** SETTING: ssl-identity width=40 sensitive
5150
** The full pathname to a file containing a certificate
5151
** and private key in PEM format. Create by concatenating
5152
** the certificate and private key files.
5153
**
5154
** This identity will be presented to SSL servers to
5155
** authenticate this client, in addition to the normal
5156
** password authentication.
5157
*/
5158
#ifdef FOSSIL_ENABLE_TCL
5159
/*
5160
** SETTING: tcl boolean default=off sensitive
5161
** If enabled Tcl integration commands will be added to the TH1
5162
** interpreter, allowing arbitrary Tcl expressions and
5163
** scripts to be evaluated from TH1. Additionally, the Tcl
5164
** interpreter will be able to evaluate arbitrary TH1
5165
** expressions and scripts.
5166
*/
5167
/*
5168
** SETTING: tcl-setup width=40 block-text sensitive
5169
** This is the setup script to be evaluated after creating
5170
** and initializing the Tcl interpreter. By default, this
5171
** is empty and no extra setup is performed.
5172
*/
5173
#endif /* FOSSIL_ENABLE_TCL */
5174
/*
5175
** SETTING: tclsh width=80 default=tclsh sensitive
5176
** Name of the external TCL interpreter used for such things
5177
** as running the GUI diff viewer launched by the --tk option
5178
** of the various "diff" commands.
5179
*/
5180
#ifdef FOSSIL_ENABLE_TH1_DOCS
5181
/*
5182
** SETTING: th1-docs boolean default=off sensitive
5183
** If enabled, this allows embedded documentation files to contain
5184
** arbitrary TH1 scripts that are evaluated on the server. If native
5185
** Tcl integration is also enabled, this setting has the
5186
** potential to allow anybody with check-in privileges to
5187
** do almost anything that the associated operating system
5188
** user account could do. Extreme caution should be used
5189
** when enabling this setting.
5190
*/
5191
#endif
5192
#ifdef FOSSIL_ENABLE_TH1_HOOKS
5193
/*
5194
** SETTING: th1-hooks boolean default=off
5195
** If enabled, special TH1 commands will be called before and
5196
** after any Fossil command or web page.
5197
*/
5198
#endif
5199
/*
5200
** SETTING: th1-setup width=40 block-text sensitive
5201
** This is the setup script to be evaluated after creating
5202
** and initializing the TH1 interpreter. By default, this
5203
** is empty and no extra setup is performed.
5204
*/
5205
/*
5206
** SETTING: th1-uri-regexp width=40 block-text
5207
** Specify which URI's are allowed in HTTP requests from
5208
** TH1 scripts. If empty, no HTTP requests are allowed
5209
** whatsoever.
5210
*/
5211
/*
5212
** SETTING: default-csp width=40 block-text keep-empty
5213
**
5214
** The text of the Content Security Policy that is included
5215
** in the Content-Security-Policy: header field of the HTTP
5216
** reply and in the default HTML <head> section that is added when the
5217
** skin header does not specify a <head> section. The text "$nonce"
5218
** is replaced by the random nonce that is created for each web page.
5219
**
5220
** If this setting is an empty string or is omitted, then
5221
** the following default Content Security Policy is used:
5222
**
5223
** default-src 'self' data:;
5224
** script-src 'self' 'nonce-$nonce';
5225
** style-src 'self' 'unsafe-inline';
5226
** img-src * data:;
5227
**
5228
** The default CSP is recommended. The main reason to change
5229
** this setting would be to add CDNs from which it is safe to
5230
** load additional content.
5231
*/
5232
/*
5233
** SETTING: uv-sync boolean default=off
5234
** If true, automatically send unversioned files as part
5235
** of a "fossil clone" or "fossil sync" command. The
5236
** default is false, in which case the -u option is
5237
** needed to clone or sync unversioned files.
5238
*/
5239
/*
5240
** SETTING: web-browser width=30 sensitive
5241
** A shell command used to launch your preferred
5242
** web browser when given a URL as an argument.
5243
** Defaults to "start" on windows, "open" on Mac,
5244
** and "firefox" on Unix.
5245
*/
5246
/*
5247
** SETTING: large-file-size width=10 default=200000000
5248
** Fossil considers any file whose size is greater than this value
5249
** to be a "large file". Fossil might issue warnings if you try to
5250
** "add" or "commit" a "large file". Set this value to 0 or less
5251
** to disable all such warnings.
5252
*/
5253
5254
/*
5255
** Look up a control setting by its name. Return a pointer to the Setting
5256
** object, or NULL if there is no such setting.
5257
**
5258
** If allowPrefix is true, then the Setting returned is the first one for
5259
** which zName is a prefix of the Setting name.
5260
*/
5261
Setting *db_find_setting(const char *zName, int allowPrefix){
5262
int lwr, mid, upr, c;
5263
int n = (int)strlen(zName) + !allowPrefix;
5264
int nSetting;
5265
const Setting *aSetting = setting_info(&nSetting);
5266
lwr = 0;
5267
upr = nSetting - 1;
5268
while( upr>=lwr ){
5269
mid = (upr+lwr)/2;
5270
c = fossil_strncmp(zName, aSetting[mid].name, n);
5271
if( c<0 ){
5272
upr = mid - 1;
5273
}else if( c>0 ){
5274
lwr = mid + 1;
5275
}else{
5276
if( allowPrefix ){
5277
while( mid>lwr && fossil_strncmp(zName, aSetting[mid-1].name, n)==0 ){
5278
mid--;
5279
}
5280
}
5281
return (Setting*)&aSetting[mid];
5282
}
5283
}
5284
return 0;
5285
}
5286
5287
/*
5288
** COMMAND: settings
5289
** COMMAND: unset*
5290
**
5291
** Usage: %fossil settings ?SETTING? ?VALUE? ?OPTIONS?
5292
** or: %fossil unset SETTING ?OPTIONS?
5293
**
5294
** The "settings" command with no arguments lists all settings and their
5295
** values. With just a SETTING name it shows the current value of that setting.
5296
** With a VALUE argument it changes the property for the current repository.
5297
**
5298
** Settings marked as versionable are overridden by the contents of the
5299
** file named .fossil-settings/PROPERTY in the check-out root, if that
5300
** file exists.
5301
**
5302
** The "unset" command clears a setting.
5303
**
5304
** Settings can have both a "local" repository-only value and "global" value
5305
** that applies to all repositories. The local values are stored in the
5306
** "config" table of the repository and the global values are stored in the
5307
** configuration database. If both a local and a global value exists for a
5308
** setting, the local value takes precedence. This command normally operates
5309
** on the local settings. Use the --global option to change global settings.
5310
**
5311
** Options:
5312
** --changed Only show settings if the value differs from the default
5313
** --exact Only consider exact name matches
5314
** --global Set or unset the given property globally instead of
5315
** setting or unsetting it for the open repository only
5316
** --value Only show the value of a given property (implies --exact)
5317
**
5318
** See also: [[configuration]]
5319
*/
5320
void setting_cmd(void){
5321
int i;
5322
int globalFlag = find_option("global","g",0)!=0;
5323
int bIfChng = find_option("changed",0,0)!=0;
5324
int exactFlag = find_option("exact",0,0)!=0;
5325
int valueFlag = find_option("value",0,0)!=0;
5326
/* Undocumented "--test-for-subsystem SUBSYS" option used to test
5327
** the db_get_for_subsystem() interface: */
5328
const char *zSubsys = find_option("test-for-subsystem",0,1);
5329
int unsetFlag = g.argv[1][0]=='u';
5330
int nSetting;
5331
const Setting *aSetting = setting_info(&nSetting);
5332
find_repository_option();
5333
verify_all_options();
5334
db_open_config(1, 0);
5335
if( !globalFlag ){
5336
db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
5337
}
5338
if( !g.repositoryOpen ){
5339
globalFlag = 1;
5340
}
5341
if( unsetFlag && g.argc!=3 ){
5342
usage("PROPERTY ?-global?");
5343
}
5344
if( valueFlag ){
5345
if( g.argc!=3 ){
5346
fossil_fatal("--value is only supported when qurying a given property");
5347
}
5348
}
5349
5350
if( g.argc==2 ){
5351
for(i=0; i<nSetting; i++){
5352
print_setting(&aSetting[i], 0, bIfChng);
5353
}
5354
}else if( g.argc==3 || g.argc==4 ){
5355
const char *zName = g.argv[2];
5356
int n = (int)strlen(zName);
5357
const Setting *pSetting = db_find_setting(zName, !exactFlag);
5358
if( pSetting==0 ){
5359
fossil_fatal("no such setting: %s", zName);
5360
}
5361
if( globalFlag && fossil_strcmp(pSetting->name, "manifest")==0 ){
5362
fossil_fatal("cannot set 'manifest' globally");
5363
}
5364
if( unsetFlag || g.argc==4 ){
5365
int isManifest = fossil_strcmp(pSetting->name, "manifest")==0;
5366
if( n!=(int)strlen(pSetting[0].name) && pSetting[1].name &&
5367
fossil_strncmp(pSetting[1].name, zName, n)==0 ){
5368
Blob x;
5369
int i;
5370
blob_init(&x,0,0);
5371
for(i=0; pSetting[i].name; i++){
5372
if( fossil_strncmp(pSetting[i].name,zName,n)!=0 ) break;
5373
blob_appendf(&x, " %s", pSetting[i].name);
5374
}
5375
fossil_fatal("ambiguous setting \"%s\" - might be:%s",
5376
zName, blob_str(&x));
5377
}
5378
if( globalFlag && isManifest ){
5379
fossil_fatal("cannot set 'manifest' globally");
5380
}
5381
if( unsetFlag ){
5382
db_unset(pSetting->name/*works-like:"x"*/, globalFlag);
5383
}else{
5384
db_protect_only(PROTECT_NONE);
5385
db_set(pSetting->name/*works-like:"x"*/, g.argv[3], globalFlag);
5386
db_protect_pop();
5387
}
5388
if( isManifest && g.localOpen ){
5389
manifest_to_disk(db_lget_int("checkout", 0));
5390
}
5391
}else{
5392
while( pSetting->name ){
5393
if( exactFlag ){
5394
if( fossil_strcmp(pSetting->name,zName)!=0 ) break;
5395
}else{
5396
if( fossil_strncmp(pSetting->name,zName,n)!=0 ) break;
5397
}
5398
if( zSubsys ){
5399
char *zValue = db_get_for_subsystem(pSetting->name, zSubsys);
5400
fossil_print("%s (subsystem %s) ->", pSetting->name, zSubsys);
5401
if( zValue ){
5402
fossil_print(" [%s]", zValue);
5403
fossil_free(zValue);
5404
}
5405
fossil_print("\n");
5406
}else{
5407
print_setting(pSetting, valueFlag, bIfChng);
5408
}
5409
pSetting++;
5410
}
5411
}
5412
}else{
5413
usage("?PROPERTY? ?VALUE? ?-global?");
5414
}
5415
}
5416
5417
/*
5418
** The input in a timespan measured in days. Return a string which
5419
** describes that timespan in units of seconds, minutes, hours, days,
5420
** or years, depending on its duration.
5421
*/
5422
char *db_timespan_name(double rSpan){
5423
if( rSpan<0 ) rSpan = -rSpan;
5424
rSpan *= 24.0*3600.0; /* Convert units to seconds */
5425
if( rSpan<120.0 ){
5426
return sqlite3_mprintf("%.1f seconds", rSpan);
5427
}
5428
rSpan /= 60.0; /* Convert units to minutes */
5429
if( rSpan<90.0 ){
5430
return sqlite3_mprintf("%.1f minutes", rSpan);
5431
}
5432
rSpan /= 60.0; /* Convert units to hours */
5433
if( rSpan<=48.0 ){
5434
return sqlite3_mprintf("%.1f hours", rSpan);
5435
}
5436
rSpan /= 24.0; /* Convert units to days */
5437
if( rSpan<=365.0 ){
5438
return sqlite3_mprintf("%.1f days", rSpan);
5439
}
5440
rSpan /= 356.24; /* Convert units to years */
5441
return sqlite3_mprintf("%.1f years", rSpan);
5442
}
5443
5444
/*
5445
** COMMAND: test-timespan
5446
**
5447
** Usage: %fossil test-timespan TIMESTAMP
5448
**
5449
** Print the approximate span of time from now to TIMESTAMP.
5450
*/
5451
void test_timespan_cmd(void){
5452
double rDiff;
5453
if( g.argc!=3 ) usage("TIMESTAMP");
5454
sqlite3_open(":memory:", &g.db);
5455
rDiff = db_double(0.0, "SELECT julianday('now') - julianday(%Q)", g.argv[2]);
5456
fossil_print("Time differences: %s\n", db_timespan_name(rDiff));
5457
sqlite3_close(g.db);
5458
g.db = 0;
5459
g.repositoryOpen = 0;
5460
g.localOpen = 0;
5461
}
5462
5463
/*
5464
** COMMAND: test-without-rowid
5465
**
5466
** Usage: %fossil test-without-rowid FILENAME...
5467
**
5468
** Change the Fossil repository FILENAME to make use of the WITHOUT ROWID
5469
** optimization. FILENAME can also be the configuration database file
5470
** (~/.fossil or ~/.config/fossil.db) or a local .fslckout or _FOSSIL_ file.
5471
**
5472
** The purpose of this command is for testing the WITHOUT ROWID capabilities
5473
** of SQLite. There is no big advantage to using WITHOUT ROWID in Fossil.
5474
**
5475
** Options:
5476
** -n|--dry-run No changes. Just print what would happen.
5477
*/
5478
void test_without_rowid(void){
5479
int i, j;
5480
Stmt q;
5481
Blob allSql;
5482
int dryRun = find_option("dry-run", "n", 0)!=0;
5483
for(i=2; i<g.argc; i++){
5484
db_open_or_attach(g.argv[i], "main");
5485
blob_init(&allSql, "BEGIN;\n", -1);
5486
db_prepare(&q,
5487
"SELECT name, sql FROM main.sqlite_schema "
5488
" WHERE type='table' AND sql NOT LIKE '%%WITHOUT ROWID%%'"
5489
" AND name IN ('global_config','shun','concealed','config',"
5490
" 'plink','tagxref','backlink','vcache');"
5491
);
5492
while( db_step(&q)==SQLITE_ROW ){
5493
const char *zTName = db_column_text(&q, 0);
5494
const char *zOrigSql = db_column_text(&q, 1);
5495
Blob newSql;
5496
blob_init(&newSql, 0, 0);
5497
for(j=0; zOrigSql[j]; j++){
5498
if( fossil_strnicmp(zOrigSql+j,"unique",6)==0 ){
5499
blob_append(&newSql, zOrigSql, j);
5500
blob_append(&newSql, "PRIMARY KEY", -1);
5501
zOrigSql += j+6;
5502
j = -1;
5503
}
5504
}
5505
blob_append(&newSql, zOrigSql, -1);
5506
blob_append_sql(&allSql,
5507
"ALTER TABLE \"%w\" RENAME TO \"x_%w\";\n"
5508
"%s WITHOUT ROWID;\n"
5509
"INSERT INTO \"%w\" SELECT * FROM \"x_%w\";\n"
5510
"DROP TABLE \"x_%w\";\n",
5511
zTName, zTName, blob_sql_text(&newSql), zTName, zTName, zTName
5512
);
5513
fossil_print("Converting table %s of %s to WITHOUT ROWID.\n",
5514
zTName, g.argv[i]);
5515
blob_reset(&newSql);
5516
}
5517
blob_append_sql(&allSql, "COMMIT;\n");
5518
db_finalize(&q);
5519
if( dryRun ){
5520
fossil_print("SQL that would have been evaluated:\n");
5521
fossil_print("%.78c\n", '-');
5522
fossil_print("%s", blob_sql_text(&allSql));
5523
}else{
5524
db_multi_exec("%s", blob_sql_text(&allSql));
5525
}
5526
blob_reset(&allSql);
5527
db_close(1);
5528
}
5529
}
5530
5531
/*
5532
** Make sure the adminlog table exists. Create it if it does not
5533
*/
5534
void create_admin_log_table(void){
5535
static int once = 0;
5536
if( once ) return;
5537
if( !db_table_exists("repository","admin_log") ){
5538
once = 1;
5539
db_multi_exec(
5540
"CREATE TABLE repository.admin_log(\n"
5541
" id INTEGER PRIMARY KEY,\n"
5542
" time INTEGER, -- Seconds since 1970\n"
5543
" page TEXT, -- path of page\n"
5544
" who TEXT, -- User who made the change\n"
5545
" what TEXT -- What changed\n"
5546
")"
5547
);
5548
}
5549
}
5550
5551
/*
5552
** Write a message into the admin_event table, if admin logging is
5553
** enabled via the admin-log configuration option.
5554
*/
5555
void admin_log(const char *zFormat, ...){
5556
Blob what = empty_blob;
5557
va_list ap;
5558
if( !db_get_boolean("admin-log", 0) ){
5559
/* Potential leak here (on %z params) but
5560
the alternative is to let blob_vappendf()
5561
do it below. */
5562
return;
5563
}
5564
create_admin_log_table();
5565
va_start(ap,zFormat);
5566
blob_vappendf( &what, zFormat, ap );
5567
va_end(ap);
5568
db_multi_exec("INSERT INTO admin_log(time,page,who,what)"
5569
" VALUES(now(), %Q, %Q, %B)",
5570
g.zPath, g.zLogin, &what);
5571
blob_reset(&what);
5572
}
5573
5574
/*
5575
** COMMAND: test-database-names
5576
**
5577
** Print the names of the various database files:
5578
** (1) The main repository database
5579
** (2) The local check-out database
5580
** (3) The global configuration database
5581
*/
5582
void test_database_name_cmd(void){
5583
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
5584
fossil_print("Repository database: %s\n", g.zRepositoryName);
5585
fossil_print("Local database: %s\n", g.zLocalDbName);
5586
fossil_print("Config database: %s\n", g.zConfigDbName);
5587
}
5588
5589
/*
5590
** Compute a "fingerprint" on the repository. A fingerprint is used
5591
** to verify that the repository has not been replaced by a clone
5592
** of the same repository. More precisely, a fingerprint is used to
5593
** verify that the mapping between SHA3 hashes and RID values is unchanged.
5594
**
5595
** The check-out database ("localdb") stores RID values. When associating
5596
** a check-out database against a repository database, it is useful to verify
5597
** the fingerprint so that we know that the RID values in the check-out
5598
** database still correspond to the correct entries in the BLOB table of
5599
** the repository.
5600
**
5601
** The fingerprint is based on the RCVFROM table. When constructing a
5602
** new fingerprint, use the most recent RCVFROM entry. (Set rcvid==0 to
5603
** accomplish this.) When verifying an old fingerprint, use the same
5604
** RCVFROM entry that generated the fingerprint in the first place.
5605
**
5606
** The fingerprint consists of the rcvid, a "/", and the MD5 checksum of
5607
** the remaining fields of the RCVFROM table entry. MD5 is used for this
5608
** because it is 4x faster than SHA3 and 5x faster than SHA1, and there
5609
** are no security concerns - this is just a checksum, not a security
5610
** token.
5611
*/
5612
char *db_fingerprint(int rcvid, int iVersion){
5613
char *z = 0;
5614
Blob sql = BLOB_INITIALIZER;
5615
Stmt q;
5616
if( iVersion==0 ){
5617
/* The original fingerprint algorithm used "quote(mtime)". But this
5618
** could give slightly different answers depending on how the floating-
5619
** point hardware is configured. For example, it gave different
5620
** answers on native Linux versus running under valgrind. */
5621
blob_append_sql(&sql,
5622
"SELECT rcvid, quote(uid), quote(mtime), quote(nonce), quote(ipaddr)"
5623
" FROM rcvfrom"
5624
);
5625
}else{
5626
/* These days, we use "datetime(mtime)" for more consistent answers */
5627
blob_append_sql(&sql,
5628
"SELECT rcvid, quote(uid), datetime(mtime), quote(nonce), quote(ipaddr)"
5629
" FROM rcvfrom"
5630
);
5631
}
5632
if( rcvid<=0 ){
5633
blob_append_sql(&sql, " ORDER BY rcvid DESC LIMIT 1");
5634
}else{
5635
blob_append_sql(&sql, " WHERE rcvid=%d", rcvid);
5636
}
5637
db_prepare_blob(&q, &sql);
5638
blob_reset(&sql);
5639
if( db_step(&q)==SQLITE_ROW ){
5640
int i;
5641
md5sum_init();
5642
for(i=1; i<=4; i++){
5643
md5sum_step_text(db_column_text(&q,i),-1);
5644
}
5645
z = mprintf("%d/%s",db_column_int(&q,0),md5sum_finish(0));
5646
}
5647
db_finalize(&q);
5648
return z;
5649
}
5650
5651
/*
5652
** COMMAND: test-fingerprint
5653
**
5654
** Usage: %fossil test-fingerprint ?RCVID?
5655
**
5656
** Display the repository fingerprint using the supplied RCVID or
5657
** using the latest RCVID if none is given on the command line.
5658
** Show both the legacy and the newer version of the fingerprint,
5659
** and the currently stored fingerprint if there is one.
5660
*/
5661
void test_fingerprint(void){
5662
int rcvid = 0;
5663
db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
5664
if( g.argc==3 ){
5665
rcvid = atoi(g.argv[2]);
5666
}else if( g.argc!=2 ){
5667
fossil_fatal("wrong number of arguments");
5668
}
5669
fossil_print("legacy: %z\n", db_fingerprint(rcvid, 0));
5670
fossil_print("version-1: %z\n", db_fingerprint(rcvid, 1));
5671
if( g.localOpen ){
5672
fossil_print("localdb: %z\n", db_lget("fingerprint","(none)"));
5673
fossil_print("db_fingerprint_ok(): %d\n", db_fingerprint_ok());
5674
}
5675
fossil_print("Fossil version: %s - %.10s %.19s\n",
5676
RELEASE_VERSION, MANIFEST_DATE, MANIFEST_UUID);
5677
}
5678
5679
/*
5680
** Set the value of the "checkout" entry in the VVAR table.
5681
** If bWriteManifest is non-zero then also attempt to write the manifest
5682
** files to disk.
5683
**
5684
** Also set "fingerprint" and "checkout-hash".
5685
*/
5686
void db_set_checkout(int rid, int bWriteManifest){
5687
char *z;
5688
if( bWriteManifest ) manifest_to_disk(rid);
5689
db_lset_int("checkout", rid);
5690
if (rid != 0) {
5691
z = db_text(0,"SELECT uuid FROM blob WHERE rid=%d",rid);
5692
db_lset("checkout-hash", z);
5693
fossil_free(z);
5694
z = db_fingerprint(0, 1);
5695
db_lset("fingerprint", z);
5696
fossil_free(z);
5697
}
5698
}
5699
5700
/*
5701
** Verify that the fingerprint recorded in the "fingerprint" entry
5702
** of the VVAR table matches the fingerprint on the currently
5703
** connected repository. Return true if the fingerprint is ok, and
5704
** return false if the fingerprint does not match.
5705
*/
5706
int db_fingerprint_ok(void){
5707
char *zCkout; /* The fingerprint recorded in the check-out database */
5708
char *zRepo; /* The fingerprint of the repository */
5709
int rc; /* Result */
5710
5711
if( !db_lget_int("checkout", 0) ){
5712
/* We have an empty check-out, fingerprint is still NULL. */
5713
return 2;
5714
}
5715
zCkout = db_text(0,"SELECT value FROM localdb.vvar WHERE name='fingerprint'");
5716
if( zCkout==0 ){
5717
/* This is an older check-out that does not record a fingerprint.
5718
** We have to assume everything is ok */
5719
return 2;
5720
}
5721
zRepo = db_fingerprint(atoi(zCkout), 1);
5722
rc = fossil_strcmp(zCkout,zRepo)==0;
5723
fossil_free(zRepo);
5724
/* If the initial test fails, try again using the older fingerprint
5725
** algorithm */
5726
if( !rc ){
5727
zRepo = db_fingerprint(atoi(zCkout), 0);
5728
rc = fossil_strcmp(zCkout,zRepo)==0;
5729
fossil_free(zRepo);
5730
}
5731
fossil_free(zCkout);
5732
return rc;
5733
}
5734
5735
/*
5736
** Adds the given rid to the UNSENT table.
5737
*/
5738
void db_add_unsent(int rid){
5739
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", rid);
5740
}
5741

Keyboard Shortcuts

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