-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathspksrc.service.installer
408 lines (346 loc) · 13.2 KB
/
spksrc.service.installer
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
193
194
195
196
197
198
199
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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
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
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
396
397
398
399
400
401
402
403
404
405
406
407
408
#!/bin/sh
# DSM 5 -> 6 upgrade path:
# Cannot remove user as still in use or may be DSM service itself
# Require warning in ChangeLog and manual user/group cleanup
INST_LOG="/tmp/${SYNOPKG_PKGNAME}_install.log"
INST_ETC="/var/packages/${SYNOPKG_PKGNAME}/etc"
INST_VARIABLES="${INST_ETC}/installer-variables"
INST_VAR="${SYNOPKG_PKGDEST}/var"
SYNOPKG_PKGVAR="${SYNOPKG_PKGDEST}/var" # backwards compatibility
# Optional FWPORTS file
FWPORTS_FILE="/var/packages/${SYNOPKG_PKGNAME}/conf/${SYNOPKG_PKGNAME}.sc"
# Versions lower then DSM 6 don't support an upgrade folder
if [ $SYNOPKG_DSM_VERSION_MAJOR -lt 6 ]; then
TMP_DIR="/var/tmp/${SYNOPKG_PKGNAME}/var"
else
TMP_DIR="${SYNOPKG_TEMP_UPGRADE_FOLDER}/var"
fi
# Source package specific variable and functions
SVC_SETUP=`dirname $0`"/service-setup"
if [ -r "${SVC_SETUP}" ]; then
. "${SVC_SETUP}"
fi
# Reload wizard variables stored by postinst
if [ -r "${INST_VARIABLES}" ]; then
. "${INST_VARIABLES}"
fi
# Expect user to be set from package specific variables
if [ -n "${USER}" -a -z "${USER_DESC}" ]; then
USER_DESC="User running $SYNOPKG_PKGNAME"
fi
# Default description if group name provided by UI
if [ -n "${GROUP}" -a -z "${GROUP_DESC}" ]; then
GROUP_DESC="SynoCommunity Package Group"
fi
# Extract share volume and share name from download location if provided
if [ -n "${SHARE_PATH}" ]; then
SHARE_VOLUME=$(echo "${SHARE_PATH}" | awk -F/ '{print "/"$2}')
SHARE_NAME=$(echo "${SHARE_PATH}" | awk -F/ '{print $3}')
fi
# Tools shortcuts
MV="/bin/mv -f"
RM="/bin/rm -rf"
CP="/bin/cp -rfp"
MKDIR="/bin/mkdir -p"
LN="/bin/ln -nsf"
TEE="/usr/bin/tee -a"
### Functions library
log_step ()
{
date >> ${INST_LOG}
echo "===> Step $1. USER=$USER GROUP=$GROUP SHARE_PATH=${SHARE_PATH}" >> ${INST_LOG}
}
save_wizard_variables ()
{
if [ -e "${INST_VARIABLES}" ]; then
$RM "${INST_VARIABLES}"
fi
if [ -n "${GROUP}" ]; then
echo "GROUP=${GROUP}" >> ${INST_VARIABLES}
fi
if [ -n "${SHARE_PATH}" ]; then
echo "SHARE_PATH=${SHARE_PATH}" >> ${INST_VARIABLES}
fi
# Restriction permissions to protect sensitive options
if [ -e "${INST_VARIABLES}" ]; then
chmod go-rwx ${INST_VARIABLES}
chown ${EFF_USER} ${INST_VARIABLES}
fi
}
# Remove user from system and from groups it is member of
syno_remove_user ()
{
RM_USER=$1
if [ -n "${RM_USER}" ]; then
# Check if user exists
if synouser --get "${RM_USER}" &> /dev/null; then
echo "Removing user ${RM_USER}" >> ${INST_LOG}
synouser --del "${RM_USER}" >> ${INST_LOG} 2>&1
synouser --rebuild all
# Also rebuild groups so users are removed
synogroup --rebuild all
fi
fi
}
# Create syno group $GROUP with parameter user as member
syno_group_create ()
{
EFF_USER=$1
if [ -n "${EFF_USER}" ]; then
echo "Creating group ${GROUP}" >> ${INST_LOG}
# Create syno group
synogroup --add "${GROUP}" "${EFF_USER}" >> ${INST_LOG}
# Set description of the syno group
synogroup --descset "${GROUP}" "${GROUP_DESC}" >> ${INST_LOG}
fi
}
# Delete syno group if empty
syno_group_remove ()
{
RM_GROUP=$1
if [ -n "${RM_GROUP}" ]; then
# Check if syno group is empty
if ! synogroup --get "${RM_GROUP}" | grep -q "0:\["; then
echo "Removing group ${RM_GROUP}" >> ${INST_LOG}
# Remove syno group
synogroup --del "${RM_GROUP}" >> ${INST_LOG} 2>&1
synogroup --rebuild all
fi
fi
}
# Add user to existing group
syno_user_add_to_group ()
{
ADD_USER=$1
ADD_GROUP=$2
# Check user already in group
if ! synogroup --get "$ADD_GROUP" | grep "^[0-9]:\[${ADD_USER}\]" &> /dev/null; then
# Add user, not in group yet
echo "Adding '${ADD_USER}' to '${ADD_GROUP}'" >> ${INST_LOG}
MEMBERS="$(synogroup --get $ADD_GROUP | grep '^[0-9]' | sed 's/.*\[\([^]]*\)].*/\1/' | tr '\n' ' ')"
# The "synogroup --member" command clears all users before adding new ones
# so all the users must be listed on the command line
synogroup --member "$ADD_GROUP" $MEMBERS "${ADD_USER}" >> ${INST_LOG}
fi
}
# Sets recursive permissions for ${GROUP} on specified directory
# Usage: set_syno_permissions "${SHARE_FOLDER}" "${GROUP}"
set_syno_permissions ()
{
DIRNAME=`realpath "${1}"`
GROUP="${2}"
VOLUME=$(echo "${DIRNAME}" | awk -F/ '{print "/"$2}')
# Ensure directory resides in /volumeX before setting GROUP permissions
if [ "`echo ${VOLUME} | cut -c2-7`" = "volume" ]; then
# Set read/write permissions for GROUP for folder and subfolders
if [ ! "`synoacltool -get \"${DIRNAME}\"| grep \"group:${GROUP}:allow:rwxpdDaARWcC-:fd--\"`" ]; then
# First Unix permissions, but only if it's in Linux mode
if [ "`synoacltool -get \"${DIRNAME}\"| grep \"Linux mode\"`" ]; then
set_unix_permissions "${DIRNAME}"
# If it is linux mode (due to old package) we need to add "administrators"-group,
# otherwise the folder is not accessible from File Station anymore!
synoacltool -add "${DIRNAME}" "group:administrators:allow:rwxpdDaARWc--:fd--" >> ${INST_LOG} 2>&1
fi
# Then fix the Synology permissions
echo "Granting '${GROUP}' group permissions on ${DIRNAME}" >> ${INST_LOG}
synoacltool -add "${DIRNAME}" "group:${GROUP}:allow:rwxpdDaARWcC-:fd--" >> ${INST_LOG} 2>&1
find "${DIRNAME}" -type d -exec synoacltool -enforce-inherit "{}" \; >> ${INST_LOG} 2>&1
fi
# Walk up the tree and set traverse execute permissions for GROUP up to VOLUME
while [ "${DIRNAME}" != "${VOLUME}" ]; do
if [ ! "`synoacltool -get \"${DIRNAME}\"| grep \"group:${GROUP}:allow:r.x\"`" ]; then
# Here we also need to make sure the admin can access data via File Station
if [ "`synoacltool -get \"${DIRNAME}\"| grep \"Linux mode\"`" ]; then
synoacltool -add "${DIRNAME}" "group:administrators:allow:rwxpdDaARWc--:fd--" >> ${INST_LOG} 2>&1
fi
# Add the new group permissions
echo "Granting '${GROUP}' group basic permissions on ${DIRNAME}" >> ${INST_LOG}
synoacltool -add "${DIRNAME}" "group:${GROUP}:allow:r-x---a-R----:---n" >> ${INST_LOG} 2>&1
fi
DIRNAME="$(dirname "${DIRNAME}")"
done
else
echo "Skip granting '${GROUP}' group permissions on ${DIRNAME} as the directory does not reside in '/volumeX'. Set manually if needed." >> ${INST_LOG}
fi
}
# Set recursive permissions using chown
set_unix_permissions ()
{
DIRNAME=$1
if [ -n "${EFF_USER}" ]; then
echo "Granting '${EFF_USER}' unix ownership on ${DIRNAME}" >> ${INST_LOG}
if [ $SYNOPKG_DSM_VERSION_MAJOR -lt 6 ]; then
chown -R ${EFF_USER}:root "${DIRNAME}" >> $INST_LOG 2>&1
else
chown -R ${EFF_USER}:${USER} "${DIRNAME}" >> $INST_LOG 2>&1
fi
fi
}
# If package was moved to new group, we need to add the new package user
# also to the old group. Only if the legacy user was in the old group.
# Usage: syno_user_add_to_legacy_group "${NEW_USER}" "${LEGACY_USER}" "${LEGACY_GROUP}"
syno_user_add_to_legacy_group () {
NEW_USER=$1
LEGACY_USER=$2
LEGACY_GROUP=$3
# Check if user in old group
if synogroup --get "$LEGACY_GROUP" | grep "^[0-9]:\[${LEGACY_USER}\]" &> /dev/null; then
# Add new user and remove old one
echo "Adding '${NEW_USER}' to '${LEGACY_GROUP}' for backwards compatibility" >> ${INST_LOG}
MEMBERS="$(synogroup --get $LEGACY_GROUP | grep '^[0-9]' | sed 's/.*\[\([^]]*\)].*/\1/' | tr '\n' ' ')"
MEMBERS=${MEMBERS//$LEGACY_USER}
# The "synogroup --member" command clears all users before adding new ones
# so all the users must be listed on the command line
synogroup --member "$LEGACY_GROUP" $MEMBERS "${NEW_USER}" >> ${INST_LOG}
fi
}
### Generic package behaviors
preinst ()
{
log_step "preinst"
call_func "service_preinst"
# Check volume exists
if [ -n "${SHARE_PATH}" ]; then
if [ ! -d "${SHARE_VOLUME}" ]; then
echo "Volume ${SHARE_VOLUME} does not exist." | $TEE ${INST_LOG}
exit 1
fi
fi
exit 0
}
postinst ()
{
log_step "postinst"
save_wizard_variables
# Link for backward compatibility of binaries location
$LN "${SYNOPKG_PKGDEST}" "/usr/local/${SYNOPKG_PKGNAME}" >> ${INST_LOG}
# Add firewall config
if [ -r "${FWPORTS_FILE}" ]; then
echo "Installing service configuration ${FWPORTS_FILE}" >> ${INST_LOG}
servicetool --install-configure-file --package "${FWPORTS_FILE}" >> ${INST_LOG} 2>&1
fi
# Service user management
if [ -n "${EFF_USER}" ]; then
if [ $SYNOPKG_DSM_VERSION_MAJOR -lt 6 ]; then
# DSM 5 specific operations
# Create prefixed synouser
if ! cat /etc/passwd | grep "${EFF_USER}:x:" &> /dev/null; then
synouser --add "${EFF_USER}" "" "$USER_DESC" 0 "" 0 >> ${INST_LOG} 2>&1
# Set HOME for consistency with DSM 6, location available even if homes not enabled
BACKUP_PASSWD="/tmp/install_${SYNOPKG_PKGNAME}_passwd"
cp /etc/passwd ${BACKUP_PASSWD}
sed -i "s#/var/services/homes/${EFF_USER}#/var/packages/${SYNOPKG_PKGNAME}/target#" /etc/passwd
fi
fi
# Register service in "users" group to access any content
if [ "$ADD_USER_IN_USERS" = "yes" ]; then
syno_user_add_to_group "${EFF_USER}" "users"
fi
fi
# Only if a group is provided via UI or set by script
if [ -n "$GROUP" ]; then
# Check if group already exists
if ! synogroup --get "$GROUP" &> /dev/null; then
# Group does not exist yet: create with user as member
syno_group_create "${EFF_USER}"
fi
if synogroup --get "$GROUP" &> /dev/null; then
syno_user_add_to_group "${EFF_USER}" "${GROUP}"
fi
# Not sure but invoked with hope DSM is updated
synogroup --rebuild all
fi
# Share management
if [ -n "${SHARE_PATH}" ]; then
echo "Configuring ${SHARE_PATH}" >> ${INST_LOG}
# Create share if does not exist
# !"#$%&’()*+,/:;<=>?@[]nˆ`{} |
if ! synoshare --get "${SHARE_NAME}" &> /dev/null ; then
synoshare --add "${SHARE_NAME}" "${SHARE_DESC}" "${SHARE_PATH}" "" "rw" "" 1 0 >> ${INST_LOG}
fi
# Add user permission if no GROUP is set in UI
# GROUP permission will be added in set_syno_permissions
if [ ! -n "$GROUP" ] && [ -n "${EFF_USER}" ]; then
synoshare --setuser "${SHARE_NAME}" RW + "${EFF_USER}" >> ${INST_LOG} 2>&1
fi
synoshare --build
$MKDIR "${SHARE_PATH}"
# Permissions for folder, up to volume
if [ -n "$GROUP" ]; then
set_syno_permissions "${SHARE_PATH}" "${GROUP}"
fi
fi
$MKDIR "${INST_VAR}"
call_func "service_postinst"
call_func "service_create_links"
$CP "${INST_LOG}" "${INST_VAR}"
if [ -n "${LOG_FILE}" ]; then
echo "Installation log: ${INST_VAR}/${SYNOPKG_PKGNAME}_install.log" >> ${LOG_FILE}
fi
if [ $SYNOPKG_DSM_VERSION_MAJOR -lt 6 ]; then
# On DSM 5 set package files permissions for consistency with DSM 6
set_unix_permissions "${SYNOPKG_PKGDEST}"
else
# On DSM 6 only var is concerned
set_unix_permissions "${INST_VAR}"
fi
exit 0
}
preuninst ()
{
log_step "preuninst"
if [ "${SYNOPKG_PKG_STATUS}" == "UNINSTALL" ]; then
# Remove firewall config
if [ -r "${FWPORTS_FILE}" ]; then
echo "Removing service configuration ${SYNOPKG_PKGNAME}.sc" >> ${INST_LOG}
servicetool --remove-configure-file --package "${SYNOPKG_PKGNAME}.sc" >> ${INST_LOG} 2>&1
fi
fi
call_func "service_preuninst"
exit 0
}
postuninst ()
{
log_step "postuninst"
if [ "${SYNOPKG_PKG_STATUS}" == "UNINSTALL" ]; then
# Remove link
$RM "/usr/local/${SYNOPKG_PKGNAME}" >> ${INST_LOG}
# Remove syno group if empty
syno_group_remove "${GROUP}"
# Remove user
syno_remove_user "${EFF_USER}"
fi
call_func "service_postuninst"
call_func "service_remove_links"
if [ "${SYNOPKG_PKG_STATUS}" == "UNINSTALL" ]; then
$RM "${INST_VARIABLES}"
fi
exit 0
}
preupgrade ()
{
log_step "preupgrade"
call_func "service_preupgrade"
# Save some stuff
$RM "$TMP_DIR" >> ${INST_LOG}
$MKDIR "$TMP_DIR" >> ${INST_LOG}
call_func "service_save"
# Beware of /. outside the quotes
# Needed to copy all files including hidden ones
$CP "${INST_VAR}"/. "$TMP_DIR" >> ${INST_LOG}
exit 0
}
postupgrade ()
{
log_step "postupgrade"
call_func "service_restore"
# Restore some stuff, has to be cp otherwise fails on directories
$CP "${TMP_DIR}"/. "${INST_VAR}" >> ${INST_LOG}
# Correct permissions of var folder
set_unix_permissions "${INST_VAR}"
$RM "$TMP_DIR" >> ${INST_LOG}
call_func "service_postupgrade"
# Make sure we also have the logging for this step
$CP "${INST_LOG}" "${INST_VAR}"
exit 0
}