summaryrefslogtreecommitdiffstats
path: root/support/nfs/getfh.c
blob: 611459ba73c106dfa4649b0ef634d14b9165d657 (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
/*
 * support/nfs/getfh.c
 *
 * Get the FH for a given client and directory. This function takes
 * the NFS protocol version number as an additional argument.
 *
 * This function has nothing in common with the SunOS getfh function,
 * which is a front-end to the RPC mount call.
 *
 * 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 <errno.h>
#include "nfslib.h"

/**
 * getfh_old - ask the kernel for an NFSv2 file handle via nfsctl()
 * @sin: pointer to IPv4 address of a client
 * @dev: device number of device where requested object resides
 * @ino: inode number of requested object
 *
 * Returns a pointer to an NFSv2 file handle, or NULL if some error
 * occurred.  errno is set to reflect the specifics of the error.
 */
struct nfs_fh_len *
getfh_old(const struct sockaddr_in *sin, const dev_t dev, const ino_t ino)
{
	union nfsctl_res	res;
	struct nfsctl_arg	arg;
	static struct nfs_fh_len rfh;

	if (sin->sin_family != AF_INET) {
		errno = EAFNOSUPPORT;
		return NULL;
	}

	memset(&arg, 0, sizeof(arg));
	memset(&res, 0, sizeof(res));

	arg.ca_version = NFSCTL_VERSION;
	arg.ca_getfh.gf_version = 2;	/* obsolete */
	arg.ca_getfh.gf_dev = dev;
	arg.ca_getfh.gf_ino = ino;
	memcpy(&arg.ca_getfh.gf_addr, sin, sizeof(*sin));

	if (nfsctl(NFSCTL_GETFH, &arg, &res) < 0)
		return NULL;

	memset(&rfh, 0, sizeof(rfh));
	rfh.fh_size = 32;
	memcpy(rfh.fh_handle, &res.cr_getfh, 32);
	return &rfh;
}

/**
 * getfh - ask the kernel for an NFSv2 file handle via nfsctl()
 * @sin: pointer to IPv4 address of a client
 * @path: pointer to a '\0'-terminated ASCII string containing an pathname
 *
 * Returns a pointer to an NFSv2 file handle, or NULL if some error
 * occurred.  errno is set to reflect the specifics of the error.
 */
struct nfs_fh_len *
getfh(const struct sockaddr_in *sin, const char *path)
{
	static union nfsctl_res res;
        struct nfsctl_arg       arg;
	static struct nfs_fh_len rfh;

	if (sin->sin_family != AF_INET) {
		errno = EAFNOSUPPORT;
		return NULL;
	}

	memset(&arg, 0, sizeof(arg));
	memset(&res, 0, sizeof(res));

        arg.ca_version = NFSCTL_VERSION;
        arg.ca_getfd.gd_version = 2;    /* obsolete */
        strncpy(arg.ca_getfd.gd_path, path,
		sizeof(arg.ca_getfd.gd_path) - 1);
	arg.ca_getfd.gd_path[sizeof (arg.ca_getfd.gd_path) - 1] = '\0';
	memcpy(&arg.ca_getfd.gd_addr, sin, sizeof(*sin));

        if (nfsctl(NFSCTL_GETFD, &arg, &res) < 0)
                return NULL;

	memset(&rfh, 0, sizeof(rfh));
	rfh.fh_size = 32;
	memcpy(rfh.fh_handle, &res.cr_getfh, 32);
	return &rfh;
}

/**
 * getfh_size - ask the kernel for a file handle via nfsctl()
 * @sin: pointer to IPv4 address of a client
 * @path: pointer to a '\0'-terminated ASCII string containing an pathname
 * @size: maximum size, in bytes, of the returned file handle
 *
 * Returns a pointer to an NFSv3 file handle, or NULL if some error
 * occurred.  errno is set to reflect the specifics of the error.
 */
struct nfs_fh_len *
getfh_size(const struct sockaddr_in *sin, const char *path, const int size)
{
        static union nfsctl_res res;
        struct nfsctl_arg       arg;

	if (sin->sin_family != AF_INET) {
		errno = EAFNOSUPPORT;
		return NULL;
	}

	memset(&arg, 0, sizeof(arg));
	memset(&res, 0, sizeof(res));

        arg.ca_version = NFSCTL_VERSION;
        strncpy(arg.ca_getfs.gd_path, path,
		sizeof(arg.ca_getfs.gd_path) - 1);
	arg.ca_getfs.gd_path[sizeof (arg.ca_getfs.gd_path) - 1] = '\0';
	memcpy(&arg.ca_getfs.gd_addr, sin, sizeof(*sin));
	arg.ca_getfs.gd_maxlen = size;

        if (nfsctl(NFSCTL_GETFS, &arg, &res) < 0)
                return NULL;

        return &res.cr_getfs;
}