forked from hummypkg/webif
379 lines
8.3 KiB
Plaintext
Executable File
379 lines
8.3 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 {
|
|
set ::auto::loglevel 2
|
|
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 < $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::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::autoflagscan {dir attr callback {recurse 1} {force 0} {seen {}}} \
|
|
{{indent 0} {forceflag ""}} {
|
|
variable dustbin
|
|
variable rootdev
|
|
|
|
incr indent 2
|
|
|
|
log "[string repeat " " $indent]\[$dir]" 2
|
|
|
|
if {$dir eq $dustbin} {
|
|
log "[string repeat " " $indent]Dustbin, skipping." 2
|
|
incr indent -2
|
|
return
|
|
}
|
|
|
|
file stat "$dir/" st
|
|
|
|
if {[specialdir $dir]} {
|
|
# Special folder
|
|
if {$st(dev) != $rootdev} {
|
|
log "[string repeat " " $indent\
|
|
]Special folder on different device, skipping." 2
|
|
incr indent -2
|
|
return
|
|
}
|
|
if {$force} {
|
|
set force 0
|
|
set forceflag ""
|
|
log "[string repeat " " $indent\
|
|
]Special folder, overriding recursion." 2
|
|
}
|
|
}
|
|
|
|
# Already seen
|
|
set key "$st(dev):$st(ino)"
|
|
if {$key in $seen} {
|
|
log "[string repeat " " $indent]Already seen, skipping." 2
|
|
incr indent -2
|
|
return
|
|
}
|
|
lappend seen $key
|
|
|
|
# Recursion
|
|
if {!$force && [file exists "$dir/.auto${attr}r"]} {
|
|
log "[string repeat " " $indent] (R)" 2
|
|
set force 1
|
|
set forceflag "$dir/.auto${attr}r"
|
|
}
|
|
|
|
oktorun
|
|
dsc
|
|
|
|
if {$force || [file exists "$dir/.auto$attr"]} {
|
|
if {[$callback $dir] eq "STOP"} {
|
|
log "[string repeat " " $indent\
|
|
]Callback returned STOP." 2
|
|
incr indent -2
|
|
return "STOP"
|
|
}
|
|
}
|
|
|
|
foreach entry [readdir -nocomplain $dir] {
|
|
if {$recurse && [file isdirectory "$dir/$entry"]} {
|
|
if {[autoflagscan "$dir/$entry" \
|
|
$attr $callback $recurse $force \
|
|
$seen] eq "STOP"} {
|
|
incr indent -2
|
|
return "STOP"
|
|
}
|
|
file stat "$dir/$entry" st
|
|
set key "$st(dev):$st(ino)"
|
|
lappend seen $key
|
|
}
|
|
}
|
|
|
|
incr indent -2
|
|
}
|
|
|
|
proc ::auto::flagscan {dir flag callback {seen {}}} {
|
|
variable dustbin
|
|
|
|
if {$dir eq $dustbin} return
|
|
|
|
if {[specialdir $dir]} return
|
|
|
|
file stat $dir st
|
|
set key "$st(dev):$st(ino)"
|
|
if {$key in $seen} {
|
|
log "Already seen $dir ($key)" 2
|
|
return
|
|
}
|
|
lappend seen $key
|
|
|
|
if {[file exists "$dir/.$flag"]} {
|
|
if {[$callback $dir] eq "STOP"} {
|
|
log "Callback returned STOP." 2
|
|
return "STOP"
|
|
}
|
|
}
|
|
|
|
foreach entry [readdir -nocomplain $dir] {
|
|
if {[file isdirectory "$dir/$entry"]} {
|
|
if {[flagscan "$dir/$entry" $flag $callback $seen]
|
|
eq "STOP"} {
|
|
return "STOP"
|
|
}
|
|
|
|
file stat "$dir/$entry" st
|
|
set key "$st(dev):$st(ino)"
|
|
lappend seen $key
|
|
}
|
|
}
|
|
}
|
|
|
|
######################################################################
|
|
# 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
|
|
}
|
|
|
|
# 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 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
|
|
}
|
|
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."
|
|
|