Changeset 2595dab in mainline for uspace/lib/libc/generic/io/io.c
- Timestamp:
- 2009-06-03T19:26:28Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d00ae4c
- Parents:
- ca3ba3a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libc/generic/io/io.c
rca3ba3a r2595dab 31 31 */ 32 32 /** @file 33 */ 34 35 #include < libc.h>33 */ 34 35 #include <stdio.h> 36 36 #include <unistd.h> 37 #include <stdio.h> 38 #include <io/io.h> 37 #include <fcntl.h> 39 38 #include <string.h> 40 39 #include <errno.h> 41 #include <console.h> 42 43 const static char nl = '\n'; 40 #include <bool.h> 41 #include <malloc.h> 42 #include <io/klog.h> 43 #include <vfs/vfs.h> 44 #include <ipc/devmap.h> 45 46 FILE stdin_null = { 47 .fd = -1, 48 .error = true, 49 .eof = true, 50 .klog = false, 51 .phone = -1 52 }; 53 54 FILE stdout_klog = { 55 .fd = -1, 56 .error = false, 57 .eof = false, 58 .klog = true, 59 .phone = -1 60 }; 61 62 FILE *stdin = &stdin_null; 63 FILE *stdout = &stdout_klog; 64 FILE *stderr = &stdout_klog; 65 66 static bool parse_mode(const char *mode, int *flags) 67 { 68 /* Parse mode except first character. */ 69 const char *mp = mode; 70 if (*mp++ == 0) { 71 errno = EINVAL; 72 return false; 73 } 74 75 if ((*mp == 'b') || (*mp == 't')) 76 mp++; 77 78 bool plus; 79 if (*mp == '+') { 80 mp++; 81 plus = true; 82 } else 83 plus = false; 84 85 if (*mp != 0) { 86 errno = EINVAL; 87 return false; 88 } 89 90 /* Parse first character of mode and determine flags for open(). */ 91 switch (mode[0]) { 92 case 'r': 93 *flags = plus ? O_RDWR : O_RDONLY; 94 break; 95 case 'w': 96 *flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY); 97 break; 98 case 'a': 99 /* TODO: a+ must read from beginning, append to the end. */ 100 if (plus) { 101 errno = ENOTSUP; 102 return false; 103 } 104 *flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY); 105 default: 106 errno = EINVAL; 107 return false; 108 } 109 110 return true; 111 } 112 113 /** Open a stream. 114 * 115 * @param path Path of the file to open. 116 * @param mode Mode string, (r|w|a)[b|t][+]. 117 * 118 */ 119 FILE *fopen(const char *path, const char *mode) 120 { 121 int flags; 122 if (!parse_mode(mode, &flags)) 123 return NULL; 124 125 /* Open file. */ 126 FILE *stream = malloc(sizeof(FILE)); 127 if (stream == NULL) { 128 errno = ENOMEM; 129 return NULL; 130 } 131 132 stream->fd = open(path, flags, 0666); 133 if (stream->fd < 0) { 134 /* errno was set by open() */ 135 free(stream); 136 return NULL; 137 } 138 139 stream->error = false; 140 stream->eof = false; 141 stream->klog = false; 142 stream->phone = -1; 143 144 return stream; 145 } 146 147 FILE *fopen_node(fs_node_t *node, const char *mode) 148 { 149 int flags; 150 if (!parse_mode(mode, &flags)) 151 return NULL; 152 153 /* Open file. */ 154 FILE *stream = malloc(sizeof(FILE)); 155 if (stream == NULL) { 156 errno = ENOMEM; 157 return NULL; 158 } 159 160 stream->fd = open_node(node, flags); 161 if (stream->fd < 0) { 162 /* errno was set by open_node() */ 163 free(stream); 164 return NULL; 165 } 166 167 stream->error = false; 168 stream->eof = false; 169 stream->klog = false; 170 stream->phone = -1; 171 172 return stream; 173 } 174 175 int fclose(FILE *stream) 176 { 177 int rc = 0; 178 179 fflush(stream); 180 181 if (stream->phone >= 0) 182 ipc_hangup(stream->phone); 183 184 if (stream->fd >= 0) 185 rc = close(stream->fd); 186 187 if ((stream != &stdin_null) && (stream != &stdout_klog)) 188 free(stream); 189 190 stream = NULL; 191 192 if (rc != 0) { 193 /* errno was set by close() */ 194 return EOF; 195 } 196 197 return 0; 198 } 199 200 /** Read from a stream. 201 * 202 * @param buf Destination buffer. 203 * @param size Size of each record. 204 * @param nmemb Number of records to read. 205 * @param stream Pointer to the stream. 206 * 207 */ 208 size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream) 209 { 210 size_t left = size * nmemb; 211 size_t done = 0; 212 213 while ((left > 0) && (!stream->error) && (!stream->eof)) { 214 ssize_t rd = read(stream->fd, buf + done, left); 215 216 if (rd < 0) 217 stream->error = true; 218 else if (rd == 0) 219 stream->eof = true; 220 else { 221 left -= rd; 222 done += rd; 223 } 224 } 225 226 return (done / size); 227 } 228 229 /** Write to a stream. 230 * 231 * @param buf Source buffer. 232 * @param size Size of each record. 233 * @param nmemb Number of records to write. 234 * @param stream Pointer to the stream. 235 * 236 */ 237 size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) 238 { 239 size_t left = size * nmemb; 240 size_t done = 0; 241 242 while ((left > 0) && (!stream->error)) { 243 ssize_t wr; 244 245 if (stream->klog) 246 wr = klog_write(buf + done, left); 247 else 248 wr = write(stream->fd, buf + done, left); 249 250 if (wr <= 0) 251 stream->error = true; 252 else { 253 left -= wr; 254 done += wr; 255 } 256 } 257 258 return (done / size); 259 } 260 261 int fputc(wchar_t c, FILE *stream) 262 { 263 char buf[STR_BOUNDS(1)]; 264 size_t sz = 0; 265 266 if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) { 267 size_t wr = fwrite(buf, sz, 1, stream); 268 269 if (wr < sz) 270 return EOF; 271 272 return (int) c; 273 } 274 275 return EOF; 276 } 277 278 int putchar(wchar_t c) 279 { 280 return fputc(c, stdout); 281 } 282 283 int fputs(const char *str, FILE *stream) 284 { 285 return fwrite(str, str_size(str), 1, stream); 286 } 44 287 45 288 int puts(const char *str) 46 289 { 47 size_t count; 48 49 if (str == NULL) 50 return putnchars("(NULL)", 6); 51 52 for (count = 0; str[count] != 0; count++); 53 54 if (console_write((void *) str, count) == count) { 55 if (console_write(&nl, 1) == 1) 56 return 0; 57 } 58 59 return EOF; 60 } 61 62 /** Put count chars from buffer to stdout without adding newline 63 * @param buf Buffer with size at least count bytes - NULL pointer NOT allowed! 64 * @param count 65 * @return 0 on succes, EOF on fail 66 */ 67 int putnchars(const char *buf, size_t count) 68 { 69 if (console_write((void *) buf, count) == count) 70 return 0; 71 72 return EOF; 73 } 74 75 /** Same as puts, but does not print newline at end 76 * 77 */ 78 int putstr(const char *str) 79 { 80 size_t count; 81 82 if (str == NULL) 83 return putnchars("(NULL)", 6); 84 85 for (count = 0; str[count] != 0; count++); 86 if (console_write((void *) str, count) == count) 87 return 0; 88 89 return EOF; 90 } 91 92 int putchar(int c) 93 { 94 char buf[STR_BOUNDS(1)]; 95 size_t offs; 96 97 offs = 0; 98 if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK) 290 return fputs(str, stdout); 291 } 292 293 int fgetc(FILE *stream) 294 { 295 char c; 296 297 if (fread(&c, sizeof(char), 1, stream) < sizeof(char)) 99 298 return EOF; 100 101 if (console_write((void *) buf, offs) == offs) 102 return c; 103 104 return EOF; 299 300 return (int) c; 105 301 } 106 302 107 303 int getchar(void) 108 304 { 109 unsigned char c; 110 111 console_flush(); 112 if (read_stdin((void *) &c, 1) == 1) 113 return c; 114 115 return EOF; 116 } 117 118 int fflush(FILE *f) 119 { 120 /* Dummy implementation */ 121 (void) f; 122 console_flush(); 305 return fgetc(stdin); 306 } 307 308 int fseek(FILE *stream, long offset, int origin) 309 { 310 off_t rc = lseek(stream->fd, offset, origin); 311 if (rc == (off_t) (-1)) { 312 /* errno has been set by lseek. */ 313 return -1; 314 } 315 316 stream->eof = false; 317 123 318 return 0; 124 319 } 125 320 321 int fflush(FILE *stream) 322 { 323 if (stream->klog) { 324 klog_update(); 325 return EOK; 326 } 327 328 if (stream->fd >= 0) 329 return fsync(stream->fd); 330 331 return ENOENT; 332 } 333 334 int feof(FILE *stream) 335 { 336 return stream->eof; 337 } 338 339 int ferror(FILE *stream) 340 { 341 return stream->error; 342 } 343 344 int fphone(FILE *stream) 345 { 346 if (stream->fd >= 0) { 347 if (stream->phone < 0) 348 stream->phone = fd_phone(stream->fd); 349 350 return stream->phone; 351 } 352 353 return -1; 354 } 355 356 void fnode(FILE *stream, fs_node_t *node) 357 { 358 if (stream->fd >= 0) { 359 fd_node(stream->fd, node); 360 } else { 361 node->fs_handle = 0; 362 node->dev_handle = 0; 363 node->index = 0; 364 } 365 } 366 126 367 /** @} 127 368 */
Note:
See TracChangeset
for help on using the changeset viewer.