~ubuntu-branches/ubuntu/saucy/nfs-utils/saucy-proposed

« back to all changes in this revision

Viewing changes to utils/mount/nfsumount.c

  • Committer: Bazaar Package Importer
  • Author(s): Luk Claes
  • Date: 2011-07-09 16:28:32 UTC
  • mfrom: (1.2.20 upstream)
  • mto: (71.1.1 ubuntu)
  • mto: This revision was merged to the branch mainline in revision 41.
  • Revision ID: james.westby@ubuntu.com-20110709162832-ovaehe77pm3hyy35
Tags: 1:1.2.4-1
* New upstream version
  - Fix host_reliable_addrinfo (Closes: #633155)
  - Allow multiple RPC listeners to share listener port number
  (Closes: #619877)
  - Add --enable-libmount-mount (Closes: #626478)
  - 12-svcgssd-document-n-option.patch applied upstream
  - Refresh 19-exports.man-Fix-comment-syntax.patch
  - 21-anticipate-RLIMIT_FSIZE.patch applied upstream
  - Add nfsidmap binary and manpage
  - Use autoreconf to avoid build failure

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include "nls.h"
32
32
 
33
33
#include "mount_constants.h"
 
34
#include "nfs_mount.h"
34
35
#include "mount.h"
35
36
#include "error.h"
36
37
#include "network.h"
37
38
#include "parse_opt.h"
38
39
#include "parse_dev.h"
 
40
#include "utils.h"
 
41
 
 
42
#define MOUNTSFILE      "/proc/mounts"
 
43
#define LINELEN         (4096)
39
44
 
40
45
#if !defined(MNT_FORCE)
41
46
/* dare not try to include <linux/mount.h> -- lots of errors */
109
114
                        res = try_remount(spec, node);
110
115
                        if (res)
111
116
                                goto writemtab;
112
 
                        return 0;
 
117
                        return EX_SUCCESS;
113
118
                } else
114
119
                        umnt_err = errno;
115
120
        }
127
132
        }
128
133
 
129
134
        if (res >= 0)
130
 
                return 0;
 
135
                return EX_SUCCESS;
131
136
 
132
137
        if (umnt_err)
133
138
                umount_error(umnt_err, node);
135
140
}
136
141
 
137
142
/*
138
 
 * Discover mount server's hostname/address by examining mount options
139
 
 *
140
 
 * Returns a pointer to a string that the caller must free, on
141
 
 * success; otherwise NULL is returned.
 
143
 * Detect NFSv4 mounts.
 
144
 *
 
145
 * Consult /proc/mounts to determine if the mount point
 
146
 * is an NFSv4 mount.  The kernel is authoritative about
 
147
 * what type of mount this is.
 
148
 *
 
149
 * Returns 1 if "mc" is an NFSv4 mount, zero if not, and
 
150
 * -1 if some error occurred.
142
151
 */
143
 
static char *nfs_umount_hostname(struct mount_options *options,
144
 
                                 char *hostname)
 
152
static int nfs_umount_is_vers4(const struct mntentchn *mc)
145
153
{
146
 
        char *option;
147
 
 
148
 
        option = po_get(options, "mountaddr");
149
 
        if (option)
150
 
                goto out;
151
 
        option = po_get(options, "mounthost");
152
 
        if (option)
153
 
                goto out;
154
 
        option = po_get(options, "addr");
155
 
        if (option)
156
 
                goto out;
157
 
 
158
 
        return hostname;
 
154
        char buffer[LINELEN], *next;
 
155
        int retval;
 
156
        FILE *f;
 
157
 
 
158
        if ((f = fopen(MOUNTSFILE, "r")) == NULL) {
 
159
                fprintf(stderr, "%s: %s\n",
 
160
                        MOUNTSFILE, strerror(errno));
 
161
                return -1;
 
162
        }
 
163
 
 
164
        retval = -1;
 
165
        while (fgets(buffer, sizeof(buffer), f) != NULL) {
 
166
                char *device, *mntdir, *type, *flags;
 
167
                struct mount_options *options;
 
168
                char *line = buffer;
 
169
 
 
170
                next = strchr(line, '\n');
 
171
                if (next != NULL)
 
172
                        *next = '\0';
 
173
 
 
174
                device = strtok(line, " \t");
 
175
                if (device == NULL)
 
176
                        continue;
 
177
                mntdir = strtok(NULL, " \t");
 
178
                if (mntdir == NULL)
 
179
                        continue;
 
180
                if (strcmp(device, mc->m.mnt_fsname) != 0 &&
 
181
                    strcmp(mntdir, mc->m.mnt_dir) != 0)
 
182
                        continue;
 
183
 
 
184
                type = strtok(NULL, " \t");
 
185
                if (type == NULL)
 
186
                        continue;
 
187
                if (strcmp(type, "nfs4") == 0)
 
188
                        goto out_nfs4;
 
189
 
 
190
                flags = strtok(NULL, " \t");
 
191
                if (flags == NULL)
 
192
                        continue;
 
193
                options = po_split(flags);
 
194
                if (options != NULL) {
 
195
                        unsigned long version;
 
196
                        int rc;
 
197
 
 
198
                        rc = nfs_nfs_version(options, &version);
 
199
                        po_destroy(options);
 
200
                        if (rc && version == 4)
 
201
                                goto out_nfs4;
 
202
                }
 
203
 
 
204
                goto out_nfs;
 
205
        }
 
206
        if (retval == -1)
 
207
                fprintf(stderr, "%s was not found in %s\n",
 
208
                        mc->m.mnt_dir, MOUNTSFILE);
159
209
 
160
210
out:
161
 
        free(hostname);
162
 
        return strdup(option);
163
 
}
164
 
 
165
 
/*
166
 
 * Returns EX_SUCCESS if mount options and device name have been
167
 
 * parsed successfully; otherwise EX_FAIL.
168
 
 */
169
 
static int nfs_umount_do_umnt(struct mount_options *options,
170
 
                              char **hostname, char **dirname)
171
 
{
172
 
        union {
173
 
                struct sockaddr         sa;
174
 
                struct sockaddr_in      s4;
175
 
                struct sockaddr_in6     s6;
176
 
        } address;
177
 
        struct sockaddr *sap = &address.sa;
178
 
        socklen_t salen = sizeof(address);
179
 
        struct pmap nfs_pmap, mnt_pmap;
180
 
        sa_family_t family;
181
 
 
182
 
        if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap))
183
 
                return EX_FAIL;
184
 
 
185
 
        /* Skip UMNT call for vers=4 mounts */
186
 
        if (nfs_pmap.pm_vers == 4)
187
 
                return EX_SUCCESS;
188
 
 
189
 
        *hostname = nfs_umount_hostname(options, *hostname);
190
 
        if (!*hostname) {
191
 
                nfs_error(_("%s: out of memory"), progname);
192
 
                return EX_FAIL;
193
 
        }
194
 
 
195
 
        if (!nfs_mount_proto_family(options, &family))
196
 
                return 0;
197
 
        if (!nfs_lookup(*hostname, family, sap, &salen))
198
 
                /* nfs_lookup reports any errors */
199
 
                return EX_FAIL;
200
 
 
201
 
        if (nfs_advise_umount(sap, salen, &mnt_pmap, dirname) == 0)
202
 
                /* nfs_advise_umount reports any errors */
203
 
                return EX_FAIL;
204
 
 
205
 
        return EX_SUCCESS;
206
 
}
207
 
 
208
 
/*
209
 
 * Pick up certain mount options used during the original mount
210
 
 * from /etc/mtab.  The basics include the server's IP address and
211
 
 * the server pathname of the share to unregister.
212
 
 *
213
 
 * These options might also describe the mount port, mount protocol
214
 
 * version, and transport protocol used to punch through a firewall.
215
 
 * We will need this information to get through the firewall again
216
 
 * to do the umount.
217
 
 *
218
 
 * Note that option parsing failures won't necessarily cause the
219
 
 * umount request to fail.  Those values will be left zero in the
220
 
 * pmap tuple.  If the GETPORT call later fails to disambiguate them,
221
 
 * then we fail.
222
 
 */
223
 
static int nfs_umount23(const char *devname, char *string)
224
 
{
225
 
        char *hostname, *dirname;
226
 
        struct mount_options *options;
227
 
        int result = EX_FAIL;
228
 
 
229
 
        if (!nfs_parse_devname(devname, &hostname, &dirname))
230
 
                return EX_USAGE;
231
 
 
232
 
        options = po_split(string);
233
 
        if (options) {
234
 
                result = nfs_umount_do_umnt(options, &hostname, &dirname);
235
 
                po_destroy(options);
236
 
        } else
237
 
                nfs_error(_("%s: option parsing error"), progname);
238
 
 
239
 
        free(hostname);
240
 
        free(dirname);
241
 
        return result;
 
211
        fclose(f);
 
212
        return retval;
 
213
 
 
214
out_nfs4:
 
215
        if (verbose)
 
216
                fprintf(stderr, "NFSv4 mount point detected\n");
 
217
        retval = 1;
 
218
        goto out;
 
219
 
 
220
out_nfs:
 
221
        if (verbose)
 
222
                fprintf(stderr, "Legacy NFS mount point detected\n");
 
223
        retval = 0;
 
224
        goto out;
242
225
}
243
226
 
244
227
static struct option umount_longopts[] =
251
234
  { NULL, 0, 0, 0 }
252
235
};
253
236
 
254
 
static void umount_usage(void)
255
 
{
256
 
        printf(_("usage: %s dir [-fvnrlh]\n"), progname);
257
 
        printf(_("options:\n\t-f\t\tforce unmount\n"));
258
 
        printf(_("\t-v\tverbose\n"));
259
 
        printf(_("\t-n\tDo not update /etc/mtab\n"));
260
 
        printf(_("\t-r\tremount\n"));
261
 
        printf(_("\t-l\tlazy unmount\n"));
262
 
        printf(_("\t-h\tprint this help\n\n"));
263
 
}
264
 
 
265
237
int nfsumount(int argc, char *argv[])
266
238
{
267
239
        int c, ret;
362
334
                }
363
335
        }
364
336
 
365
 
        ret = 0;
 
337
        ret = EX_SUCCESS;
366
338
        if (mc) {
367
 
                if (!lazy && strcmp(mc->m.mnt_type, "nfs4") != 0)
368
 
                        /* We ignore the error from nfs_umount23.
369
 
                         * If the actual umount succeeds (in del_mtab),
370
 
                         * we don't want to signal an error, as that
371
 
                         * could cause /sbin/mount to retry!
372
 
                         */
373
 
                        nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
374
 
                ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir) ?: ret;
 
339
                if (!lazy) {
 
340
                        switch (nfs_umount_is_vers4(mc)) {
 
341
                        case 0:
 
342
                                /* We ignore the error from nfs_umount23.
 
343
                                 * If the actual umount succeeds (in del_mtab),
 
344
                                 * we don't want to signal an error, as that
 
345
                                 * could cause /sbin/mount to retry!
 
346
                                 */
 
347
                                nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
 
348
                                break;
 
349
                        case 1:
 
350
                                break;
 
351
                        default:
 
352
                                return EX_FAIL;
 
353
                        }
 
354
                }
 
355
                ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
375
356
        } else if (*spec != '/') {
376
357
                if (!lazy)
377
358
                        ret = nfs_umount23(spec, "tcp,v3");