xref: /minix/minix/servers/devman/buf.c (revision 83133719)
1 /* buf.c - by Alen Stojanov and David van Moolenbroek, taken from procfs */
2 #define _SYSTEM		1	/* tell headers that this is the kernel */
3 #define DEVMAN_SERVER	1
4 
5 #include <minix/config.h>
6 #include <errno.h>
7 #include <unistd.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <lib.h>
12 #include <minix/timers.h>
13 
14 #include <minix/callnr.h>
15 #include <minix/type.h>
16 #include <minix/const.h>
17 #include <minix/com.h>
18 #include <minix/syslib.h>
19 #include <minix/sysutil.h>
20 #include <minix/vfsif.h>
21 #include <minix/endpoint.h>
22 #include <minix/sysinfo.h>
23 #include <minix/u64.h>
24 #include <minix/sysinfo.h>
25 #include <minix/type.h>
26 #include <minix/ipc.h>
27 
28 #include <sys/time.h>
29 #include <sys/times.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 
33 #include <minix/vtreefs.h>
34 
35 #include <minix/devman.h>
36 
37 
38 #include <stdarg.h>
39 #include <assert.h>
40 #include <string.h>
41 #define BUF_SIZE 4096
42 
43 static char buf[BUF_SIZE + 1];
44 static size_t off, left, used;
45 static off_t skip;
46 
47 /*===========================================================================*
48  *				buf_init				     *
49  *===========================================================================*/
50 void buf_init(off_t start, size_t len)
51 {
52 	/* Initialize the buffer for fresh use. The first 'start' bytes of the
53 	 * produced output are to be skipped. After that, up to a total of
54 	 * 'len' bytes are requested.
55 	 */
56 
57 	skip = start;
58 	left = MIN(len, BUF_SIZE);
59 	off = 0;
60 	used = 0;
61 }
62 
63 /*===========================================================================*
64  *				buf_printf				     *
65  *===========================================================================*/
66 void buf_printf(char *fmt, ...)
67 {
68 	/* Add formatted text to the end of the buffer.
69 	 */
70 	va_list args;
71 	ssize_t len, max;
72 
73 	if (left == 0)
74 		return;
75 
76 	/* There is no way to estimate how much space the result will take, so
77 	 * we need to produce the string even when skipping part of the start.
78 	 * If part of the result is to be skipped, do not memcpy; instead, save
79 	 * the offset of where the result starts within the buffer.
80 	 *
81 	 * The null terminating character is not part of the result, so room
82 	 * must be given for it to be stored after completely filling up the
83 	 * requested part of the buffer.
84 	 */
85 	max = MIN(skip + left, BUF_SIZE);
86 
87 	va_start(args, fmt);
88 	len = vsnprintf(&buf[off + used], max + 1, fmt, args);
89 	va_end(args);
90 
91 	if (skip > 0) {
92 		assert(off == 0);
93 		assert(used == 0);
94 
95 		if (skip >= len) {
96 			skip -= len;
97 
98 			return;
99 		}
100 
101 		off = skip;
102 		if (left > BUF_SIZE - off)
103 			left = BUF_SIZE - off;
104 		len -= off;
105 		skip = 0;
106 	}
107 
108 	assert(skip == 0);
109 	assert(len >= 0);
110 	assert((long) left >= 0);
111 
112 	if (len > (ssize_t) left)
113 		len = left;
114 
115 	used += len;
116 	left -= len;
117 }
118 
119 /*===========================================================================*
120  *				buf_append				     *
121  *===========================================================================*/
122 void buf_append(char *data, size_t len)
123 {
124 	/* Add arbitrary data to the end of the buffer.
125 	 */
126 
127 	if (left == 0)
128 		return;
129 
130 	if (skip > 0) {
131 		if (skip >= (ssize_t) len) {
132 			skip -= len;
133 
134 			return;
135 		}
136 
137 		data += skip;
138 		len -= skip;
139 		skip = 0;
140 	}
141 
142 	if (len > left)
143 		len = left;
144 
145 	memcpy(&buf[off + used], data, len);
146 
147 	used += len;
148 	left -= len;
149 }
150 
151 /*===========================================================================*
152  *				buf_get					     *
153  *===========================================================================*/
154 size_t buf_get(char **ptr)
155 {
156 	/* Return the buffer's starting address and the length of the used
157 	 * part, not counting the trailing null character for the latter.
158 	 */
159 
160 	*ptr = &buf[off];
161 
162 	return used;
163 }
164