[b06e68ef] | 1 | /* |
---|
[09b1f1a] | 2 | * Provide UNIX/POSIX-like io system calls for RTEMS using the |
---|
[b06e68ef] | 3 | * RTEMS IO manager |
---|
| 4 | * |
---|
| 5 | * $Id$ |
---|
| 6 | */ |
---|
| 7 | |
---|
| 8 | #include <rtems.h> |
---|
| 9 | #include <rtems/assoc.h> /* assoc.h not included by rtems.h */ |
---|
| 10 | |
---|
[5e9b32b] | 11 | #include <stdio.h> /* O_RDONLY, et.al. */ |
---|
[b06e68ef] | 12 | #include <fcntl.h> /* O_RDONLY, et.al. */ |
---|
[331d9e3b] | 13 | #include <assert.h> |
---|
[c64e4ed4] | 14 | |
---|
[09b1f1a] | 15 | #if ! defined(O_NDELAY) |
---|
| 16 | # if defined(solaris2) |
---|
| 17 | # define O_NDELAY O_NONBLOCK |
---|
| 18 | # elif defined(RTEMS_NEWLIB) |
---|
| 19 | # define O_NDELAY _FNBIO |
---|
| 20 | # endif |
---|
[b06e68ef] | 21 | #endif |
---|
[c64e4ed4] | 22 | |
---|
[09b1f1a] | 23 | |
---|
[b06e68ef] | 24 | #include <errno.h> |
---|
| 25 | #include <string.h> /* strcmp */ |
---|
| 26 | #include <unistd.h> |
---|
| 27 | #include <stdlib.h> /* calloc() */ |
---|
| 28 | |
---|
| 29 | #include "libio.h" /* libio.h not pulled in by rtems */ |
---|
| 30 | |
---|
| 31 | /* |
---|
| 32 | * Semaphore to protect the io table |
---|
| 33 | */ |
---|
| 34 | |
---|
| 35 | Objects_Id rtems_libio_semaphore; |
---|
| 36 | |
---|
| 37 | #define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O') |
---|
| 38 | #define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n) |
---|
| 39 | |
---|
| 40 | unsigned32 rtems_libio_number_iops; |
---|
| 41 | rtems_libio_t *rtems_libio_iops; |
---|
| 42 | rtems_libio_t *rtems_libio_last_iop; |
---|
| 43 | |
---|
| 44 | #define rtems_libio_iop(fd) ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \ |
---|
| 45 | &rtems_libio_iops[fd] : 0) |
---|
| 46 | |
---|
| 47 | #define rtems_libio_check_fd(fd) \ |
---|
| 48 | do { \ |
---|
[dcec5a4] | 49 | if ((unsigned32) (fd) >= rtems_libio_number_iops) \ |
---|
[b06e68ef] | 50 | { \ |
---|
| 51 | errno = EBADF; \ |
---|
| 52 | return -1; \ |
---|
| 53 | } \ |
---|
| 54 | } while (0) |
---|
| 55 | |
---|
| 56 | #define rtems_libio_check_buffer(buffer) \ |
---|
| 57 | do { \ |
---|
| 58 | if ((buffer) == 0) \ |
---|
| 59 | { \ |
---|
| 60 | errno = EINVAL; \ |
---|
| 61 | return -1; \ |
---|
| 62 | } \ |
---|
| 63 | } while (0) |
---|
| 64 | |
---|
| 65 | #define rtems_libio_check_count(count) \ |
---|
| 66 | do { \ |
---|
| 67 | if ((count) == 0) \ |
---|
| 68 | { \ |
---|
| 69 | return 0; \ |
---|
| 70 | } \ |
---|
| 71 | } while (0) |
---|
| 72 | |
---|
| 73 | #define rtems_libio_check_permissions(iop, flag) \ |
---|
| 74 | do { \ |
---|
| 75 | if (((iop)->flags & (flag)) == 0) \ |
---|
| 76 | { \ |
---|
| 77 | errno = EINVAL; \ |
---|
| 78 | return -1; \ |
---|
| 79 | } \ |
---|
| 80 | } while (0) |
---|
| 81 | |
---|
[e2d79559] | 82 | /* |
---|
| 83 | * External I/O handlers |
---|
| 84 | * |
---|
| 85 | * Space for all possible handlers is preallocated |
---|
| 86 | * to speed up dispatch to external handlers. |
---|
| 87 | */ |
---|
| 88 | |
---|
| 89 | static rtems_libio_handler_t handlers[15]; |
---|
| 90 | |
---|
| 91 | void |
---|
| 92 | rtems_register_libio_handler( |
---|
| 93 | int handler_flag, |
---|
| 94 | const rtems_libio_handler_t *handler |
---|
| 95 | ) |
---|
| 96 | { |
---|
| 97 | int handler_index = rtems_file_descriptor_type_index(handler_flag); |
---|
| 98 | |
---|
| 99 | if ((handler_index < 0) || (handler_index >= 15)) |
---|
| 100 | rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER ); |
---|
| 101 | handlers[handler_index] = *handler; |
---|
| 102 | } |
---|
| 103 | |
---|
[b06e68ef] | 104 | |
---|
| 105 | void |
---|
| 106 | rtems_libio_config( |
---|
| 107 | rtems_configuration_table *config, |
---|
| 108 | unsigned32 max_fds |
---|
[e2d79559] | 109 | ) |
---|
[b06e68ef] | 110 | { |
---|
| 111 | rtems_libio_number_iops = max_fds; |
---|
| 112 | |
---|
| 113 | /* |
---|
| 114 | * tweak config to reflect # of semaphores we will need |
---|
| 115 | */ |
---|
| 116 | |
---|
[e6d4b1d] | 117 | /* one for iop table */ |
---|
| 118 | config->RTEMS_api_configuration->maximum_semaphores += 1; |
---|
| 119 | config->RTEMS_api_configuration->maximum_semaphores += max_fds; |
---|
[b06e68ef] | 120 | } |
---|
| 121 | |
---|
| 122 | /* |
---|
| 123 | * Called by bsp startup code to init the libio area. |
---|
| 124 | */ |
---|
| 125 | |
---|
| 126 | void |
---|
| 127 | rtems_libio_init(void) |
---|
| 128 | { |
---|
| 129 | rtems_status_code rc; |
---|
| 130 | |
---|
| 131 | if (rtems_libio_number_iops > 0) |
---|
| 132 | { |
---|
| 133 | rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops, |
---|
| 134 | sizeof(rtems_libio_t)); |
---|
| 135 | if (rtems_libio_iops == NULL) |
---|
| 136 | rtems_fatal_error_occurred(RTEMS_NO_MEMORY); |
---|
| 137 | |
---|
| 138 | rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1); |
---|
| 139 | } |
---|
| 140 | |
---|
[7f6a24ab] | 141 | rc = rtems_semaphore_create( |
---|
| 142 | RTEMS_LIBIO_SEM, |
---|
| 143 | 1, |
---|
| 144 | RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, |
---|
| 145 | RTEMS_NO_PRIORITY, |
---|
| 146 | &rtems_libio_semaphore |
---|
| 147 | ); |
---|
[b06e68ef] | 148 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 149 | rtems_fatal_error_occurred(rc); |
---|
| 150 | } |
---|
| 151 | |
---|
| 152 | /* |
---|
| 153 | * Convert RTEMS status to a UNIX errno |
---|
| 154 | */ |
---|
| 155 | |
---|
| 156 | rtems_assoc_t errno_assoc[] = { |
---|
| 157 | { "OK", RTEMS_SUCCESSFUL, 0 }, |
---|
| 158 | { "TIMEOUT", RTEMS_TIMEOUT, ETIME }, |
---|
| 159 | { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM }, |
---|
[9e406d9] | 160 | { "NO DEVICE", RTEMS_UNSATISFIED, ENOSYS }, |
---|
[b06e68ef] | 161 | { 0, 0, 0 }, |
---|
| 162 | }; |
---|
| 163 | |
---|
| 164 | static unsigned32 |
---|
| 165 | rtems_libio_errno(rtems_status_code code) |
---|
| 166 | { |
---|
| 167 | int rc; |
---|
| 168 | |
---|
| 169 | if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code))) |
---|
| 170 | { |
---|
| 171 | errno = rc; |
---|
| 172 | return -1; |
---|
| 173 | } |
---|
| 174 | return 0; |
---|
| 175 | } |
---|
| 176 | |
---|
| 177 | /* |
---|
| 178 | * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand |
---|
| 179 | */ |
---|
| 180 | |
---|
| 181 | rtems_assoc_t access_modes_assoc[] = { |
---|
| 182 | { "READ", LIBIO_FLAGS_READ, O_RDONLY }, |
---|
| 183 | { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY }, |
---|
| 184 | { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR }, |
---|
| 185 | { 0, 0, 0 }, |
---|
| 186 | }; |
---|
| 187 | |
---|
| 188 | rtems_assoc_t status_flags_assoc[] = { |
---|
| 189 | { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY }, |
---|
| 190 | { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND }, |
---|
| 191 | { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT }, |
---|
| 192 | { 0, 0, 0 }, |
---|
| 193 | }; |
---|
| 194 | |
---|
| 195 | static unsigned32 |
---|
| 196 | rtems_libio_fcntl_flags(unsigned32 fcntl_flags) |
---|
| 197 | { |
---|
| 198 | unsigned32 flags = 0; |
---|
| 199 | unsigned32 access_modes; |
---|
| 200 | |
---|
| 201 | /* |
---|
| 202 | * Access mode is a small integer |
---|
| 203 | */ |
---|
| 204 | |
---|
| 205 | access_modes = fcntl_flags & O_ACCMODE; |
---|
| 206 | fcntl_flags &= ~O_ACCMODE; |
---|
| 207 | flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes); |
---|
| 208 | |
---|
| 209 | /* |
---|
| 210 | * Everything else is single bits |
---|
| 211 | */ |
---|
| 212 | |
---|
| 213 | flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags); |
---|
| 214 | return flags; |
---|
| 215 | } |
---|
| 216 | |
---|
| 217 | |
---|
| 218 | static rtems_libio_t * |
---|
| 219 | rtems_libio_allocate(void) |
---|
| 220 | { |
---|
| 221 | rtems_libio_t *iop; |
---|
| 222 | rtems_status_code rc; |
---|
| 223 | |
---|
| 224 | rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
| 225 | |
---|
| 226 | for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++) |
---|
| 227 | if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) |
---|
| 228 | { |
---|
| 229 | /* |
---|
| 230 | * Got one; create a semaphore for it |
---|
| 231 | */ |
---|
| 232 | |
---|
[7f6a24ab] | 233 | rc = rtems_semaphore_create( |
---|
| 234 | RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops), |
---|
[c64e4ed4] | 235 | 1, |
---|
[7f6a24ab] | 236 | RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, |
---|
| 237 | RTEMS_NO_PRIORITY, |
---|
| 238 | &iop->sem |
---|
| 239 | ); |
---|
[b06e68ef] | 240 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 241 | goto failed; |
---|
| 242 | |
---|
| 243 | iop->flags = LIBIO_FLAGS_OPEN; |
---|
| 244 | goto done; |
---|
| 245 | } |
---|
| 246 | |
---|
| 247 | failed: |
---|
| 248 | iop = 0; |
---|
| 249 | |
---|
| 250 | done: |
---|
| 251 | rtems_semaphore_release(rtems_libio_semaphore); |
---|
| 252 | return iop; |
---|
| 253 | } |
---|
| 254 | |
---|
| 255 | static void |
---|
| 256 | rtems_libio_free(rtems_libio_t *iop) |
---|
| 257 | { |
---|
| 258 | rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
| 259 | |
---|
| 260 | if (iop->sem) |
---|
| 261 | rtems_semaphore_delete(iop->sem); |
---|
| 262 | (void) memset(iop, 0, sizeof(*iop)); |
---|
| 263 | |
---|
| 264 | rtems_semaphore_release(rtems_libio_semaphore); |
---|
| 265 | } |
---|
| 266 | |
---|
| 267 | int |
---|
[dcec5a4] | 268 | __rtems_open( |
---|
[b06e68ef] | 269 | const char *pathname, |
---|
| 270 | unsigned32 flag, |
---|
| 271 | unsigned32 mode) |
---|
| 272 | { |
---|
| 273 | rtems_status_code rc; |
---|
| 274 | rtems_libio_t *iop = 0; |
---|
| 275 | rtems_driver_name_t *np; |
---|
| 276 | rtems_libio_open_close_args_t args; |
---|
| 277 | |
---|
[e2d79559] | 278 | /* |
---|
| 279 | * Additional external I/O handlers would be supported by |
---|
| 280 | * adding code to pick apart the pathname appropriately. |
---|
| 281 | * The networking code does not require changes here since |
---|
| 282 | * network file descriptors are obtained using socket(), not |
---|
| 283 | * open(). |
---|
| 284 | */ |
---|
| 285 | |
---|
| 286 | if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL) |
---|
[b06e68ef] | 287 | goto done; |
---|
| 288 | |
---|
| 289 | iop = rtems_libio_allocate(); |
---|
| 290 | if (iop == 0) |
---|
| 291 | { |
---|
| 292 | rc = RTEMS_TOO_MANY; |
---|
| 293 | goto done; |
---|
| 294 | } |
---|
| 295 | |
---|
| 296 | iop->driver = np; |
---|
| 297 | iop->pathname = (char *) pathname; |
---|
| 298 | iop->flags |= rtems_libio_fcntl_flags(flag); |
---|
| 299 | |
---|
| 300 | args.iop = iop; |
---|
| 301 | args.flags = iop->flags; |
---|
| 302 | args.mode = mode; |
---|
| 303 | |
---|
| 304 | rc = rtems_io_open(np->major, np->minor, (void *) &args); |
---|
| 305 | |
---|
| 306 | done: |
---|
[331d9e3b] | 307 | |
---|
[b06e68ef] | 308 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 309 | { |
---|
| 310 | if (iop) |
---|
| 311 | rtems_libio_free(iop); |
---|
| 312 | return rtems_libio_errno(rc); |
---|
| 313 | } |
---|
| 314 | |
---|
| 315 | return iop - rtems_libio_iops; |
---|
| 316 | } |
---|
| 317 | |
---|
| 318 | int |
---|
[dcec5a4] | 319 | __rtems_close( |
---|
[b06e68ef] | 320 | int fd |
---|
| 321 | ) |
---|
| 322 | { |
---|
| 323 | rtems_status_code rc; |
---|
| 324 | rtems_driver_name_t *np; |
---|
[e2d79559] | 325 | rtems_libio_t *iop; |
---|
[b06e68ef] | 326 | rtems_libio_open_close_args_t args; |
---|
| 327 | |
---|
[e2d79559] | 328 | if (rtems_file_descriptor_type(fd)) { |
---|
| 329 | int (*fp)(int fd); |
---|
| 330 | |
---|
| 331 | fp = handlers[rtems_file_descriptor_type_index(fd)].close; |
---|
| 332 | if (fp == NULL) { |
---|
| 333 | errno = EBADF; |
---|
| 334 | return -1; |
---|
| 335 | } |
---|
| 336 | return (*fp)(fd); |
---|
| 337 | } |
---|
| 338 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 339 | rtems_libio_check_fd(fd); |
---|
| 340 | |
---|
| 341 | np = iop->driver; |
---|
| 342 | |
---|
| 343 | args.iop = iop; |
---|
| 344 | args.flags = 0; |
---|
| 345 | args.mode = 0; |
---|
| 346 | |
---|
| 347 | rc = rtems_io_close(np->major, np->minor, (void *) &args); |
---|
| 348 | |
---|
| 349 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 350 | return rtems_libio_errno(rc); |
---|
| 351 | return 0; |
---|
| 352 | } |
---|
| 353 | |
---|
| 354 | int |
---|
[dcec5a4] | 355 | __rtems_read( |
---|
[b06e68ef] | 356 | int fd, |
---|
| 357 | void * buffer, |
---|
| 358 | unsigned32 count |
---|
| 359 | ) |
---|
| 360 | { |
---|
| 361 | rtems_status_code rc; |
---|
| 362 | rtems_driver_name_t *np; |
---|
[e2d79559] | 363 | rtems_libio_t *iop; |
---|
[b06e68ef] | 364 | rtems_libio_rw_args_t args; |
---|
| 365 | |
---|
[e2d79559] | 366 | if (rtems_file_descriptor_type(fd)) { |
---|
| 367 | int (*fp)(int fd, void *buffer, unsigned32 count); |
---|
| 368 | |
---|
| 369 | fp = handlers[rtems_file_descriptor_type_index(fd)].read; |
---|
| 370 | if (fp == NULL) { |
---|
| 371 | errno = EBADF; |
---|
| 372 | return -1; |
---|
| 373 | } |
---|
| 374 | return (*fp)(fd, buffer, count); |
---|
| 375 | } |
---|
| 376 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 377 | rtems_libio_check_fd(fd); |
---|
| 378 | rtems_libio_check_buffer(buffer); |
---|
| 379 | rtems_libio_check_count(count); |
---|
| 380 | rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ); |
---|
| 381 | |
---|
| 382 | np = iop->driver; |
---|
| 383 | |
---|
| 384 | args.iop = iop; |
---|
| 385 | args.offset = iop->offset; |
---|
| 386 | args.buffer = buffer; |
---|
| 387 | args.count = count; |
---|
| 388 | args.flags = iop->flags; |
---|
| 389 | args.bytes_moved = 0; |
---|
| 390 | |
---|
| 391 | rc = rtems_io_read(np->major, np->minor, (void *) &args); |
---|
| 392 | |
---|
| 393 | iop->offset += args.bytes_moved; |
---|
| 394 | |
---|
| 395 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 396 | return rtems_libio_errno(rc); |
---|
| 397 | |
---|
| 398 | return args.bytes_moved; |
---|
| 399 | } |
---|
| 400 | |
---|
| 401 | int |
---|
[dcec5a4] | 402 | __rtems_write( |
---|
[b06e68ef] | 403 | int fd, |
---|
| 404 | const void *buffer, |
---|
| 405 | unsigned32 count |
---|
| 406 | ) |
---|
| 407 | { |
---|
| 408 | rtems_status_code rc; |
---|
| 409 | rtems_driver_name_t *np; |
---|
[e2d79559] | 410 | rtems_libio_t *iop; |
---|
[b06e68ef] | 411 | rtems_libio_rw_args_t args; |
---|
| 412 | |
---|
[e2d79559] | 413 | if (rtems_file_descriptor_type(fd)) { |
---|
| 414 | int (*fp)(int fd, const void *buffer, unsigned32 count); |
---|
| 415 | |
---|
| 416 | fp = handlers[rtems_file_descriptor_type_index(fd)].write; |
---|
| 417 | if (fp == NULL) { |
---|
| 418 | errno = EBADF; |
---|
| 419 | return -1; |
---|
| 420 | } |
---|
| 421 | return (*fp)(fd, buffer, count); |
---|
| 422 | } |
---|
| 423 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 424 | rtems_libio_check_fd(fd); |
---|
| 425 | rtems_libio_check_buffer(buffer); |
---|
| 426 | rtems_libio_check_count(count); |
---|
| 427 | rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE); |
---|
| 428 | |
---|
| 429 | np = iop->driver; |
---|
| 430 | |
---|
| 431 | args.iop = iop; |
---|
| 432 | args.offset = iop->offset; |
---|
| 433 | args.buffer = (void *) buffer; |
---|
| 434 | args.count = count; |
---|
| 435 | args.flags = iop->flags; |
---|
| 436 | args.bytes_moved = 0; |
---|
| 437 | |
---|
| 438 | rc = rtems_io_write(np->major, np->minor, (void *) &args); |
---|
| 439 | |
---|
| 440 | iop->offset += args.bytes_moved; |
---|
| 441 | |
---|
| 442 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 443 | return rtems_libio_errno(rc); |
---|
| 444 | |
---|
| 445 | return args.bytes_moved; |
---|
| 446 | } |
---|
| 447 | |
---|
| 448 | int |
---|
[dcec5a4] | 449 | __rtems_ioctl( |
---|
[b06e68ef] | 450 | int fd, |
---|
| 451 | unsigned32 command, |
---|
| 452 | void * buffer) |
---|
| 453 | { |
---|
| 454 | rtems_status_code rc; |
---|
| 455 | rtems_driver_name_t *np; |
---|
[e2d79559] | 456 | rtems_libio_t *iop; |
---|
[b06e68ef] | 457 | rtems_libio_ioctl_args_t args; |
---|
| 458 | |
---|
[e2d79559] | 459 | if (rtems_file_descriptor_type(fd)) { |
---|
| 460 | int (*fp)(int fd, unsigned32 command, void *buffer); |
---|
| 461 | |
---|
| 462 | fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl; |
---|
| 463 | if (fp == NULL) { |
---|
| 464 | errno = EBADF; |
---|
| 465 | return -1; |
---|
| 466 | } |
---|
| 467 | return (*fp)(fd, command, buffer); |
---|
| 468 | } |
---|
| 469 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 470 | rtems_libio_check_fd(fd); |
---|
| 471 | |
---|
| 472 | np = iop->driver; |
---|
| 473 | |
---|
| 474 | args.iop = iop; |
---|
| 475 | args.command = command; |
---|
| 476 | args.buffer = buffer; |
---|
| 477 | |
---|
| 478 | rc = rtems_io_control(np->major, np->minor, (void *) &args); |
---|
| 479 | |
---|
| 480 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 481 | return rtems_libio_errno(rc); |
---|
| 482 | |
---|
| 483 | return args.ioctl_return; |
---|
| 484 | } |
---|
| 485 | |
---|
| 486 | /* |
---|
| 487 | * internal only?? |
---|
| 488 | */ |
---|
| 489 | |
---|
| 490 | |
---|
| 491 | int |
---|
[dcec5a4] | 492 | __rtems_lseek( |
---|
[b06e68ef] | 493 | int fd, |
---|
| 494 | rtems_libio_offset_t offset, |
---|
| 495 | int whence |
---|
| 496 | ) |
---|
| 497 | { |
---|
[e2d79559] | 498 | rtems_libio_t *iop; |
---|
| 499 | |
---|
| 500 | if (rtems_file_descriptor_type(fd)) { |
---|
| 501 | int (*fp)(int fd, rtems_libio_offset_t offset, int whence); |
---|
[b06e68ef] | 502 | |
---|
[e2d79559] | 503 | fp = handlers[rtems_file_descriptor_type_index(fd)].lseek; |
---|
| 504 | if (fp == NULL) { |
---|
| 505 | errno = EBADF; |
---|
| 506 | return -1; |
---|
| 507 | } |
---|
| 508 | return (*fp)(fd, offset, whence); |
---|
| 509 | } |
---|
| 510 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 511 | rtems_libio_check_fd(fd); |
---|
| 512 | |
---|
| 513 | switch (whence) |
---|
| 514 | { |
---|
| 515 | case SEEK_SET: |
---|
| 516 | iop->offset = offset; |
---|
| 517 | break; |
---|
| 518 | |
---|
| 519 | case SEEK_CUR: |
---|
| 520 | iop->offset += offset; |
---|
| 521 | break; |
---|
| 522 | |
---|
| 523 | case SEEK_END: |
---|
| 524 | iop->offset = iop->size - offset; |
---|
| 525 | break; |
---|
| 526 | |
---|
| 527 | default: |
---|
| 528 | errno = EINVAL; |
---|
| 529 | return -1; |
---|
| 530 | } |
---|
| 531 | return 0; |
---|
| 532 | } |
---|