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 & ~XS_PERM_IGNORE) {
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