201 lines
7.6 KiB
Bash
201 lines
7.6 KiB
Bash
#!/bin/sh /etc/rc.common
|
|
# Copyright (C) 2010-2025 OpenWrt.org
|
|
|
|
START=85
|
|
STOP=10
|
|
USE_PROCD=1
|
|
PROG_afpd='/usr/sbin/afpd'
|
|
PROG_cnid='/usr/sbin/cnid_metad'
|
|
|
|
# Default config file location
|
|
config_file='/etc/afp.conf'
|
|
|
|
# Config file contents and status
|
|
afpd_config=''
|
|
config_overwrite=''
|
|
config_error=0
|
|
setup_error=0
|
|
# Log tag
|
|
log_tag='afpd-init'
|
|
|
|
# Configuration dictionary
|
|
valid_global='|'
|
|
valid_global=$valid_global'ad_domain|admin_auth_user|admin_group|force_user|force_group|k5_keytab|k5_service|k5_realm|'
|
|
valid_global=$valid_global'nt_domain|nt_separator|save_password|set_password|uam_list|uam_path|mac_charset|unix_charset|'
|
|
valid_global=$valid_global'vol_charset|passwd_file|passwd_minlen|afp_interfaces|afp_listen|afp_port|appletalk|'
|
|
valid_global=$valid_global'cnid_listen|cnid_server|ddp_address|ddp_zone|disconnect_time|dsireadbuf|hostname|'
|
|
valid_global=$valid_global'max_connections|sleep_time|chmod_request|dircachesize|extmap_file|'
|
|
valid_global=$valid_global'force_xattr_with_sticky_bit|guest_account|ignored_attributes|legacy_icon|login_message|'
|
|
valid_global=$valid_global'mimic_model|vol_dbpath|zeroconf_name|log_file|log_level|map_acls|ldap_auth_method|'
|
|
valid_global=$valid_global'ldap_auth_dn|ldap_auth_pw|ldap_uri|ldap_userbase|ldap_userscope|ldap_groupbase|'
|
|
valid_global=$valid_global'ldap_groupscope|ldap_uuid_attr|ldap_name_attr|ldap_group_attr|ldap_uuid_string|'
|
|
valid_global=$valid_global'ldap_uuid_encoding|ldap_user_filter|ldap_group_filter|vol_dbnest|fce_ignore_names|'
|
|
valid_homes='|basedir_regex|path|home_name|'
|
|
valid_volume='|'
|
|
valid_volume=$valid_volume'mac_charset|unix_charset|vol_charset|casefold|chmod_request|force_xattr_with_sticky_bit|'
|
|
valid_volume=$valid_volume'ignored_attributes|login_message|vol_dbpath|path|server_name|vol_size_limit|valid_users|'
|
|
valid_volume=$valid_volume'invalid_users|hosts_allow|hosts_deny|ea|password|file_perm|directory_perm|umask|preexec|'
|
|
valid_volume=$valid_volume'postexec|root_preexec|root_postexec|rolist|rwlist|veto_files|acls|case_sensitive|prodos|'
|
|
valid_volume=$valid_volume'read_only|time_machine|vol_dbnest|cnid_scheme|volume_name|'
|
|
valid_share='share_name'
|
|
|
|
NL=$'\n'
|
|
|
|
generate_config() {
|
|
# Save name of sections
|
|
config_name=''
|
|
global_name=''
|
|
homes_name=''
|
|
volume_names=''
|
|
# Volume name validation
|
|
share_names=''
|
|
fixed_names=''
|
|
|
|
# Call-back per section
|
|
config_cb() {
|
|
section_type="$1"
|
|
section_name="$2"
|
|
|
|
# Call-back per option
|
|
option_cb() {
|
|
local name="$1"
|
|
local value="$2"
|
|
# Validate options against dictionary of possible values
|
|
if [ "$section_type" = 'setup' -a "$CONFIG_SECTION" = "$config_name" ]; then
|
|
if [ "$name" = 'config_overwrite' ]; then
|
|
if [ "$value" = "0" -o "$value" = "1" ]; then
|
|
config_overwrite=$value
|
|
else
|
|
# Garbage on this option means we should not proceed no matter what
|
|
logger -p err -t $log_tag "Invalid SETUP config_overwrite option: $value"
|
|
setup_error=1
|
|
fi
|
|
elif [ "$name" = 'config_file' ]; then
|
|
config_file="$value"
|
|
else
|
|
config_error=1 && logger -p err -t $log_tag "Invalid SETUP configuration option: $name:$value"
|
|
fi
|
|
elif [ "$section_type" = 'global' -a "$CONFIG_SECTION" = "$global_name" ]; then
|
|
case "$valid_global" in
|
|
*'|'$name'|'*) afpd_config=$afpd_config"${name//_/ } = $value$NL" ;;
|
|
*) config_error=1 && logger -p err -t $log_tag "Invalid GLOBAL configuration option: $name:$value" ;;
|
|
esac
|
|
elif [ "$section_type" = 'homes' -a "$CONFIG_SECTION" = "$homes_name" ]; then
|
|
case "$valid_homes" in
|
|
*'|'$name'|'*) afpd_config=$afpd_config"${name//_/ } = $value$NL" ;;
|
|
*) config_error=1 && logger -p err -t $log_tag "Invalid HOMES configuration option: $name:$value" ;;
|
|
esac
|
|
elif [ "$section_type" = 'volume' ]; then
|
|
if [ "$name" = "$valid_share" ]; then
|
|
# Special case - share name... check for duplicates... track changes... fix heading.
|
|
case "||$share_names" in
|
|
*'||'$value'||'*) config_error=1 && logger -p err -t $log_tag "Duplicated share name $CONFIG_SECTION-$name:$value" ;;
|
|
*) ;;
|
|
esac
|
|
share_names=$share_names"$value||"
|
|
fixed_names=$fixed_names"$CONFIG_SECTION "
|
|
afpd_config="${afpd_config//\[\[$CONFIG_SECTION\]\]/[$value]}"
|
|
else
|
|
case "$valid_volume" in
|
|
*'|'$name'|'*) afpd_config=$afpd_config"${name//_/ } = $value$NL" ;;
|
|
*) config_error=1 && logger -p err -t $log_tag "Invalid VOLUME $CONFIG_SECTION configuration option: $name:$value" ;;
|
|
esac
|
|
fi
|
|
else
|
|
config_error=1 && logger -p err -t $log_tag "Invalid option. Section: $CONFIG_SECTION ($section_type), option: $name:$value"
|
|
fi
|
|
}
|
|
|
|
# Call-back per list - error, we don't use lists
|
|
list_cb() {
|
|
config_error=1 && logger -p err -t $log_tag "Invalid list in $CONFIG_SECTION: $1:$2"
|
|
}
|
|
|
|
# Identify sections and create section headers (placeholder for volumes)
|
|
if [ "$section_type" = 'setup' ]; then
|
|
# Find the name of the first (and only?) setup (control) section
|
|
if [ -z "$config_name" ]; then
|
|
config_name=$section_name
|
|
else
|
|
config_error=1 && logger -p err -t $log_tag 'Multiple SETUP sections defined'
|
|
fi
|
|
elif [ "$section_type" = 'global' ]; then
|
|
# Find the name of the first (and only?) global section
|
|
if [ -z "$global_name" ]; then
|
|
global_name=$section_name
|
|
[ -z "$afpd_config" ] || afpd_config=$afpd_config"$NL"
|
|
afpd_config=$afpd_config"[Global]$NL"
|
|
else
|
|
config_error=1 && logger -p err -t $log_tag 'Multiple GLOBAL sections defined'
|
|
fi
|
|
elif [ "$section_type" = 'homes' ]; then
|
|
# Find the name of the first (and only?) homes section
|
|
if [ -z "$homes_name" ]; then
|
|
homes_name=$section_name
|
|
[ -z "$afpd_config" ] || afpd_config=$afpd_config"$NL"
|
|
afpd_config=$afpd_config"[Homes]$NL"
|
|
else
|
|
config_error=1 && logger -p err -t $log_tag 'Multiple HOMES sections defined'
|
|
fi
|
|
elif [ "$section_type" = 'volume' ]; then
|
|
# Collect the names of the volume sections
|
|
volume_names=$volume_names"$section_name "
|
|
[ -z "$afpd_config" ] || afpd_config=$afpd_config"$NL"
|
|
afpd_config=$afpd_config"[[$section_name]]$NL"
|
|
elif [ "$section_type" != '' ]; then
|
|
# It's not the end of file
|
|
config_error=1 && logger -p err -t $log_tag "Invalid $section_type section defined"
|
|
fi
|
|
}
|
|
|
|
# Load config (trigger callbacks)
|
|
config_load afpd
|
|
|
|
# config_overwrite is messed up... don't know what to do
|
|
if [ "$setup_error" -eq 1 ]; then
|
|
exit 1
|
|
fi
|
|
# So, should we? Shouldn't? Nobody said but gave us share details.
|
|
[ -z "$config_overwrite" ] && [ -n "$volume_names" -o -n "$homes_name" ] && {
|
|
logger -p warn -t $log_tag "No valid config_overwrite at SETUP config. Ignoring defined VOLUMES and/or HOMES"
|
|
}
|
|
|
|
# Only update configuration file if UCI config asks for it
|
|
build_config=$(expr "${config_overwrite}" == "1")
|
|
if [ "$build_config" -eq 1 ]; then
|
|
# One last check for valid volume names
|
|
[ "$volume_names" = "$fixed_names" ] || {
|
|
config_error=1 && logger -p err -t $log_tag "Not all volumes have valid option $valid_share"
|
|
}
|
|
# Continue only if configuration was decent - any errors were logged already
|
|
if [ "$config_error" -eq 1 ]; then
|
|
exit 1
|
|
fi
|
|
# Create file
|
|
mkdir -p `dirname "$config_file"`
|
|
echo "$afpd_config" > "$config_file"
|
|
logger -p info -t $log_tag "Configuration written to $config_file"
|
|
else
|
|
logger -p info -t $log_tag 'Configuration not modified - setup:config_overwrite=0 or missing'
|
|
fi
|
|
}
|
|
|
|
start_service() {
|
|
mkdir -p /var/netatalk/CNID/
|
|
|
|
generate_config
|
|
|
|
# afpd
|
|
procd_open_instance
|
|
procd_set_param command $PROG_afpd -d -F $config_file
|
|
procd_set_param file $config_file
|
|
procd_set_param respawn
|
|
procd_close_instance
|
|
|
|
# cnid
|
|
procd_open_instance
|
|
procd_set_param command $PROG_cnid -d -F $config_file
|
|
procd_set_param respawn
|
|
procd_close_instance
|
|
}
|