File: clean-up-unmanaged-libraries

package info (click to toggle)
libgcrypt20 1.10.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bookworm-backports, bookworm-proposed-updates
  • size: 16,700 kB
  • sloc: ansic: 155,507; asm: 39,345; sh: 12,851; makefile: 798
file content (216 lines) | stat: -rwxr-xr-x 5,493 bytes parent folder | download | duplicates (6)
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
#!/bin/dash
# (This script requires either dash or bash due to its use of test -ef.)

# Copyright 2020 Collabora Ltd.
# SPDX-License-Identifier: MIT
# (see "Expat" paragraph in debian/copyright)

set -eu

# global
bug_ref=911225
force=
me="$0"
need_ldconfig=
really=yes
verbose=

debug () {
    [ -z "$verbose" ] || echo "DEBUG: $me: $*" >&2
}

warning () {
    echo "WARNING: $me: $*" >&2
}

usage () {
    local status="${1:-2}"

    if [ "$status" -gt 0 ]; then
        exec >&2
    fi

    cat <<EOF
Usage: $me [OPTIONS] MULTIARCH SONAME...

Clean up unmanaged copies of SONAME that might still exist
in /lib/MULTIARCH after upgrading to a version that is in
/usr/lib/MULTIARCH. On non-merged-/usr systems, because /lib/MULTIARCH
is higher-precedence than /usr/lib/MULTIARCH, that can result in the
old version continuing to be used, breaking versioned dependencies.

See #911225, #949395 and related bugs.

Options:
--bug-ref=BUG   Mention BUG in log messages
--dry-run       Don't remove the files, just report
--force         Run even if the system is merged-/usr
--verbose       Be more verbose
EOF
    exit "$status"
}

do_soname () {
    local multiarch="$1"
    local soname="$2"
    local impl
    local owner
    local removal="/lib/$multiarch/removed-by-upgrade-bug$bug_ref"
    local found_one=

    # We had better not remove the only copy of $soname. This script is
    # for the situation where it moved from /lib/MULTIARCH/SONAME to
    # /usr/lib/MULTIARCH/SONAME, so fail in all other cases.
    if ! [ -e "/usr/lib/$multiarch/$soname" ]; then
        warning "/usr/lib/$multiarch/$soname does not exist"
        return 1
    fi

    # Safety-catch against problems with dpkg-query: if no package is said
    # to own the new version of the library, fail early.
    if owner=$(dpkg-query -S "/usr/lib/$multiarch/$soname"); then
        owner="${owner%%:*}"
        debug "/usr/lib/$multiarch/$soname is owned by $owner"
    else
        warning "/usr/lib/$multiarch/$soname is not owned by a package?"
        return 1
    fi

    for impl in "/lib/$multiarch/$soname".*; do
        if ! [ -e "$impl" ]; then
            continue
        fi

        found_one=yes

        if owner=$(dpkg-query -S "$impl"); then
            owner="${owner%%:*}"
            warning "$impl is owned by $owner, not deleting"
            continue
        fi

        if [ "/usr$impl" -ef "$impl" ] && owner=$(dpkg-query -S "/usr$impl"); then
            owner="${owner%%:*}"
            warning "/usr$impl is owned by $owner, not deleting"
            continue
        fi

        warning "$impl is not owned by any package"
        warning "Related files:"
        ls -il \
            "/lib/$multiarch/$soname" \
            "/lib/$multiarch/$soname".* \
            "/usr/lib/$multiarch/$soname" \
            "/usr/lib/$multiarch/$soname".* \
            >&2 || :

        if [ -n "$really" ]; then
            warning "Moving $impl into $removal"
            install -d "$removal"
            rm -f "$removal/${impl##*/}"
            mv "$impl" "$removal/."
        else
            warning "Not moving $impl into $removal (--dry-run)"
        fi

        echo >&2
        need_ldconfig=yes
    done

    if [ -z "$found_one" ]; then
        debug "No stray files found at /lib/$multiarch/$soname.*"
    fi
}

main () {
    local getopt_temp
    local multiarch
    local soname

    getopt_temp="help"
    getopt_temp="$getopt_temp,bug-ref:"
    getopt_temp="$getopt_temp,dry-run"
    getopt_temp="$getopt_temp,force"
    getopt_temp="$getopt_temp,verbose"

    getopt_temp="$(getopt -o '' --long "$getopt_temp" -n "$me" -- "$@")"
    eval "set -- $getopt_temp"

    while [ "$#" -gt 0 ]
    do
        case "$1" in
            (--dry-run)
                really=
                verbose=yes
                shift
                ;;

            (--bug-ref)
                bug_ref="$2"
                shift 2
                ;;

            (--force)
                force=yes
                shift
                ;;

            (--help)
                usage 0
                ;;

            (--verbose)
                verbose=yes
                shift
                ;;

            (--)
                shift
                break
                ;;

            (-*)
                warning "Unknown option: $1"
                usage 2
                ;;

            (*)
                break
                ;;
        esac
    done

    if [ "$#" -lt 2 ]; then
        warning "A multiarch tuple and at least one SONAME are required"
        usage 2
    fi

    multiarch="$1"
    shift

    if [ -n "$force" ]; then
        debug "Using force"
    elif [ "/usr/lib/$multiarch" -ef "/lib/$multiarch" ]; then
        # On a merged-/usr system, a new library like libglib-2.0.so.0.5000.0
        # will take precedence over a stale library like
        # libglib-2.0.so.0.4200.0 in the same directory without us needing
        # to do anything, so the safe route is to avoid doing anything.
        debug "Merged-/usr system, no need to do anything without --force"
        return 0
    fi

    for soname in "$@"; do
        do_soname "$multiarch" "$soname"
    done

    if [ -n "$need_ldconfig" ] && [ -n "$really" ]; then
        warning "Changes were made, running ldconfig..."
        ldconfig || ldconfig --verbose
    elif [ -n "$need_ldconfig" ]; then
        debug "Would run ldconfig, but skipped due to --dry-run"
    fi
}

main "$@"

# vim:set sw=4 sts=4 et: