~ubuntu-branches/debian/sid/lvm2/sid

« back to all changes in this revision

Viewing changes to libdaemon/client/daemon-shared.c

  • Committer: Package Import Robot
  • Author(s): Bastian Blank
  • Date: 2013-03-03 12:33:47 UTC
  • mfrom: (1.1.15)
  • Revision ID: package-import@ubuntu.com-20130303123347-smfwei6dodkdth55
Tags: 2.02.98-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2011-2012 Red Hat, Inc.
3
 
 *
4
 
 * This file is part of LVM2.
5
 
 *
6
 
 * This copyrighted material is made available to anyone wishing to use,
7
 
 * modify, copy, or redistribute it subject to the terms and conditions
8
 
 * of the GNU Lesser General Public License v.2.1.
9
 
 *
10
 
 * You should have received a copy of the GNU Lesser General Public License
11
 
 * along with this program; if not, write to the Free Software Foundation,
12
 
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
13
 
 */
14
 
 
15
 
#include <errno.h>
16
 
#include <stdio.h>
17
 
#include <malloc.h>
18
 
#include <string.h>
19
 
#include <unistd.h>
20
 
#include <assert.h>
21
 
 
22
 
#include "daemon-shared.h"
23
 
#include "libdevmapper.h"
24
 
 
25
 
/*
26
 
 * Read a single message from a (socket) filedescriptor. Messages are delimited
27
 
 * by blank lines. This call will block until all of a message is received. The
28
 
 * memory will be allocated from heap. Upon error, all memory is freed and the
29
 
 * buffer pointer is set to NULL.
30
 
 *
31
 
 * See also write_buffer about blocking (read_buffer has identical behaviour).
32
 
 */
33
 
int read_buffer(int fd, char **buffer) {
34
 
        int bytes = 0;
35
 
        int buffersize = 32;
36
 
        char *new;
37
 
        *buffer = malloc(buffersize + 1);
38
 
 
39
 
        while (1) {
40
 
                int result = read(fd, (*buffer) + bytes, buffersize - bytes);
41
 
                if (result > 0)
42
 
                        bytes += result;
43
 
                if (result == 0) {
44
 
                        errno = ECONNRESET;
45
 
                        goto fail; /* we should never encounter EOF here */
46
 
                }
47
 
                if (result < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
48
 
                        goto fail;
49
 
 
50
 
                if (!strncmp((*buffer) + bytes - 4, "\n##\n", 4)) {
51
 
                        *(*buffer + bytes - 4) = 0;
52
 
                        break; /* success, we have the full message now */
53
 
                }
54
 
 
55
 
                if (bytes == buffersize) {
56
 
                        buffersize += 1024;
57
 
                        if (!(new = realloc(*buffer, buffersize + 1)))
58
 
                                goto fail;
59
 
 
60
 
                        *buffer = new;
61
 
                }
62
 
                /* TODO call select here if we encountered EAGAIN/EWOULDBLOCK */
63
 
        }
64
 
        return 1;
65
 
fail:
66
 
        free(*buffer);
67
 
        *buffer = NULL;
68
 
        return 0;
69
 
}
70
 
 
71
 
/*
72
 
 * Write a buffer to a filedescriptor. Keep trying. Blocks (even on
73
 
 * SOCK_NONBLOCK) until all of the write went through.
74
 
 *
75
 
 * TODO use select on EWOULDBLOCK/EAGAIN to avoid useless spinning
76
 
 */
77
 
int write_buffer(int fd, const char *buffer, int length) {
78
 
        static const char terminate[] = "\n##\n";
79
 
        int done = 0;
80
 
        int written = 0;
81
 
write:
82
 
        while (1) {
83
 
                int result = write(fd, buffer + written, length - written);
84
 
                if (result > 0)
85
 
                        written += result;
86
 
                if (result < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
87
 
                        return 0; /* too bad */
88
 
                if (written == length) {
89
 
                        if (done)
90
 
                                return 1;
91
 
                        else
92
 
                                break; /* done */
93
 
                }
94
 
        }
95
 
 
96
 
        buffer = terminate;
97
 
        length = 4;
98
 
        written = 0;
99
 
        done = 1;
100
 
        goto write;
101
 
}
102
 
 
103
 
char *format_buffer(const char *what, const char *id, va_list ap)
104
 
{
105
 
        char *buffer, *old;
106
 
        char *next;
107
 
        int keylen;
108
 
 
109
 
        dm_asprintf(&buffer, "%s = \"%s\"\n", what, id);
110
 
        if (!buffer) goto fail;
111
 
 
112
 
        while ((next = va_arg(ap, char *))) {
113
 
                old = buffer;
114
 
                assert(strchr(next, '='));
115
 
                keylen = strchr(next, '=') - next;
116
 
                if (strstr(next, "%d")) {
117
 
                        int value = va_arg(ap, int);
118
 
                        dm_asprintf(&buffer, "%s%.*s= %d\n", buffer, keylen, next, value);
119
 
                        dm_free(old);
120
 
                } else if (strstr(next, "%s")) {
121
 
                        char *value = va_arg(ap, char *);
122
 
                        dm_asprintf(&buffer, "%s%.*s= \"%s\"\n", buffer, keylen, next, value);
123
 
                        dm_free(old);
124
 
                } else if (strstr(next, "%b")) {
125
 
                        char *block = va_arg(ap, char *);
126
 
                        if (!block)
127
 
                                continue;
128
 
                        dm_asprintf(&buffer, "%s%.*s%s", buffer, keylen, next, block);
129
 
                        dm_free(old);
130
 
                } else {
131
 
                        dm_asprintf(&buffer, "%s%s", buffer, next);
132
 
                        dm_free(old);
133
 
                }
134
 
                if (!buffer) goto fail;
135
 
        }
136
 
 
137
 
        return buffer;
138
 
fail:
139
 
        dm_free(buffer);
140
 
        return NULL;
141
 
}