]>
git.proxmox.com Git - mirror_zfs.git/blob - zfs/lib/libdmu-ctl/dctl_client.c
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
33 #include <sys/types.h>
34 #include <sys/socket.h>
36 #include <sys/debug.h>
38 #include <sys/dmu_ctl.h>
39 #include <sys/dmu_ctl_impl.h>
42 * Try to connect to the socket given in path.
44 * For nftw() convenience, returns 0 if unsuccessful, otherwise
45 * returns the socket descriptor.
47 static int try_connect(const char *path
)
49 struct sockaddr_un name
;
52 sock
= socket(PF_UNIX
, SOCK_STREAM
, 0);
59 * The socket fd cannot be 0 otherwise nftw() will not interpret the
60 * return code correctly.
64 name
.sun_family
= AF_UNIX
;
65 strncpy(name
.sun_path
, path
, sizeof(name
.sun_path
));
67 name
.sun_path
[sizeof(name
.sun_path
) - 1] = '\0';
69 if (connect(sock
, (struct sockaddr
*) &name
, sizeof(name
)) == -1) {
80 static int nftw_cb(const char *fpath
, const struct stat
*sb
, int typeflag
,
83 if (!S_ISSOCK(sb
->st_mode
))
86 if (strcmp(&fpath
[ftwbuf
->base
], SOCKNAME
) != 0)
89 return try_connect(fpath
);
93 * For convenience, if check_subdirs is true we walk the directory tree to
96 int dctlc_connect(const char *dir
, boolean_t check_subdirs
)
102 fd
= nftw(dir
, nftw_cb
, 10, FTW_PHYS
);
104 fpath
= malloc(strlen(dir
) + strlen(SOCKNAME
) + 2);
109 strcat(fpath
, "/" SOCKNAME
);
111 fd
= try_connect(fpath
);
116 return fd
== 0 ? -1 : fd
;
119 void dctlc_disconnect(int fd
)
121 (void) shutdown(fd
, SHUT_RDWR
);
124 static int dctl_reply_copyin(int fd
, dctl_cmd_t
*cmd
)
126 return dctl_send_data(fd
, (void *)(uintptr_t) cmd
->u
.dcmd_copy
.ptr
,
127 cmd
->u
.dcmd_copy
.size
);
130 static int dctl_reply_copyinstr(int fd
, dctl_cmd_t
*cmd
)
134 size_t len
, buflen
, to_copy
;
137 reply
.dcmd_msg
= DCTL_GEN_REPLY
;
139 from
= (char *)(uintptr_t) cmd
->u
.dcmd_copy
.ptr
;
141 buflen
= cmd
->u
.dcmd_copy
.size
;
142 to_copy
= strnlen(from
, buflen
- 1);
144 reply
.u
.dcmd_reply
.rc
= from
[to_copy
] == '\0' ? 0 : ENAMETOOLONG
;
145 reply
.u
.dcmd_reply
.size
= to_copy
;
147 error
= dctl_send_msg(fd
, &reply
);
149 if (!error
&& to_copy
> 0)
150 error
= dctl_send_data(fd
, from
, to_copy
);
155 static int dctl_reply_copyout(int fd
, dctl_cmd_t
*cmd
)
157 return dctl_read_data(fd
, (void *)(uintptr_t) cmd
->u
.dcmd_copy
.ptr
,
158 cmd
->u
.dcmd_copy
.size
);
161 static int dctl_reply_fd_read(int fd
, dctl_cmd_t
*cmd
)
166 ssize_t rrc
, size
= cmd
->u
.dcmd_fd_io
.size
;
172 rrc
= read(cmd
->u
.dcmd_fd_io
.fd
, buf
, size
);
174 reply
.dcmd_msg
= DCTL_GEN_REPLY
;
175 reply
.u
.dcmd_reply
.rc
= rrc
== -1 ? errno
: 0;
176 reply
.u
.dcmd_reply
.size
= rrc
;
178 error
= dctl_send_msg(fd
, &reply
);
180 if (!error
&& rrc
> 0)
181 error
= dctl_send_data(fd
, buf
, rrc
);
189 static int dctl_reply_fd_write(int fd
, dctl_cmd_t
*cmd
)
194 ssize_t wrc
, size
= cmd
->u
.dcmd_fd_io
.size
;
200 error
= dctl_read_data(fd
, buf
, size
);
204 wrc
= write(cmd
->u
.dcmd_fd_io
.fd
, buf
, size
);
206 reply
.dcmd_msg
= DCTL_GEN_REPLY
;
207 reply
.u
.dcmd_reply
.rc
= wrc
== -1 ? errno
: 0;
208 reply
.u
.dcmd_reply
.size
= wrc
;
210 error
= dctl_send_msg(fd
, &reply
);
218 int dctlc_ioctl(int fd
, int32_t request
, void *arg
)
225 cmd
.dcmd_msg
= DCTL_IOCTL
;
227 cmd
.u
.dcmd_ioctl
.cmd
= request
;
228 cmd
.u
.dcmd_ioctl
.arg
= (uintptr_t) arg
;
230 error
= dctl_send_msg(fd
, &cmd
);
232 while (!error
&& (error
= dctl_read_msg(fd
, &cmd
)) == 0) {
233 switch (cmd
.dcmd_msg
) {
234 case DCTL_IOCTL_REPLY
:
235 error
= cmd
.u
.dcmd_reply
.rc
;
238 error
= dctl_reply_copyin(fd
, &cmd
);
241 error
= dctl_reply_copyinstr(fd
, &cmd
);
244 error
= dctl_reply_copyout(fd
, &cmd
);
247 error
= dctl_reply_fd_read(fd
, &cmd
);
250 error
= dctl_reply_fd_write(fd
, &cmd
);
253 fprintf(stderr
, "%s(): invalid message "
254 "received.\n", __func__
);
262 return error
? -1 : 0;