Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch sha3-port Through [033d78f03f] Excluding Merge-Ins
This is equivalent to a diff from f16a3dd322 to 033d78f03f
2021-02-08
| ||
20:45 | MILESTONE: f-ls just read a file listing from the main fossil repo (v2 hashes). Set f-mfparse back to hard-coded sha1 for the time being, as i'm not sure i can automatically figure out one or the other hash (need to add a flag to specify which to use). check-in: 8367e0ce6e user: stephan tags: sha3-port | |
20:35 | Ported in more of the fossil(1) hashing-related infrastructure. check-in: 033d78f03f user: stephan tags: sha3-port | |
18:23 | f-apps compile and f-sanity runs. MILESTONE. Still need to test the other f-apps, though. check-in: 76c290eb05 user: stephan tags: sha3-port | |
16:42 | th1 was removed by stephan check-in: cc0bac7250 user: dan tags: trunk | |
16:03 | Baby steps towards dual sha1/sha3 support. This does not yet compile but i'm nervous about losing work done so far. It's been painless but tedious, which is not bad, all things considered. check-in: 240701a6ec user: stephan tags: sha3-port | |
13:34 | Apply the sqlite3.c CPPFLAGS currently used by fossil(1). check-in: f16a3dd322 user: stephan tags: trunk | |
07:44 | Brought core SQL schemas up to date wrt fossil(1). check-in: 490dadcad9 user: stephan tags: trunk | |
Changes to auto.def.
︙ | ︙ | |||
316 317 318 319 320 321 322 | # Each generated Makefile requires an input file with a .in extension: set makefiles { config.make Makefile doc/Doxyfile src/Makefile f-apps/Makefile | < | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | # Each generated Makefile requires an input file with a .in extension: set makefiles { config.make Makefile doc/Doxyfile src/Makefile f-apps/Makefile cpp/Makefile } foreach {f} $makefiles { makeFromDotIn $f } if {0} { |
︙ | ︙ |
Changes to autosetup/README.autosetup.
|
| | | 1 2 3 4 5 6 7 8 | README.autosetup created by autosetup v0.6.9 This is the autosetup directory for a local install of autosetup. It contains autosetup, support files and loadable modules. *.tcl files in this directory are optional modules which can be loaded with the 'use' directive. |
︙ | ︙ |
Changes to autosetup/autosetup.
1 2 3 4 5 6 7 8 | #!/bin/sh # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ # All rights reserved # vim:se syntax=tcl: # \ dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@" # Note that the version has a trailing + on unreleased versions | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/bin/sh # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ # All rights reserved # vim:se syntax=tcl: # \ dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@" # Note that the version has a trailing + on unreleased versions set autosetup(version) 0.6.9 # Can be set to 1 to debug early-init problems set autosetup(debug) [expr {"--debug" in $argv}] ################################################################## # # Main flow of control, option handling |
︙ | ︙ | |||
89 90 91 92 93 94 95 | # At the is point we don't know what is a valid option # We simply parse anything that looks like an option set autosetup(getopt) [getopt argv] #"=Core Options:" options-add { | | | | | | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | # At the is point we don't know what is a valid option # We simply parse anything that looks like an option set autosetup(getopt) [getopt argv] #"=Core Options:" options-add { help:=local => "display help and options. Optionally specify a module name, such as --help=system" licence license => "display the autosetup license" version => "display the version of autosetup" ref:=text manual:=text reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'" debug => "display debugging output as autosetup runs" install:=. => "install autosetup to the current or given directory" } if {$autosetup(installed)} { # hidden options so we can produce a nice error options-add { sysinstall:path } } else { |
︙ | ︙ | |||
200 201 202 203 204 205 206 | } else { user-error "Unexpected parameter: $arg" } } autosetup_add_dep $autosetup(autodef) | | < | < < < | < < | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | } else { user-error "Unexpected parameter: $arg" } } autosetup_add_dep $autosetup(autodef) define CONFIGURE_OPTS "" foreach arg $autosetup(argv) { define-append CONFIGURE_OPTS [quote-if-needed $arg] } define AUTOREMAKE [file-normalize $autosetup(exe)] define-append AUTOREMAKE [get-define CONFIGURE_OPTS] # Log how we were invoked configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]" configlog "Tclsh: [info nameofexecutable]" # Note that auto.def is *not* loaded in the global scope source $autosetup(autodef) # Could warn here if options {} was not specified show-notices if {$autosetup(debug)} { msg-result "Writing all defines to config.log" |
︙ | ︙ | |||
344 345 346 347 348 349 350 | set result [lindex [dict get $::autosetup(optset) $opt] end] } } if {![info exists result]} { # No user-specified value. Has options-defaults been set? foreach opt $names { | | | | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | set result [lindex [dict get $::autosetup(optset) $opt] end] } } if {![info exists result]} { # No user-specified value. Has options-defaults been set? foreach opt $names { if {[dict exists $::autosetup(options-defaults) $opt]} { set result [dict get $autosetup(options-defaults) $opt] } } } if {[info exists result]} { set value $result if {$retopt} { |
︙ | ︙ | |||
377 378 379 380 381 382 383 | } } } # Parse the option definition in $opts and update # ::autosetup(setoptions) and ::autosetup(optionhelp) appropriately # | | | > | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 | } } } # Parse the option definition in $opts and update # ::autosetup(setoptions) and ::autosetup(optionhelp) appropriately # proc options-add {opts {header ""}} { global autosetup # First weed out comment lines set realopts {} foreach line [split $opts \n] { if {![string match "#*" [string trimleft $line]]} { append realopts $line \n } } set opts $realopts for {set i 0} {$i < [llength $opts]} {incr i} { set opt [lindex $opts $i] if {[string match =* $opt]} { # This is a special heading lappend autosetup(optionhelp) $opt "" set header {} continue } unset -nocomplain defaultvalue equal value #puts "i=$i, opt=$opt" regexp {^([^:=]*)(:)?(=)?(.*)$} $opt -> name colon equal value if {$name in $autosetup(options)} { |
︙ | ︙ | |||
454 455 456 457 458 459 460 | dict set autosetup(optset) $name $setvalue #puts "Found boolean option --$name=$setvalue" } } else { # String option. lappend autosetup(options) $name | | | > | | < | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 | dict set autosetup(optset) $name $setvalue #puts "Found boolean option --$name=$setvalue" } } else { # String option. lappend autosetup(options) $name if {$colon eq ":"} { # Was ":name=default" given? # If so, set $value to the display name and $defaultvalue to the default # (This is the preferred way to set a default value for a string option) if {[regexp {^([^=]+)=(.*)$} $value -> value defaultvalue]} { dict set autosetup(optdefault) $name $defaultvalue } } # Maybe override the default value if {[dict exists $autosetup(options-defaults) $name]} { # A default was specified with options-defaults, so use it set defaultvalue [dict get $autosetup(options-defaults) $name] dict set autosetup(optdefault) $name $defaultvalue } elseif {![info exists defaultvalue]} { # For backward compatibility, if ":name" was given, use name as both # the display text and the default value, but only if the user # specified the option without the value set defaultvalue $value } if {$equal eq "="} { # String option with optional value set opthelp "--$name?=$value?" } else { |
︙ | ︙ | |||
509 510 511 512 513 514 515 516 517 | } # Now create the help for this option if appropriate if {[lindex $opts $i+1] eq "=>"} { set desc [lindex $opts $i+2] if {[info exists defaultvalue]} { set desc [string map [list @default@ $defaultvalue] $desc] } # A multi-line description | > > > > > | | > > > > | > > > > > > > > | 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | } # Now create the help for this option if appropriate if {[lindex $opts $i+1] eq "=>"} { set desc [lindex $opts $i+2] if {[info exists defaultvalue]} { set desc [string map [list @default@ $defaultvalue] $desc] } #string match \n* $desc if {$header ne ""} { lappend autosetup(optionhelp) $header "" set header "" } # A multi-line description lappend autosetup(optionhelp) $opthelp $desc incr i 2 } } } # @module-options optionlist # # Like 'options', but used within a module. proc module-options {opts} { set header "" if {$::autosetup(showhelp) > 1 && [llength $opts]} { set header "Module Options:" } options-add $opts $header if {$::autosetup(showhelp)} { # Ensure that the module isn't executed on --help # We are running under eval or source, so use break # to prevent further execution #return -code break -level 2 return -code break } } proc max {a b} { expr {$a > $b ? $a : $b} } proc options-wrap-desc {text length firstprefix nextprefix initial} { |
︙ | ︙ | |||
550 551 552 553 554 555 556 | set space " " } if {$len} { puts "" } } | < < | < | < < < < | < < < < < < < < < < | 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | set space " " } if {$len} { puts "" } } proc options-show {} { # Determine the max option width set max 0 foreach {opt desc} $::autosetup(optionhelp) { if {[string match =* $opt] || [string match \n* $desc]} { continue } set max [max $max [string length $opt]] } set indent [string repeat " " [expr $max+4]] set cols [getenv COLUMNS 80] catch { lassign [exec stty size] rows cols } incr cols -1 # Now output foreach {opt desc} $::autosetup(optionhelp) { if {[string match =* $opt]} { puts [string range $opt 1 end] continue } puts -nonewline " [format %-${max}s $opt]" if {[string match \n* $desc]} { puts $desc } else { options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2] } } } |
︙ | ︙ | |||
611 612 613 614 615 616 617 | # ## name[=0|1] => "Description of this boolean option" # # The default is 'name=0', meaning that the option is disabled by default. # If 'name=1' is used to make the option enabled by default, the description should reflect # that with text like "Disable support for ...". # | | | < < < < | < | | | > | < < | | | | | < | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | # ## name[=0|1] => "Description of this boolean option" # # The default is 'name=0', meaning that the option is disabled by default. # If 'name=1' is used to make the option enabled by default, the description should reflect # that with text like "Disable support for ...". # # An argument option (one which takes a parameter) is of the form: # ## name:[=]value => "Description of this option" # # If the 'name:value' form is used, the value must be provided with the option (as '--name=myvalue'). # If the 'name:=value' form is used, the value is optional and the given value is used as the default # if it is not provided. # # The description may contain '@default@', in which case it will be replaced with the default # value for the option (taking into account defaults specified with 'options-defaults'. # # Undocumented options are also supported by omitting the '=> description'. # These options are not displayed with '--help' and can be useful for internal options or as aliases. # # For example, '--disable-lfs' is an alias for '--disable=largefile': # ## lfs=1 largefile=1 => "Disable large file support" # proc options {optlist} { # Allow options as a list or args options-add $optlist "Local Options:" if {$::autosetup(showhelp)} { options-show exit 0 } # Check for invalid options if {[opt-bool option-checking]} { foreach o [dict keys $::autosetup(getopt)] { if {$o ni $::autosetup(options)} { user-error "Unknown option --$o" } } } } # @options-defaults dictionary # |
︙ | ︙ | |||
1181 1182 1183 1184 1185 1186 1187 | lappend dirs $autosetup(srcdir)/autosetup } foreach m $args { if {[info exists libmodule($m)]} { continue } set libmodule($m) 1 | < | | | | < < < < | < < | 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 | lappend dirs $autosetup(srcdir)/autosetup } foreach m $args { if {[info exists libmodule($m)]} { continue } set libmodule($m) 1 if {[info exists modsource(${m}.tcl)]} { automf_load eval $modsource(${m}.tcl) } else { set locs [list ${m}.tcl ${m}/init.tcl] set found 0 foreach dir $dirs { foreach loc $locs { set source $dir/$loc if {[file exists $source]} { incr found break } } if {$found} { break } } if {$found} { # For the convenience of the "use" source, point to the directory # it is being loaded from set ::usedir [file dirname $source] automf_load source $source autosetup_add_dep $source } else { autosetup-error "use: No such module: $m" } } } } proc autosetup_load_auto_modules {} { global autosetup modsource # First load any embedded auto modules foreach mod [array names modsource *.auto] { automf_load eval $modsource($mod) } # Now any external auto modules foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] { automf_load source $file } } # Load module source in the global scope by executing the given command proc automf_load {args} { if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} { autosetup-full-error [error-dump $msg $opts $::autosetup(debug)] } } # Initial settings set autosetup(exe) $::argv0 set autosetup(istcl) 1 set autosetup(start) [clock millis] set autosetup(installed) 0 set autosetup(sysinstall) 0 set autosetup(msg-checking) 0 set autosetup(msg-quiet) 0 set autosetup(inittypes) {} # Embedded modules are inserted below here set autosetup(installed) 1 set autosetup(sysinstall) 0 # ----- @module asciidoc-formatting.tcl ----- set modsource(asciidoc-formatting.tcl) { |
︙ | ︙ | |||
1451 1452 1453 1454 1455 1456 1457 | proc autosetup_help {what} { use_pager puts "Usage: [file tail $::autosetup(exe)] \[options\] \[settings\]\n" puts "This is [autosetup_version], a build environment \"autoconfigurator\"" puts "See the documentation online at http://msteveb.github.com/autosetup/\n" | | < | > | < < < < > > | > > | | < > | 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 | proc autosetup_help {what} { use_pager puts "Usage: [file tail $::autosetup(exe)] \[options\] \[settings\]\n" puts "This is [autosetup_version], a build environment \"autoconfigurator\"" puts "See the documentation online at http://msteveb.github.com/autosetup/\n" if {$what eq "local"} { if {[file exists $::autosetup(autodef)]} { # This relies on auto.def having a call to 'options' # which will display options and quit source $::autosetup(autodef) } else { options-show } } else { incr ::autosetup(showhelp) if {[catch {use $what}]} { user-error "Unknown module: $what" } else { options-show } } exit 0 } proc autosetup_show_license {} { global modsource autosetup use_pager |
︙ | ︙ |
Changes to autosetup/autosetup-find-tclsh.
1 2 | #!/bin/sh # Looks for a suitable tclsh or jimsh in the PATH | | | | > > | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/bin/sh # Looks for a suitable tclsh or jimsh in the PATH # If not found, builds a bootstrap jimsh from source # Prefer $autosetup_tclsh if is set in the environment d=`dirname "$0"` { "$d/jimsh0" "$d/autosetup-test-tclsh"; } 2>/dev/null && exit 0 PATH="$PATH:$d"; export PATH for tclsh in $autosetup_tclsh jimsh tclsh tclsh8.5 tclsh8.6; do { $tclsh "$d/autosetup-test-tclsh"; } 2>/dev/null && exit 0 done echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0" for cc in ${CC_FOR_BUILD:-cc} gcc; do { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue "$d/jimsh0" "$d/autosetup-test-tclsh" && exit 0 done echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc." echo false |
Changes to autosetup/local.tcl.
|
| | > | | 1 2 3 4 5 6 7 8 9 10 | # For this project, disable the pager for --help and --ref # The user can still enable by using --nopager=0 or --disable-nopager dict set autosetup(optdefault) nopager 1 # Searches for a usable Tcl (prefer 8.6, 8.5, 8.4) in the given paths # Returns a dictionary of the contents of the tclConfig.sh file, or # empty if not found proc parse-tclconfig-sh {args} { foreach p $args { # Allow pointing directly to the path containing tclConfig.sh |
︙ | ︙ |
Changes to f-apps/f-mfparse.c.
︙ | ︙ | |||
129 130 131 132 133 134 135 | f_out("Rather large - not dumping to console.\n"); } f_out("Dumping mf to file [%s]\n", ofile); rc = fsl_buffer_to_filename(&bout, ofile); assert(!rc); { fsl_buffer sha = fsl_buffer_empty; | | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | f_out("Rather large - not dumping to console.\n"); } f_out("Dumping mf to file [%s]\n", ofile); rc = fsl_buffer_to_filename(&bout, ofile); assert(!rc); { fsl_buffer sha = fsl_buffer_empty; rc = fsl_sha3sum_filename(ofile, &sha); assert(!rc); f_out("SHA of [%s] = [%b]\n", ofile, &sha); seemsSafeEnough = (0==fsl_strcmp(fsl_buffer_cstr(&sha), mf.uuid)); f_out("SHA match? %s\n", seemsSafeEnough ? "yes" : "NO!"); fsl_buffer_clear(&sha); |
︙ | ︙ |
Changes to f-apps/f-timeline.c.
︙ | ︙ | |||
99 100 101 102 103 104 105 | /* "AND bf.rid=mlink.fid " */ /*"AND bm.rid=mlink.mid "*/ "ORDER BY filename.name %s", fsl_cx_filename_collation(f)); if(rc){ return fsl_cx_uplift_db_error(f, db); } | | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | /* "AND bf.rid=mlink.fid " */ /*"AND bm.rid=mlink.mid "*/ "ORDER BY filename.name %s", fsl_cx_filename_collation(f)); if(rc){ return fsl_cx_uplift_db_error(f, db); } rc = fsl_stmt_bind_text(st, 1, uuid, -1, 0); assert(0==rc); while(FSL_RC_STEP_ROW==(rc=fsl_stmt_step(st))){ char const * changeType; if(!doneHead){ doneHead = 1; fsl_outputf(f,"\n\t%-11s%s %13s Name\n", "Change", "File UUID", "Size"); } |
︙ | ︙ |
Changes to f-apps/test.c.
︙ | ︙ | |||
112 113 114 115 116 117 118 | assert(0==rc); assert(id>0); rc = fsl_sym_to_uuid(f, "current", FSL_CATYPE_CHECKIN, &uuid, &id2); assert(0==rc); assert(uuid); assert(id2 == id); | | | | < | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | assert(0==rc); assert(id>0); rc = fsl_sym_to_uuid(f, "current", FSL_CATYPE_CHECKIN, &uuid, &id2); assert(0==rc); assert(uuid); assert(id2 == id); assert(fsl_is_uuid(uuid)); f_out("Current checkout: %s\n", uuid); fsl_free(uuid); } return rc; } /* static */ int test_leaves_rebuild(){ int rc; f_out("Rebuilding leaves...\n"); |
︙ | ︙ | |||
148 149 150 151 152 153 154 | assert(rid>0); rc = fsl_content_get(f, rid, &c); fsl_cx_err_report(f, 1); assert(!rc); assert(1032==c.used); rc = fsl_sha1sum_buffer( &c, &c ); assert(!rc); | | | | | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | assert(rid>0); rc = fsl_content_get(f, rid, &c); fsl_cx_err_report(f, 1); assert(!rc); assert(1032==c.used); rc = fsl_sha1sum_buffer( &c, &c ); assert(!rc); assert(fsl_is_uuid_len((int)c.used)); assert(0==fsl_strcmp( sym, fsl_buffer_cstr(&c) )); /* Now fetch a few other versions of that same file and ensure that they meet our expectations... */ sym = "e9b776a8a72753823e4553a309edae21897cb2c4"; rid = 0; rc = fsl_sym_to_rid(f, sym, FSL_CATYPE_ANY, &rid); assert(!rc); assert(rid>0); rc = fsl_content_get(f, rid, &c); assert(!rc); assert(2076==c.used); rc = fsl_sha1sum_buffer( &c, &c ); assert(!rc); assert(fsl_is_uuid_len((int)c.used)); assert(0==fsl_strcmp( sym, fsl_buffer_cstr(&c) )); sym = "f7d3a2e155d59a96ecc37001b05de26dee23c0cf"; rid = 0; rc = fsl_sym_to_rid(f, sym, FSL_CATYPE_ANY, &rid); assert(!rc); assert(rid>0); rc = fsl_content_get(f, rid, &c); assert(!rc); assert(2481==c.used); rc = fsl_sha1sum_buffer( &c, &c ); assert(!rc); assert(fsl_is_uuid_len((int)c.used)); assert(0==fsl_strcmp( sym, fsl_buffer_cstr(&c) )); sym = "31e01e2a3c"; rid = 0; rc = fsl_sym_to_rid(f, sym, FSL_CATYPE_WIKI, &rid); assert(!rc); |
︙ | ︙ |
Changes to include/fossil-scm/fossil-content.h.
︙ | ︙ | |||
2163 2164 2165 2166 2167 2168 2169 | FSL_EXPORT int fsl_delta_src_id( fsl_cx * f, fsl_id_t deltaRid, fsl_id_t * rv ); /** Return true if the given artifact ID should is listed in f's shun table, else false. */ | | | 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 | FSL_EXPORT int fsl_delta_src_id( fsl_cx * f, fsl_id_t deltaRid, fsl_id_t * rv ); /** Return true if the given artifact ID should is listed in f's shun table, else false. */ FSL_EXPORT int fsl_uuid_is_shunned(fsl_cx * f, fsl_uuid_cstr zUuid); /** Given a fsl_cx with an opened checkout, and a filename, this function canonicalizes zOrigName to a form suitable for use as an in-repo filename, _appending_ the results to pOut. If pOut is NULL, it performs its normal checking but does not write a result, other than to return 0 for success. |
︙ | ︙ | |||
2994 2995 2996 2997 2998 2999 3000 | @endcode except that (A) bIn is const in this call and non-const in the other form (due to cursor traversal requirements) and (B) it returns FSL_RC_MISUSE if pIn is NULL. */ FSL_EXPORT int fsl_repo_import_buffer( fsl_cx * f, fsl_buffer const * bIn, | | > > > > > > > > > > > > > > > > > > > > > | 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 | @endcode except that (A) bIn is const in this call and non-const in the other form (due to cursor traversal requirements) and (B) it returns FSL_RC_MISUSE if pIn is NULL. */ FSL_EXPORT int fsl_repo_import_buffer( fsl_cx * f, fsl_buffer const * bIn, fsl_id_t * rid, fsl_uuid_str * uuid ); /** Hashes all of pIn, appending the hash to pOut. Returns 0 on succes, FSL_RC_OOM if allocation of space in pOut fails. The hash algorithm used depends on the given fossil context's current hash policy and the value of the 2nd argument: If the 2nd argument is false, the hash is performed per the first argument's policy. If the 2nd argument is true, the hash policy is effectively inverted. e.g. if the context prefers SHA3 hashes, the alternate form will use SHA1. Returns FSL_RC_RANGE if the hash is not possible due to conflicting values for the policy and its alternate (e.g. a context with policy FSL_HPOLICY_SHA3_ONLY will refuse to apply an SHA1 hash). Returns 0 on success. */ FSL_EXPORT int fsl_cx_hash_buffer( const fsl_cx * f, int useAlternate, fsl_buffer const * pIn, fsl_buffer * pOut); #if 0 /** NOT YET IMPLEMENTED - just thinking out loud here. */ struct fsl_repo_open_opt { |
︙ | ︙ |
Changes to include/fossil-scm/fossil-hash.h.
︙ | ︙ | |||
31 32 33 34 35 36 37 | #endif /** Various set-in-stone constants used by the API. */ enum fsl_hash_constants { /** | | | > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 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 | #endif /** Various set-in-stone constants used by the API. */ enum fsl_hash_constants { /** The length, in bytes, of fossil's hex-form SHA1 UUID strings. */ FSL_UUIDv1_STRLEN = 40, /** The length, in bytes, of fossil's hex-form SHA3-256 UUID strings. */ FSL_UUIDv2_STRLEN = 64, /** The length, in bytes, of a hex-form MD5 hash. */ FSL_MD5_STRLEN = 32, FSL_UUID_STRLEN_MIN = FSL_UUIDv1_STRLEN, FSL_UUID_STRLEN_MAX = FSL_UUIDv2_STRLEN }; /** Internal IDs for artifact hash types the library works. */ enum fsl_hash_types_t { /** Invalid hash type. */ FSL_HTYPE_ERROR = 0, /** SHA1. */ FSL_HTYPE_SHA1 = 1, /** SHA3-256. */ FSL_HTYPE_K256 = 2 }; typedef enum fsl_hash_types_t fsl_hash_types_t; enum fsl_hash_policy_t { /* Use SHA1 hashes */ FSL_HPOLICY_SHA1 = 0, /* SHA1 but auto-promote to SHA3 */ FSL_HPOLICY_AUTO = 1, /* Use SHA3 hashes */ FSL_HPOLICY_SHA3 = 2, /* Use SHA3 hashes exclusively */ FSL_HPOLICY_SHA3_ONLY = 3, /* Shun all SHA1 objects */ FSL_HPOLICY_SHUN_SHA1 = 4 }; typedef enum fsl_hash_policy_t fsl_hash_policy_t; typedef struct fsl_md5_cx fsl_md5_cx; typedef struct fsl_sha1_cx fsl_sha1_cx; typedef struct fsl_sha3_cx fsl_sha3_cx; /** |
︙ | ︙ | |||
211 212 213 214 215 216 217 | #endif /** Holds state for SHA1 calculations. It is intended to be used like this: @code unsigned char digest[20] | | | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | #endif /** Holds state for SHA1 calculations. It is intended to be used like this: @code unsigned char digest[20] char hex[FSL_UUIDv1_STRLEN+1]; fsl_sha1_cx cx = fsl_sha1_cx_empty; // alternately: fsl_sha1_init(&cx) ...call fsl_sha1_update(&cx,...) any number of times to ...incrementally calculate the hash. fsl_sha1_final(&cx, digest); // ends the calculation fsl_sha1_digest_to_base16(digest, hex); // digest now contains the raw 20-byte SHA1 digest. |
︙ | ︙ | |||
300 301 302 303 304 305 306 307 308 | returns 0. @see fsl_sha1_update() @see fsl_sha1_digest_to_base16() */ FSL_EXPORT int fsl_sha1_final(fsl_sha1_cx *context, unsigned char * digest); /** Convert a digest into base-16. digest must be at least 20 bytes | > > > > > > > > | | | | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | returns 0. @see fsl_sha1_update() @see fsl_sha1_digest_to_base16() */ FSL_EXPORT int fsl_sha1_final(fsl_sha1_cx *context, unsigned char * digest); /** A convenience form of fsl_sha1_final() which writes FSL_UUIDv1_STRLEN+1 bytes (hash plus terminating NUL byte) to the 2nd argument and returns a (const char *)-type cast of the 2nd argument. */ FSL_EXPORT const char * fsl_sha1_final_hex(fsl_sha1_cx *context, char * zHex); /** Convert a digest into base-16. digest must be at least 20 bytes long and hold an SHA1 digest. zBuf must be at least (FSL_UUIDv1_STRLEN + 1) bytes long, to which FSL_UUIDv1_STRLEN characters of hexidecimal-form SHA1 hash and 1 NUL byte will be written. @see fsl_sha1_final() */ FSL_EXPORT void fsl_sha1_digest_to_base16(unsigned char *digest, char *zBuf); /** Computes the SHA1 checksum of pIn and stores the resulting |
︙ | ︙ | |||
371 372 373 374 375 376 377 | enum fsl_sha3_hash_size { /** Sentinel value. Must be 0. */ FSL_SHA3_INVALID = 0, FSL_SHA3_128 = 128, FSL_SHA3_160 = 160, FSL_SHA3_192 = 192, FSL_SHA3_224 = 224, FSL_SHA3_256 = 256, FSL_SHA3_288 = 288, FSL_SHA3_320 = 320, FSL_SHA3_352 = 352, FSL_SHA3_384 = 384, FSL_SHA3_416 = 416, FSL_SHA3_448 = 448, FSL_SHA3_480 = 480, | | > > | | 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | enum fsl_sha3_hash_size { /** Sentinel value. Must be 0. */ FSL_SHA3_INVALID = 0, FSL_SHA3_128 = 128, FSL_SHA3_160 = 160, FSL_SHA3_192 = 192, FSL_SHA3_224 = 224, FSL_SHA3_256 = 256, FSL_SHA3_288 = 288, FSL_SHA3_320 = 320, FSL_SHA3_352 = 352, FSL_SHA3_384 = 384, FSL_SHA3_416 = 416, FSL_SHA3_448 = 448, FSL_SHA3_480 = 480, FSL_SHA3_512 = 512, /* Default SHA3 flavor */ FSL_SHA3_DEFAULT = 256 }; /** Type for holding SHA3 processing state. Each instance must be initialized with fsl_sha3_init(), populated with fsl_sha3_update(), and "sealed" with fsl_sha3_end(). Sample usage: @code fsl_sha3_cx cx; fsl_sha3_init(&cx, FSL_SHA3_DEFAULT); fsl_sha3_update(&cx, memory, lengthOfMemory); fsl_sha3_end(&cx); printf("Hash = %s\n", (char const *)cx.hex); @endcode After fsl_sha3_end() is called cx.hex contains the hex-string forms of the digest. Note that fsl_sha3_update() may be called an arbitrary |
︙ | ︙ | |||
416 417 418 419 420 421 422 | entry is returned, else FSL_SHA3_INVALID is returned. @see fsl_sha3_init() */ FSL_EXPORT enum fsl_sha3_hash_size fsl_sha3_hash_size_for_int(int); /** | | | > > > > > > | | > > > | > > > > > > > > | > > > | > > > | > > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 | entry is returned, else FSL_SHA3_INVALID is returned. @see fsl_sha3_init() */ FSL_EXPORT enum fsl_sha3_hash_size fsl_sha3_hash_size_for_int(int); /** Initialize a new hash. The second argument specifies the size of the hash in bits. Results are undefined if cx is NULL or sz is not a valid positive value. After calling this, use fsl_sha3_update() to hash data and fsl_sha3_end() to finalize the hashing process and generate a digest. */ FSL_EXPORT void fsl_sha3_init2(fsl_sha3_cx *cx, enum fsl_sha3_hash_size sz); /** Equivalent to fsl_sha3_init2(cx, FSL_SHA3_DEFAULT). */ FSL_EXPORT void fsl_sha3_init(fsl_sha3_cx *cx); /** Updates cx's state to include the first len bytes of data. If cx is NULL results are undefined (segfault!). If mem is not NULL then it must be at least n bytes long. If n is 0 then this function has no side-effects. @see fsl_sha3_init() @see fsl_sha3_end() */ FSL_EXPORT void fsl_sha3_update( fsl_sha3_cx *cx, void const *data, unsigned int len); /** To be called when SHA3 hashing is complete: finishes the hash calculation and populates cx->hex with the final hash code in hexidecimal-string form. Returns the binary-form digest value, which refers to cx->size/8 bytes of memory which lives in the cx object. After this call cx->hex will be populated with cx->size/4 bytes of lower-case ASCII hex codes plus a terminating NUL byte. Potential TODO: change fsl_sha1_final() and fsl_md5_final() to use these same return semantics. @see fsl_sha3_init() @see fsl_sha3_update() */ FSL_EXPORT unsigned char const * fsl_sha3_end(fsl_sha3_cx *cx); /** SHA3-256 counterpart of fsl_sha1_digest_to_base16(). digest must be at least 32 bytes long and hold an SHA3 digest. zBuf must be at least (FSL_UUIDv2_STRLEN+1) bytes long, to which FSL_UUIDv2_STRLEN characters of hexidecimal-form SHA3 hash and 1 NUL byte will be written @see fsl_sha3_end(). */ FSL_EXPORT void fsl_sha3_digest_to_base16(unsigned char *digest, char *zBuf); /** SHA3 counter part of fsl_sha1sum_buffer(). */ FSL_EXPORT int fsl_sha3sum_buffer(fsl_buffer const *pIn, fsl_buffer *pCksum); /** SHA3 counter part of fsl_sha1sum_cstr(). */ FSL_EXPORT char *fsl_sha3sum_cstr(const char *zIn, fsl_int_t len); /** SHA3 counterpart of fsl_sha1sum_stream(). */ FSL_EXPORT int fsl_sha3sum_stream(fsl_input_f src, void * srcState, fsl_buffer *pCksum); /** SHA3 counterpart of fsl_sha1sum_filename(). */ FSL_EXPORT int fsl_sha3sum_filename(const char *zFilename, fsl_buffer *pCksum); /** Expects zHash to be a full-length hash value of one of the fsl_hash_types_t-specified types, and nHash to be the length, in bytes, of zHash's contents (which must be the full hash length, not a prefix). If zHash can be validated as a hash, its corresponding hash type is returned, else FSL_HTYPE_ERROR is returned. */ FSL_EXPORT fsl_hash_types_t fsl_validate_hash(const char *zHash, int nHash); /** Expects (zHash, nHash) to refer to a full hash (of a supported content hash type) of pIn's contents. This routine hashes pIn's contents and, if it compares equivalent to zHash then the ID of the hash type is returned. On a mismatch, FSL_HTYPE_ERROR is returned. */ FSL_EXPORT fsl_hash_types_t fsl_verify_blob_hash(fsl_buffer const * pIn, const char *zHash, int nHash); /** Sets f's hash policy and returns the previous value. */ FSL_EXPORT fsl_hash_policy_t fsl_cx_hash_policy_set(fsl_cx *f, fsl_hash_policy_t p); /** Returns f's current hash policy. */ FSL_EXPORT fsl_hash_policy_t fsl_cx_hash_policy_get(fsl_cx const*f); /** Returns a human-friendly name for f's current hash policy. */ FSL_EXPORT char const * fsl_cx_hash_policy_name(fsl_cx const*f); /** Returns a human-readable name for the given hash type, or its second argument h is not a supported hash type. */ FSL_EXPORT const char * fsl_hash_type_name(fsl_hash_types_t h, const char *zUnknown); #if defined(__cplusplus) } /*extern "C"*/ #endif #endif /* NET_FOSSIL_SCM_FSL_HASH_H_INCLUDED */ |
Changes to include/fossil-scm/fossil-internal.h.
︙ | ︙ | |||
546 547 548 549 550 551 552 553 554 555 556 557 558 559 | fsl_id_t mtimeManifest; /** The "project-code" config option. */ char * projectCode; /** Holds various glob lists. */ struct { /** Holds the "ignore-glob" globs. */ | > | 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 | fsl_id_t mtimeManifest; /** The "project-code" config option. */ char * projectCode; fsl_hash_policy_t hashPolicy; /** Holds various glob lists. */ struct { /** Holds the "ignore-glob" globs. */ |
︙ | ︙ | |||
666 667 668 669 670 671 672 673 674 675 676 | {/*mf*/ NULL/*head*/,5/*max*/,0/*size*/}, \ fsl_acache_empty_m/*arty*/, \ fsl_id_bag_empty_m/*mfSeen*/, \ fsl_id_bag_empty_m/*leafCheck*/, \ fsl_id_bag_empty_m/*toVerify*/, \ 0/*mtimeManifest*/, \ NULL/*projectCode*/, \ {/*globs*/ \ fsl_list_empty_m/*ignore*/, \ fsl_list_empty_m/*binary*/, \ fsl_list_empty_m/*crnl*/ \ | > | | 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 | {/*mf*/ NULL/*head*/,5/*max*/,0/*size*/}, \ fsl_acache_empty_m/*arty*/, \ fsl_id_bag_empty_m/*mfSeen*/, \ fsl_id_bag_empty_m/*leafCheck*/, \ fsl_id_bag_empty_m/*toVerify*/, \ 0/*mtimeManifest*/, \ NULL/*projectCode*/, \ FSL_HPOLICY_AUTO/*hashPolicy*/, \ {/*globs*/ \ fsl_list_empty_m/*ignore*/, \ fsl_list_empty_m/*binary*/, \ fsl_list_empty_m/*crnl*/ \ } \ }, \ {/*ticket*/ \ fsl_list_empty_m/*customFields*/, \ 0/*hasTicket*/, \ 0/*hasCTime*/, \ 0/*hasChng*/, \ 0/*hasCngRid*/ \ |
︙ | ︙ |
Changes to include/fossil-scm/fossil-util.h.
︙ | ︙ | |||
57 58 59 60 61 62 63 | arguments. That depends on the routine which uses the comparison function. */ typedef int (*fsl_generic_cmp_f)( void const * lhs, void const * rhs ); /** fsl_uuid_str and fsl_uuid_cstr are "for documentation and | | | | | | | | | | | | | | | | | | | | > > > > > | 57 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 93 94 95 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 | arguments. That depends on the routine which uses the comparison function. */ typedef int (*fsl_generic_cmp_f)( void const * lhs, void const * rhs ); /** fsl_uuid_str and fsl_uuid_cstr are "for documentation and readability purposes" typedefs used to denote strings which the API requires to be in the form of Fossil UUID strings. Such strings are exactly FSL_UUIDv1_STRLEN or FSL_UUIDv2_STRLEN bytes long plus a terminating NUL byte and contain only lower-case hexadecimal bytes. Where this typedef is used, the library requires, enforces, and/or assumes (at different times) that fsl_is_uuid() returns true for such strings (if they are not NULL, though not all contexts allow a NULL UUID). These typedef are _not_ used to denote arguments which may refer to partial UUIDs or symbolic names, only 100% bonafide Fossil UUIDs (which are different from RFC4122 UUIDs). The API guarantees that this typedef will always be (char *) and that fsl_uuid_cstr will always ben (char const *), and thus it is safe/portable to use those type instead of these. These typedefs serve only to improve the readability of certain APIs by implying (through the use of this typedef) the preconditions defined for UUID strings. @see fsl_is_uuid() */ typedef char * fsl_uuid_str; /** The const counterpart of fsl_uuid_str. @see fsl_is_uuid() */ typedef char const * fsl_uuid_cstr; /** If the NUL-terminated input str is exactly FSL_UUIDv1_STRLEN or FSL_UUIDv2_STRLEN bytes long and contains only lower-case hexadecimal characters, returns the length of the string, else returns 0. Note that Fossil UUIDs are not RFC4122 UUIDs, but are SHA1 or SHA3-256 hash strings. Don't let that disturb you. As Tim Berners-Lee writes: 'The assertion that the space of URIs is a universal space sometimes encounters opposition from those who feel there should not be one universal space. These people need not oppose the concept because it is not of a single universal space: Indeed, the fact that URIs form universal space does not prevent anyone else from forming their own universal space, which of course by definition would be able to envelop within it as a subset the universal URI space. Therefore the web meets the "independent design" test, that if a similar system had been concurrently and independently invented elsewhere, in such a way that the arbitrary design decisions were made differently, when they met later, the two systems could be made to interoperate.' Source: https://www.w3.org/DesignIssues/Axioms.html (Just mentally translate URI as UUID.) */ FSL_EXPORT int fsl_is_uuid(char const * str); /** If x is a valid fossil UUID length, it is returned, else 0 is returned. */ FSL_EXPORT int fsl_is_uuid_len(int x); /** Expects str to be a string containing an unsigned decimal value. Returns its decoded value, or -1 on error. */ FSL_EXPORT fsl_size_t fsl_str_to_size(char const * str); |
︙ | ︙ | |||
1452 1453 1454 1455 1456 1457 1458 | /** fsl_strcmp() variant which compares at most nByte bytes of the given strings, case-sensitively. Returns 0 if nByte is 0. */ FSL_EXPORT int fsl_strncmp(const char *zA, const char *zB, fsl_size_t nByte); /** | | > > > > > > > > > > | 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 | /** fsl_strcmp() variant which compares at most nByte bytes of the given strings, case-sensitively. Returns 0 if nByte is 0. */ FSL_EXPORT int fsl_strncmp(const char *zA, const char *zB, fsl_size_t nByte); /** Equivalent to fsl_strncmp(lhs, rhs, X), where X is either FSL_UUIDv1_STRLEN or FSL_UUIDv2_STRLEN: if both lhs and rhs are longer than FSL_UUIDv1_STRLEN then they are assumed to be FSL_UUIDv2_STRLEN bytes long and are compared as such, else they are assumed to be FSL_UUIDv1_STRLEN bytes long and compared as such. Potential FIXME/TODO: if their lengths differ, i.e. one is v1 and one is v2, compare them up to their common length then, if they still compare equivalent, treat the shorter one as less-than the longer. */ FSL_EXPORT int fsl_uuidcmp( fsl_uuid_cstr lhs, fsl_uuid_cstr rhs ); /** Returns false if s is NULL or starts with any of (0 (NUL), '0' (ASCII character zero), 'f', 'n', "off"), case-insensitively, else it returns true. |
︙ | ︙ |
Changes to src/fsl.c.
︙ | ︙ | |||
183 184 185 186 187 188 189 | free(mem); return NULL; }else{ return realloc(mem, n); } } | | | | > > > > | | > > > > > > > | > | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | free(mem); return NULL; }else{ return realloc(mem, n); } } int fsl_is_uuid(char const * str){ fsl_size_t const len = fsl_strlen(str); if(FSL_UUIDv1_STRLEN==len){ return fsl_validate16(str, FSL_UUIDv1_STRLEN) ? FSL_UUIDv1_STRLEN : 0; }else if(FSL_UUIDv2_STRLEN==len){ return fsl_validate16(str, FSL_UUIDv2_STRLEN) ? FSL_UUIDv2_STRLEN : 0; }else{ return 0; } } int fsl_is_uuid_len(int x){ switch(x){ case FSL_UUIDv1_STRLEN: case FSL_UUIDv2_STRLEN: return x; default: return 0; } } void fsl_error_clear( fsl_error * err ){ if(err){ fsl_buffer_clear(&err->msg); *err = fsl_error_empty; } } |
︙ | ︙ | |||
368 369 370 371 372 373 374 | }while( a==b && a!=0 && (--nByte)>0 ); return (nByte>0) ? (((unsigned char)a) - (unsigned char)b) : 0; } } int fsl_uuidcmp( fsl_uuid_cstr lhs, fsl_uuid_cstr rhs ){ | > | > > > > > | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | }while( a==b && a!=0 && (--nByte)>0 ); return (nByte>0) ? (((unsigned char)a) - (unsigned char)b) : 0; } } int fsl_uuidcmp( fsl_uuid_cstr lhs, fsl_uuid_cstr rhs ){ if(lhs[FSL_UUIDv1_STRLEN] && rhs[FSL_UUIDv1_STRLEN]){ return fsl_strncmp( lhs, rhs, FSL_UUIDv2_STRLEN); }else if(!lhs[FSL_UUIDv1_STRLEN] && !rhs[FSL_UUIDv1_STRLEN]){ return fsl_strncmp( lhs, rhs, FSL_UUIDv1_STRLEN ); }else{ return fsl_strcmp(lhs, rhs); } } int fsl_strnicmp(const char *zA, const char *zB, fsl_int_t nByte){ if( zA==0 ){ if( zB==0 ) return 0; return -1; }else if( zB==0 ){ |
︙ | ︙ |
Changes to src/fsl_auth.c.
︙ | ︙ | |||
44 45 46 47 48 49 50 | fsl_strlen(f->cache.projectCode)); fsl_sha1_update(&hash, "/", 1); fsl_sha1_update(&hash, zLoginName, fsl_strlen(zLoginName)); fsl_sha1_update(&hash, "/", 1); fsl_sha1_update(&hash, zPw, fsl_strlen(zPw)); fsl_sha1_final(&hash, zResult); fsl_sha1_digest_to_base16(zResult, zDigest); | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | fsl_strlen(f->cache.projectCode)); fsl_sha1_update(&hash, "/", 1); fsl_sha1_update(&hash, zLoginName, fsl_strlen(zLoginName)); fsl_sha1_update(&hash, "/", 1); fsl_sha1_update(&hash, zPw, fsl_strlen(zPw)); fsl_sha1_final(&hash, zResult); fsl_sha1_digest_to_base16(zResult, zDigest); return fsl_strndup( zDigest, FSL_UUIDv1_STRLEN ); } } FSL_EXPORT char * fsl_repo_login_group_name(fsl_cx * f){ return f ? fsl_config_get_text(f, FSL_CONFDB_REPO, "login-group-name", 0) |
︙ | ︙ |
Changes to src/fsl_content.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | Author contact information: drh@hwaci.com https://www.hwaci.com/drh/ ***************************************************************************** This file houses the code for the fsl_content_xxx() APIS. */ | < > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | Author contact information: drh@hwaci.com https://www.hwaci.com/drh/ ***************************************************************************** This file houses the code for the fsl_content_xxx() APIS. */ #include "fossil-scm/fossil-internal.h" #include <assert.h> #include <memory.h> /* memcmp() */ /* Only for debugging */ #include <stdio.h> #define MARKER(pfexp) \ do{ printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); \ printf pfexp; \ } while(0) |
︙ | ︙ | |||
328 329 330 331 332 333 334 | fsl_stmt * s1 = NULL; fsl_buffer cmpr = fsl_buffer_empty; fsl_buffer hash = fsl_buffer_empty; char markAsUnclustered = 0; char markAsUnsent = 1; char isDephantomize = 0; fsl_db * dbR = fsl_cx_db_repo(f); | > | | > > > > > | > > > > > > > > > > > > | < | | > > > > > | | 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 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 | fsl_stmt * s1 = NULL; fsl_buffer cmpr = fsl_buffer_empty; fsl_buffer hash = fsl_buffer_empty; char markAsUnclustered = 0; char markAsUnsent = 1; char isDephantomize = 0; fsl_db * dbR = fsl_cx_db_repo(f); int const zUuidLen = zUuid ? fsl_is_uuid(zUuid) : 0; int rc = 0; char inTrans = 0; assert(f); assert(dbR); assert(pBlob); assert(srcId==0 || zUuid!=NULL); assert(!zUuid || zUuidLen); if(!dbR) return FSL_RC_NOT_A_REPO; if(!zUuid){ assert(0==uncompSize); /* "auxiliary hash" bits from: https://fossil-scm.org/fossil/file?ci=c965636958eb58aa&name=src%2Fcontent.c&ln=527-537 */ /* First check the auxiliary hash to see if there is already an artifact ** that uses the auxiliary hash name */ rc = fsl_cx_hash_buffer(f, 1, pBlob, &hash); if(rc) goto end; assert(hash.used>=FSL_UUIDv1_STRLEN); rid = fsl_uuid_to_rid(f, fsl_buffer_cstr(&hash)); assert(rid>=0 && "Cannot have malformed/ambiguous UUID at this point."); if(!rid){ /* No existing artifact with the auxiliary hash name. Therefore, use ** the primary hash name. */ hash.used = 0; rc = fsl_cx_hash_buffer(f, 0, pBlob, &hash); if(rc) goto end; assert(hash.used>=FSL_UUIDv1_STRLEN); } }else{ rc = fsl_buffer_append(&hash, zUuid, zUuidLen); if(rc) goto end; } assert(!rc); if(uncompSize){ /* pBlob is assumed to be compressed. */ assert(fsl_buffer_is_compressed(pBlob)); size = uncompSize; }else{ size = pBlob->used; if(srcId>0){ rc = fsl_delta_applied_size(pBlob->mem, pBlob->used, &size); if(rc) goto end; } } rc = fsl_db_transaction_begin(dbR); if(rc) goto end; inTrans = 1; if( f->cache.hashPolicy==FSL_HPOLICY_AUTO && hash.used>FSL_UUIDv1_STRLEN ){ f->cache.hashPolicy = FSL_HPOLICY_SHA3; rc = fsl_config_set_int32(f, FSL_CONFDB_REPO, "hash-policy", FSL_HPOLICY_SHA3); if(rc) goto end; } /* Check to see if the entry already exists and if it does whether or not the entry is a phantom. */ rc = fsl_db_prepare_cached(dbR, &s1, "SELECT rid, size FROM blob WHERE uuid=?"); if(rc) goto end; rc = fsl_stmt_bind_text( s1, 1, fsl_buffer_cstr(&hash), |
︙ | ︙ | |||
529 530 531 532 533 534 535 | TODO: figure out what that is. */ rc = fsl_content_mark_available(f, rid); if(rc) goto end; } if( isDephantomize ){ #if 0 | | | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | TODO: figure out what that is. */ rc = fsl_content_mark_available(f, rid); if(rc) goto end; } if( isDephantomize ){ #if 0 /* FIXME?: MISSING */ after_dephantomize(rid, 0); #else assert(!"Missing code: after_dephantomize()"); #endif } /* Add the element to the unclustered table if has never been |
︙ | ︙ | |||
557 558 559 560 561 562 563 | "VALUES(%"FSL_ID_T_PFMT")", (fsl_id_t)rid); if(rc) goto end; } rc = fsl_repo_verify_before_commit(f, rid); if(rc) goto end /* FSL_RC_OOM is basically the "only possible" failure after this point. */; | < < | 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 | "VALUES(%"FSL_ID_T_PFMT")", (fsl_id_t)rid); if(rc) goto end; } rc = fsl_repo_verify_before_commit(f, rid); if(rc) goto end /* FSL_RC_OOM is basically the "only possible" failure after this point. */; /* Code after end: relies on the following 2 lines: */ rc = fsl_db_transaction_end(dbR, 0); inTrans = 0; if(!rc){ if(outRid) *outRid = rid; } end: if(inTrans){ assert(0!=rc); fsl_db_transaction_end(dbR,1); } fsl_buffer_clear(&hash); if(!uncompSize){ fsl_buffer_clear(&cmpr); }/* else cmpr.mem (if any) belongs to pBlob */ return rc; } char fsl_acache_expire_oldest(fsl_acache * c){ fsl_int_t i; fsl_int_t mnAge = c->nextAge; fsl_int_t mn = -1; for(i=0; i<(fsl_int_t)c->used; i++){ if( c->list[i].age<mnAge ){ |
︙ | ︙ | |||
682 683 684 685 686 687 688 | } assert(!"delta-loop in repository"); return fsl_cx_err_set(f, FSL_RC_CONSISTENCY, "Serious problem: delta-loop in repository"); } int fsl_content_put( fsl_cx * f, fsl_buffer const * pBlob, fsl_id_t * newRid){ | < < < < < | < < < < < < < < < < < < < | < < < < < < | > | | | 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 | } assert(!"delta-loop in repository"); return fsl_cx_err_set(f, FSL_RC_CONSISTENCY, "Serious problem: delta-loop in repository"); } int fsl_content_put( fsl_cx * f, fsl_buffer const * pBlob, fsl_id_t * newRid){ return fsl_content_put_ex(f, pBlob, NULL, 0, 0, 0, newRid); } int fsl_uuid_is_shunned(fsl_cx * f, fsl_uuid_cstr zUuid){ fsl_int32_t i = 0; fsl_db * db = fsl_cx_db_repo(f); if( !db || zUuid==0 || zUuid[0]==0 ) return 0; i = fsl_db_g_int32( db, 0, "SELECT 1 FROM shun WHERE uuid=%Q", zUuid); return 1==i; } int fsl_content_new( fsl_cx * f, fsl_uuid_cstr uuid, char isPrivate, fsl_id_t * newId ){ fsl_id_t rid = 0; int rc; fsl_db * db = fsl_cx_db_repo(f); fsl_stmt * s1 = NULL, * s2 = NULL; int const uuidLen = uuid ? fsl_is_uuid(uuid) : 0; if(!f || !uuid) return FSL_RC_MISUSE; else if(!uuidLen) return FSL_RC_RANGE; if(!db) return FSL_RC_NOT_A_REPO; if( fsl_uuid_is_shunned(f, uuid) ){ return fsl_cx_err_set(f, FSL_RC_ACCESS, "UUID is shunned: %s", uuid) /* need new error code? */; } rc = fsl_db_transaction_begin(db); if(rc) return rc; rc = fsl_db_prepare_cached(db, &s1, "INSERT INTO blob(rcvid,size,uuid,content)" "VALUES(0,-1,?,NULL)"); if(rc) goto end; rc = fsl_stmt_bind_text(s1, 1, uuid, uuidLen, 0); if(!rc) rc = fsl_stmt_step(s1); fsl_stmt_cached_yield(s1); if(FSL_RC_STEP_DONE!=rc) goto end; else rc = 0; rid = fsl_db_last_insert_id(db); assert(rid>0); rc = fsl_db_prepare_cached(db, &s2, |
︙ | ︙ | |||
1306 1307 1308 1309 1310 1311 1312 | assert(0==fbuf->used); fsl_buffer_reset(nbuf); fsl_buffer_reset(canon); if(rc && inTrans) fsl_db_transaction_rollback(db); return rc; } | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 | assert(0==fbuf->used); fsl_buffer_reset(nbuf); fsl_buffer_reset(canon); if(rc && inTrans) fsl_db_transaction_rollback(db); return rc; } fsl_hash_types_t fsl_validate_hash(const char *zHash, int nHash){ /* fossil(1) counterpart: hname_validate() */ fsl_hash_types_t rc; switch(nHash){ case FSL_UUIDv1_STRLEN: rc = FSL_HTYPE_SHA1; break; case FSL_UUIDv2_STRLEN: rc = FSL_HTYPE_K256; break; default: return FSL_HTYPE_ERROR; } return fsl_validate16(zHash, (fsl_size_t)nHash) ? rc : FSL_HTYPE_ERROR; } const char * fsl_hash_type_name(fsl_hash_types_t h, const char *zUnknown){ /* fossil(1) counterpart: hname_alg() */ switch(h){ case FSL_HTYPE_SHA1: return "SHA1"; case FSL_HTYPE_K256: return "SHA3-256"; default: return zUnknown; } } fsl_hash_types_t fsl_verify_blob_hash(fsl_buffer const * pIn, const char *zHash, int nHash){ fsl_hash_types_t id = FSL_HTYPE_ERROR; switch(nHash){ case FSL_UUIDv1_STRLEN:{ fsl_sha1_cx cx; char hex[FSL_UUIDv1_STRLEN+1] = {0}; fsl_sha1_init(&cx); fsl_sha1_update(&cx, pIn->mem, (unsigned)pIn->used); fsl_sha1_final_hex(&cx, hex); if(0==memcmp(hex, zHash, FSL_UUIDv1_STRLEN)){ id = FSL_HTYPE_SHA1; } break; } case FSL_UUIDv2_STRLEN:{ fsl_sha3_cx cx; unsigned char const * hex; fsl_sha3_init(&cx); fsl_sha3_update(&cx, pIn->mem, (unsigned)pIn->used); hex = fsl_sha3_end(&cx); if(0==memcmp(hex, zHash, FSL_UUIDv2_STRLEN)){ id = FSL_HTYPE_K256; } break; } default: break; } return id; } #undef MARKER |
Changes to src/fsl_cx.c.
︙ | ︙ | |||
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 | rc = fsl_cx_db_main_open_or_attach(f, repoDbFile, FSL_DB_ROLE_REPO, NULL); if(!rc && !(FSL_CX_F_IS_OPENING_CKOUT & f->flags)){ rc = fsl_cx_after_open(f); } if(!rc){ fsl_cx_username_from_repo(f); f->cache.allowSymlinks = fsl_config_get_bool(f, FSL_CONFDB_REPO, f->cache.allowSymlinks, "allow-symlinks"); } } return rc; } } /** | > > > > > > > | 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 | rc = fsl_cx_db_main_open_or_attach(f, repoDbFile, FSL_DB_ROLE_REPO, NULL); if(!rc && !(FSL_CX_F_IS_OPENING_CKOUT & f->flags)){ rc = fsl_cx_after_open(f); } if(!rc){ fsl_db * const db = fsl_cx_db_repo(f); fsl_cx_username_from_repo(f); f->cache.allowSymlinks = fsl_config_get_bool(f, FSL_CONFDB_REPO, f->cache.allowSymlinks, "allow-symlinks"); if(fsl_db_exists(db, "SELECT 1 FROM blob WHERE length(uuid)>40") || !fsl_db_exists(db, "SELECT 1 FROM blob WHERE length(uuid)==40")){ f->cache.hashPolicy = FSL_HPOLICY_SHA3; }else{ f->cache.hashPolicy = FSL_HPOLICY_AUTO; } } } return rc; } } /** |
︙ | ︙ | |||
1034 1035 1036 1037 1038 1039 1040 | assert(f->error.code); if(!f->error.code){ rc = fsl_cx_err_set(f, FSL_RC_NOT_FOUND, "Could not load UUID for RID %"FSL_ID_T_PFMT, (fsl_id_t)rid); } }else{ | | | 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 | assert(f->error.code); if(!f->error.code){ rc = fsl_cx_err_set(f, FSL_RC_NOT_FOUND, "Could not load UUID for RID %"FSL_ID_T_PFMT, (fsl_id_t)rid); } }else{ assert(fsl_is_uuid(f->ckout.uuid)); rc = 0; } f->ckout.rid = rid; }else if(rid==0){ /* This is a legal case not possible before libfossil (and only afterwards possible in fossil(1)) - an empty repo without an active checkin. |
︙ | ︙ | |||
1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 | } int fsl_output_f_fsl_cx(void * state, void const * src, fsl_size_t n ){ return (state && src && n) ? fsl_output((fsl_cx*)state, src, n) : (n ? FSL_RC_MISUSE : 0); } #if 0 struct tm * fsl_cx_localtime( fsl_cx const * f, const time_t * clock ){ if(!clock) return NULL; else if(!f) return localtime(clock); else return (f->flags & FSL_CX_F_LOCALTIME_GMT) ? gmtime(clock) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 | } int fsl_output_f_fsl_cx(void * state, void const * src, fsl_size_t n ){ return (state && src && n) ? fsl_output((fsl_cx*)state, src, n) : (n ? FSL_RC_MISUSE : 0); } int fsl_cx_hash_buffer( const fsl_cx * f, int useAlternate, fsl_buffer const * pIn, fsl_buffer * pOut){ /* fossil(1) counterpart: hname_hash() */ if(useAlternate){ switch(f->cache.hashPolicy){ case FSL_HPOLICY_AUTO: case FSL_HPOLICY_SHA1: return fsl_sha3sum_buffer(pIn, pOut); case FSL_HPOLICY_SHA3: return fsl_sha1sum_buffer(pIn, pOut); default: return FSL_RC_RANGE; } }else{ switch(f->cache.hashPolicy){ case FSL_HPOLICY_SHA1: case FSL_HPOLICY_AUTO: return fsl_sha1sum_buffer(pIn, pOut); case FSL_HPOLICY_SHA3: case FSL_HPOLICY_SHA3_ONLY: case FSL_HPOLICY_SHUN_SHA1: return fsl_sha3sum_buffer(pIn, pOut); } } assert(!"not reached"); return FSL_RC_RANGE; } fsl_hash_policy_t fsl_cx_hash_policy_set(fsl_cx *f, fsl_hash_policy_t p){ fsl_hash_policy_t const old = f->cache.hashPolicy; f->cache.hashPolicy = p; return old; } fsl_hash_policy_t fsl_cx_hash_policy_get(fsl_cx const*f){ return f->cache.hashPolicy; } char const * fsl_cx_hash_policy_name(fsl_cx const*f){ switch(f->cache.hashPolicy){ case FSL_HPOLICY_SHUN_SHA1: return "shun-sha1"; case FSL_HPOLICY_SHA3: return "sha3"; case FSL_HPOLICY_SHA3_ONLY: return "sha3-only"; case FSL_HPOLICY_SHA1: return "sha1"; case FSL_HPOLICY_AUTO: return "auto"; default: return "unknown"; } } #if 0 struct tm * fsl_cx_localtime( fsl_cx const * f, const time_t * clock ){ if(!clock) return NULL; else if(!f) return localtime(clock); else return (f->flags & FSL_CX_F_LOCALTIME_GMT) ? gmtime(clock) |
︙ | ︙ |
Changes to src/fsl_md5.c.
︙ | ︙ | |||
342 343 344 345 346 347 348 | fsl_size_t read = (fsl_size_t)BufSize; rc = src(srcState, zBuf, &read); if(rc) return rc; else if(read) fsl_md5_update(&ctx, (unsigned char*)zBuf, read); if(read < (fsl_size_t)BufSize) break; } fsl_buffer_reset(pCksum); | | | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | fsl_size_t read = (fsl_size_t)BufSize; rc = src(srcState, zBuf, &read); if(rc) return rc; else if(read) fsl_md5_update(&ctx, (unsigned char*)zBuf, read); if(read < (fsl_size_t)BufSize) break; } fsl_buffer_reset(pCksum); rc = fsl_buffer_resize(pCksum, FSL_MD5_STRLEN); if(!rc){ fsl_md5_final(&ctx, zResult); fsl_md5_digest_to_base16(zResult, fsl_buffer_str(pCksum)); } return rc; } |
︙ | ︙ |
Changes to src/fsl_mf.c.
︙ | ︙ | |||
72 73 74 75 76 77 78 | fsl_free(t); } } fsl_card_Q * fsl_card_Q_malloc(int type, fsl_uuid_cstr target, fsl_uuid_cstr baseline){ | > > | | | | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | fsl_free(t); } } fsl_card_Q * fsl_card_Q_malloc(int type, fsl_uuid_cstr target, fsl_uuid_cstr baseline){ int const targetLen = target ? fsl_is_uuid(target) : 0; int const baselineLen = baseline ? fsl_is_uuid(baseline) : 0; if(!type || !target || !targetLen || (baseline && !baselineLen)) return NULL; else{ fsl_card_Q * c = (fsl_card_Q*)fsl_malloc(sizeof(fsl_card_Q)); if(c){ int rc = 0; *c = fsl_card_Q_empty; c->type = type; c->target = fsl_strndup(target, targetLen); if(!c->target) rc = FSL_RC_OOM; else if(baseline){ c->baseline = fsl_strndup(baseline, baselineLen); if(!c->baseline) rc = FSL_RC_OOM; } if(rc){ fsl_card_Q_free(c); c = NULL; } } |
︙ | ︙ | |||
147 148 149 150 151 152 153 154 | } fsl_card_F * fsl_card_F_malloc(char const * name, char const * uuid, fsl_file_perm_t perm, char const * oldName){ fsl_card_F * t; if(!name || !*name) return NULL; | > | | | | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | } fsl_card_F * fsl_card_F_malloc(char const * name, char const * uuid, fsl_file_perm_t perm, char const * oldName){ fsl_card_F * t; int const uLen = uuid ? fsl_is_uuid(uuid) : 0; if(!name || !*name) return NULL; else if(uuid && !uLen) return NULL; t = (fsl_card_F *)fsl_malloc(sizeof(fsl_card_F)); if(t){ int rc = 0; *t = fsl_card_F_empty; t->perm = perm; t->name = fsl_strdup(name); if(!t->name) rc = FSL_RC_OOM; if(!rc && uLen){ t->uuid = fsl_strndup(uuid, uLen); if(!t->uuid) rc = FSL_RC_OOM; } if(!rc && oldName){ t->priorName = fsl_strdup(oldName); if(!t->priorName) rc = FSL_RC_OOM; } if(rc){ |
︙ | ︙ | |||
529 530 531 532 533 534 535 | The function returns FSL_RC_RANGE if (valLen!=ASSERTLEN). ASSERTLEN is assumed to be either an SHA1 or MD5 hash value and it is validated against fsl_validate16(value,valLen), returning FSL_RC_CA_SYNTAX if that check fails. */ static int fsl_deck_sethex_impl( fsl_deck * mf, fsl_uuid_cstr value, | | | | | > > | | | 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 | The function returns FSL_RC_RANGE if (valLen!=ASSERTLEN). ASSERTLEN is assumed to be either an SHA1 or MD5 hash value and it is validated against fsl_validate16(value,valLen), returning FSL_RC_CA_SYNTAX if that check fails. */ static int fsl_deck_sethex_impl( fsl_deck * mf, fsl_uuid_cstr value, char letter, fsl_size_t assertLen, char ** mfMember ){ assert(mf); assert( assertLen==FSL_UUIDv1_STRLEN || assertLen==FSL_UUIDv2_STRLEN || assertLen==FSL_MD5_STRLEN ); if(!fsl_deck_check_type(mf,letter)) return FSL_RC_TYPE; else if(!value){ fsl_deck_free_string(mf, *mfMember); *mfMember = NULL; return 0; }else if(fsl_strlen(value) != assertLen){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid length for %c-card: expecting %d.", letter, (int)assertLen); }else if(!fsl_validate16(value, assertLen)) { return fsl_error_set(&mf->error, FSL_RC_CA_SYNTAX, "Invalid hexadecimal value for %c-card.", letter); }else{ fsl_deck_free_string(mf, *mfMember); *mfMember = fsl_strndup(value, assertLen); return *mfMember ? 0 : FSL_RC_OOM; } } /** Implements fsl_set_set_XXX() where XXX is a fsl_buffer member of fsl_deck. */ |
︙ | ︙ | |||
574 575 576 577 578 579 580 581 582 583 584 585 | return 0; } } int fsl_deck_B_set( fsl_deck * mf, fsl_uuid_cstr uuidBaseline){ if(!mf) return FSL_RC_MISUSE; else{ if(mf->B.baseline){ fsl_deck_finalize(mf->B.baseline); mf->B.baseline = NULL; } return fsl_deck_sethex_impl(mf, uuidBaseline, 'B', | > > > > > | | 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 | return 0; } } int fsl_deck_B_set( fsl_deck * mf, fsl_uuid_cstr uuidBaseline){ if(!mf) return FSL_RC_MISUSE; else{ int const bLen = fsl_is_uuid(uuidBaseline); if(!bLen){ return fsl_error_set(&mf->error, FSL_RC_CA_SYNTAX, "Invalid B-card value: %s", uuidBaseline); } if(mf->B.baseline){ fsl_deck_finalize(mf->B.baseline); mf->B.baseline = NULL; } return fsl_deck_sethex_impl(mf, uuidBaseline, 'B', bLen, &mf->B.uuid); } } /** Internal impl for card setters which consider of a simple (char *) member. */ |
︙ | ︙ | |||
619 620 621 622 623 624 625 | } return rc; } } int fsl_deck_K_set( fsl_deck * mf, fsl_uuid_cstr uuid){ | > | | > | | | 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 | } return rc; } } int fsl_deck_K_set( fsl_deck * mf, fsl_uuid_cstr uuid){ int const uLen = fsl_is_uuid(uuid); return (mf && uLen) ? fsl_deck_sethex_impl(mf, uuid, 'K', uLen, &mf->K) : FSL_RC_MISUSE; } int fsl_deck_L_set( fsl_deck * mf, char const * v, fsl_int_t n){ return mf ? fsl_deck_set_string(mf, 'L', &mf->L, v, n) : FSL_RC_MISUSE; } int fsl_deck_M_add( fsl_deck * mf, char const *uuid){ int rc; char * dupe; int const uLen = uuid ? fsl_is_uuid(uuid) : 0; if(!mf || !uuid) return FSL_RC_MISUSE; else if(!fsl_deck_check_type(mf, 'M')) return FSL_RC_TYPE; else if(!uLen) return FSL_RC_RANGE; dupe = fsl_strndup(uuid, uLen); if(!dupe) rc = FSL_RC_OOM; else{ rc = fsl_list_append( &mf->M, dupe ); if(rc){ fsl_free(dupe); } } |
︙ | ︙ | |||
658 659 660 661 662 663 664 665 666 | : FSL_RC_MISUSE; } int fsl_deck_P_add( fsl_deck * mf, char const *parentUuid){ int rc; char * dupe; if(!mf || !parentUuid || !*parentUuid) return FSL_RC_MISUSE; else if(!fsl_deck_check_type(mf, 'P')) return FSL_RC_TYPE; | > | | | 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 | : FSL_RC_MISUSE; } int fsl_deck_P_add( fsl_deck * mf, char const *parentUuid){ int rc; char * dupe; int const uLen = parentUuid ? fsl_is_uuid(parentUuid) : 0; if(!mf || !parentUuid || !*parentUuid) return FSL_RC_MISUSE; else if(!fsl_deck_check_type(mf, 'P')) return FSL_RC_TYPE; else if(!uLen){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid UUID for P-card."); } dupe = fsl_strndup(parentUuid, uLen); if(!dupe) rc = FSL_RC_OOM; else{ rc = fsl_list_append( &mf->P, dupe ); if(rc){ fsl_free(dupe); } } |
︙ | ︙ | |||
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 | ? fsl_deck_b_setuffer_impl(mf, v, n, 'W', &mf->W) : FSL_RC_MISUSE; } int fsl_deck_A_set( fsl_deck * mf, char const * name, char const * tgt, char const * uuidSrc ){ if(!mf || !name || !tgt) return FSL_RC_MISUSE; else if(!fsl_deck_check_type(mf, 'A')) return FSL_RC_TYPE; else if(!*tgt){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid target name in A card."); } /* TODO: validate tgt based on mf->type and require UUID for types EVENT/TICKET. */ | > | | | > | | | | 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 | ? fsl_deck_b_setuffer_impl(mf, v, n, 'W', &mf->W) : FSL_RC_MISUSE; } int fsl_deck_A_set( fsl_deck * mf, char const * name, char const * tgt, char const * uuidSrc ){ int const uLen = (uuidSrc && *uuidSrc) ? fsl_is_uuid(uuidSrc) : 0; if(!mf || !name || !tgt) return FSL_RC_MISUSE; else if(!fsl_deck_check_type(mf, 'A')) return FSL_RC_TYPE; else if(!*tgt){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid target name in A card."); } /* TODO: validate tgt based on mf->type and require UUID for types EVENT/TICKET. */ else if(uuidSrc && *uuidSrc && !uLen){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid source UUID in A card."); } else{ int rc = 0; fsl_deck_free_string(mf, mf->A.tgt); fsl_deck_free_string(mf, mf->A.src); fsl_deck_free_string(mf, mf->A.name); mf->A.name = mf->A.src = NULL; if(! (mf->A.tgt = fsl_strdup(tgt))) rc = FSL_RC_OOM; else if( !(mf->A.name = fsl_strdup(name))) rc = FSL_RC_OOM; else if(uLen){ mf->A.src = fsl_strndup(uuidSrc,uLen); if(!mf->A.src) rc = FSL_RC_OOM /* Leave mf->A.tgt/name for downstream cleanup. */; } return rc; } } int fsl_deck_D_set( fsl_deck * mf, fsl_double_t date){ if(!mf) return FSL_RC_MISUSE; else if(date<=0) return FSL_RC_RANGE; else if(!fsl_deck_check_type(mf, 'D')) return FSL_RC_TYPE; else{ mf->D = date; return 0; } } int fsl_deck_E_set( fsl_deck * mf, fsl_double_t date, char const * uuid){ int const uLen = uuid ? fsl_is_uuid(uuid) : 0; if(!mf || !uLen) return FSL_RC_MISUSE; else if(date<=0){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid date value for E card."); }else if(!uLen){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid UUID for E card."); } else{ mf->E.julian = date; fsl_deck_free_string(mf, mf->E.uuid); mf->E.uuid = fsl_strndup(uuid, uLen); return mf->E.uuid ? 0 : FSL_RC_OOM; } } int fsl_deck_F_add2( fsl_deck * mf, fsl_card_F * t){ if(!mf || !t) return FSL_RC_MISUSE; else if(!fsl_deck_check_type(mf, 'F')) return FSL_RC_TYPE; |
︙ | ︙ | |||
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | } } int fsl_deck_F_add( fsl_deck * mf, char const * name, char const * uuid, fsl_file_perm_t perms, char const * oldName){ if(!mf || !name) return FSL_RC_MISUSE; else if(!fsl_deck_check_type(mf, 'F')) return FSL_RC_TYPE; else if(!*name){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "F-card name may not be empty."); } else if(!fsl_is_simple_pathname(name, 1) || (oldName && !fsl_is_simple_pathname(oldName, 1))){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid filename for F-card (simple form required): " "name=[%s], oldName=[%s].", name, oldName); } | > | | 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 | } } int fsl_deck_F_add( fsl_deck * mf, char const * name, char const * uuid, fsl_file_perm_t perms, char const * oldName){ int const uLen = uuid ? fsl_is_uuid(uuid) : 0; if(!mf || !name) return FSL_RC_MISUSE; else if(!fsl_deck_check_type(mf, 'F')) return FSL_RC_TYPE; else if(!*name){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "F-card name may not be empty."); } else if(!fsl_is_simple_pathname(name, 1) || (oldName && !fsl_is_simple_pathname(oldName, 1))){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid filename for F-card (simple form required): " "name=[%s], oldName=[%s].", name, oldName); } else if(uuid && !uLen){ return fsl_error_set(&mf->error, FSL_RC_RANGE, "Invalid UUID for F-card."); } else { int rc; fsl_card_F * t; switch(perms){ |
︙ | ︙ | |||
1465 1466 1467 1468 1469 1470 1471 | fsl_list_visitor_f() impl for outputing P cards. obj must be a (fsl_deck_out_state *) and obj->counter must be set to 0 before running the visit iteration. */ static int fsl_list_v_mf_output_card_P(void * obj, void * visitorState ){ fsl_deck_out_state * os = (fsl_deck_out_state *)visitorState; char const * uuid = (char const *)obj; | < < | > < < | | 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 | fsl_list_visitor_f() impl for outputing P cards. obj must be a (fsl_deck_out_state *) and obj->counter must be set to 0 before running the visit iteration. */ static int fsl_list_v_mf_output_card_P(void * obj, void * visitorState ){ fsl_deck_out_state * os = (fsl_deck_out_state *)visitorState; char const * uuid = (char const *)obj; int const uLen = uuid ? fsl_is_uuid(uuid) : 0; if(!uLen){ os->rc = fsl_error_set(&os->error, FSL_RC_RANGE, "Invalid UUID in P card."); } else if(!os->counter++) fsl_appendf_f_mf(os, "P ", 2); else fsl_appendf_f_mf(os, " ", 1); /* Reminder: fsl_appendf_f_mf() updates os->rc. */ if(!os->rc){ fsl_appendf_f_mf(os, uuid, (fsl_size_t)uLen); } return os->rc; } static int fsl_deck_out_P( fsl_deck_out_state * os ){ if(!fsl_deck_out_tcheck(os, 'P')) return os->rc; |
︙ | ︙ | |||
2957 2958 2959 2960 2961 2962 2963 | wiki_end: fsl_buffer_clear(&buf); if(rc) goto end; }/*WIKI*/ if( d->type==FSL_CATYPE_EVENT ){ | | | 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 | wiki_end: fsl_buffer_clear(&buf); if(rc) goto end; }/*WIKI*/ if( d->type==FSL_CATYPE_EVENT ){ char buf[FSL_UUIDv2_STRLEN + 7 /* event-UUID */] = {0}; char zLength[40] = {0}; fsl_id_t tagid; fsl_id_t prior, subsequent; char const * zWiki; char const * zTag; fsl_size_t nWiki = 0; fsl_snprintf(buf, sizeof(buf), "event-%s", d->E.uuid); |
︙ | ︙ | |||
3622 3623 3624 3625 3626 3627 3628 | x.zEnd = z+n; x.atEol= 1; /* Parsing helpers... */ #define TOKEN(DEFOS) tokLen=0; token = fsl_mf_next_token(&x,&tokLen); \ if(token && tokLen && (DEFOS)) fsl_bytes_defossilize(token, &tokLen) #define TOKEN_EXISTS(MSG_IF_NOT) if(!token){ SYNTAX(MSG_IF_NOT); }(void)0 | | < < | | > > | 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 | x.zEnd = z+n; x.atEol= 1; /* Parsing helpers... */ #define TOKEN(DEFOS) tokLen=0; token = fsl_mf_next_token(&x,&tokLen); \ if(token && tokLen && (DEFOS)) fsl_bytes_defossilize(token, &tokLen) #define TOKEN_EXISTS(MSG_IF_NOT) if(!token){ SYNTAX(MSG_IF_NOT); }(void)0 #define TOKEN_CHECKHEX(MSG) if(token && (int)tokLen!=fsl_is_uuid((char const *)token))\ { SYNTAX(MSG); } #define TOKEN_UUID(CARD) TOKEN_CHECKHEX("Malformed UUID in " #CARD "-card") #define TOKEN_MD5(ERRMSG) if(!token || FSL_MD5_STRLEN!=(int)tokLen) \ {SYNTAX(ERRMSG);} /** Reminder: we do not know the type of the manifest at this point, so all of the fsl_deck_add/set() bits below can't do their validation. We have to determine at parse-time (or afterwards) which type of deck it is based on the cards we've seen. We guess the type as early as possible to enable during-parse validation, and do a post-parse check for the legality of cards added before |
︙ | ︙ | |||
3999 4000 4001 4002 4003 4004 4005 | */ case 'R':{ if(1<SEEN(R)){ ERROR(FSL_RC_RANGE,"More than one R-card"); } TOKEN(0); TOKEN_EXISTS("Missing MD5 token in R-card"); | | | 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 | */ case 'R':{ if(1<SEEN(R)){ ERROR(FSL_RC_RANGE,"More than one R-card"); } TOKEN(0); TOKEN_EXISTS("Missing MD5 token in R-card"); TOKEN_MD5("Malformed MD5 token in R-card"); d->R = (char *)token; ++stealBuf; /* rc = fsl_deck_R_set(d, (char const *)token); */ break; } /* T (+|*|-)<tagname> <uuid> ?<value>? |
︙ | ︙ | |||
4028 4029 4030 4031 4032 4033 4034 | unsigned char * name, * value; fsl_tag_type tagType = FSL_TAGTYPE_INVALID; TOKEN(0); TOKEN_EXISTS("Missing name for T-card"); name = token; TOKEN(0); TOKEN_EXISTS("Missing UUID on T-card"); | | | 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 | unsigned char * name, * value; fsl_tag_type tagType = FSL_TAGTYPE_INVALID; TOKEN(0); TOKEN_EXISTS("Missing name for T-card"); name = token; TOKEN(0); TOKEN_EXISTS("Missing UUID on T-card"); if(fsl_is_uuid_len((int)tokLen)){ TOKEN_UUID(T); /* A valid UUID */ if(FSL_CATYPE_EVENT==d->type){ SYNTAX("Non-self-referential T-card in Event artifact"); } uuid = token; }else if( 1==tokLen && '*'==(char)*token ){ |
︙ | ︙ | |||
4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 | if(rid<0){ return fsl_cx_err_set(f, FSL_RC_RANGE, "Invalid RID for fsl_deck_load_rid(): " "%"FSL_ID_T_PFMT, (fsl_id_t)rid); } rc = fsl_content_get(f, rid, &buf); if(!rc){ fsl_deck_clean(d); fsl_deck_init(f, d, FSL_CATYPE_ANY); #if 0 /* If we set d->type=type, the parser can fail more quickly. However, that failure will bypass our more specific reporting of the problem (see below). As the type mismatch case is expected to be fairly rare, we'll leave this out for now, but it might be worth considering as a small optimization later on. */ d->type = type /* may help parsing fail more quickly if it's not the type we want.*/; #endif rc = fsl_deck_parse(d, &buf); if(!rc){ assert(rid == d->rid); if( type!=FSL_CATYPE_ANY && d->type!=type ){ rc = fsl_cx_err_set(f, FSL_RC_TYPE, "RID %"FSL_ID_T_PFMT" is of type %s, " "but the caller requested type %s.", (fsl_id_t)rid, | > > > > > > > | 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 | if(rid<0){ return fsl_cx_err_set(f, FSL_RC_RANGE, "Invalid RID for fsl_deck_load_rid(): " "%"FSL_ID_T_PFMT, (fsl_id_t)rid); } rc = fsl_content_get(f, rid, &buf); if(!rc){ #if 0 MARKER(("fsl_content_get(%d) len=%d =\n%.*s\n", (int)rid, (int)buf.used, (int)buf.used, (char const*)buf.mem)); #endif fsl_deck_clean(d); fsl_deck_init(f, d, FSL_CATYPE_ANY); #if 0 /* If we set d->type=type, the parser can fail more quickly. However, that failure will bypass our more specific reporting of the problem (see below). As the type mismatch case is expected to be fairly rare, we'll leave this out for now, but it might be worth considering as a small optimization later on. */ d->type = type /* may help parsing fail more quickly if it's not the type we want.*/; #endif rc = fsl_deck_parse(d, &buf); #if 0 MARKER(("rid=%d, d->rid=%d\n", (int)rid, (int)d->rid)); #endif if(!rc){ assert(rid == d->rid); if( type!=FSL_CATYPE_ANY && d->type!=type ){ rc = fsl_cx_err_set(f, FSL_RC_TYPE, "RID %"FSL_ID_T_PFMT" is of type %s, " "but the caller requested type %s.", (fsl_id_t)rid, |
︙ | ︙ |
Changes to src/fsl_repo.c.
︙ | ︙ | |||
147 148 149 150 151 152 153 | rid = fsl_stmt_g_id(&q, 0); }while( fsl_stmt_g_int32(&q, 1)==1 && rid>0 ); fsl_stmt_finalize(&q); goto gotit; } symLen = fsl_strlen(sym); | | | | | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | rid = fsl_stmt_g_id(&q, 0); }while( fsl_stmt_g_int32(&q, 1)==1 && rid>0 ); fsl_stmt_finalize(&q); goto gotit; } symLen = fsl_strlen(sym); /* SHA1/SHA3 hash or prefix */ if( symLen>=4 && symLen<=FSL_UUIDv2_STRLEN && fsl_validate16(sym, symLen) ){ fsl_stmt q = fsl_stmt_empty; char zUuid[FSL_UUIDv2_STRLEN+1]; memcpy(zUuid, sym, symLen); zUuid[symLen] = 0; fsl_canonical16(zUuid, symLen); rid = 0; /* Reminder to self: caching these queries would be cool but it can't work with the GLOBs. */ |
︙ | ︙ | |||
296 297 298 299 300 301 302 | fsl_free( rvv ); } } return rc; } fsl_id_t fsl_uuid_to_rid( fsl_cx * f, char const * uuid ){ | | | | | | | > > > > > > | | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 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 | fsl_free( rvv ); } } return rc; } fsl_id_t fsl_uuid_to_rid( fsl_cx * f, char const * uuid ){ fsl_db * const db = fsl_needs_repo(f); fsl_size_t const uuidLen = (uuid && db) ? fsl_strlen(uuid) : 0; if(!f || !uuid || !uuidLen) return -1; else if(!db){ /* f's error state has already been set */ return -2; } else if(!fsl_validate16(uuid, uuidLen)){ fsl_cx_err_set(f, FSL_RC_RANGE, "Invalid UUID (prefix): %s", uuid); return -3; } else if(uuidLen>FSL_UUIDv2_STRLEN){ fsl_cx_err_set(f, FSL_RC_RANGE, "UUID is too long: %s", uuid); return -4; } else { fsl_id_t rid = -5; fsl_stmt q = fsl_stmt_empty; fsl_stmt * qS = NULL; int rc; rc = fsl_is_uuid_len((int)uuidLen) /* Optimization for the common internally-used case. FIXME: there is an *astronomically small* chance of a prefix collision on a v1-length uuidLen against a v2-length blob.uuid value, leading to no match found for an existing v2 uuid here. Like... a *REALLY* small chance. */ ? fsl_db_prepare_cached(db, &qS, "SELECT rid FROM blob WHERE " "uuid=?") : fsl_db_prepare(db, &q, "SELECT rid FROM blob WHERE " "uuid GLOB '%s*'", uuid); if(!rc){ fsl_stmt * st = qS ? qS : &q; if(qS){ rc = fsl_stmt_bind_text(qS, 1, uuid, (fsl_int_t)uuidLen, 0); } if(!rc){ rc = fsl_stmt_step(st); switch(rc){ case FSL_RC_STEP_ROW: rc = 0; rid = fsl_stmt_g_id(st, 0); |
︙ | ︙ |
Changes to src/fsl_sha1.c.
︙ | ︙ | |||
1728 1729 1730 1731 1732 1733 1734 | digest is stored in the first 20 bytes. zBuf should be "char zBuf[41]". */ void fsl_sha1_digest_to_base16(unsigned char *digest, char *zBuf){ static char const zEncode[] = "0123456789abcdef"; int ix; | | | 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 | digest is stored in the first 20 bytes. zBuf should be "char zBuf[41]". */ void fsl_sha1_digest_to_base16(unsigned char *digest, char *zBuf){ static char const zEncode[] = "0123456789abcdef"; int ix; for(ix=0; ix<FSL_UUIDv1_STRLEN/2; ix++){ *zBuf++ = zEncode[(*digest>>4)&0xf]; *zBuf++ = zEncode[*digest++ & 0xf]; } *zBuf = '\0'; } |
︙ | ︙ | |||
1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 | digest[i] = (unsigned char) ((ctx->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); } } return 0; #endif } int fsl_sha1sum_stream(fsl_input_f src, void * srcState, fsl_buffer *pCksum){ fsl_sha1_cx ctx; int rc; | > > > > > > > > < < | < | | | 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 | digest[i] = (unsigned char) ((ctx->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); } } return 0; #endif } char const * fsl_sha1_final_hex(fsl_sha1_cx *context, char * zHex){ unsigned char zResult[FSL_UUIDv1_STRLEN/2]; fsl_sha1_final(context, zResult); fsl_sha1_digest_to_base16(zResult, zHex); return (char const *)zHex; } int fsl_sha1sum_stream(fsl_input_f src, void * srcState, fsl_buffer *pCksum){ enum { BufSize = 1024 * 4 }; fsl_sha1_cx ctx; int rc; unsigned char zBuf[BufSize]; if(!src || !pCksum) return FSL_RC_MISUSE; fsl_sha1_init(&ctx); for(;;){ fsl_size_t read = (fsl_size_t)BufSize; rc = src(srcState, zBuf, &read); if(rc) return rc; else if(read) fsl_sha1_update(&ctx, (unsigned char*)zBuf, read); if(read < (fsl_size_t)BufSize) break; } fsl_buffer_reset(pCksum); rc = fsl_buffer_resize(pCksum, FSL_UUIDv1_STRLEN); if(!rc){ fsl_sha1_final_hex(&ctx, fsl_buffer_str(pCksum)); } return rc; } int fsl_sha1sum_filename(const char *zFilename, fsl_buffer *pCksum){ if(!zFilename || !pCksum) return FSL_RC_MISUSE; else{ #if 1 int rc; FILE *in = fsl_fopen(zFilename, "rb"); if(!in) rc = FSL_RC_IO; else{ rc = fsl_sha1sum_stream(fsl_input_f_FILE, in, pCksum); fsl_fclose(in); } return rc; #else /* Requires v1 code which has not yet been ported in. */ FILE *in; fsl_sha1_cx ctx; unsigned char zResult[FSL_UUIDv1_STRLEN/2]; char zBuf[10240]; if( fsl_wd_islink(zFilename) ){ /* Instead of file content, return sha1 of link destination path */ Blob destinationPath; int rc; |
︙ | ︙ | |||
1867 1868 1869 1870 1871 1872 1873 | int n; n = fread(zBuf, 1, sizeof(zBuf), in); if( n<=0 ) break; fsl_sha1_update(&ctx, (unsigned char*)zBuf, (unsigned)n); } fclose_fclose(in); blob_zero(pCksum); | | < | < | < | | | < | | 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 | int n; n = fread(zBuf, 1, sizeof(zBuf), in); if( n<=0 ) break; fsl_sha1_update(&ctx, (unsigned char*)zBuf, (unsigned)n); } fclose_fclose(in); blob_zero(pCksum); blob_resize(pCksum, FSL_UUIDv1_STRLEN); fsl_sha1_final(&ctx, zResult); fsl_sha1_digest_to_base16(zResult, blob_buffer(pCksum)); return 0; #endif } } int fsl_sha1sum_buffer(fsl_buffer const *pIn, fsl_buffer *pCksum){ if(!pIn || !pCksum) return FSL_RC_MISUSE; else{ fsl_sha1_cx ctx; int rc; fsl_sha1_init(&ctx); fsl_sha1_update(&ctx, pIn->mem, pIn->used); fsl_buffer_reset(pCksum); rc = fsl_buffer_resize(pCksum, FSL_UUIDv1_STRLEN /*resize() adds 1 for NUL*/); if(!rc){ fsl_sha1_final_hex(&ctx, fsl_buffer_str(pCksum)); assert(0==pCksum->mem[pCksum->used]); } return rc; } } char *fsl_sha1sum_cstr(const char *zIn, fsl_int_t len){ if(!zIn || !len) return NULL; else{ fsl_sha1_cx ctx; char * zHex = (char *)fsl_malloc(FSL_UUIDv1_STRLEN+1); if(!zHex) return NULL; fsl_sha1_init(&ctx); fsl_sha1_update(&ctx, zIn, (len<0) ? fsl_strlen(zIn) : (fsl_size_t)len); fsl_sha1_final_hex(&ctx, zHex); return zHex; } } |
Changes to src/fsl_sha3.c.
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include "fossil-scm/fossil-hash.h" #include <assert.h> #include <string.h> /* strlen() */ #include <stddef.h> /* NULL on linux */ #include <sys/types.h> #include <assert.h> /* ** Macros to determine whether the machine is big or little endian, ** and whether or not that determination is run-time or compile-time. ** ** For best performance, an attempt is made to guess at the byte-order ** using C-preprocessor macros. If that is unsuccessful, or if ** -DSHA3_BYTEORDER=0 is set, then byte-order is determined | > > > > > > > > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #include "fossil-scm/fossil-hash.h" #include <assert.h> #include <string.h> /* strlen() */ #include <stddef.h> /* NULL on linux */ #include <sys/types.h> #include <assert.h> #if 0 #include <stdio.h> #define MARKER(pfexp) \ do{ printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); \ printf pfexp; \ } while(0) #endif /* ** Macros to determine whether the machine is big or little endian, ** and whether or not that determination is run-time or compile-time. ** ** For best performance, an attempt is made to guess at the byte-order ** using C-preprocessor macros. If that is unsuccessful, or if ** -DSHA3_BYTEORDER=0 is set, then byte-order is determined |
︙ | ︙ | |||
412 413 414 415 416 417 418 | case 384: return FSL_SHA3_384; case 416: return FSL_SHA3_416; case 448: return FSL_SHA3_448; case 480: return FSL_SHA3_480; case 512: return FSL_SHA3_512; default: return FSL_SHA3_INVALID; } } | | > > > > | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | case 384: return FSL_SHA3_384; case 416: return FSL_SHA3_416; case 448: return FSL_SHA3_448; case 480: return FSL_SHA3_480; case 512: return FSL_SHA3_512; default: return FSL_SHA3_INVALID; } } void fsl_sha3_init(fsl_sha3_cx *cx){ fsl_sha3_init2(cx, FSL_SHA3_DEFAULT); } void fsl_sha3_init2(fsl_sha3_cx *p, enum fsl_sha3_hash_size iSize){ assert(iSize>0); memset(p, 0, sizeof(*p)); p->size = iSize; if( iSize>=128 && iSize<=512 ){ p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; }else{ p->nRate = (1600 - 2*256)/8; } |
︙ | ︙ | |||
505 506 507 508 509 510 511 | p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; } DigestToBase16( &p->u.x[p->nRate], p->hex, (int)p->size/8 ); assert(0 == p->hex[(int)p->size/4+1]); return &p->u.x[p->nRate]; } | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; } DigestToBase16( &p->u.x[p->nRate], p->hex, (int)p->size/8 ); assert(0 == p->hex[(int)p->size/4+1]); return &p->u.x[p->nRate]; } void fsl_sha3_digest_to_base16(unsigned char *digest, char *zBuf){ static char const zEncode[] = "0123456789abcdef"; int ix; for(ix=0; ix<FSL_UUIDv2_STRLEN/2; ix++){ *zBuf++ = zEncode[(*digest>>4)&0xf]; *zBuf++ = zEncode[*digest++ & 0xf]; } *zBuf = '\0'; } int fsl_sha3sum_stream(fsl_input_f src, void * srcState, fsl_buffer *pCksum){ fsl_sha3_cx ctx; int rc; enum { BufSize = 1024 * 4 }; unsigned char zBuf[BufSize]; if(!src || !pCksum) return FSL_RC_MISUSE; fsl_sha3_init(&ctx); for(;;){ fsl_size_t read = (fsl_size_t)BufSize; rc = src(srcState, zBuf, &read); if(rc) return rc; else if(read) fsl_sha3_update(&ctx, (unsigned char*)zBuf, read); if(read < (fsl_size_t)BufSize) break; } fsl_buffer_reset(pCksum); rc = fsl_buffer_resize(pCksum, FSL_UUIDv2_STRLEN); if(!rc){ fsl_sha3_end(&ctx); rc = fsl_buffer_append(pCksum, ctx.hex, fsl_strlen((const char *)ctx.hex)); } return rc; } int fsl_sha3sum_buffer(fsl_buffer const *pIn, fsl_buffer *pCksum){ if(!pIn || !pCksum) return FSL_RC_MISUSE; else{ fsl_sha3_cx ctx; int rc; fsl_sha3_init(&ctx); fsl_sha3_update(&ctx, pIn->mem, pIn->used); fsl_buffer_reset(pCksum); rc = fsl_buffer_resize(pCksum, FSL_UUIDv2_STRLEN /*resize() adds 1 for NUL*/); if(!rc){ pCksum->used = 0; fsl_sha3_end(&ctx); assert(fsl_strlen((char const*)ctx.hex)==FSL_UUIDv2_STRLEN); rc = fsl_buffer_append(pCksum, ctx.hex, fsl_strlen((char const*)ctx.hex)); assert(!rc && "Cannot fail - pre-allocated"); if(!rc){ assert(0==pCksum->mem[pCksum->used]); } } return rc; } } char *fsl_sha3sum_cstr(const char *zIn, fsl_int_t len){ if(!zIn || !len) return NULL; else{ fsl_sha3_cx ctx; fsl_sha3_init(&ctx); fsl_sha3_update(&ctx, zIn, (len<0) ? fsl_strlen(zIn) : (fsl_size_t)len); fsl_sha3_end(&ctx); return fsl_strdup((char const *)ctx.hex); } } int fsl_sha3sum_filename(const char *zFilename, fsl_buffer *pCksum){ if(!zFilename || !pCksum) return FSL_RC_MISUSE; else{ #if 1 int rc; FILE *in = fsl_fopen(zFilename, "rb"); if(!in) rc = FSL_RC_IO; else{ rc = fsl_sha3sum_stream(fsl_input_f_FILE, in, pCksum); fsl_fclose(in); } return rc; #else /* Requires v1 code which has not yet been ported in. */ FILE *in; fsl_sha1_cx ctx; char zBuf[10240]; int rc; if( fsl_wd_islink(zFilename) ){ /* Instead of file content, return sha3 of link destination path */ Blob destinationPath; blob_read_link(&destinationPath, zFilename); rc = fsl_sha3sum_buffer(&destinationPath, pCksum); fsl_buffer_clear(&destinationPath); return rc; } in = fossil_fopen(zFilename,"rb"); if( in==0 ){ return 1; } fsl_sha3_init(&ctx); for(;;){ int n; n = fread(zBuf, 1, sizeof(zBuf), in); if( n<=0 ) break; fsl_sha3_update(&ctx, (unsigned char*)zBuf, (unsigned)n); } fclose_fclose(in); blob_zero(pCksum); blob_resize(pCksum, FSL_UUIDv1_STRLEN); fsl_sha3_end(&ctx); rc = fsl_buffer_append(pCksum, ctx.hex, fsl_strlen(ctx.hex)); return rc; #endif } } #undef SHA3_BYTEORDER #undef MARKER |
Changes to src/fsl_tag.c.
︙ | ︙ | |||
49 50 51 52 53 54 55 | } fsl_card_T * fsl_card_T_malloc(fsl_tag_type tagType, char const * uuid, char const * name, char const * value){ fsl_card_T * t; | | > | | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | } fsl_card_T * fsl_card_T_malloc(fsl_tag_type tagType, char const * uuid, char const * name, char const * value){ fsl_card_T * t; int const uuidLen = uuid ? fsl_is_uuid(uuid) : 0; if(uuid && !uuidLen) return NULL; t = (fsl_card_T *)fsl_malloc(sizeof(fsl_card_T)); if(t){ int rc = 0; *t = fsl_card_T_empty; t->type = tagType; if(uuid && *uuid){ t->uuid = fsl_strndup(uuid, uuidLen); if(!t->uuid) rc = FSL_RC_OOM; } if(!rc && name && *name){ t->name = fsl_strdup(name); if(!t->name){ rc = FSL_RC_OOM; } |
︙ | ︙ |
Changes to src/fsl_vfile.c.
︙ | ︙ | |||
84 85 86 87 88 89 90 | if(rc) goto end; rc = fsl_stmt_bind_id_name(&qIns, ":vid", vid); while( !rc && !(rc=fsl_deck_F_next(&d, &fc)) && fc){ fsl_id_t rid; fsl_int64_t size; if(!fc->uuid /* was removed in this version */ || fsl_uuid_is_shunned(f,fc->uuid)) continue; | | | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | if(rc) goto end; rc = fsl_stmt_bind_id_name(&qIns, ":vid", vid); while( !rc && !(rc=fsl_deck_F_next(&d, &fc)) && fc){ fsl_id_t rid; fsl_int64_t size; if(!fc->uuid /* was removed in this version */ || fsl_uuid_is_shunned(f,fc->uuid)) continue; rc = fsl_stmt_bind_text(&qRid, 1, fc->uuid, -1, 0); if(rc) break; rc = fsl_stmt_step(&qRid); if(FSL_RC_STEP_ROW==rc){ rid = fsl_stmt_g_id(&qRid,0); size = fsl_stmt_g_int64(&qRid,1); }else if(FSL_RC_STEP_DONE==rc){ rid = 0; |
︙ | ︙ | |||
135 136 137 138 139 140 141 142 143 144 145 146 147 148 | else rc = fsl_db_transaction_commit(dbC); if(rc && !f->error.code){ if(dbC->error.code) fsl_cx_uplift_db_error(f, dbC); else if(dbR->error.code) fsl_cx_uplift_db_error(f, dbR); } return rc; } /** UNTESTED single-file version of fsl_vfile_changes_scan(). vid is the version to scan changes against. If 0 or less, the current checkout is used. The vfile table must have been previously populated with vid's contents (which it will have been for the | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | else rc = fsl_db_transaction_commit(dbC); if(rc && !f->error.code){ if(dbC->error.code) fsl_cx_uplift_db_error(f, dbC); else if(dbR->error.code) fsl_cx_uplift_db_error(f, dbR); } return rc; } /** Internal code de-duplifier for places which need to re-check a file's hash in order to be sure whether it was really modified. hashLen must be the length of the previous (db-side) hash of the file. This routine will hash that file using the same hash type. Returns 0 on success. On error, if *errReported is set to non-0 then the error state has already been set */ static int fsl_vfile_recheck_file_hash( fsl_cx * f, const char * zName, int hashLen, fsl_buffer * pTgt ){ int errReported = 0; int rc = 0; pTgt->used = 0; if(FSL_UUIDv1_STRLEN==hashLen){ rc = fsl_sha1sum_filename(zName, pTgt); }else if(FSL_UUIDv2_STRLEN==hashLen){ rc = fsl_sha3sum_filename(zName, pTgt); }else{ rc = fsl_cx_err_set(f, FSL_RC_CHECKSUM_MISMATCH, "Cannot determine which hash to use for file: %s", zName); errReported = 1; } if(rc && !errReported && FSL_RC_OOM != rc){ rc = fsl_cx_err_set(f, rc, "Error %s while reading SHA of file: %s", fsl_rc_cstr(rc), zName); } return rc; } /** UNTESTED single-file version of fsl_vfile_changes_scan(). vid is the version to scan changes against. If 0 or less, the current checkout is used. The vfile table must have been previously populated with vid's contents (which it will have been for the |
︙ | ︙ | |||
216 217 218 219 220 221 222 | default: assert(!rc); goto end; } { | < < | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | default: assert(!rc); goto end; } { fsl_id_t id = fsl_stmt_g_id(q, 0); fsl_id_t rid = fsl_stmt_g_id(q, 2); /* fsl_size_t nName = 0; */ char const * zName = fsl_stmt_g_text(q, 1, NULL/* &nName */); /* fsl_size_t const rootLen = fsl_strlen(f->ckout.dir); */ /* char const * relName = zName + rootLen; */ int const isDeleted = fsl_stmt_g_int32(q, 3); |
︙ | ︙ | |||
296 297 298 299 300 301 302 | if(origSize!=currentSize){ /* A file size change is definitive - the file has changed. No need to check the mtime or sha1sum */ changed = FSL_VFILE_CHANGE_MOD; }else if( !forceVFileUpdate && changed==FSL_VFILE_CHANGE_MOD && rid!=0 && !isDeleted ){ | | < | < < | | < | < | < < | < | < < | | < | < | < < | 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 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | if(origSize!=currentSize){ /* A file size change is definitive - the file has changed. No need to check the mtime or sha1sum */ changed = FSL_VFILE_CHANGE_MOD; }else if( !forceVFileUpdate && changed==FSL_VFILE_CHANGE_MOD && rid!=0 && !isDeleted ){ /* File is believed to have changed but it is the same size. Double check that it really has changed by looking at content. */ fsl_size_t nUuid = 0; char const * uuid; fsl_buffer * fileCksum = &f->fileContent; assert(!fileCksum->used && "Misuse of f->fileContent."); assert( origSize==currentSize ); uuid = fsl_stmt_g_text(q, 5, &nUuid); assert(uuid && fsl_is_uuid(uuid)==(int)nUuid); rc = fsl_vfile_recheck_file_hash(f, zName, (int)nUuid, fileCksum); if(rc) goto end; assert(fsl_is_uuid_len((int)fileCksum->used)); if( 0 == fsl_uuidcmp(fsl_buffer_cstr(fileCksum), uuid) ){ changed = 0; } fileCksum->used = 0; /* MARKER(("SHA1 compare says %d: %s\n", changed, zName)); */ }else if( !forceVFileUpdate && (changed==FSL_VFILE_CHANGE_NONE || changed==FSL_VFILE_CHANGE_MERGE_MOD || changed==FSL_VFILE_CHANGE_INTEGRATE_MOD) && (useMtime==0 || currentMtime!=oldMtime) ){ /* For files that were formerly believed to be unchanged or that were changed by merging, if their mtime changes, or unconditionally if --sha1sum is used, check to see if they have been edited by looking at their hash */ fsl_size_t nUuid = 0; char const * uuid; fsl_buffer * fileCksum = &f->fileContent; assert(!fileCksum->used && "Misuse of f->fileContent."); assert( origSize==currentSize ); uuid = fsl_stmt_g_text(q, 5, &nUuid); assert(uuid && fsl_is_uuid(uuid)==(int)nUuid); rc = fsl_vfile_recheck_file_hash(f, zName, (int)nUuid, fileCksum); if(rc) goto end; assert(fsl_is_uuid_len((int)fileCksum->used)); if( fsl_uuidcmp(fsl_buffer_cstr(fileCksum), uuid) ){ changed = FSL_VFILE_CHANGE_MOD; } fileCksum->used = 0; /* MARKER(("SHA1 compare says %d: %s\n", changed, zName)); */ } if( (cksigFlags & FSL_VFILE_CKSIG_SETMTIME) |
︙ | ︙ | |||
406 407 408 409 410 411 412 | fsl_db * db = fsl_needs_checkout(f); fsl_fstat fst = fsl_fstat_empty; fsl_deck deck = fsl_deck_empty; #ifndef _WIN32 fsl_deck * d = NULL; #endif fsl_size_t rootLen; | < < | 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | fsl_db * db = fsl_needs_checkout(f); fsl_fstat fst = fsl_fstat_empty; fsl_deck deck = fsl_deck_empty; #ifndef _WIN32 fsl_deck * d = NULL; #endif fsl_size_t rootLen; if(!db) return FSL_RC_NOT_A_CHECKOUT; assert(f->ckout.dir); if(vid<0) vid = f->ckout.rid; assert(vid>=0); rootLen = fsl_strlen(f->ckout.dir); |
︙ | ︙ | |||
539 540 541 542 543 544 545 | /* File is believed to have changed but it is the same size. Double check that it really has changed by looking at content. */ fsl_size_t nUuid = 0; char const * uuid; fsl_buffer * fileCksum = &f->fileContent; assert(!fileCksum->used && "Misuse of f->fileContent."); assert( origSize==currentSize ); | | < < | | < | < | < < < | < < | | < | < | < < | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | /* File is believed to have changed but it is the same size. Double check that it really has changed by looking at content. */ fsl_size_t nUuid = 0; char const * uuid; fsl_buffer * fileCksum = &f->fileContent; assert(!fileCksum->used && "Misuse of f->fileContent."); assert( origSize==currentSize ); uuid = fsl_stmt_g_text(&q, 5, &nUuid); assert(uuid && fsl_is_uuid_len((int)nUuid)); rc = fsl_vfile_recheck_file_hash(f, zName, (int)nUuid, fileCksum); if(rc) goto end; assert(fsl_is_uuid_len((int)fileCksum->used)); if( 0 == fsl_uuidcmp(fsl_buffer_cstr(fileCksum), uuid) ){ changed = 0; } fileCksum->used = 0; /* MARKER(("SHA1 compare says %d: %s\n", changed, zName)); */ }else if( !forceVFileUpdate && (changed==FSL_VFILE_CHANGE_NONE || changed==FSL_VFILE_CHANGE_MERGE_MOD || changed==FSL_VFILE_CHANGE_INTEGRATE_MOD) && (useMtime==0 || currentMtime!=oldMtime) ){ /* For files that were formerly believed to be unchanged or that were changed by merging, if their mtime changes, or unconditionally if --sha1sum is used, check to see if they have been edited by looking at their SHA1 sum */ fsl_size_t nUuid = 0; char const * uuid; fsl_buffer * fileCksum = &f->fileContent; assert(!fileCksum->used && "Misuse of f->fileContent."); assert( origSize==currentSize ); uuid = fsl_stmt_g_text(&q, 5, &nUuid); assert(uuid && fsl_is_uuid_len((int)nUuid)); rc = fsl_vfile_recheck_file_hash(f, zName, (int)nUuid, fileCksum); if(rc) goto end; assert(fsl_is_uuid_len((int)fileCksum->used)); if( fsl_uuidcmp(fsl_buffer_cstr(fileCksum), uuid) ){ changed = FSL_VFILE_CHANGE_MOD; } fileCksum->used = 0; /* MARKER(("SHA1 compare says %d: %s\n", changed, zName)); */ } if( (cksigFlags & FSL_VFILE_CKSIG_SETMTIME) |
︙ | ︙ |