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