forked from hummypkg/webif
415 lines
9.2 KiB
Plaintext
Executable File
415 lines
9.2 KiB
Plaintext
Executable File
#!/mod/bin/jimsh
|
|
|
|
source /mod/webif/lib/setup
|
|
require system.class settings.class ts.class rsv.class browse.class \
|
|
queue.class \
|
|
lock plugin safe_delete pretty_size
|
|
|
|
source /mod/webif/lib/auto/util.jim
|
|
|
|
set ::auto::settings [settings]
|
|
set ::auto::loglevel [$::auto::settings autolog]
|
|
|
|
set ::auto::prelocked 0
|
|
set ::auto::earlyexit 0
|
|
set ::auto::force 0
|
|
|
|
while {[llength $argv]} {
|
|
switch -- [lindex $argv 0] {
|
|
-d {
|
|
incr ::auto::loglevel
|
|
set ::auto::logfd stdout
|
|
}
|
|
-f {
|
|
set ::auto::force 1
|
|
}
|
|
-prelocked {
|
|
set ::auto::prelocked 1
|
|
}
|
|
-logprefix {
|
|
set argv [lrange $argv 1 end]
|
|
if {[llength $argv]} {
|
|
set ::auto::logprefix [lindex $argv 0]
|
|
}
|
|
}
|
|
-test {
|
|
set ::auto::earlyexit 1
|
|
}
|
|
default {
|
|
# Pass to rest of script.
|
|
break
|
|
}
|
|
}
|
|
set argv [lrange $argv 1 end]
|
|
}
|
|
|
|
# Acquire lock
|
|
if {$::auto::logfd ne "unset"} {
|
|
puts $::auto::logfd "Acquiring lock..."
|
|
}
|
|
if {!$::auto::prelocked && ![acquire_lock webif_autoscan]} {
|
|
if {$::auto::loglevel > 1} {
|
|
system plog auto "Could not acquire lock."
|
|
}
|
|
puts "Could not acquire exclusive lock, terminating."
|
|
exit
|
|
}
|
|
|
|
::auto::loginit
|
|
|
|
######################################################################
|
|
# Determine if it's time to run
|
|
|
|
if {[system uptime] < 180} {
|
|
::auto::log "Aborting, system has just booted." 2
|
|
exit
|
|
}
|
|
|
|
::auto::dsc
|
|
::auto::oktorun
|
|
if {!$::auto::force} {
|
|
set autofreq [$::auto::settings autofreq]
|
|
if {$autofreq == 0} { set autofreq 10 }
|
|
|
|
set timesincelast $(([clock seconds] - [$::auto::settings autolast]) \
|
|
/ 60)
|
|
if {$timesincelast < 0} {
|
|
# time machine issue: correct it
|
|
$::auto::settings autolast 0
|
|
} elseif {$timesincelast < $autofreq} {
|
|
::auto::log "Aborting, not yet time to run." 2
|
|
::auto::log " elapsed (minutes): $timesincelast (<$autofreq)" 2
|
|
exit
|
|
}
|
|
}
|
|
|
|
if {$::auto::earlyexit} {
|
|
if {!$::auto::force} {
|
|
$::auto::settings autolast [clock seconds]
|
|
}
|
|
puts "Early exit."
|
|
exit
|
|
}
|
|
|
|
#########################################################################
|
|
# Initialisation
|
|
|
|
set scanstart [clock milliseconds]
|
|
::auto::log "Auto processing starting" 2
|
|
|
|
::auto::tmpdir "webif_auto"
|
|
|
|
if {[system pkginst undelete]} {
|
|
set ::auto::dustbin "[system dustbin]"
|
|
} else {
|
|
set ::auto::dustbin ""
|
|
}
|
|
|
|
set ::auto::root [system mediaroot]
|
|
file stat "$::auto::root/" rootstat
|
|
set ::auto::rootdev $rootstat(dev)
|
|
|
|
#########################################################################
|
|
# Utility functions
|
|
|
|
set ::auto::flagdb {}
|
|
set ::auto::activeflags {}
|
|
set ::auto::extraflags {}
|
|
|
|
proc ::auto::buildflagdb {dir {active {}}} {{seen {}} {indent 0}} {
|
|
variable flagdb
|
|
variable activeflags
|
|
variable extraflags
|
|
variable dustbin
|
|
variable rootdev
|
|
|
|
incr indent 2
|
|
set pre [string repeat " " $indent]
|
|
|
|
log "${pre}\[$dir]" 3
|
|
|
|
if {$dir eq $dustbin} {
|
|
log "${pre}Dustbin, skipping." 3
|
|
incr indent -2
|
|
return
|
|
}
|
|
|
|
if {[catch {file stat "$dir/" st} msg]} {
|
|
log "${pre}Can't stat $dir - $msg, skipping.." 2
|
|
incr indent -2
|
|
return
|
|
}
|
|
|
|
if {[specialdir $dir]} {
|
|
# Special folder
|
|
if {$st(dev) != $rootdev} {
|
|
log "${pre}Special folder on different device, skipping." 3
|
|
incr indent -2
|
|
return
|
|
}
|
|
if {[llength $active]} {
|
|
set active {}
|
|
log "${pre}Special folder, overriding recursion." 3
|
|
}
|
|
}
|
|
|
|
# Already seen
|
|
set key "$st(dev):$st(ino)"
|
|
if {$key in $seen} {
|
|
log "${pre}Already seen, skipping." 3
|
|
incr indent -2
|
|
return
|
|
}
|
|
lappend seen $key
|
|
|
|
set flags [lmap i \
|
|
[glob -nocomplain -directory $dir -tails ".auto*"] \
|
|
{ string range $i 5 end }]
|
|
|
|
foreach x $extraflags {
|
|
foreach f [lmap i \
|
|
[glob -nocomplain -directory $dir -tails ".$x"] \
|
|
{ string range $i 1 end }] {
|
|
ladd flags $f
|
|
}
|
|
}
|
|
|
|
foreach f $flags {
|
|
# If recursive flag found, add to active set.
|
|
if {[string index $f end] eq "R"} {
|
|
ladd active [string range $f 0 end-1]
|
|
}
|
|
}
|
|
|
|
# Add any active flags to the set.
|
|
foreach f $active {
|
|
ladd flags $f
|
|
}
|
|
|
|
if {[llength $flags]} {
|
|
lappend flagdb $dir $flags
|
|
log "${pre} $flags" 3
|
|
foreach f $flags { ladd activeflags $f }
|
|
}
|
|
|
|
foreach entry [readdir -nocomplain $dir] {
|
|
if {[file isdirectory "$dir/$entry"]} {
|
|
buildflagdb "$dir/$entry" $active
|
|
}
|
|
}
|
|
|
|
set active {}
|
|
|
|
incr indent -2
|
|
}
|
|
|
|
set ::auto::recalcdirs {}
|
|
|
|
proc ::auto::recalcdir {dir} {
|
|
variable recalcdirs
|
|
ladd recalcdirs $dir
|
|
}
|
|
|
|
proc ::auto::direntries {dir callback} {
|
|
foreach entry [readdir -nocomplain $dir] {
|
|
if {![string match {*.ts} $entry]} continue
|
|
if {[catch {set ts [ts fetch "$dir/$entry"]}]} continue
|
|
if {$ts == 0} continue
|
|
if {[$callback $ts] eq "STOP"} break
|
|
}
|
|
}
|
|
|
|
proc ::auto::flagscan {root flag callback {recurse 1}} {
|
|
variable flagdb
|
|
variable activeflags
|
|
|
|
if {$flag ni $activeflags} {
|
|
log "No $flag flags in filesystem, suppressing scan."
|
|
return
|
|
}
|
|
|
|
if {!$recurse} {
|
|
# Just this exact directory
|
|
if {[dict exists $flagdb $root] && $flag in $flagdb($root)} {
|
|
log "[string toupper $flag]: \[$root]" 2
|
|
$callback $root
|
|
}
|
|
return
|
|
}
|
|
|
|
set rootl [string length $root]
|
|
|
|
foreach {dir flags} $flagdb {
|
|
if {![string equal -length $rootl $dir $root]} continue
|
|
if {$flag in $flags} {
|
|
oktorun
|
|
dsc
|
|
log "[string toupper $flag]: \[$dir]" 2
|
|
if {[$callback $dir] eq "STOP"} break
|
|
}
|
|
}
|
|
}
|
|
|
|
alias ::auto::autoflagscan ::auto::flagscan
|
|
|
|
######################################################################
|
|
# Plugin registration
|
|
|
|
set ::auto::plugins {}
|
|
|
|
proc ::auto::register {plugin {priority 500} {fn ""}} {
|
|
variable plugins
|
|
|
|
if {$fn eq ""} { set fn "::${plugin}::run" }
|
|
lappend plugins [list $plugin $fn $priority]
|
|
log "Registered $plugin with priority $priority ($fn)" 2
|
|
}
|
|
|
|
proc ::auto::register_flag {plugin flag} {
|
|
variable extraflags
|
|
ladd extraflags $flag
|
|
log "Registered flag '$flag' for $plugin" 2
|
|
}
|
|
|
|
# Backwards compatibility with legacy plugins
|
|
set ::auto::legacy {}
|
|
proc register {type fn {priority 50}} {
|
|
set module [lindex [split $fn :] 2]
|
|
|
|
switch -- $type {
|
|
predecryptscan { incr priority 600 }
|
|
postdecryptscan { incr priority 500 }
|
|
prededupscan { incr priority 800 }
|
|
postdedupscan { incr priority 700 }
|
|
preshrinkscan { incr priority 400 }
|
|
postshrinkscan { incr priority 300 }
|
|
prempgscan { incr priority 300 }
|
|
postmpgscan { incr priority 200 }
|
|
premp3scan { incr priority 300 }
|
|
postmp3scan { incr priority 200 }
|
|
preexpirescan { incr priority 900 }
|
|
postexpirescan { incr priority 800 }
|
|
postdecryptsingledir {
|
|
::auto::log \
|
|
"Mapping ::${module}::rundir on to $fn" 1
|
|
alias ::${module}::rundir $fn
|
|
return
|
|
}
|
|
default {
|
|
::auto::log \
|
|
"Legacy registration ignored for $type $fn" 1
|
|
return
|
|
}
|
|
}
|
|
::auto::register $module $priority $fn
|
|
lappend ::auto::legacy $module
|
|
}
|
|
|
|
######################################################################
|
|
# Load plugins
|
|
|
|
# Bundled
|
|
eval_plugins auto 1 "" /mod/webif/lib/auto/plugin
|
|
|
|
# Third party
|
|
|
|
# temporary for legacy plugins
|
|
set settings $::auto::settings
|
|
set root $::auto::root
|
|
eval_plugins auto 1
|
|
unset settings root
|
|
|
|
######################################################################
|
|
# Set expected variables for legacy plugins
|
|
|
|
if {[llength $::auto::legacy]} {
|
|
::auto::log "Legacy plugins in use - $::auto::legacy" 1
|
|
|
|
set settings $::auto::settings
|
|
set root $::auto::root
|
|
alias log ::auto::log
|
|
alias scan_run ::auto::flagscan
|
|
alias scanup ::auto::autoflagscanup
|
|
}
|
|
|
|
######################################################################
|
|
# Run media flag database
|
|
|
|
::auto::log "Scanning media for flags..."
|
|
set st [clock milliseconds]
|
|
::auto::buildflagdb $::auto::root
|
|
::auto::log "Scan completed ([::auto::elapsed $st] seconds)"
|
|
::auto::log "Active flags: $::auto::activeflags"
|
|
if {$::auto::loglevel > 1} {
|
|
foreach {dir flags} $::auto::flagdb {
|
|
::auto::log "[format %-80s $dir] - $flags" 2
|
|
}
|
|
}
|
|
|
|
######################################################################
|
|
# Run plugins
|
|
|
|
set ::auto::orderedplugins [\
|
|
lsort -index end -decreasing -integer $::auto::plugins]
|
|
|
|
set __dummy ""
|
|
proc ::auto::runplugin {fn {_plugin ""} args} {
|
|
variable orderedplugins
|
|
variable legacy
|
|
|
|
foreach p $orderedplugins {
|
|
lassign $p plugin xfn priority
|
|
|
|
if {$_plugin ne "" && $plugin ne $_plugin} continue
|
|
|
|
if {$fn eq "run"} {
|
|
set rfn $xfn
|
|
} else {
|
|
set rfn "::${plugin}::$fn"
|
|
}
|
|
|
|
if {[exists -proc $rfn] || [exists -alias $rfn]} {
|
|
set st [clock milliseconds]
|
|
log [string repeat * 56] 2
|
|
log "*********> $rfn (Priority $priority)" 2
|
|
if {$plugin in $legacy && $fn ne "rundir"} {
|
|
set call [list $rfn __dummy]
|
|
} else {
|
|
set call [list $rfn $args]
|
|
}
|
|
if {[catch {uplevel 1 {*}$call} msg]} {
|
|
log "$rfn: $msg" 0
|
|
lassign [info stacktrace] p f l
|
|
log " $f:$l @ $p" 0
|
|
}
|
|
log "<********* $rfn ([elapsed $st] seconds)" 2
|
|
}
|
|
}
|
|
}
|
|
|
|
set ::auto::passes {init run cleanup}
|
|
if {[lindex $argv 0] eq "-singledir"} {
|
|
foreach dir [lrange $argv 1 end] {
|
|
::auto::runplugin rundir "" $dir
|
|
}
|
|
} elseif {[llength $argv] > 0} {
|
|
foreach pass $::auto::passes {
|
|
foreach arg $argv { ::auto::runplugin $pass $arg }
|
|
}
|
|
} else {
|
|
foreach pass $::auto::passes {
|
|
::auto::runplugin $pass
|
|
}
|
|
$::auto::settings autolast [clock seconds]
|
|
}
|
|
|
|
if {!$::auto::prelocked} { release_lock webif_autoscan }
|
|
|
|
foreach dir $::auto::recalcdirs {
|
|
::auto::log "Running unwatched recalculation for $dir" 2
|
|
ts resetnew $dir
|
|
}
|
|
|
|
::auto::log "Auto processing completed in [::auto::elapsed $scanstart] seconds."
|
|
|