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
|
/*
* support/nfs/export.c
*
* Add or delete an NFS export in knfsd.
*
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <sys/types.h>
#include <asm/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "nfslib.h"
/* if /proc/net/rpc/... exists, then
* write to it, as that interface is more stable.
* Write:
* client fsidtype fsid path
* to /proc/net/rpc/nfsd.fh/channel
* and
* client path expiry flags anonuid anongid fsid
* to /proc/net/rpc/nfsd.export/channel
*/
static int
exp_unexp(struct nfsctl_export *exp, int export)
{
FILE *f;
struct stat stb;
__u32 fsid;
char fsidstr[8];
__u16 dev;
__u32 inode;
int err;
f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
if (f == NULL) return -1;
qword_print(f, exp->ex_client);
qword_print(f, exp->ex_path);
if (export) {
qword_printint(f, 0x7fffffff);
qword_printint(f, exp->ex_flags);
qword_printint(f, exp->ex_anon_uid);
qword_printint(f, exp->ex_anon_gid);
qword_printint(f, exp->ex_dev);
} else
qword_printint(f, 1);
err = qword_eol(f);
fclose(f);
if (stat(exp->ex_path, &stb) != 0)
return -1;
f = fopen("/proc/net/rpc/nfsd.fh/channel", "w");
if (f==NULL) return -1;
if (exp->ex_flags & NFSEXP_FSID) {
qword_print(f,exp->ex_client);
qword_printint(f,1);
fsid = exp->ex_dev;
qword_printhex(f, (char*)&fsid, 4);
if (export) {
qword_printint(f, 0x7fffffff);
qword_print(f, exp->ex_path);
} else
qword_printint(f, 1);
err = qword_eol(f) || err;
}
qword_print(f,exp->ex_client);
qword_printint(f,0);
dev = htons(major(stb.st_dev)); memcpy(fsidstr, &dev, 2);
dev = htons(minor(stb.st_dev)); memcpy(fsidstr+2, &dev, 2);
inode = stb.st_ino; memcpy(fsidstr+4, &inode, 4);
qword_printhex(f, fsidstr, 8);
if (export) {
qword_printint(f, 0x7fffffff);
qword_print(f, exp->ex_path);
} else
qword_printint(f, 1);
err = qword_eol(f) || err;
fclose(f);
return err;
}
int
nfsexport(struct nfsctl_export *exp)
{
struct nfsctl_arg arg;
int fd;
if ((fd=open("/proc/net/rpc/nfsd.fh/channel", O_WRONLY))>= 0) {
close(fd);
return exp_unexp(exp, 1);
}
arg.ca_version = NFSCTL_VERSION;
memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
return nfsctl(NFSCTL_EXPORT, &arg, NULL);
}
int
nfsunexport(struct nfsctl_export *exp)
{
struct nfsctl_arg arg;
int fd;
if ((fd=open("/proc/net/rpc/nfsd.fh/channel", O_WRONLY))>= 0) {
close(fd);
return exp_unexp(exp, 0);
}
arg.ca_version = NFSCTL_VERSION;
memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
return nfsctl(NFSCTL_UNEXPORT, &arg, NULL);
}
|