Fossil

Check-in [3f5ab717]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Clarify the difference between fossil_fatal() and fossil_panic(). The fossil_panic() interface puts a message on the error log when generating webpages. Otherwise the two routines are identical. Convert some fossil_fatal() calls into fossil_panic() where appropriate. The goal here is to limit messages on the error log to things that require attention from the system administrator, or represent bugs.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 3f5ab71744cb6e2aa400352e6e8c7df8cf9ead7c90a12d4192f58c20e289f171
User & Date: drh 2018-07-15 19:56:20.244
Context
2018-07-16
13:33
Initialize variable to quell compiler warning about potentially unitialized variable. ... (check-in: 0cb83dec user: andybradford tags: trunk)
11:35
Merge enhancements from trunk. ... (check-in: 03a9b6f8 user: drh tags: webmail)
2018-07-15
19:56
Clarify the difference between fossil_fatal() and fossil_panic(). The fossil_panic() interface puts a message on the error log when generating webpages. Otherwise the two routines are identical. Convert some fossil_fatal() calls into fossil_panic() where appropriate. The goal here is to limit messages on the error log to things that require attention from the system administrator, or represent bugs. ... (check-in: 3f5ab717 user: drh tags: trunk)
18:31
Improvements to error logging. Only log fossil_panic() calls, not fossil_fatal() calls. ... (check-in: 06d4751a user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/add.c.
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
  hardFlag = find_option("hard",0,0)!=0;

  /* We should be done with options.. */
  verify_all_options();

  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("no checkout rename files in");
  }
  if( g.argc<4 ){
    usage("OLDNAME NEWNAME");
  }
  zDest = g.argv[g.argc-1];
  db_begin_transaction();
  if( g.argv[1][0]=='r' ){ /* i.e. "rename" */







|







873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
  hardFlag = find_option("hard",0,0)!=0;

  /* We should be done with options.. */
  verify_all_options();

  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("no checkout in which to rename files");
  }
  if( g.argc<4 ){
    usage("OLDNAME NEWNAME");
  }
  zDest = g.argv[g.argc-1];
  db_begin_transaction();
  if( g.argv[1][0]=='r' ){ /* i.e. "rename" */
Changes to src/blob.c.
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
** Return a pointer to a null-terminated string for a blob that has
** been created using blob_append_sql() and not blob_appendf().  If
** text was ever added using blob_appendf() then throw an error.
*/
char *blob_sql_text(Blob *p){
  blob_is_init(p);
  if( (p->blobFlags & BLOBFLAG_NotSQL) ){
    fossil_fatal("Internal error: Use of blob_appendf() to construct SQL text");
  }
  return blob_str(p);
}


/*
** Return a pointer to a null-terminated string for a blob.







|







337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
** Return a pointer to a null-terminated string for a blob that has
** been created using blob_append_sql() and not blob_appendf().  If
** text was ever added using blob_appendf() then throw an error.
*/
char *blob_sql_text(Blob *p){
  blob_is_init(p);
  if( (p->blobFlags & BLOBFLAG_NotSQL) ){
    fossil_panic("use of blob_appendf() to construct SQL text");
  }
  return blob_str(p);
}


/*
** Return a pointer to a null-terminated string for a blob.
Changes to src/bundle.c.
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  char *zErrMsg = 0;
  char *zSql;
  if( !doInit && file_size(zFile, ExtFILE)<0 ){
    fossil_fatal("no such file: %s", zFile);
  }
  assert( g.db );
  zSql = sqlite3_mprintf("ATTACH %Q AS %Q", zFile, zBName);
  if( zSql==0 ) fossil_fatal("out of memory");
  rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
  sqlite3_free(zSql);
  if( rc!=SQLITE_OK || zErrMsg ){
    if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db);
    fossil_fatal("not a valid bundle: %s", zFile);
  }
  if( doInit ){
    db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName);
  }else{
    sqlite3_stmt *pStmt;
    zSql = sqlite3_mprintf("SELECT bcname, bcvalue"
                           "  FROM \"%w\".bconfig", zBName);
    if( zSql==0 ) fossil_fatal("out of memory");
    rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0);
    if( rc ) fossil_fatal("not a valid bundle: %s", zFile);
    sqlite3_free(zSql);
    sqlite3_finalize(pStmt);
    zSql = sqlite3_mprintf("SELECT blobid, uuid, sz, delta, notes, data"
                           "  FROM \"%w\".bblob", zBName);
    if( zSql==0 ) fossil_fatal("out of memory");
    rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0);
    if( rc ) fossil_fatal("not a valid bundle: %s", zFile);
    sqlite3_free(zSql);
    sqlite3_finalize(pStmt);
  }
}








|












|






|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  char *zErrMsg = 0;
  char *zSql;
  if( !doInit && file_size(zFile, ExtFILE)<0 ){
    fossil_fatal("no such file: %s", zFile);
  }
  assert( g.db );
  zSql = sqlite3_mprintf("ATTACH %Q AS %Q", zFile, zBName);
  if( zSql==0 ) fossil_panic("out of memory");
  rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
  sqlite3_free(zSql);
  if( rc!=SQLITE_OK || zErrMsg ){
    if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db);
    fossil_fatal("not a valid bundle: %s", zFile);
  }
  if( doInit ){
    db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName);
  }else{
    sqlite3_stmt *pStmt;
    zSql = sqlite3_mprintf("SELECT bcname, bcvalue"
                           "  FROM \"%w\".bconfig", zBName);
    if( zSql==0 ) fossil_panic("out of memory");
    rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0);
    if( rc ) fossil_fatal("not a valid bundle: %s", zFile);
    sqlite3_free(zSql);
    sqlite3_finalize(pStmt);
    zSql = sqlite3_mprintf("SELECT blobid, uuid, sz, delta, notes, data"
                           "  FROM \"%w\".bblob", zBName);
    if( zSql==0 ) fossil_panic("out of memory");
    rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0);
    if( rc ) fossil_fatal("not a valid bundle: %s", zFile);
    sqlite3_free(zSql);
    sqlite3_finalize(pStmt);
  }
}

Changes to src/db.c.
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500

/*
** Return the rowid of the most recent insert
*/
int db_last_insert_rowid(void){
  i64 x = sqlite3_last_insert_rowid(g.db);
  if( x<0 || x>(i64)2147483647 ){
    fossil_fatal("rowid out of range (0..2147483647)");
  }
  return (int)x;
}

/*
** Return the number of rows that were changed by the most recent
** INSERT, UPDATE, or DELETE.  Auxiliary changes caused by triggers







|







486
487
488
489
490
491
492
493
494
495
496
497
498
499
500

/*
** Return the rowid of the most recent insert
*/
int db_last_insert_rowid(void){
  i64 x = sqlite3_last_insert_rowid(g.db);
  if( x<0 || x>(i64)2147483647 ){
    fossil_panic("rowid out of range (0..2147483647)");
  }
  return (int)x;
}

/*
** Return the number of rows that were changed by the most recent
** INSERT, UPDATE, or DELETE.  Auxiliary changes caused by triggers
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
  size_t blobSize = 0;

  blobSize = blob_size(pKey);
  if( blobSize==0 ) return;
  fossil_get_page_size(&pageSize);
  assert( pageSize>0 );
  if( blobSize>pageSize ){
    fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize);
  }
  p = fossil_secure_alloc_page(&n);
  assert( p!=NULL );
  assert( n==pageSize );
  assert( n>=blobSize );
  memcpy(p, blob_str(pKey), blobSize);
  zSavedKey = p;







|







1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
  size_t blobSize = 0;

  blobSize = blob_size(pKey);
  if( blobSize==0 ) return;
  fossil_get_page_size(&pageSize);
  assert( pageSize>0 );
  if( blobSize>pageSize ){
    fossil_panic("key blob too large: %u versus %u", blobSize, pageSize);
  }
  p = fossil_secure_alloc_page(&n);
  assert( p!=NULL );
  assert( n==pageSize );
  assert( n>=blobSize );
  memcpy(p, blob_str(pKey), blobSize);
  zSavedKey = p;
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
){
  if( zSavedKey!=NULL ){
    size_t blobSize = blob_size(pKey);
    if( blobSize==0 ){
      db_unsave_encryption_key();
    }else{
      if( blobSize>savedKeySize ){
        fossil_fatal("key blob too large: %u versus %u",
                     blobSize, savedKeySize);
      }
      fossil_secure_zero(zSavedKey, savedKeySize);
      memcpy(zSavedKey, blob_str(pKey), blobSize);
    }
  }else{
    db_save_encryption_key(pKey);







|







1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
){
  if( zSavedKey!=NULL ){
    size_t blobSize = blob_size(pKey);
    if( blobSize==0 ){
      db_unsave_encryption_key();
    }else{
      if( blobSize>savedKeySize ){
        fossil_panic("key blob too large: %u versus %u",
                     blobSize, savedKeySize);
      }
      fossil_secure_zero(zSavedKey, savedKeySize);
      memcpy(zSavedKey, blob_str(pKey), blobSize);
    }
  }else{
    db_save_encryption_key(pKey);
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  size_t n = 0;
  size_t pageSize = 0;
  HANDLE hProcess = NULL;

  fossil_get_page_size(&pageSize);
  assert( pageSize>0 );
  if( nSize>pageSize ){
    fossil_fatal("key too large: %u versus %u", nSize, pageSize);
  }
  p = fossil_secure_alloc_page(&n);
  assert( p!=NULL );
  assert( n==pageSize );
  assert( n>=nSize );
  hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId);
  if( hProcess!=NULL ){
    SIZE_T nRead = 0;
    if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){
      CloseHandle(hProcess);
      if( nRead==nSize ){
        db_unsave_encryption_key();
        zSavedKey = p;
        savedKeySize = n;
      }else{
        fossil_fatal("bad size read, %u out of %u bytes at %p from pid %lu",
                     nRead, nSize, pAddress, processId);
      }
    }else{
      CloseHandle(hProcess);
      fossil_fatal("failed read, %u bytes at %p from pid %lu: %lu", nSize,
                   pAddress, processId, GetLastError());
    }
  }else{
    fossil_fatal("failed to open pid %lu: %lu", processId, GetLastError());
  }
}
#endif /* defined(_WIN32) */
#endif /* USE_SEE */

/*
** If the database file zDbFile has a name that suggests that it is







|















|




|



|







1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  size_t n = 0;
  size_t pageSize = 0;
  HANDLE hProcess = NULL;

  fossil_get_page_size(&pageSize);
  assert( pageSize>0 );
  if( nSize>pageSize ){
    fossil_panic("key too large: %u versus %u", nSize, pageSize);
  }
  p = fossil_secure_alloc_page(&n);
  assert( p!=NULL );
  assert( n==pageSize );
  assert( n>=nSize );
  hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId);
  if( hProcess!=NULL ){
    SIZE_T nRead = 0;
    if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){
      CloseHandle(hProcess);
      if( nRead==nSize ){
        db_unsave_encryption_key();
        zSavedKey = p;
        savedKeySize = n;
      }else{
        fossil_panic("bad size read, %u out of %u bytes at %p from pid %lu",
                     nRead, nSize, pAddress, processId);
      }
    }else{
      CloseHandle(hProcess);
      fossil_panic("failed read, %u bytes at %p from pid %lu: %lu", nSize,
                   pAddress, processId, GetLastError());
    }
  }else{
    fossil_panic("failed to open pid %lu: %lu", processId, GetLastError());
  }
}
#endif /* defined(_WIN32) */
#endif /* USE_SEE */

/*
** If the database file zDbFile has a name that suggests that it is
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
** the database connection.
**
** After calling this routine, db_database_slot(zLabel) should
** return 0.
*/
void db_set_main_schemaname(sqlite3 *db, const char *zLabel){
  if( sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, zLabel) ){
    fossil_fatal("Fossil requires a version of SQLite that supports the "
                 "SQLITE_DBCONFIG_MAINDBNAME interface.");
  }
}

/*
** Return the slot number for database zLabel.  The first database
** opened is slot 0.  The "temp" database is slot 1.  Attached databases







|







1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
** the database connection.
**
** After calling this routine, db_database_slot(zLabel) should
** return 0.
*/
void db_set_main_schemaname(sqlite3 *db, const char *zLabel){
  if( sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, zLabel) ){
    fossil_panic("Fossil requires a version of SQLite that supports the "
                 "SQLITE_DBCONFIG_MAINDBNAME interface.");
  }
}

/*
** Return the slot number for database zLabel.  The first database
** opened is slot 0.  The "temp" database is slot 1.  Attached databases
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
        char *zPath = fossil_getenv("HOMEPATH");
        if( zDrive && zPath ) zHome = mprintf("%s%s", zDrive, zPath);
      }
    }
  }
  if( zHome==0 ){
    if( isOptional ) return 0;
    fossil_fatal("cannot locate home directory - please set the "
                 "FOSSIL_HOME, LOCALAPPDATA, APPDATA, or HOMEPATH "
                 "environment variables");
  }
#else
  if( zHome==0 ){
    zHome = fossil_getenv("HOME");
  }
  if( zHome==0 ){
    if( isOptional ) return 0;
    fossil_fatal("cannot locate home directory - please set the "
                 "FOSSIL_HOME or HOME environment variables");
  }
#endif
  if( file_isdir(zHome, ExtFILE)!=1 ){
    if( isOptional ) return 0;
    fossil_fatal("invalid home directory: %s", zHome);
  }
#if defined(_WIN32) || defined(__CYGWIN__)
  /* . filenames give some window systems problems and many apps problems */
  zDbName = mprintf("%//_fossil", zHome);
#else
  zDbName = mprintf("%s/.fossil", zHome);
#endif
  if( file_size(zDbName, ExtFILE)<1024*3 ){
    if( file_access(zHome, W_OK) ){
      if( isOptional ) return 0;
      fossil_fatal("home directory %s must be writeable", zHome);
    }
    db_init_database(zDbName, zConfigSchema, (char*)0);
  }
  if( file_access(zDbName, W_OK) ){
    if( isOptional ) return 0;
    fossil_fatal("configuration file %s must be writeable", zDbName);
  }
  if( useAttach ){
    db_open_or_attach(zDbName, "configdb");
    g.dbConfig = 0;
  }else{
    g.dbConfig = db_open(zDbName);
    db_set_main_schemaname(g.dbConfig, "configdb");







|









|





|










|





|







1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
        char *zPath = fossil_getenv("HOMEPATH");
        if( zDrive && zPath ) zHome = mprintf("%s%s", zDrive, zPath);
      }
    }
  }
  if( zHome==0 ){
    if( isOptional ) return 0;
    fossil_panic("cannot locate home directory - please set the "
                 "FOSSIL_HOME, LOCALAPPDATA, APPDATA, or HOMEPATH "
                 "environment variables");
  }
#else
  if( zHome==0 ){
    zHome = fossil_getenv("HOME");
  }
  if( zHome==0 ){
    if( isOptional ) return 0;
    fossil_panic("cannot locate home directory - please set the "
                 "FOSSIL_HOME or HOME environment variables");
  }
#endif
  if( file_isdir(zHome, ExtFILE)!=1 ){
    if( isOptional ) return 0;
    fossil_panic("invalid home directory: %s", zHome);
  }
#if defined(_WIN32) || defined(__CYGWIN__)
  /* . filenames give some window systems problems and many apps problems */
  zDbName = mprintf("%//_fossil", zHome);
#else
  zDbName = mprintf("%s/.fossil", zHome);
#endif
  if( file_size(zDbName, ExtFILE)<1024*3 ){
    if( file_access(zHome, W_OK) ){
      if( isOptional ) return 0;
      fossil_panic("home directory %s must be writeable", zHome);
    }
    db_init_database(zDbName, zConfigSchema, (char*)0);
  }
  if( file_access(zDbName, W_OK) ){
    if( isOptional ) return 0;
    fossil_panic("configuration file %s must be writeable", zDbName);
  }
  if( useAttach ){
    db_open_or_attach(zDbName, "configdb");
    g.dbConfig = 0;
  }else{
    g.dbConfig = db_open(zDbName);
    db_set_main_schemaname(g.dbConfig, "configdb");
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
  }
rep_not_found:
  if( (bFlags & OPEN_OK_NOT_FOUND)==0 ){
#ifdef FOSSIL_ENABLE_JSON
    g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
#endif
    if( nArgUsed==0 ){
      fossil_fatal("use --repository or -R to specify the repository database");
    }else{
      fossil_fatal("specify the repository name as a command-line argument");
    }
  }
}

/*
** Return TRUE if the schema is out-of-date
*/







|

|







1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
  }
rep_not_found:
  if( (bFlags & OPEN_OK_NOT_FOUND)==0 ){
#ifdef FOSSIL_ENABLE_JSON
    g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
#endif
    if( nArgUsed==0 ){
      fossil_panic("use --repository or -R to specify the repository database");
    }else{
      fossil_panic("specify the repository name as a command-line argument");
    }
  }
}

/*
** Return TRUE if the schema is out-of-date
*/
Changes to src/dispatch.c.
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  if( z[i]=='?' ){
    z[i] = 0;
    zQ = &z[i+1];
  }else{
    zQ = &z[i];
  }
  if( dispatch_name_search(z, CMDFLAG_WEBPAGE, ppCmd) ){
    fossil_fatal("\"%s\" aliased to \"%s\" but \"%s\" does not exist",
                 zName, z, z);
  }
  z = zQ;
  while( *z ){
    char *zName = z;
    char *zValue = 0;
    while( *z && *z!='=' && *z!='&' && *z!='!' ){ z++; }







|







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  if( z[i]=='?' ){
    z[i] = 0;
    zQ = &z[i+1];
  }else{
    zQ = &z[i];
  }
  if( dispatch_name_search(z, CMDFLAG_WEBPAGE, ppCmd) ){
    fossil_panic("\"%s\" aliased to \"%s\" but \"%s\" does not exist",
                 zName, z, z);
  }
  z = zQ;
  while( *z ){
    char *zName = z;
    char *zValue = 0;
    while( *z && *z!='=' && *z!='&' && *z!='!' ){ z++; }
Changes to src/doc.c.
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
** Verify that all entries in the aMime[] table are in sorted order.
** Abort with a fatal error if any is out-of-order.
*/
static void mimetype_verify(void){
  int i;
  for(i=1; i<count(aMime); i++){
    if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){
      fossil_fatal("mimetypes out of sequence: %s before %s",
                   aMime[i-1].zSuffix, aMime[i].zSuffix);
    }
  }
}

/*
** Guess the mime-type of a document based on its name.







|







296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
** Verify that all entries in the aMime[] table are in sorted order.
** Abort with a fatal error if any is out-of-order.
*/
static void mimetype_verify(void){
  int i;
  for(i=1; i<count(aMime); i++){
    if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){
      fossil_panic("mimetypes out of sequence: %s before %s",
                   aMime[i-1].zSuffix, aMime[i].zSuffix);
    }
  }
}

/*
** Guess the mime-type of a document based on its name.
Changes to src/event.c.
585
586
587
588
589
590
591
592
593
594
595

  user_select();
  if (event_commit_common(rid, zId, blob_str(pContent), zETime,
      zMimeType, zComment, zTags, zClr)==0 ){
#ifdef FOSSIL_ENABLE_JSON
    g.json.resultCode = FSL_JSON_E_ASSERT;
#endif
    fossil_fatal("Internal error: Fossil tried to make an "
                 "invalid artifact for the technote.");
  }
}







|



585
586
587
588
589
590
591
592
593
594
595

  user_select();
  if (event_commit_common(rid, zId, blob_str(pContent), zETime,
      zMimeType, zComment, zTags, zClr)==0 ){
#ifdef FOSSIL_ENABLE_JSON
    g.json.resultCode = FSL_JSON_E_ASSERT;
#endif
    fossil_panic("Internal error: Fossil tried to make an "
                 "invalid artifact for the technote.");
  }
}
Changes to src/file.c.
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
*/
void file_getcwd(char *zBuf, int nBuf){
#ifdef _WIN32
  win32_getcwd(zBuf, nBuf);
#else
  if( getcwd(zBuf, nBuf-1)==0 ){
    if( errno==ERANGE ){
      fossil_fatal("pwd too big: max %d", nBuf-1);
    }else{
      fossil_fatal("cannot find current working directory; %s",
                   strerror(errno));
    }
  }
#endif
}

/*







|

|







894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
*/
void file_getcwd(char *zBuf, int nBuf){
#ifdef _WIN32
  win32_getcwd(zBuf, nBuf);
#else
  if( getcwd(zBuf, nBuf-1)==0 ){
    if( errno==ERANGE ){
      fossil_panic("pwd too big: max %d", nBuf-1);
    }else{
      fossil_panic("cannot find current working directory; %s",
                   strerror(errno));
    }
  }
#endif
}

/*
Changes to src/http_ssl.c.
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
    if( zCaSetting==0 || zCaSetting[0]=='\0' ){
      /* CA location not specified, use platform's default certificate store */
      X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
    }else{
      /* User has specified a CA location, make sure it exists and use it */
      switch( file_isdir(zCaSetting, ExtFILE) ){
        case 0: { /* doesn't exist */
          fossil_fatal("ssl-ca-location is set to '%s', "
              "but is not a file or directory", zCaSetting);
          break;
        }
        case 1: { /* directory */
          zCaDirectory = zCaSetting;
          break;
        }
        case 2: { /* file */
          zCaFile = zCaSetting;
          break;
        }
      }
      if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
        fossil_fatal("Failed to use CA root certificates from "
          "ssl-ca-location '%s'", zCaSetting);
      }
    }

    /* Load client SSL identity, preferring the filename specified on the
    ** command line */
    if( g.zSSLIdentity!=0 ){
      identityFile = g.zSSLIdentity;
    }else{
      identityFile = db_get("ssl-identity", 0);
    }
    if( identityFile!=0 && identityFile[0]!='\0' ){
      if( SSL_CTX_use_certificate_file(sslCtx,identityFile,SSL_FILETYPE_PEM)!=1
       || SSL_CTX_use_PrivateKey_file(sslCtx,identityFile,SSL_FILETYPE_PEM)!=1
      ){
        fossil_fatal("Could not load SSL identity from %s", identityFile);
      }
    }
    /* Register a callback to tell the user what to do when the server asks
    ** for a cert */
    SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);

    sslIsInit = 1;







|













|















|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
    if( zCaSetting==0 || zCaSetting[0]=='\0' ){
      /* CA location not specified, use platform's default certificate store */
      X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
    }else{
      /* User has specified a CA location, make sure it exists and use it */
      switch( file_isdir(zCaSetting, ExtFILE) ){
        case 0: { /* doesn't exist */
          fossil_panic("ssl-ca-location is set to '%s', "
              "but is not a file or directory", zCaSetting);
          break;
        }
        case 1: { /* directory */
          zCaDirectory = zCaSetting;
          break;
        }
        case 2: { /* file */
          zCaFile = zCaSetting;
          break;
        }
      }
      if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
        fossil_panic("Failed to use CA root certificates from "
          "ssl-ca-location '%s'", zCaSetting);
      }
    }

    /* Load client SSL identity, preferring the filename specified on the
    ** command line */
    if( g.zSSLIdentity!=0 ){
      identityFile = g.zSSLIdentity;
    }else{
      identityFile = db_get("ssl-identity", 0);
    }
    if( identityFile!=0 && identityFile[0]!='\0' ){
      if( SSL_CTX_use_certificate_file(sslCtx,identityFile,SSL_FILETYPE_PEM)!=1
       || SSL_CTX_use_PrivateKey_file(sslCtx,identityFile,SSL_FILETYPE_PEM)!=1
      ){
        fossil_panic("Could not load SSL identity from %s", identityFile);
      }
    }
    /* Register a callback to tell the user what to do when the server asks
    ** for a cert */
    SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);

    sslIsInit = 1;
Changes to src/http_transport.c.
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
    blob_append_escaped_arg(&zCmd, zHost);
    fossil_free(zHost);
  }else{
    blob_append_escaped_arg(&zCmd, pUrlData->name);
  }
  if( !is_safe_fossil_command(pUrlData->fossil) ){
    fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on "
                 "the server.", pUrlData->fossil);
  }
  blob_append_escaped_arg(&zCmd, pUrlData->fossil);
  blob_append(&zCmd, " test-http", 10);
  if( pUrlData->path && pUrlData->path[0] ){
    blob_append_escaped_arg(&zCmd, pUrlData->path);
  }else{
    fossil_fatal("ssh:// URI does not specify a path to the repository");
  }
  if( g.fSshTrace ){
    fossil_print("%s\n", blob_str(&zCmd));  /* Show the whole SSH command */
  }
  popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
  if( sshPid==0 ){
    socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);







|







|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
    blob_append_escaped_arg(&zCmd, zHost);
    fossil_free(zHost);
  }else{
    blob_append_escaped_arg(&zCmd, pUrlData->name);
  }
  if( !is_safe_fossil_command(pUrlData->fossil) ){
    fossil_panic("the ssh:// URL is asking to run an unsafe command [%s] on "
                 "the server.", pUrlData->fossil);
  }
  blob_append_escaped_arg(&zCmd, pUrlData->fossil);
  blob_append(&zCmd, " test-http", 10);
  if( pUrlData->path && pUrlData->path[0] ){
    blob_append_escaped_arg(&zCmd, pUrlData->path);
  }else{
    fossil_panic("ssh:// URI does not specify a path to the repository");
  }
  if( g.fSshTrace ){
    fossil_print("%s\n", blob_str(&zCmd));  /* Show the whole SSH command */
  }
  popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
  if( sshPid==0 ){
    socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
      sqlite3_randomness(sizeof(iRandId), &iRandId);
      transport.zOutFile = mprintf("%s-%llu-out.http",
                                       g.zRepositoryName, iRandId);
      transport.zInFile = mprintf("%s-%llu-in.http",
                                       g.zRepositoryName, iRandId);
      transport.pFile = fossil_fopen(transport.zOutFile, "wb");
      if( transport.pFile==0 ){
        fossil_fatal("cannot output temporary file: %s", transport.zOutFile);
      }
      transport.isOpen = 1;
    }else{
      rc = socket_open(pUrlData);
      if( rc==0 ) transport.isOpen = 1;
    }
  }







|







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
      sqlite3_randomness(sizeof(iRandId), &iRandId);
      transport.zOutFile = mprintf("%s-%llu-out.http",
                                       g.zRepositoryName, iRandId);
      transport.zInFile = mprintf("%s-%llu-in.http",
                                       g.zRepositoryName, iRandId);
      transport.pFile = fossil_fopen(transport.zOutFile, "wb");
      if( transport.pFile==0 ){
        fossil_panic("cannot output temporary file: %s", transport.zOutFile);
      }
      transport.isOpen = 1;
    }else{
      rc = socket_open(pUrlData);
      if( rc==0 ) transport.isOpen = 1;
    }
  }
Changes to src/import.c.
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
      fossil_free(gg.aData); gg.aData = 0;
      gg.nData = atoi(&zLine[5]);
      if( gg.nData ){
        int got;
        gg.aData = fossil_malloc( gg.nData+1 );
        got = fread(gg.aData, 1, gg.nData, pIn);
        if( got!=gg.nData ){
          fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
        }
        gg.aData[got] = '\0';
        if( gg.zComment==0 &&
            (gg.xFinish==finish_commit || gg.xFinish==finish_tag) ){
	  /* Strip trailing newline, it's appended to the comment. */
	  if( gg.aData[got-1] == '\n' )
	    gg.aData[got-1] = '\0';







|







604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
      fossil_free(gg.aData); gg.aData = 0;
      gg.nData = atoi(&zLine[5]);
      if( gg.nData ){
        int got;
        gg.aData = fossil_malloc( gg.nData+1 );
        got = fread(gg.aData, 1, gg.nData, pIn);
        if( got!=gg.nData ){
          fossil_panic("short read: got %d of %d bytes", got, gg.nData);
        }
        gg.aData[got] = '\0';
        if( gg.zComment==0 &&
            (gg.xFinish==finish_commit || gg.xFinish==finish_tag) ){
	  /* Strip trailing newline, it's appended to the comment. */
	  if( gg.aData[got-1] == '\n' )
	    gg.aData[got-1] = '\0';
Changes to src/json.c.
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
      break;
    }
    inFile = (0==strcmp("-",jfile))
      ? stdin
      : fossil_fopen(jfile,"rb");
    if(!inFile){
      g.json.resultCode = FSL_JSON_E_FILE_OPEN_FAILED;
      fossil_fatal("Could not open JSON file [%s].",jfile)
        /* Does not return. */
        ;
    }
    cgi_parse_POST_JSON(inFile, 0);
    if( stdin != inFile ){
      fclose(inFile);
    }







|







994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
      break;
    }
    inFile = (0==strcmp("-",jfile))
      ? stdin
      : fossil_fopen(jfile,"rb");
    if(!inFile){
      g.json.resultCode = FSL_JSON_E_FILE_OPEN_FAILED;
      fossil_panic("Could not open JSON file [%s].",jfile)
        /* Does not return. */
        ;
    }
    cgi_parse_POST_JSON(inFile, 0);
    if( stdin != inFile ){
      fclose(inFile);
    }
Changes to src/json_branch.c.
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

  blob_appendf(&branch, "U %F\n", g.zLogin);
  md5sum_blob(&branch, &mcksum);
  blob_appendf(&branch, "Z %b\n", &mcksum);

  brid = content_put(&branch);
  if( brid==0 ){
    fossil_fatal("Problem committing manifest: %s", g.zErrMsg);
  }
  db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
  if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
    fossil_fatal("%s", g.zErrMsg);
  }
  assert( blob_is_reset(&branch) );
  content_deltify(rootid, &brid, 1, 0);
  if( zNewRid ){
    *zNewRid = brid;
  }








|



|







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

  blob_appendf(&branch, "U %F\n", g.zLogin);
  md5sum_blob(&branch, &mcksum);
  blob_appendf(&branch, "Z %b\n", &mcksum);

  brid = content_put(&branch);
  if( brid==0 ){
    fossil_panic("Problem committing manifest: %s", g.zErrMsg);
  }
  db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
  if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
    fossil_panic("%s", g.zErrMsg);
  }
  assert( blob_is_reset(&branch) );
  content_deltify(rootid, &brid, 1, 0);
  if( zNewRid ){
    *zNewRid = brid;
  }

Changes to src/json_status.c.
166
167
168
169
170
171
172
173
174
175
176
177
178
179
      case -4:  zLabel = "INTEGRATE  ";  break;
    }
    blob_append(report, zPrefix, nPrefix);
    blob_appendf(report, "%s %s\n", zLabel, db_column_text(&q, 0));
  }
  db_finalize(&q);
  if( nErr ){
    fossil_fatal("aborting due to prior errors");
  }
#endif
  return cson_object_value( oPay );
}

#endif /* FOSSIL_ENABLE_JSON */







|






166
167
168
169
170
171
172
173
174
175
176
177
178
179
      case -4:  zLabel = "INTEGRATE  ";  break;
    }
    blob_append(report, zPrefix, nPrefix);
    blob_appendf(report, "%s %s\n", zLabel, db_column_text(&q, 0));
  }
  db_finalize(&q);
  if( nErr ){
    fossil_panic("aborting due to prior errors");
  }
#endif
  return cson_object_value( oPay );
}

#endif /* FOSSIL_ENABLE_JSON */
Changes to src/main.c.
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
{
  const char *zCmdName = "unknown";
  const CmdOrPage *pCmd = 0;
  int rc;

  fossil_limit_memory(1);
  if( sqlite3_libversion_number()<3014000 ){
    fossil_fatal("Unsuitable SQLite version %s, must be at least 3.14.0",
                 sqlite3_libversion());
  }
  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
  memset(&g, 0, sizeof(g));
  g.now = time(0);
  g.httpHeader = empty_blob;







|







595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
{
  const char *zCmdName = "unknown";
  const CmdOrPage *pCmd = 0;
  int rc;

  fossil_limit_memory(1);
  if( sqlite3_libversion_number()<3014000 ){
    fossil_panic("Unsuitable SQLite version %s, must be at least 3.14.0",
                 sqlite3_libversion());
  }
  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
  memset(&g, 0, sizeof(g));
  g.now = time(0);
  g.httpHeader = empty_blob;
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
    g.zVfsName = fossil_getenv("FOSSIL_VFS");
  }
  if( g.zVfsName ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(g.zVfsName);
    if( pVfs ){
      sqlite3_vfs_register(pVfs, 1);
    }else{
      fossil_fatal("no such VFS: \"%s\"", g.zVfsName);
    }
  }
  if( fossil_getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
    zCmdName = "cgi";
    g.isHTTP = 1;
  }else if( g.argc<2 && !fossilExeHasAppendedRepo() ){
    fossil_print(







|







633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
    g.zVfsName = fossil_getenv("FOSSIL_VFS");
  }
  if( g.zVfsName ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(g.zVfsName);
    if( pVfs ){
      sqlite3_vfs_register(pVfs, 1);
    }else{
      fossil_panic("no such VFS: \"%s\"", g.zVfsName);
    }
  }
  if( fossil_getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
    zCmdName = "cgi";
    g.isHTTP = 1;
  }else if( g.argc<2 && !fossilExeHasAppendedRepo() ){
    fossil_print(
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
    g.zLogin = find_option("user", "U", 1);
    g.zSSLIdentity = find_option("ssl-identity", 0, 1);
    g.zErrlog = find_option("errorlog", 0, 1);
    fossil_init_flags_from_options();
    if( find_option("utc",0,0) ) g.fTimeFormat = 1;
    if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
    if( zChdir && file_chdir(zChdir, 0) ){
      fossil_fatal("unable to change directories to %s", zChdir);
    }
    if( find_option("help",0,0)!=0 ){
      /* If --help is found anywhere on the command line, translate the command
       * to "fossil help cmdname" where "cmdname" is the first argument that
       * does not begin with a "-" character.  If all arguments start with "-",
       * translate to "fossil help argv[1] argv[2]...". */
      int i, nNewArgc;







|







684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
    g.zLogin = find_option("user", "U", 1);
    g.zSSLIdentity = find_option("ssl-identity", 0, 1);
    g.zErrlog = find_option("errorlog", 0, 1);
    fossil_init_flags_from_options();
    if( find_option("utc",0,0) ) g.fTimeFormat = 1;
    if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
    if( zChdir && file_chdir(zChdir, 0) ){
      fossil_panic("unable to change directories to %s", zChdir);
    }
    if( find_option("help",0,0)!=0 ){
      /* If --help is found anywhere on the command line, translate the command
       * to "fossil help cmdname" where "cmdname" is the first argument that
       * does not begin with a "-" character.  If all arguments start with "-",
       * translate to "fossil help argv[1] argv[2]...". */
      int i, nNewArgc;
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
      if( fd>=2 ) break;
      if( fd<0 ) x = errno;
    }while( nTry++ < 2 );
    if( fd<2 ){
      g.cgiOutput = 1;
      g.httpOut = stdout;
      g.fullHttpReply = !g.isHTTP;
      fossil_fatal("file descriptor 2 is not open. (fd=%d, errno=%d)",
                   fd, x);
    }
  }
#endif
  rc = dispatch_name_search(zCmdName, CMDFLAG_COMMAND|CMDFLAG_PREFIX, &pCmd);
  if( rc==1 ){
#ifdef FOSSIL_ENABLE_TH1_HOOKS
    if( !g.isHTTP && !g.fNoThHook ){
      rc = Th_CommandHook(zCmdName, 0);
    }else{
      rc = TH_OK;
    }
    if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
      if( rc==TH_OK || rc==TH_RETURN ){
#endif
        fossil_fatal("%s: unknown command: %s\n"
                     "%s: use \"help\" for more information",
                     g.argv[0], zCmdName, g.argv[0]);
#ifdef FOSSIL_ENABLE_TH1_HOOKS
      }
      if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
        Th_CommandNotify(zCmdName, 0);
      }







|















|







733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
      if( fd>=2 ) break;
      if( fd<0 ) x = errno;
    }while( nTry++ < 2 );
    if( fd<2 ){
      g.cgiOutput = 1;
      g.httpOut = stdout;
      g.fullHttpReply = !g.isHTTP;
      fossil_panic("file descriptor 2 is not open. (fd=%d, errno=%d)",
                   fd, x);
    }
  }
#endif
  rc = dispatch_name_search(zCmdName, CMDFLAG_COMMAND|CMDFLAG_PREFIX, &pCmd);
  if( rc==1 ){
#ifdef FOSSIL_ENABLE_TH1_HOOKS
    if( !g.isHTTP && !g.fNoThHook ){
      rc = Th_CommandHook(zCmdName, 0);
    }else{
      rc = TH_OK;
    }
    if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
      if( rc==TH_OK || rc==TH_RETURN ){
#endif
        fossil_panic("%s: unknown command: %s\n"
                     "%s: use \"help\" for more information",
                     g.argv[0], zCmdName, g.argv[0]);
#ifdef FOSSIL_ENABLE_TH1_HOOKS
      }
      if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
        Th_CommandNotify(zCmdName, 0);
      }
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
  return 0;
}

/*
** Print a usage comment and quit
*/
void usage(const char *zFormat){
  fossil_fatal("Usage: %s %s %s", g.argv[0], g.argv[1], zFormat);
}

/*
** Remove n elements from g.argv beginning with the i-th element.
*/
static void remove_from_argv(int i, int n){
  int j;







|







814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
  return 0;
}

/*
** Print a usage comment and quit
*/
void usage(const char *zFormat){
  fossil_panic("Usage: %s %s %s", g.argv[0], g.argv[1], zFormat);
}

/*
** Remove n elements from g.argv beginning with the i-th element.
*/
static void remove_from_argv(int i, int n){
  int j;
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
** Any remaining command-line argument begins with "-" print
** an error message and quit.
*/
void verify_all_options(void){
  int i;
  for(i=1; i<g.argc; i++){
    if( g.argv[i][0]=='-' && g.argv[i][1]!=0 ){
      fossil_fatal(
        "unrecognized command-line option, or missing argument: %s",
        g.argv[i]);
    }
  }
}

/*







|







932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
** Any remaining command-line argument begins with "-" print
** an error message and quit.
*/
void verify_all_options(void){
  int i;
  for(i=1; i<g.argc; i++){
    if( g.argv[i][0]=='-' && g.argv[i][1]!=0 ){
      fossil_panic(
        "unrecognized command-line option, or missing argument: %s",
        g.argv[i]);
    }
  }
}

/*
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
    if( strncmp(g.zTop, "http://", 7)==0 ){
      /* it is HTTP, replace prefix with HTTPS. */
      g.zHttpsURL = mprintf("https://%s", &g.zTop[7]);
    }else if( strncmp(g.zTop, "https://", 8)==0 ){
      /* it is already HTTPS, use it. */
      g.zHttpsURL = mprintf("%s", g.zTop);
    }else{
      fossil_fatal("argument to --baseurl should be 'http://host/path'"
                   " or 'https://host/path'");
    }
    for(i=n=0; (c = g.zTop[i])!=0; i++){
      if( c=='/' ){
        n++;
        if( n==3 ){
          g.zTop += i;
          break;
        }
      }
    }
    if( g.zTop==g.zBaseURL ){
      fossil_fatal("argument to --baseurl should be 'http://host/path'"
                   " or 'https://host/path'");
    }
    if( g.zTop[1]==0 ) g.zTop++;
  }else{
    zHost = PD("HTTP_HOST","");
    zMode = PD("HTTPS","off");
    zCur = PD("SCRIPT_NAME","/");







|












|







1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
    if( strncmp(g.zTop, "http://", 7)==0 ){
      /* it is HTTP, replace prefix with HTTPS. */
      g.zHttpsURL = mprintf("https://%s", &g.zTop[7]);
    }else if( strncmp(g.zTop, "https://", 8)==0 ){
      /* it is already HTTPS, use it. */
      g.zHttpsURL = mprintf("%s", g.zTop);
    }else{
      fossil_panic("argument to --baseurl should be 'http://host/path'"
                   " or 'https://host/path'");
    }
    for(i=n=0; (c = g.zTop[i])!=0; i++){
      if( c=='/' ){
        n++;
        if( n==3 ){
          g.zTop += i;
          break;
        }
      }
    }
    if( g.zTop==g.zBaseURL ){
      fossil_panic("argument to --baseurl should be 'http://host/path'"
                   " or 'https://host/path'");
    }
    if( g.zTop[1]==0 ) g.zTop++;
  }else{
    zHost = PD("HTTP_HOST","");
    zMode = PD("HTTPS","off");
    zCur = PD("SCRIPT_NAME","/");
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
    }

    file_canonical_name(zRepo, &dir, 0);
    zDir = blob_str(&dir);
    if( !noJail ){
      if( file_isdir(zDir, ExtFILE)==1 ){
        if( file_chdir(zDir, 1) ){
          fossil_fatal("unable to chroot into %s", zDir);
        }
        g.fJail = 1;
        zRepo = "/";
      }else{
        for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){}
        if( zDir[i]!='/' ) fossil_fatal("bad repository name: %s", zRepo);
        if( i>0 ){
          zDir[i] = 0;
          if( file_chdir(zDir, 1) ){
            fossil_fatal("unable to chroot into %s", zDir);
          }
          zDir[i] = '/';
        }
        zRepo = &zDir[i];
      }
    }
    if( stat(zRepo, &sStat)!=0 ){
      fossil_fatal("cannot stat() repository: %s", zRepo);
    }
    i = setgid(sStat.st_gid);
    i = i || setuid(sStat.st_uid);
    if(i){
      fossil_fatal("setgid/uid() failed with errno %d", errno);
    }
    if( g.db==0 && file_isfile(zRepo, ExtFILE) ){
      db_open_repository(zRepo);
    }
  }
#endif
  return zRepo;







|





|



|







|




|







1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
    }

    file_canonical_name(zRepo, &dir, 0);
    zDir = blob_str(&dir);
    if( !noJail ){
      if( file_isdir(zDir, ExtFILE)==1 ){
        if( file_chdir(zDir, 1) ){
          fossil_panic("unable to chroot into %s", zDir);
        }
        g.fJail = 1;
        zRepo = "/";
      }else{
        for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){}
        if( zDir[i]!='/' ) fossil_panic("bad repository name: %s", zRepo);
        if( i>0 ){
          zDir[i] = 0;
          if( file_chdir(zDir, 1) ){
            fossil_panic("unable to chroot into %s", zDir);
          }
          zDir[i] = '/';
        }
        zRepo = &zDir[i];
      }
    }
    if( stat(zRepo, &sStat)!=0 ){
      fossil_panic("cannot stat() repository: %s", zRepo);
    }
    i = setgid(sStat.st_gid);
    i = i || setuid(sStat.st_uid);
    if(i){
      fossil_panic("setgid/uid() failed with errno %d", errno);
    }
    if( g.db==0 && file_isfile(zRepo, ExtFILE) ){
      db_open_repository(zRepo);
    }
  }
#endif
  return zRepo;
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
  LPVOID *ppAddress,   /* The extracted pointer value. */
  SIZE_T *pnSize       /* The extracted size value. */
){
  unsigned int nSize = 0;
  if( sscanf(zPidKey, "%lu:%p:%u", pProcessId, ppAddress, &nSize)==3 ){
    *pnSize = (SIZE_T)nSize;
  }else{
    fossil_fatal("failed to parse pid key");
  }
}
#endif

/*
** undocumented format:
**







|







2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
  LPVOID *ppAddress,   /* The extracted pointer value. */
  SIZE_T *pnSize       /* The extracted size value. */
){
  unsigned int nSize = 0;
  if( sscanf(zPidKey, "%lu:%p:%u", pProcessId, ppAddress, &nSize)==3 ){
    *pnSize = (SIZE_T)nSize;
  }else{
    fossil_panic("failed to parse pid key");
  }
}
#endif

/*
** undocumented format:
**
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
  }
#endif

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){
    fossil_fatal("no repository specified");
  }
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  if( g.argc>=5 ){
    g.httpIn = fossil_fopen(g.argv[2], "rb");
    g.httpOut = fossil_fopen(g.argv[3], "wb");
    zIpAddr = g.argv[4];







|







2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
  }
#endif

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){
    fossil_panic("no repository specified");
  }
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  if( g.argc>=5 ){
    g.httpIn = fossil_fopen(g.argv[2], "rb");
    g.httpOut = fossil_fopen(g.argv[3], "wb");
    zIpAddr = g.argv[4];
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
                            zBrowser, zIpAddr, zInitPage);
    }
  }
  if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
  if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
  db_close(1);
  if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
    fossil_fatal("unable to listen on TCP socket %d", iPort);
  }
  if( zMaxLatency ){
    signal(SIGALRM, sigalrm_handler);
    alarm(atoi(zMaxLatency));
  }
  g.httpIn = stdin;
  g.httpOut = stdout;







|







2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
                            zBrowser, zIpAddr, zInitPage);
    }
  }
  if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
  if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
  db_close(1);
  if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
    fossil_panic("unable to listen on TCP socket %d", iPort);
  }
  if( zMaxLatency ){
    signal(SIGALRM, sigalrm_handler);
    alarm(atoi(zMaxLatency));
  }
  g.httpIn = stdin;
  g.httpOut = stdout;
Changes to src/manifest.c.
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
      if( !throwError ){
        db_multi_exec(
           "INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)",
           p->rid, rid
        );
        return 1;
      }
      fossil_fatal("cannot access baseline manifest %S", p->zBaseline);
    }
  }
  return 0;
}

/*
** Rewind a manifest-file iterator back to the beginning of the manifest.







|







1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
      if( !throwError ){
        db_multi_exec(
           "INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)",
           p->rid, rid
        );
        return 1;
      }
      fossil_panic("cannot access baseline manifest %S", p->zBaseline);
    }
  }
  return 0;
}

/*
** Rewind a manifest-file iterator back to the beginning of the manifest.
Changes to src/popen.c.
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#ifdef _WIN32
#include <windows.h>
#include <fcntl.h>
/*
** Print a fatal error and quit.
*/
static void win32_fatal_error(const char *zMsg){
  fossil_fatal("%s", zMsg);
}
#else
#include <signal.h>
#include <sys/wait.h>
#endif

/*







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#ifdef _WIN32
#include <windows.h>
#include <fcntl.h>
/*
** Print a fatal error and quit.
*/
static void win32_fatal_error(const char *zMsg){
  fossil_panic("%s", zMsg);
}
#else
#include <signal.h>
#include <sys/wait.h>
#endif

/*
Changes to src/printf.c.
1057
1058
1059
1060
1061
1062
1063






1064
1065
1066
1067
1068
1069
1070
  }
  return rc;
}

/*
** Print an error message, rollback all databases, and quit.  These
** routines never return.






**
** Use fossil_fatal() for malformed inputs that should be reported back
** to the user, but which do not represent a configuration problem or bug.
**
** Use fossil_panic() for any kind of error that should be brought to the
** attention of the system administrator.
*/







>
>
>
>
>
>







1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
  }
  return rc;
}

/*
** Print an error message, rollback all databases, and quit.  These
** routines never return.
**
** The only different between fossil_fatal() and fossil_panic() is that
** fossil_panic() makes an entry in the error log whereas fossil_fatal()
** does not.  If there is not error log, then both routines work the
** same.  Hence, the routines are interchangable for commands and only
** make a difference with processing web pages.
**
** Use fossil_fatal() for malformed inputs that should be reported back
** to the user, but which do not represent a configuration problem or bug.
**
** Use fossil_panic() for any kind of error that should be brought to the
** attention of the system administrator.
*/
Changes to src/purge.c.
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    return 0;
  }

  /* Make sure we are not removing a manifest that is the baseline of some
  ** manifest that is being left behind.  This step is not strictly necessary.
  ** is is just a safety check. */
  if( purge_baseline_out_from_under_delta(zTab) ){
    fossil_fatal("attempt to purge a baseline manifest without also purging "
                 "all of its deltas");
  }

  /* Make sure that no delta that is left behind requires a purged artifact
  ** as its basis.  If such artifacts exist, go ahead and undelta them now.
  */
  db_prepare(&q, "SELECT rid FROM delta WHERE srcid IN \"%w\""







|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    return 0;
  }

  /* Make sure we are not removing a manifest that is the baseline of some
  ** manifest that is being left behind.  This step is not strictly necessary.
  ** is is just a safety check. */
  if( purge_baseline_out_from_under_delta(zTab) ){
    fossil_panic("attempt to purge a baseline manifest without also purging "
                 "all of its deltas");
  }

  /* Make sure that no delta that is left behind requires a purged artifact
  ** as its basis.  If such artifacts exist, go ahead and undelta them now.
  */
  db_prepare(&q, "SELECT rid FROM delta WHERE srcid IN \"%w\""
Changes to src/skins.c.
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/*
** Return a skin detail setting
*/
const char *skin_detail(const char *zName){
  struct SkinDetail *pDetail;
  skin_detail_initialize();
  pDetail = skin_detail_find(zName);
  if( pDetail==0 ) fossil_fatal("no such skin detail: %s", zName);
  return pDetail->zValue;
}
int skin_detail_boolean(const char *zName){
  return !is_false(skin_detail(zName));
}

/*







|







252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/*
** Return a skin detail setting
*/
const char *skin_detail(const char *zName){
  struct SkinDetail *pDetail;
  skin_detail_initialize();
  pDetail = skin_detail_find(zName);
  if( pDetail==0 ) fossil_panic("no such skin detail: %s", zName);
  return pDetail->zValue;
}
int skin_detail_boolean(const char *zName){
  return !is_false(skin_detail(zName));
}

/*
Changes to src/sqlcmd.c.
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    *pzKey = zKey;
    if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
      *pnKey = (int)strlen(zKey);
    }else{
      *pnKey = -1;
    }
  }else{
    fossil_fatal("failed to allocate %u bytes for key", nByte);
  }
}
#endif

/*
** This routine closes the Fossil databases and/or invalidates the global
** state variables that keep track of them.







|







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    *pzKey = zKey;
    if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
      *pnKey = (int)strlen(zKey);
    }else{
      *pnKey = -1;
    }
  }else{
    fossil_panic("failed to allocate %u bytes for key", nByte);
  }
}
#endif

/*
** This routine closes the Fossil databases and/or invalidates the global
** state variables that keep track of them.
Changes to src/tar.c.
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  if(blen > next10){
    blen++;
  }
  /* build the string */
  blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
  /* this _must_ be right */
  if(blob_size(&tball.pax) != blen){
    fossil_fatal("internal error: PAX tar header has bad length");
  }
}


/*
** set the header type, calculate the checksum and output
** the header







|







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  if(blen > next10){
    blen++;
  }
  /* build the string */
  blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
  /* this _must_ be right */
  if(blob_size(&tball.pax) != blen){
    fossil_panic("internal error: PAX tar header has bad length");
  }
}


/*
** set the header type, calculate the checksum and output
** the header
Changes to src/util.c.
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

  fossil_get_page_size(&pageSize);
  assert( pageSize>0 );
  assert( pageSize%2==0 );
#if defined(_WIN32)
  p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
  if( p==NULL ){
    fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError());
  }
  if( !VirtualLock(p, pageSize) ){
    fossil_fatal("VirtualLock failed: %lu\n", GetLastError());
  }
#elif defined(USE_MMAN_H)
  p = mmap(0, pageSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  if( p==MAP_FAILED ){
    fossil_fatal("mmap failed: %d\n", errno);
  }
  if( mlock(p, pageSize) ){
    fossil_fatal("mlock failed: %d\n", errno);
  }
#else
  p = fossil_malloc(pageSize);
#endif
  fossil_secure_zero(p, pageSize);
  if( pN ) *pN = pageSize;
  return p;
}
void fossil_secure_free_page(void *p, size_t n){
  if( !p ) return;
  assert( n>0 );
  fossil_secure_zero(p, n);
#if defined(_WIN32)
  if( !VirtualUnlock(p, n) ){
    fossil_fatal("VirtualUnlock failed: %lu\n", GetLastError());
  }
  if( !VirtualFree(p, 0, MEM_RELEASE) ){
    fossil_fatal("VirtualFree failed: %lu\n", GetLastError());
  }
#elif defined(USE_MMAN_H)
  if( munlock(p, n) ){
    fossil_fatal("munlock failed: %d\n", errno);
  }
  if( munmap(p, n) ){
    fossil_fatal("munmap failed: %d\n", errno);
  }
#else
  fossil_free(p);
#endif
}

/*







|


|




|


|














|


|



|


|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

  fossil_get_page_size(&pageSize);
  assert( pageSize>0 );
  assert( pageSize%2==0 );
#if defined(_WIN32)
  p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
  if( p==NULL ){
    fossil_panic("VirtualAlloc failed: %lu\n", GetLastError());
  }
  if( !VirtualLock(p, pageSize) ){
    fossil_panic("VirtualLock failed: %lu\n", GetLastError());
  }
#elif defined(USE_MMAN_H)
  p = mmap(0, pageSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  if( p==MAP_FAILED ){
    fossil_panic("mmap failed: %d\n", errno);
  }
  if( mlock(p, pageSize) ){
    fossil_panic("mlock failed: %d\n", errno);
  }
#else
  p = fossil_malloc(pageSize);
#endif
  fossil_secure_zero(p, pageSize);
  if( pN ) *pN = pageSize;
  return p;
}
void fossil_secure_free_page(void *p, size_t n){
  if( !p ) return;
  assert( n>0 );
  fossil_secure_zero(p, n);
#if defined(_WIN32)
  if( !VirtualUnlock(p, n) ){
    fossil_panic("VirtualUnlock failed: %lu\n", GetLastError());
  }
  if( !VirtualFree(p, 0, MEM_RELEASE) ){
    fossil_panic("VirtualFree failed: %lu\n", GetLastError());
  }
#elif defined(USE_MMAN_H)
  if( munlock(p, n) ){
    fossil_panic("munlock failed: %d\n", errno);
  }
  if( munmap(p, n) ){
    fossil_panic("munmap failed: %d\n", errno);
  }
#else
  fossil_free(p);
#endif
}

/*
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
** fossil_timer_start() was called and returned the given timer ID (or
** since it was last reset). Returns 0 if timerId is out of range.
*/
sqlite3_uint64 fossil_timer_fetch(int timerId){
  if( timerId>0 && timerId<=FOSSIL_TIMER_COUNT ){
    struct FossilTimer * start = &fossilTimerList[timerId-1];
    if( !start->id ){
      fossil_fatal("Invalid call to fetch a non-allocated "
                   "timer (#%d)", timerId);
      /*NOTREACHED*/
    }else{
      sqlite3_uint64 eu = 0, es = 0;
      fossil_cpu_times( &eu, &es );
      return (eu - start->u) + (es - start->s);
    }
  }
  return 0;
}

/*
** Resets the timer associated with the given ID, as obtained via
** fossil_timer_start(), to the current CPU time values.
*/
sqlite3_uint64 fossil_timer_reset(int timerId){
  if( timerId>0 && timerId<=FOSSIL_TIMER_COUNT ){
    struct FossilTimer * start = &fossilTimerList[timerId-1];
    if( !start->id ){
      fossil_fatal("Invalid call to reset a non-allocated "
                   "timer (#%d)", timerId);
      /*NOTREACHED*/
    }else{
      sqlite3_uint64 const rc = fossil_timer_fetch(timerId);
      fossil_cpu_times( &start->u, &start->s );
      return rc;
    }







|



















|







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
** fossil_timer_start() was called and returned the given timer ID (or
** since it was last reset). Returns 0 if timerId is out of range.
*/
sqlite3_uint64 fossil_timer_fetch(int timerId){
  if( timerId>0 && timerId<=FOSSIL_TIMER_COUNT ){
    struct FossilTimer * start = &fossilTimerList[timerId-1];
    if( !start->id ){
      fossil_panic("Invalid call to fetch a non-allocated "
                   "timer (#%d)", timerId);
      /*NOTREACHED*/
    }else{
      sqlite3_uint64 eu = 0, es = 0;
      fossil_cpu_times( &eu, &es );
      return (eu - start->u) + (es - start->s);
    }
  }
  return 0;
}

/*
** Resets the timer associated with the given ID, as obtained via
** fossil_timer_start(), to the current CPU time values.
*/
sqlite3_uint64 fossil_timer_reset(int timerId){
  if( timerId>0 && timerId<=FOSSIL_TIMER_COUNT ){
    struct FossilTimer * start = &fossilTimerList[timerId-1];
    if( !start->id ){
      fossil_panic("Invalid call to reset a non-allocated "
                   "timer (#%d)", timerId);
      /*NOTREACHED*/
    }else{
      sqlite3_uint64 const rc = fossil_timer_fetch(timerId);
      fossil_cpu_times( &start->u, &start->s );
      return rc;
    }
518
519
520
521
522
523
524
525
526
527
528
529
**
** On platforms that have pledge(), use this routine.
** On all other platforms, this routine does not exist, but instead
** a macro defined in config.h is used to provide a no-op.
*/
void fossil_pledge(const char *promises){
  if( pledge(promises, 0) ){
    fossil_fatal("pledge(\"%s\",NULL) fails with errno=%d",
      promises, (int)errno);
  }
}
#endif /* defined(HAVE_PLEDGE) */







|




518
519
520
521
522
523
524
525
526
527
528
529
**
** On platforms that have pledge(), use this routine.
** On all other platforms, this routine does not exist, but instead
** a macro defined in config.h is used to provide a no-op.
*/
void fossil_pledge(const char *promises){
  if( pledge(promises, 0) ){
    fossil_panic("pledge(\"%s\",NULL) fails with errno=%d",
      promises, (int)errno);
  }
}
#endif /* defined(HAVE_PLEDGE) */
Changes to src/verify.c.
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  blob_zero(&uuid);
  db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( !hname_validate(blob_buffer(&uuid), blob_size(&uuid)) ){
    fossil_fatal("not a valid rid: %d", rid);
  }
  if( content_get(rid, &content) ){
    if( !hname_verify_hash(&content, blob_buffer(&uuid), blob_size(&uuid)) ){
      fossil_fatal("hash of rid %d does not match its uuid (%b)",
                    rid, &uuid);
    }
    blob_reset(&content);
  }
  blob_reset(&uuid);
}








|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  blob_zero(&uuid);
  db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( !hname_validate(blob_buffer(&uuid), blob_size(&uuid)) ){
    fossil_fatal("not a valid rid: %d", rid);
  }
  if( content_get(rid, &content) ){
    if( !hname_verify_hash(&content, blob_buffer(&uuid), blob_size(&uuid)) ){
      fossil_panic("hash of rid %d does not match its uuid (%b)",
                    rid, &uuid);
    }
    blob_reset(&content);
  }
  blob_reset(&uuid);
}

Changes to src/winfile.c.
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
** characters are converted to '/'.
*/
void win32_getcwd(char *zBuf, int nBuf){
  int i;
  char *zUtf8;
  wchar_t *zWide = fossil_malloc( sizeof(wchar_t)*nBuf );
  if( GetCurrentDirectoryW(nBuf, zWide)==0 ){
    fossil_fatal("cannot find current working directory.");
  }
  zUtf8 = fossil_path_to_utf8(zWide);
  fossil_free(zWide);
  for(i=0; zUtf8[i]; i++) if( zUtf8[i]=='\\' ) zUtf8[i] = '/';
  strncpy(zBuf, zUtf8, nBuf);
  fossil_path_free(zUtf8);
}







|







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
** characters are converted to '/'.
*/
void win32_getcwd(char *zBuf, int nBuf){
  int i;
  char *zUtf8;
  wchar_t *zWide = fossil_malloc( sizeof(wchar_t)*nBuf );
  if( GetCurrentDirectoryW(nBuf, zWide)==0 ){
    fossil_panic("cannot find current working directory.");
  }
  zUtf8 = fossil_path_to_utf8(zWide);
  fossil_free(zWide);
  for(i=0; zUtf8[i]; i++) if( zUtf8[i]=='\\' ) zUtf8[i] = '/';
  strncpy(zBuf, zUtf8, nBuf);
  fossil_path_free(zUtf8);
}
Changes to src/winhttp.c.
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
** Issue a fatal error.
*/
static NORETURN void winhttp_fatal(
  const char *zOp,
  const char *zService,
  const char *zErr
){
  fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr);
}

/*
** Make sure the server stops as soon as possible after the stopper file
** is found.  If there is no stopper file name, do nothing.
*/
static void win32_server_stopper(void *pAppData){







|







282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
** Issue a fatal error.
*/
static NORETURN void winhttp_fatal(
  const char *zOp,
  const char *zService,
  const char *zErr
){
  fossil_panic("unable to %s service '%s': %s", zOp, zService, zErr);
}

/*
** Make sure the server stops as soon as possible after the stopper file
** is found.  If there is no stopper file name, do nothing.
*/
static void win32_server_stopper(void *pAppData){
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
  savedKeySize = db_get_saved_encryption_key_size();
  if( zSavedKey!=0 && savedKeySize>0 ){
    blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(),
                 zSavedKey, savedKeySize);
  }
#endif
  if( WSAStartup(MAKEWORD(2,0), &wd) ){
    fossil_fatal("unable to initialize winsock");
  }
  DualSocket_init(&ds);
  while( iPort<=mxPort ){
    if( zIpAddr ){
      if( DualSocket_listen(&ds, zIpAddr, iPort)==0 ){
        iPort++;
        continue;







|







558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
  savedKeySize = db_get_saved_encryption_key_size();
  if( zSavedKey!=0 && savedKeySize>0 ){
    blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(),
                 zSavedKey, savedKeySize);
  }
#endif
  if( WSAStartup(MAKEWORD(2,0), &wd) ){
    fossil_panic("unable to initialize winsock");
  }
  DualSocket_init(&ds);
  while( iPort<=mxPort ){
    if( zIpAddr ){
      if( DualSocket_listen(&ds, zIpAddr, iPort)==0 ){
        iPort++;
        continue;
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
        continue;
      }
    }
    break;
  }
  if( iPort>mxPort ){
    if( mnPort==mxPort ){
      fossil_fatal("unable to open listening socket on port %d", mnPort);
    }else{
      fossil_fatal("unable to open listening socket on any"
                   " port in the range %d..%d", mnPort, mxPort);
    }
  }
  if( !GetTempPathW(MAX_PATH, zTmpPath) ){
    fossil_fatal("unable to get path to the temporary directory.");
  }
  zTempPrefix = mprintf("%sfossil_server_P%d",
                        fossil_unicode_to_utf8(zTmpPath), iPort);
  fossil_print("Temporary files: %s*\n", zTempPrefix);
  fossil_print("Listening for %s requests on TCP port %d\n",
               (flags&HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
  if( zBrowser ){







|

|




|







580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
        continue;
      }
    }
    break;
  }
  if( iPort>mxPort ){
    if( mnPort==mxPort ){
      fossil_panic("unable to open listening socket on port %d", mnPort);
    }else{
      fossil_panic("unable to open listening socket on any"
                   " port in the range %d..%d", mnPort, mxPort);
    }
  }
  if( !GetTempPathW(MAX_PATH, zTmpPath) ){
    fossil_panic("unable to get path to the temporary directory.");
  }
  zTempPrefix = mprintf("%sfossil_server_P%d",
                        fossil_unicode_to_utf8(zTmpPath), iPort);
  fossil_print("Temporary files: %s*\n", zTempPrefix);
  fossil_print("Listening for %s requests on TCP port %d\n",
               (flags&HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
  if( zBrowser ){
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
      wsaError =  WSAGetLastError();
      DualSocket_close(&ds);
      if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
        WSACleanup();
        return;
      }else{
        WSACleanup();
        fossil_fatal("error from accept()");
      }
    }
    if( client.s4!=INVALID_SOCKET ){
      pRequest = fossil_malloc(sizeof(HttpRequest));
      pRequest->id = ++idCnt;
      pRequest->s = client.s4;
      memcpy(&pRequest->addr, &client_addr.a4, sizeof(client_addr.a4));







|







638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
      wsaError =  WSAGetLastError();
      DualSocket_close(&ds);
      if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
        WSACleanup();
        return;
      }else{
        WSACleanup();
        fossil_panic("error from accept()");
      }
    }
    if( client.s4!=INVALID_SOCKET ){
      pRequest = fossil_malloc(sizeof(HttpRequest));
      pRequest->id = ++idCnt;
      pRequest->s = client.s4;
      memcpy(&pRequest->addr, &client_addr.a4, sizeof(client_addr.a4));
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
             0,
             NULL
           );
  }
  if( nMsg ){
    zMsg = fossil_unicode_to_utf8(tmp);
  }else{
    fossil_fatal("unable to get system error message.");
  }
  if( tmp ){
    LocalFree((HLOCAL) tmp);
  }
  return zMsg;
}








|







738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
             0,
             NULL
           );
  }
  if( nMsg ){
    zMsg = fossil_unicode_to_utf8(tmp);
  }else{
    fossil_panic("unable to get system error message.");
  }
  if( tmp ){
    LocalFree((HLOCAL) tmp);
  }
  return zMsg;
}

883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
  if( GetStdHandle(STD_INPUT_HANDLE)!=NULL ){ return 1; }

  /* Try to start the control dispatcher thread for the service. */
  if( !StartServiceCtrlDispatcherW(ServiceTable) ){
    if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){
      return 1;
    }else{
      fossil_fatal("error from StartServiceCtrlDispatcher()");
    }
  }
  return 0;
}

/* Duplicate #ifdef needed for mkindex */
#ifdef _WIN32







|







883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
  if( GetStdHandle(STD_INPUT_HANDLE)!=NULL ){ return 1; }

  /* Try to start the control dispatcher thread for the service. */
  if( !StartServiceCtrlDispatcherW(ServiceTable) ){
    if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){
      return 1;
    }else{
      fossil_panic("error from StartServiceCtrlDispatcher()");
    }
  }
  return 0;
}

/* Duplicate #ifdef needed for mkindex */
#ifdef _WIN32