1 /*
2     Common routines between Xen store user library and daemon.
3     Copyright (C) 2005 Rusty Russell IBM Corporation
4 
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9 
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include "xenstore_lib.h"
25 
26 /* Common routines for the Xen store daemon and client library. */
27 
xs_daemon_rootdir(void)28 const char *xs_daemon_rootdir(void)
29 {
30 	char *s = getenv("XENSTORED_ROOTDIR");
31 	return (s ? s : XEN_LIB_STORED);
32 }
33 
xs_daemon_rundir(void)34 const char *xs_daemon_rundir(void)
35 {
36 	char *s = getenv("XENSTORED_RUNDIR");
37 	return (s ? s : XEN_RUN_STORED);
38 }
39 
xs_daemon_path(void)40 static const char *xs_daemon_path(void)
41 {
42 	static char buf[PATH_MAX];
43 	char *s = getenv("XENSTORED_PATH");
44 	if (s)
45 		return s;
46 	if (snprintf(buf, sizeof(buf), "%s/socket",
47 		     xs_daemon_rundir()) >= PATH_MAX)
48 		return NULL;
49 	return buf;
50 }
51 
xs_daemon_tdb(void)52 const char *xs_daemon_tdb(void)
53 {
54 	static char buf[PATH_MAX];
55 	snprintf(buf, sizeof(buf), "%s/tdb", xs_daemon_rootdir());
56 	return buf;
57 }
58 
xs_daemon_socket(void)59 const char *xs_daemon_socket(void)
60 {
61 	return xs_daemon_path();
62 }
63 
xs_daemon_socket_ro(void)64 const char *xs_daemon_socket_ro(void)
65 {
66 	static char buf[PATH_MAX];
67 	const char *s = xs_daemon_path();
68 	if (s == NULL)
69 		return NULL;
70 	if (snprintf(buf, sizeof(buf), "%s_ro", s) >= PATH_MAX)
71 		return NULL;
72 	return buf;
73 }
74 
xs_domain_dev(void)75 const char *xs_domain_dev(void)
76 {
77 	char *s = getenv("XENSTORED_PATH");
78 	if (s)
79 		return s;
80 #if defined(__RUMPUSER_XEN__) || defined(__RUMPRUN__)
81 	return "/dev/xen/xenbus";
82 #elif defined(__linux__)
83 	if (access("/dev/xen/xenbus", F_OK) == 0)
84 		return "/dev/xen/xenbus";
85 	return "/proc/xen/xenbus";
86 #elif defined(__NetBSD__)
87 	return "/kern/xen/xenbus";
88 #elif defined(__FreeBSD__)
89 	return "/dev/xen/xenstore";
90 #else
91 	return "/dev/xen/xenbus";
92 #endif
93 }
94 
95 /* Simple routines for writing to sockets, etc. */
xs_write_all(int fd,const void * data,unsigned int len)96 bool xs_write_all(int fd, const void *data, unsigned int len)
97 {
98 	while (len) {
99 		int done;
100 
101 		done = write(fd, data, len);
102 		if (done < 0 && errno == EINTR)
103 			continue;
104 		if (done <= 0)
105 			return false;
106 		data += done;
107 		len -= done;
108 	}
109 
110 	return true;
111 }
112 
113 /* Convert strings to permissions.  False if a problem. */
xs_strings_to_perms(struct xs_permissions * perms,unsigned int num,const char * strings)114 bool xs_strings_to_perms(struct xs_permissions *perms, unsigned int num,
115 			 const char *strings)
116 {
117 	const char *p;
118 	char *end;
119 	unsigned int i;
120 
121 	for (p = strings, i = 0; i < num; i++) {
122 		/* "r", "w", or "b" for both. */
123 		switch (*p) {
124 		case 'r':
125 			perms[i].perms = XS_PERM_READ;
126 			break;
127 		case 'w':
128 			perms[i].perms = XS_PERM_WRITE;
129 			break;
130 		case 'b':
131 			perms[i].perms = XS_PERM_READ|XS_PERM_WRITE;
132 			break;
133 		case 'n':
134 			perms[i].perms = XS_PERM_NONE;
135 			break;
136 		default:
137 			errno = EINVAL;
138 			return false;
139 		}
140 		p++;
141 		perms[i].id = strtol(p, &end, 0);
142 		if (*end || !*p) {
143 			errno = EINVAL;
144 			return false;
145 		}
146 		p = end + 1;
147 	}
148 	return true;
149 }
150 
151 /* Convert permissions to a string (up to len MAX_STRLEN(unsigned int)+1). */
xs_perm_to_string(const struct xs_permissions * perm,char * buffer,size_t buf_len)152 bool xs_perm_to_string(const struct xs_permissions *perm,
153                        char *buffer, size_t buf_len)
154 {
155 	switch ((int)perm->perms) {
156 	case XS_PERM_WRITE:
157 		*buffer = 'w';
158 		break;
159 	case XS_PERM_READ:
160 		*buffer = 'r';
161 		break;
162 	case XS_PERM_READ|XS_PERM_WRITE:
163 		*buffer = 'b';
164 		break;
165 	case XS_PERM_NONE:
166 		*buffer = 'n';
167 		break;
168 	default:
169 		errno = EINVAL;
170 		return false;
171 	}
172 	snprintf(buffer+1, buf_len-1, "%i", (int)perm->id);
173 	return true;
174 }
175 
176 /* Given a string and a length, count how many strings (nul terms). */
xs_count_strings(const char * strings,unsigned int len)177 unsigned int xs_count_strings(const char *strings, unsigned int len)
178 {
179 	unsigned int num;
180 	const char *p;
181 
182 	for (p = strings, num = 0; p < strings + len; p++)
183 		if (*p == '\0')
184 			num++;
185 
186 	return num;
187 }
188