~ubuntu-branches/debian/sid/netatalk/sid

« back to all changes in this revision

Viewing changes to bin/ad/ad_rm.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2011-06-05 21:04:21 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20110605210421-19gag2srevj0ocxh
Tags: 2.2~beta4-1
* New upstream release.
  + Fixes "Internal Error" after ad_open on sparc.
    Closes: bug#606005. Thanks to Alfredo Sola.
* Adjust references to unofficial packages in README.Debian.
* Use dversionmangle (not uversionmangle) in watch file. Fix add
  leading dash (-) to upstream version in mangling.
* Update patches:
  + Drop patches 107 and 294 (Zeroconf support): Implemented
    (differently) upstream now.
  + Drop patches 109 and 112 (avoid broken XFS linkage) obsolete.
  + Drop patch 200 (hostname resolving): adopted upstream.
  + Refresh patch 205.
* Rewrite copyright file using draft 174 of DEP-5 format.
* Build-depend on and recommend unversioned (i.e. default) BerkeleyDB
  packages.
  Closes: bug#621413. Thanks to Ondřej Surý.
  Simplify suggestions on older versioned BerkeleyDB packages.
* Stop installing some documentation dropped upstream, and let CDBS
  automagically handle some of the remains.
* Update control file:
  + Bump policy compliance to standards-version 3.9.2.
  + Shorten Vcs-* URLs.
* Add patches 115 and (for automade file) 214 to avoid installing
  unneeded /default dir.
  Closes: bug#628119. Thanks to Russell Muetzelfeldt and Luk Claes.
* Don't ship .la files. Closes: bug#621849. Thanks to Andreas Metzler
  and Luk Claes.
* Stop renaming afile and achfile, dropped upstream.
* Explicitly enable DDP (AppleTalk), now disabled by default.
* Enable Zeroconf, should be stable now.
* Simplify package relations:
  + Drop (build-)dependency fallback unneeded even for oldstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2010, Frank Lahm <franklahm@googlemail.com>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 */
 
14
 
 
15
#ifdef HAVE_CONFIG_H
 
16
#include "config.h"
 
17
#endif /* HAVE_CONFIG_H */
 
18
 
 
19
#include <sys/types.h>
 
20
#include <sys/stat.h>
 
21
#include <errno.h>
 
22
#include <limits.h>
 
23
#include <signal.h>
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
#include <unistd.h>
 
28
 
 
29
#include <atalk/ftw.h>
 
30
#include <atalk/adouble.h>
 
31
#include <atalk/vfs.h>
 
32
#include <atalk/util.h>
 
33
#include <atalk/unix.h>
 
34
#include <atalk/volume.h>
 
35
#include <atalk/volinfo.h>
 
36
#include <atalk/bstrlib.h>
 
37
#include <atalk/bstradd.h>
 
38
#include <atalk/queue.h>
 
39
 
 
40
#include "ad.h"
 
41
 
 
42
#define STRIP_TRAILING_SLASH(p) {                                   \
 
43
        while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/')  \
 
44
            *--(p).p_end = 0;                                       \
 
45
    }
 
46
 
 
47
static afpvol_t volume;
 
48
 
 
49
static cnid_t did, pdid;
 
50
static int Rflag;
 
51
static volatile sig_atomic_t alarmed;
 
52
static int badrm, rval;
 
53
 
 
54
static char           *netatalk_dirs[] = {
 
55
    ".AppleDB",
 
56
    ".AppleDesktop",
 
57
    NULL
 
58
};
 
59
 
 
60
/* Forward declarations */
 
61
static int rm(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf);
 
62
 
 
63
/*
 
64
  Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
 
65
  Returns pointer to name or NULL.
 
66
*/
 
67
static const char *check_netatalk_dirs(const char *name)
 
68
{
 
69
    int c;
 
70
 
 
71
    for (c=0; netatalk_dirs[c]; c++) {
 
72
        if ((strcmp(name, netatalk_dirs[c])) == 0)
 
73
            return netatalk_dirs[c];
 
74
    }
 
75
    return NULL;
 
76
}
 
77
 
 
78
static void upfunc(void)
 
79
{
 
80
    did = pdid;
 
81
}
 
82
 
 
83
/*
 
84
  SIGNAL handling:
 
85
  catch SIGINT and SIGTERM which cause clean exit. Ignore anything else.
 
86
*/
 
87
 
 
88
static void sig_handler(int signo)
 
89
{
 
90
    alarmed = 1;
 
91
    return;
 
92
}
 
93
 
 
94
static void set_signal(void)
 
95
{
 
96
    struct sigaction sv;
 
97
 
 
98
    sv.sa_handler = sig_handler;
 
99
    sv.sa_flags = SA_RESTART;
 
100
    sigemptyset(&sv.sa_mask);
 
101
    if (sigaction(SIGTERM, &sv, NULL) < 0)
 
102
        ERROR("error in sigaction(SIGTERM): %s", strerror(errno));
 
103
 
 
104
    if (sigaction(SIGINT, &sv, NULL) < 0)
 
105
        ERROR("error in sigaction(SIGINT): %s", strerror(errno));
 
106
 
 
107
    memset(&sv, 0, sizeof(struct sigaction));
 
108
    sv.sa_handler = SIG_IGN;
 
109
    sigemptyset(&sv.sa_mask);
 
110
 
 
111
    if (sigaction(SIGABRT, &sv, NULL) < 0)
 
112
        ERROR("error in sigaction(SIGABRT): %s", strerror(errno));
 
113
 
 
114
    if (sigaction(SIGHUP, &sv, NULL) < 0)
 
115
        ERROR("error in sigaction(SIGHUP): %s", strerror(errno));
 
116
 
 
117
    if (sigaction(SIGQUIT, &sv, NULL) < 0)
 
118
        ERROR("error in sigaction(SIGQUIT): %s", strerror(errno));
 
119
}
 
120
 
 
121
static void usage_rm(void)
 
122
{
 
123
    printf(
 
124
        "Usage: ad rm [-vR] <file|dir> [<file|dir> ...]\n\n"
 
125
        "The rm utility attempts to remove the non-directory type files specified\n"
 
126
        "on the command line.\n"
 
127
        "If the files and directories reside on an AFP volume, the corresponding\n"
 
128
        "CNIDs are deleted from the volumes database.\n\n"
 
129
        "The options are as follows:\n\n"
 
130
        "   -R   Attempt to remove the file hierarchy rooted in each file argument.\n"
 
131
        "   -v   Be verbose when deleting files, showing them as they are removed.\n"
 
132
        );
 
133
    exit(EXIT_FAILURE);
 
134
}
 
135
 
 
136
int ad_rm(int argc, char *argv[])
 
137
{
 
138
    int ch;
 
139
 
 
140
    pdid = htonl(1);
 
141
    did = htonl(2);
 
142
 
 
143
    while ((ch = getopt(argc, argv, "vR")) != -1)
 
144
        switch (ch) {
 
145
        case 'R':
 
146
            Rflag = 1;
 
147
            break;
 
148
        case 'v':
 
149
            vflag = 1;
 
150
            break;
 
151
        default:
 
152
            usage_rm();
 
153
            break;
 
154
        }
 
155
    argc -= optind;
 
156
    argv += optind;
 
157
 
 
158
    if (argc < 1)
 
159
        usage_rm();
 
160
 
 
161
    set_signal();
 
162
    cnid_init();
 
163
 
 
164
    /* Set end of argument list */
 
165
    argv[argc] = NULL;
 
166
 
 
167
    for (int i = 0; argv[i] != NULL; i++) {
 
168
        /* Load .volinfo file for source */
 
169
        openvol(argv[i], &volume);
 
170
 
 
171
        if (nftw(argv[i], rm, upfunc, 20, FTW_DEPTH | FTW_PHYS) == -1) {
 
172
            if (alarmed) {
 
173
                SLOG("...break");
 
174
            } else {
 
175
                SLOG("Error: %s", argv[i]);
 
176
            }
 
177
            closevol(&volume);
 
178
        }
 
179
    }
 
180
    return rval;
 
181
}
 
182
 
 
183
static int rm(const char *path,
 
184
              const struct stat *statp,
 
185
              int tflag,
 
186
              struct FTW *ftw)
 
187
{
 
188
    cnid_t cnid;
 
189
 
 
190
    if (alarmed)
 
191
        return -1;
 
192
 
 
193
    const char *dir = strrchr(path, '/');
 
194
    if (dir == NULL)
 
195
        dir = path;
 
196
    else
 
197
        dir++;
 
198
    if (check_netatalk_dirs(dir) != NULL)
 
199
        return FTW_SKIP_SUBTREE;
 
200
 
 
201
    switch (statp->st_mode & S_IFMT) {
 
202
 
 
203
    case S_IFLNK:
 
204
        if (volume.volinfo.v_path) {
 
205
            if ((volume.volinfo.v_adouble == AD_VERSION2)
 
206
                && (strstr(path, ".AppleDouble") != NULL)) {
 
207
                /* symlink inside adouble dir */
 
208
                if (unlink(path) != 0)
 
209
                    badrm = rval = 1;
 
210
                break;
 
211
            }
 
212
 
 
213
            /* Get CNID of Parent and add new childir to CNID database */
 
214
            pdid = did;
 
215
            if ((cnid = cnid_for_path(&volume, path, &did)) == CNID_INVALID) {
 
216
                SLOG("Error resolving CNID for %s", path);
 
217
                return -1;
 
218
            }
 
219
            if (cnid_delete(volume.volume.v_cdb, cnid) != 0) {
 
220
                SLOG("Error removing CNID %u for %s", ntohl(cnid), path);
 
221
                return -1;
 
222
            }
 
223
        }
 
224
 
 
225
        if (unlink(path) != 0) {
 
226
            badrm = rval = 1;
 
227
            break;
 
228
        }
 
229
 
 
230
        break;
 
231
 
 
232
    case S_IFDIR:
 
233
        if (!Rflag) {
 
234
            SLOG("%s is a directory", path);
 
235
            return FTW_SKIP_SUBTREE;
 
236
        }
 
237
 
 
238
        if (volume.volinfo.v_path) {
 
239
            if ((volume.volinfo.v_adouble == AD_VERSION2)
 
240
                && (strstr(path, ".AppleDouble") != NULL)) {
 
241
                /* should be adouble dir itself */
 
242
                if (rmdir(path) != 0) {
 
243
                    SLOG("Error removing dir \"%s\": %s", path, strerror(errno));
 
244
                    badrm = rval = 1;
 
245
                    return -1;
 
246
                }
 
247
                break;
 
248
            }
 
249
 
 
250
            /* Get CNID of Parent and add new childir to CNID database */
 
251
            if ((did = cnid_for_path(&volume, path, &pdid)) == CNID_INVALID) {
 
252
                SLOG("Error resolving CNID for %s", path);
 
253
                return -1;
 
254
            }
 
255
            if (cnid_delete(volume.volume.v_cdb, did) != 0) {
 
256
                SLOG("Error removing CNID %u for %s", ntohl(did), path);
 
257
                return -1;
 
258
            }
 
259
        }
 
260
 
 
261
        if (rmdir(path) != 0) {
 
262
            SLOG("Error removing dir \"%s\": %s", path, strerror(errno));
 
263
            badrm = rval = 1;
 
264
            return -1;
 
265
        }
 
266
 
 
267
        break;
 
268
 
 
269
    case S_IFBLK:
 
270
    case S_IFCHR:
 
271
        SLOG("%s is a device file.", path);
 
272
        badrm = rval = 1;
 
273
        break;
 
274
 
 
275
    case S_IFSOCK:
 
276
        SLOG("%s is a socket.", path);
 
277
        badrm = rval = 1;
 
278
        break;
 
279
 
 
280
    case S_IFIFO:
 
281
        SLOG("%s is a FIFO.", path);
 
282
        badrm = rval = 1;
 
283
        break;
 
284
 
 
285
    default:
 
286
        if (volume.volinfo.v_path) {
 
287
            if ((volume.volinfo.v_adouble == AD_VERSION2)
 
288
                && (strstr(path, ".AppleDouble") != NULL)) {
 
289
                /* file in adouble dir */
 
290
                if (unlink(path) != 0)
 
291
                    badrm = rval = 1;
 
292
                break;
 
293
            }
 
294
 
 
295
            /* Get CNID of Parent and add new childir to CNID database */
 
296
            pdid = did;
 
297
            if ((cnid = cnid_for_path(&volume, path, &did)) == CNID_INVALID) {
 
298
                SLOG("Error resolving CNID for %s", path);
 
299
                return -1;
 
300
            }
 
301
            if (cnid_delete(volume.volume.v_cdb, cnid) != 0) {
 
302
                SLOG("Error removing CNID %u for %s", ntohl(cnid), path);
 
303
                return -1;
 
304
            }
 
305
 
 
306
            /* Ignore errors, because with -R adouble stuff is always alread gone */
 
307
            volume.volume.vfs->vfs_deletefile(&volume.volume, -1, path);
 
308
        }
 
309
 
 
310
        if (unlink(path) != 0) {
 
311
            badrm = rval = 1;
 
312
            break;
 
313
        }
 
314
 
 
315
        break;
 
316
    }
 
317
 
 
318
    if (vflag && !badrm)
 
319
        (void)printf("%s\n", path);
 
320
 
 
321
    return 0;
 
322
}