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;