mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
There are some internals in the libxenstore interface which should be removed. Move those functions into xs_lib.c and the related definitions into xs_lib.h. Remove the functions from the mapfile. Add xs_lib.o to xenstore_client as some of the internal functions are needed there. Bump the libxenstore version to 4.0 as the change is incompatible. Note that the removed functions should not result in any problem as they ought to be used by xenstored or xenstore_client only. Avoid an enum as part of a structure as the size of an enum is compiler implementation dependent. Signed-off-by: Juergen Gross <jgross@suse.com> Acked-by: Ian Jackson <iwj@xenproject.org>
294 lines
5.9 KiB
C
294 lines
5.9 KiB
C
/*
|
|
Common routines between Xen store user library and daemon.
|
|
Copyright (C) 2005 Rusty Russell IBM Corporation
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include "xs_lib.h"
|
|
|
|
/* Common routines for the Xen store daemon and client library. */
|
|
|
|
const char *xs_daemon_rootdir(void)
|
|
{
|
|
char *s = getenv("XENSTORED_ROOTDIR");
|
|
return (s ? s : XEN_LIB_STORED);
|
|
}
|
|
|
|
const char *xs_daemon_rundir(void)
|
|
{
|
|
char *s = getenv("XENSTORED_RUNDIR");
|
|
return (s ? s : XEN_RUN_STORED);
|
|
}
|
|
|
|
static const char *xs_daemon_path(void)
|
|
{
|
|
static char buf[PATH_MAX];
|
|
char *s = getenv("XENSTORED_PATH");
|
|
if (s)
|
|
return s;
|
|
if (snprintf(buf, sizeof(buf), "%s/socket",
|
|
xs_daemon_rundir()) >= PATH_MAX)
|
|
return NULL;
|
|
return buf;
|
|
}
|
|
|
|
const char *xs_daemon_tdb(void)
|
|
{
|
|
static char buf[PATH_MAX];
|
|
snprintf(buf, sizeof(buf), "%s/tdb", xs_daemon_rootdir());
|
|
return buf;
|
|
}
|
|
|
|
const char *xs_daemon_socket(void)
|
|
{
|
|
return xs_daemon_path();
|
|
}
|
|
|
|
const char *xs_daemon_socket_ro(void)
|
|
{
|
|
return xs_daemon_path();
|
|
}
|
|
|
|
const char *xs_domain_dev(void)
|
|
{
|
|
char *s = getenv("XENSTORED_PATH");
|
|
if (s)
|
|
return s;
|
|
#if defined(__RUMPUSER_XEN__) || defined(__RUMPRUN__)
|
|
return "/dev/xen/xenbus";
|
|
#elif defined(__linux__)
|
|
if (access("/dev/xen/xenbus", F_OK) == 0)
|
|
return "/dev/xen/xenbus";
|
|
return "/proc/xen/xenbus";
|
|
#elif defined(__NetBSD__)
|
|
return "/kern/xen/xenbus";
|
|
#elif defined(__FreeBSD__)
|
|
return "/dev/xen/xenstore";
|
|
#else
|
|
return "/dev/xen/xenbus";
|
|
#endif
|
|
}
|
|
|
|
/* Simple routines for writing to sockets, etc. */
|
|
bool xs_write_all(int fd, const void *data, unsigned int len)
|
|
{
|
|
while (len) {
|
|
int done;
|
|
|
|
done = write(fd, data, len);
|
|
if (done < 0 && errno == EINTR)
|
|
continue;
|
|
if (done <= 0)
|
|
return false;
|
|
data += done;
|
|
len -= done;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Convert strings to permissions. False if a problem. */
|
|
bool xs_strings_to_perms(struct xs_permissions *perms, unsigned int num,
|
|
const char *strings)
|
|
{
|
|
const char *p;
|
|
char *end;
|
|
unsigned int i;
|
|
|
|
for (p = strings, i = 0; i < num; i++) {
|
|
/* "r", "w", or "b" for both. */
|
|
switch (*p) {
|
|
case 'r':
|
|
perms[i].perms = XS_PERM_READ;
|
|
break;
|
|
case 'w':
|
|
perms[i].perms = XS_PERM_WRITE;
|
|
break;
|
|
case 'b':
|
|
perms[i].perms = XS_PERM_READ|XS_PERM_WRITE;
|
|
break;
|
|
case 'n':
|
|
perms[i].perms = XS_PERM_NONE;
|
|
break;
|
|
default:
|
|
errno = EINVAL;
|
|
return false;
|
|
}
|
|
p++;
|
|
perms[i].id = strtol(p, &end, 0);
|
|
if (*end || !*p) {
|
|
errno = EINVAL;
|
|
return false;
|
|
}
|
|
p = end + 1;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/* Convert permissions to a string (up to len MAX_STRLEN(unsigned int)+1). */
|
|
bool xs_perm_to_string(const struct xs_permissions *perm,
|
|
char *buffer, size_t buf_len)
|
|
{
|
|
switch ((int)perm->perms & ~XS_PERM_IGNORE) {
|
|
case XS_PERM_WRITE:
|
|
*buffer = 'w';
|
|
break;
|
|
case XS_PERM_READ:
|
|
*buffer = 'r';
|
|
break;
|
|
case XS_PERM_READ|XS_PERM_WRITE:
|
|
*buffer = 'b';
|
|
break;
|
|
case XS_PERM_NONE:
|
|
*buffer = 'n';
|
|
break;
|
|
default:
|
|
errno = EINVAL;
|
|
return false;
|
|
}
|
|
snprintf(buffer+1, buf_len-1, "%i", (int)perm->id);
|
|
return true;
|
|
}
|
|
|
|
/* Given a string and a length, count how many strings (nul terms). */
|
|
unsigned int xs_count_strings(const char *strings, unsigned int len)
|
|
{
|
|
unsigned int num;
|
|
const char *p;
|
|
|
|
for (p = strings, num = 0; p < strings + len; p++)
|
|
if (*p == '\0')
|
|
num++;
|
|
|
|
return num;
|
|
}
|
|
|
|
char *expanding_buffer_ensure(struct expanding_buffer *ebuf, int min_avail)
|
|
{
|
|
int want;
|
|
char *got;
|
|
|
|
if (ebuf->avail >= min_avail)
|
|
return ebuf->buf;
|
|
|
|
if (min_avail >= INT_MAX/3)
|
|
return 0;
|
|
|
|
want = ebuf->avail + min_avail + 10;
|
|
got = realloc(ebuf->buf, want);
|
|
if (!got)
|
|
return 0;
|
|
|
|
ebuf->buf = got;
|
|
ebuf->avail = want;
|
|
return ebuf->buf;
|
|
}
|
|
|
|
char *sanitise_value(struct expanding_buffer *ebuf,
|
|
const char *val, unsigned len)
|
|
{
|
|
int used, remain, c;
|
|
unsigned char *ip;
|
|
|
|
#define ADD(c) (ebuf->buf[used++] = (c))
|
|
#define ADDF(f,c) (used += sprintf(ebuf->buf+used, (f), (c)))
|
|
|
|
assert(len < INT_MAX/5);
|
|
|
|
ip = (unsigned char *)val;
|
|
used = 0;
|
|
remain = len;
|
|
|
|
if (!expanding_buffer_ensure(ebuf, remain + 1))
|
|
return NULL;
|
|
|
|
while (remain-- > 0) {
|
|
c= *ip++;
|
|
|
|
if (c >= ' ' && c <= '~' && c != '\\') {
|
|
ADD(c);
|
|
continue;
|
|
}
|
|
|
|
if (!expanding_buffer_ensure(ebuf, used + remain + 5))
|
|
/* for "<used>\\nnn<remain>\0" */
|
|
return 0;
|
|
|
|
ADD('\\');
|
|
switch (c) {
|
|
case '\t': ADD('t'); break;
|
|
case '\n': ADD('n'); break;
|
|
case '\r': ADD('r'); break;
|
|
case '\\': ADD('\\'); break;
|
|
default:
|
|
if (c < 010) ADDF("%03o", c);
|
|
else ADDF("x%02x", c);
|
|
}
|
|
}
|
|
|
|
ADD(0);
|
|
assert(used <= ebuf->avail);
|
|
return ebuf->buf;
|
|
|
|
#undef ADD
|
|
#undef ADDF
|
|
}
|
|
|
|
void unsanitise_value(char *out, unsigned *out_len_r, const char *in)
|
|
{
|
|
const char *ip;
|
|
char *op;
|
|
unsigned c;
|
|
int n;
|
|
|
|
for (ip = in, op = out; (c = *ip++); *op++ = c) {
|
|
if (c == '\\') {
|
|
c = *ip++;
|
|
|
|
#define GETF(f) do { \
|
|
n = 0; \
|
|
sscanf(ip, f "%n", &c, &n); \
|
|
ip += n; \
|
|
} while (0)
|
|
|
|
switch (c) {
|
|
case 't': c= '\t'; break;
|
|
case 'n': c= '\n'; break;
|
|
case 'r': c= '\r'; break;
|
|
case '\\': c= '\\'; break;
|
|
case 'x': GETF("%2x"); break;
|
|
case '0': case '4':
|
|
case '1': case '5':
|
|
case '2': case '6':
|
|
case '3': case '7': --ip; GETF("%3o"); break;
|
|
case 0: --ip; break;
|
|
default:;
|
|
}
|
|
#undef GETF
|
|
}
|
|
}
|
|
|
|
*op = 0;
|
|
|
|
if (out_len_r)
|
|
*out_len_r = op - out;
|
|
}
|