1 2/* 3 Copyright 2004, Broadcom Corporation 4 All Rights Reserved. 5 6 THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 7 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 8 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 9 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 10*/ 11 12 13#include "upnp_dbg.h" 14#include "upnp_osl.h" 15#include "upnp.h" 16 17#define UIO_FILE (1<<0) 18#define UIO_STRING (1<<2) 19#define UIO_DYNAMIC (1<<3) 20 21/* 22 23 Define UIO_TRACE to track the creation and deletion of uio 24 structures when you suspect a leak. When this symbol is defined, 25 each UFILE structure will be tracked with a unique identifier. That 26 identifier will br printed when the structure is allocated and when 27 it is freed. If you see the identifiers grow much beyond 2 or 3, 28 then you probably are leaking UFILE structures. 29 30 #define UIO_TRACE 1 31*/ 32 33#ifdef UIO_TRACE 34fd_set uio_fds; 35#endif 36 37struct _ufile { 38#ifdef UIO_TRACE 39 int identifier; 40#endif 41 int flags; 42 int bytes_written; 43 union { 44 FILE *fp; 45 struct { 46 char *buffer; 47 int avail; 48 } str; 49 } io; 50}; 51 52UFILE *uio_new() 53{ 54 UFILE *up; 55#ifdef UIO_TRACE 56 int i; 57#endif 58 59 up = (UFILE *) malloc(sizeof(UFILE)); 60 if (up) { 61 memset(up, 0, sizeof(UFILE)); 62#ifdef UIO_TRACE 63 for (i = 0; i < 64; i++) { 64 if (!FD_ISSET(i, &uio_fds)) { 65 up->index = i; 66 FD_SET(up->index, &uio_fds); 67 printf("%s %d\n", __FUNCTION__, up->index); 68 break; 69 } 70 } 71#endif 72 } 73 return up; 74} 75 76void uio_delete(UFILE *up) 77{ 78#ifdef UIO_TRACE 79 printf("%s %d\n", __FUNCTION__, up->index); 80 FD_CLR(up->index, &uio_fds); 81#endif 82 83 free(up); 84} 85 86 87UFILE *udopen(int fd) 88{ 89 UFILE *up = NULL; 90 FILE *fp; 91 92 fp = fdopen(fd, "w"); 93 if (fp != NULL) { 94 up = uio_new(); 95 if (up) { 96 up->flags |= UIO_FILE; 97 up->io.fp = fp; 98 } else { 99 fclose(fp); 100 } 101 } 102 103 return up; 104} 105 106 107UFILE *ufopen(const char *fname) 108{ 109 UFILE *up = NULL; 110 FILE *fp; 111 112 fp = fopen(fname, "w"); 113 if (fp != NULL) { 114 up = uio_new(); 115 if (up) { 116 up->flags |= UIO_FILE; 117 up->io.fp = fp; 118 } 119 } 120 121 return up; 122} 123 124 125UFILE *usopen(char *str, int maxlen) 126{ 127 UFILE *up; 128 129 up = uio_new(); 130 if (up) { 131 up->flags |= UIO_STRING; 132 if (str) { 133 up->io.str.buffer = str; 134 up->io.str.avail = maxlen; 135 } else { 136 if (maxlen <= 0) 137 maxlen = 1024; 138 up->flags |= UIO_DYNAMIC; 139 up->io.str.buffer = malloc(maxlen); 140 up->io.str.avail = maxlen; 141 } 142 } 143 144 return up; 145} 146 147 148int uprintf(UFILE *up, char *fmt, ...) 149{ 150 va_list ap; 151 int len, n = 0; 152 char *buf; 153 154 va_start(ap, fmt); 155 if (up->flags & UIO_STRING) { 156 while (TRUE) { 157 buf = &up->io.str.buffer[up->bytes_written]; 158 len = up->io.str.avail - up->bytes_written; 159 n = vsnprintf(buf, len, fmt, ap); 160 if (n < 0 || n > len) { 161 /* we tried to overwrite the end of the buffer */ 162 if (up->flags & UIO_DYNAMIC) { 163 buf = realloc(up->io.str.buffer, up->io.str.avail + 256); 164#ifdef UIO_TRACE 165 printf("realloc was %d, now %d\n", up->io.str.avail, up->io.str.avail + 256); 166#endif 167 if (buf) { 168 up->io.str.buffer = buf; 169 up->io.str.avail += 256; 170 continue; 171 } 172 } 173 } else { 174 up->bytes_written += n; 175 } 176 break; 177 } /* end while */ 178 } else if (up->flags & UIO_FILE) { 179 n = vfprintf(up->io.fp, fmt, ap); 180 if (n > 0) { 181 up->bytes_written += n; 182 } 183 } 184 va_end(ap); 185 186 return n; 187} 188 189 190void uclose(UFILE *up) 191{ 192 if (up->flags & UIO_FILE) { 193 fclose(up->io.fp); 194 } else if (up->flags & UIO_DYNAMIC) { 195 free(up->io.str.buffer); 196 } 197 uio_delete(up); 198} 199 200 201int utell(UFILE *up) 202{ 203 return up->bytes_written; 204} 205 206 207char *ubuffer(UFILE *up) 208{ 209 char *buf = NULL; 210 211 if (up->flags & UIO_STRING) { 212 buf = up->io.str.buffer; 213 } else { 214 UPNP_ERROR(("Called %s on UFILE that does not use buffers.\n", __FUNCTION__)); 215 } 216 return buf; 217} 218 219 220int ufileno(UFILE *up) 221{ 222 int fd = 0; 223 224 if (up->flags & UIO_FILE) { 225 fd = fileno(up->io.fp); 226 } else { 227 UPNP_ERROR(("Called %s on UFILE that does not use file descriptors.\n", __FUNCTION__)); 228 } 229 return fd; 230} 231 232 233void uflush(UFILE *up) 234{ 235 if (up->flags & UIO_FILE) { 236 fflush(up->io.fp); 237 } else if (up->flags & UIO_STRING) { 238 up->bytes_written = 0; 239 } 240} 241