summaryrefslogtreecommitdiffstats
path: root/net/netatalk/files/afpd.init
blob: 33658945391405905358c034cefb573f9dbe57a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
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
134
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
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/bin/sh /etc/rc.common
# Copyright (C) 2010-2025 OpenWrt.org

START=85
STOP=10
USE_PROCD=1
PROG_netatalk='/usr/sbin/netatalk'

# 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

	procd_open_instance
	procd_set_param command $PROG_netatalk -d -F $config_file
	procd_set_param file $config_file
	procd_set_param respawn
	procd_close_instance
}