summaryrefslogtreecommitdiffstats
path: root/files/scripts/update-fullfiletimelist
blob: 4dc23aecbcd6bda0005297fc43716c3346890437 (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
#!/bin/bash

# Note: this is only an example of how you'd call create-filelist.  Edit to fit
# your requirements.  Note that you must supply a valid path for the lockfile,
# and it must be outside of your repository unless you want that lockfile to
# show up in your file lists.

# Takes a list of module names.  Generates file lists for all of them and them
# moves them into place at once.  If you are creating hardlinks between rsync
# modules, it is required that you update the file lists of both mirrors at the
# same time.  Otherwise the clients may make separate copies of the files.

# The directory where all of the modules live
# Or pass it with -t
TOPD=/srv/mirror/pub

# The modules to process.  Or pass them on the command line.
MODS=()

# Path to the create-filelist program.
# Or specify it with -p.
CREATE=/usr/local/bin/create-filelist

# These strings will be eval'ed later with $mod replaced by its value in
# context.
FILELIST=fullfilelist
TIMELIST='fullfiletimelist-$mod'
IMAGELIST='imagelist-$mod'

usage () {
    echo
    echo "Usage: $0 [-l lockfile] [-p creator path] [-t top directory] module [module ...]"
    echo
    echo "    -l: Path to the lock file"
    echo "    -p: Path to the create-filelist program"
    echo "    -t: Path to directory containing modules"
    echo
    echo "At least one module to process must be provided."
    echo "All paths must be absolute."
}

while [[ $# > 0 ]]; do
    opt=$1
    case $opt in
        -l)
            LOCKFILE=$(realpath $2)
            shift
            ;;
        -p)
            CREATE=$(realpath $2)
            shift
            ;;
        -t)
            TOPD=$(realpath $2)
            shift
            ;;
        -*)
            (>&2 echo "Unknown option $opt."; usage)
            exit 1
            ;;
        *)  # Remaining args are modules
            MODS+=($opt)
            ;;
    esac
    shift
done

if [[ -z $LOCKFILE ]]; then
    (>&2 echo "Must specify LOCKFILE, either by editing the source or via the -l option."; usage)
    exit 2
fi
if [[ ! -d $(dirname $LOCKFILE) ]]; then
    (>&2 echo "Given directory $(dirname $LOCKFILE) does not exist."; usage)
    exit 2
fi
if [[ ! -f $CREATE ]]; then
    (>&2 echo "Specified executable $CREATE does not exist."; usage)
    exit 2
fi

if [[ ! -d $TOPD ]]; then
    (>&2 echo "Provided directory $TOPD does not exist."; usage)
    exit 2
fi

if [[ ${#MODS[@]} -eq 0 ]]; then
    (>&2 echo "No modules specified"; usage)
    exit 2
fi

tmpd=$(mktemp -d -t create-filelist.XXXXXXXXXX)
if [[ $? -ne 0 ]]; then
    (>&2 echo "Creating temporary directory failed?")
    exit 1
fi
trap "rm -rf $tmpd" EXIT
cd $tmpd

(
    # We want to wait forever until we can do what we're asked
    flock -x 9

    # If you don't want to wait forever, try one of the following:
    # flock -n 9 || exit 1      - Gives up immediately
    # flock -w 120 9 || exit 1  - Waits 120 seconds and then gives up
    # Don't change the '9', unless you change the last line of this script.

    for mod in ${MODS[@]}; do
        currentfl=$TOPD/$mod/${FILELIST/'$mod'/$mod}
        currenttl=$TOPD/$mod/${TIMELIST/'$mod'/$mod}
        currentil=$TOPD/$mod/${IMAGELIST/'$mod'/$mod}
        flname=$(basename $currentfl)
        tlname=$(basename $currenttl)
        ilname=$(basename $currentil)

        $CREATE -c -s -d $TOPD/$mod -f $flname -t $tlname -i $ilname

        # If a file list exists and doesn't differ from what we just generated,
        # delete the latter.
        if [[ -f $currentfl ]] && diff -q $currentfl $flname > /dev/null; then
            rm -f $flname
        fi
        if [[ -f $currenttl ]] && diff -q $currenttl $tlname > /dev/null; then
            rm -f $tlname
        fi
        if [[ -f $currentil ]] && diff -q $currentil $ilname > /dev/null; then
            rm -f $ilname
        fi
    done

    # Now we have the new file lists but in a temporary directory which
    # probably isn't on the same filesystem.  Copy them to temporary files in
    # the right place.
    for mod in ${MODS[@]}; do
        currentfl=$TOPD/$mod/${FILELIST/'$mod'/$mod}
        currenttl=$TOPD/$mod/${TIMELIST/'$mod'/$mod}
        currentil=$TOPD/$mod/${IMAGELIST/'$mod'/$mod}
        flname=$(basename $currentfl)
        fldir=$(dirname $currentfl)
        tlname=$(basename $currenttl)
        tldir=$(dirname $currenttl)
        ilname=$(basename $currentil)
        ildir=$(dirname $currentil)

        if [[ -f $flname ]]; then
            tmpf=$(mktemp -p $fldir $flname.XXXXXXXXXX)
            cp -p $flname $tmpf
            chmod 644 $tmpf
            mv $tmpf $currentfl
        fi
        if [[ -f $tlname ]]; then
            tmpf=$(mktemp -p $tldir $tlname.XXXXXXXXXX)
            cp -p $tlname $tmpf
            chmod 644 $tmpf
            mv $tmpf $currenttl
        fi
        if [[ -f $ilname ]]; then
            tmpf=$(mktemp -p $ildir $ilname.XXXXXXXXXX)
            cp -p $ilname $tmpf
            chmod 644 $tmpf
            mv $tmpf $currentil
        fi
    done

) 9>$LOCKFILE