[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[] = { |
---|
[3473f605] | 157 | { "OK", RTEMS_SUCCESSFUL, 0 }, |
---|
[9646d5be] | 158 | { "BUSY", RTEMS_RESOURCE_IN_USE, EBUSY }, |
---|
| 159 | { "INVALID NAME", RTEMS_INVALID_NAME, EINVAL }, |
---|
| 160 | { "NOT IMPLEMENTED", RTEMS_NOT_IMPLEMENTED, ENOSYS }, |
---|
| 161 | { "TIMEOUT", RTEMS_TIMEOUT, ETIMEDOUT }, |
---|
[3473f605] | 162 | { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM }, |
---|
[9646d5be] | 163 | { "NO DEVICE", RTEMS_UNSATISFIED, ENODEV }, |
---|
[3473f605] | 164 | { "INVALID NUMBER", RTEMS_INVALID_NUMBER, EBADF}, |
---|
| 165 | { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE, EPERM}, |
---|
[7d352a49] | 166 | { "IO ERROR", RTEMS_IO_ERROR, EIO}, |
---|
[b06e68ef] | 167 | { 0, 0, 0 }, |
---|
| 168 | }; |
---|
| 169 | |
---|
| 170 | static unsigned32 |
---|
| 171 | rtems_libio_errno(rtems_status_code code) |
---|
| 172 | { |
---|
| 173 | int rc; |
---|
| 174 | |
---|
| 175 | if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code))) |
---|
| 176 | { |
---|
| 177 | errno = rc; |
---|
| 178 | return -1; |
---|
| 179 | } |
---|
[3473f605] | 180 | return -1; |
---|
[b06e68ef] | 181 | } |
---|
| 182 | |
---|
| 183 | /* |
---|
| 184 | * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand |
---|
| 185 | */ |
---|
| 186 | |
---|
| 187 | rtems_assoc_t access_modes_assoc[] = { |
---|
[3473f605] | 188 | { "READ", LIBIO_FLAGS_READ, O_RDONLY }, |
---|
| 189 | { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY }, |
---|
[b06e68ef] | 190 | { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR }, |
---|
| 191 | { 0, 0, 0 }, |
---|
| 192 | }; |
---|
| 193 | |
---|
| 194 | rtems_assoc_t status_flags_assoc[] = { |
---|
| 195 | { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY }, |
---|
| 196 | { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND }, |
---|
| 197 | { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT }, |
---|
| 198 | { 0, 0, 0 }, |
---|
| 199 | }; |
---|
| 200 | |
---|
| 201 | static unsigned32 |
---|
| 202 | rtems_libio_fcntl_flags(unsigned32 fcntl_flags) |
---|
| 203 | { |
---|
| 204 | unsigned32 flags = 0; |
---|
| 205 | unsigned32 access_modes; |
---|
| 206 | |
---|
| 207 | /* |
---|
| 208 | * Access mode is a small integer |
---|
| 209 | */ |
---|
| 210 | |
---|
| 211 | access_modes = fcntl_flags & O_ACCMODE; |
---|
| 212 | fcntl_flags &= ~O_ACCMODE; |
---|
| 213 | flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes); |
---|
| 214 | |
---|
| 215 | /* |
---|
| 216 | * Everything else is single bits |
---|
| 217 | */ |
---|
| 218 | |
---|
| 219 | flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags); |
---|
| 220 | return flags; |
---|
| 221 | } |
---|
| 222 | |
---|
| 223 | |
---|
| 224 | static rtems_libio_t * |
---|
| 225 | rtems_libio_allocate(void) |
---|
| 226 | { |
---|
| 227 | rtems_libio_t *iop; |
---|
| 228 | rtems_status_code rc; |
---|
| 229 | |
---|
| 230 | rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
| 231 | |
---|
| 232 | for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++) |
---|
| 233 | if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) |
---|
| 234 | { |
---|
| 235 | /* |
---|
| 236 | * Got one; create a semaphore for it |
---|
| 237 | */ |
---|
| 238 | |
---|
[7f6a24ab] | 239 | rc = rtems_semaphore_create( |
---|
| 240 | RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops), |
---|
[c64e4ed4] | 241 | 1, |
---|
[7f6a24ab] | 242 | RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, |
---|
| 243 | RTEMS_NO_PRIORITY, |
---|
| 244 | &iop->sem |
---|
| 245 | ); |
---|
[b06e68ef] | 246 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 247 | goto failed; |
---|
| 248 | |
---|
| 249 | iop->flags = LIBIO_FLAGS_OPEN; |
---|
| 250 | goto done; |
---|
| 251 | } |
---|
| 252 | |
---|
| 253 | failed: |
---|
| 254 | iop = 0; |
---|
| 255 | |
---|
| 256 | done: |
---|
| 257 | rtems_semaphore_release(rtems_libio_semaphore); |
---|
| 258 | return iop; |
---|
| 259 | } |
---|
| 260 | |
---|
| 261 | static void |
---|
| 262 | rtems_libio_free(rtems_libio_t *iop) |
---|
| 263 | { |
---|
| 264 | rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
| 265 | |
---|
| 266 | if (iop->sem) |
---|
| 267 | rtems_semaphore_delete(iop->sem); |
---|
| 268 | (void) memset(iop, 0, sizeof(*iop)); |
---|
| 269 | |
---|
| 270 | rtems_semaphore_release(rtems_libio_semaphore); |
---|
| 271 | } |
---|
| 272 | |
---|
| 273 | int |
---|
[dcec5a4] | 274 | __rtems_open( |
---|
[b06e68ef] | 275 | const char *pathname, |
---|
| 276 | unsigned32 flag, |
---|
| 277 | unsigned32 mode) |
---|
| 278 | { |
---|
| 279 | rtems_status_code rc; |
---|
| 280 | rtems_libio_t *iop = 0; |
---|
| 281 | rtems_driver_name_t *np; |
---|
| 282 | rtems_libio_open_close_args_t args; |
---|
| 283 | |
---|
[e2d79559] | 284 | /* |
---|
| 285 | * Additional external I/O handlers would be supported by |
---|
| 286 | * adding code to pick apart the pathname appropriately. |
---|
| 287 | * The networking code does not require changes here since |
---|
| 288 | * network file descriptors are obtained using socket(), not |
---|
| 289 | * open(). |
---|
| 290 | */ |
---|
| 291 | |
---|
| 292 | if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL) |
---|
[b06e68ef] | 293 | goto done; |
---|
| 294 | |
---|
| 295 | iop = rtems_libio_allocate(); |
---|
| 296 | if (iop == 0) |
---|
| 297 | { |
---|
| 298 | rc = RTEMS_TOO_MANY; |
---|
| 299 | goto done; |
---|
| 300 | } |
---|
| 301 | |
---|
| 302 | iop->driver = np; |
---|
| 303 | iop->pathname = (char *) pathname; |
---|
| 304 | iop->flags |= rtems_libio_fcntl_flags(flag); |
---|
| 305 | |
---|
| 306 | args.iop = iop; |
---|
| 307 | args.flags = iop->flags; |
---|
| 308 | args.mode = mode; |
---|
| 309 | |
---|
| 310 | rc = rtems_io_open(np->major, np->minor, (void *) &args); |
---|
| 311 | |
---|
| 312 | done: |
---|
[331d9e3b] | 313 | |
---|
[b06e68ef] | 314 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 315 | { |
---|
| 316 | if (iop) |
---|
| 317 | rtems_libio_free(iop); |
---|
| 318 | return rtems_libio_errno(rc); |
---|
| 319 | } |
---|
| 320 | |
---|
| 321 | return iop - rtems_libio_iops; |
---|
| 322 | } |
---|
| 323 | |
---|
| 324 | int |
---|
[dcec5a4] | 325 | __rtems_close( |
---|
[b06e68ef] | 326 | int fd |
---|
| 327 | ) |
---|
| 328 | { |
---|
| 329 | rtems_status_code rc; |
---|
| 330 | rtems_driver_name_t *np; |
---|
[e2d79559] | 331 | rtems_libio_t *iop; |
---|
[b06e68ef] | 332 | rtems_libio_open_close_args_t args; |
---|
[78d87bd] | 333 | int status; |
---|
[b06e68ef] | 334 | |
---|
[e2d79559] | 335 | if (rtems_file_descriptor_type(fd)) { |
---|
| 336 | int (*fp)(int fd); |
---|
| 337 | |
---|
| 338 | fp = handlers[rtems_file_descriptor_type_index(fd)].close; |
---|
| 339 | if (fp == NULL) { |
---|
| 340 | errno = EBADF; |
---|
| 341 | return -1; |
---|
| 342 | } |
---|
[78d87bd] | 343 | status = (*fp)(fd); |
---|
| 344 | return status; |
---|
[e2d79559] | 345 | } |
---|
| 346 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 347 | rtems_libio_check_fd(fd); |
---|
| 348 | |
---|
| 349 | np = iop->driver; |
---|
| 350 | |
---|
| 351 | args.iop = iop; |
---|
| 352 | args.flags = 0; |
---|
| 353 | args.mode = 0; |
---|
| 354 | |
---|
| 355 | rc = rtems_io_close(np->major, np->minor, (void *) &args); |
---|
| 356 | |
---|
[78d87bd] | 357 | rtems_libio_free(iop); |
---|
| 358 | |
---|
[b06e68ef] | 359 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 360 | return rtems_libio_errno(rc); |
---|
| 361 | return 0; |
---|
| 362 | } |
---|
| 363 | |
---|
| 364 | int |
---|
[dcec5a4] | 365 | __rtems_read( |
---|
[b06e68ef] | 366 | int fd, |
---|
| 367 | void * buffer, |
---|
| 368 | unsigned32 count |
---|
| 369 | ) |
---|
| 370 | { |
---|
| 371 | rtems_status_code rc; |
---|
| 372 | rtems_driver_name_t *np; |
---|
[e2d79559] | 373 | rtems_libio_t *iop; |
---|
[b06e68ef] | 374 | rtems_libio_rw_args_t args; |
---|
| 375 | |
---|
[e2d79559] | 376 | if (rtems_file_descriptor_type(fd)) { |
---|
| 377 | int (*fp)(int fd, void *buffer, unsigned32 count); |
---|
| 378 | |
---|
| 379 | fp = handlers[rtems_file_descriptor_type_index(fd)].read; |
---|
| 380 | if (fp == NULL) { |
---|
| 381 | errno = EBADF; |
---|
| 382 | return -1; |
---|
| 383 | } |
---|
| 384 | return (*fp)(fd, buffer, count); |
---|
| 385 | } |
---|
| 386 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 387 | rtems_libio_check_fd(fd); |
---|
| 388 | rtems_libio_check_buffer(buffer); |
---|
| 389 | rtems_libio_check_count(count); |
---|
| 390 | rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ); |
---|
| 391 | |
---|
| 392 | np = iop->driver; |
---|
| 393 | |
---|
| 394 | args.iop = iop; |
---|
| 395 | args.offset = iop->offset; |
---|
| 396 | args.buffer = buffer; |
---|
| 397 | args.count = count; |
---|
| 398 | args.flags = iop->flags; |
---|
| 399 | args.bytes_moved = 0; |
---|
| 400 | |
---|
| 401 | rc = rtems_io_read(np->major, np->minor, (void *) &args); |
---|
| 402 | |
---|
| 403 | iop->offset += args.bytes_moved; |
---|
| 404 | |
---|
| 405 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 406 | return rtems_libio_errno(rc); |
---|
| 407 | |
---|
| 408 | return args.bytes_moved; |
---|
| 409 | } |
---|
| 410 | |
---|
| 411 | int |
---|
[dcec5a4] | 412 | __rtems_write( |
---|
[b06e68ef] | 413 | int fd, |
---|
| 414 | const void *buffer, |
---|
| 415 | unsigned32 count |
---|
| 416 | ) |
---|
| 417 | { |
---|
| 418 | rtems_status_code rc; |
---|
| 419 | rtems_driver_name_t *np; |
---|
[e2d79559] | 420 | rtems_libio_t *iop; |
---|
[b06e68ef] | 421 | rtems_libio_rw_args_t args; |
---|
| 422 | |
---|
[e2d79559] | 423 | if (rtems_file_descriptor_type(fd)) { |
---|
| 424 | int (*fp)(int fd, const void *buffer, unsigned32 count); |
---|
| 425 | |
---|
| 426 | fp = handlers[rtems_file_descriptor_type_index(fd)].write; |
---|
| 427 | if (fp == NULL) { |
---|
| 428 | errno = EBADF; |
---|
| 429 | return -1; |
---|
| 430 | } |
---|
| 431 | return (*fp)(fd, buffer, count); |
---|
| 432 | } |
---|
| 433 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 434 | rtems_libio_check_fd(fd); |
---|
| 435 | rtems_libio_check_buffer(buffer); |
---|
| 436 | rtems_libio_check_count(count); |
---|
| 437 | rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE); |
---|
| 438 | |
---|
| 439 | np = iop->driver; |
---|
| 440 | |
---|
| 441 | args.iop = iop; |
---|
| 442 | args.offset = iop->offset; |
---|
| 443 | args.buffer = (void *) buffer; |
---|
| 444 | args.count = count; |
---|
| 445 | args.flags = iop->flags; |
---|
| 446 | args.bytes_moved = 0; |
---|
| 447 | |
---|
| 448 | rc = rtems_io_write(np->major, np->minor, (void *) &args); |
---|
| 449 | |
---|
| 450 | iop->offset += args.bytes_moved; |
---|
| 451 | |
---|
| 452 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 453 | return rtems_libio_errno(rc); |
---|
| 454 | |
---|
| 455 | return args.bytes_moved; |
---|
| 456 | } |
---|
| 457 | |
---|
| 458 | int |
---|
[dcec5a4] | 459 | __rtems_ioctl( |
---|
[b06e68ef] | 460 | int fd, |
---|
| 461 | unsigned32 command, |
---|
| 462 | void * buffer) |
---|
| 463 | { |
---|
| 464 | rtems_status_code rc; |
---|
| 465 | rtems_driver_name_t *np; |
---|
[e2d79559] | 466 | rtems_libio_t *iop; |
---|
[b06e68ef] | 467 | rtems_libio_ioctl_args_t args; |
---|
| 468 | |
---|
[e2d79559] | 469 | if (rtems_file_descriptor_type(fd)) { |
---|
| 470 | int (*fp)(int fd, unsigned32 command, void *buffer); |
---|
| 471 | |
---|
| 472 | fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl; |
---|
| 473 | if (fp == NULL) { |
---|
| 474 | errno = EBADF; |
---|
| 475 | return -1; |
---|
| 476 | } |
---|
| 477 | return (*fp)(fd, command, buffer); |
---|
| 478 | } |
---|
| 479 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 480 | rtems_libio_check_fd(fd); |
---|
| 481 | |
---|
| 482 | np = iop->driver; |
---|
| 483 | |
---|
| 484 | args.iop = iop; |
---|
| 485 | args.command = command; |
---|
| 486 | args.buffer = buffer; |
---|
| 487 | |
---|
| 488 | rc = rtems_io_control(np->major, np->minor, (void *) &args); |
---|
| 489 | |
---|
| 490 | if (rc != RTEMS_SUCCESSFUL) |
---|
| 491 | return rtems_libio_errno(rc); |
---|
| 492 | |
---|
| 493 | return args.ioctl_return; |
---|
| 494 | } |
---|
| 495 | |
---|
| 496 | /* |
---|
| 497 | * internal only?? |
---|
| 498 | */ |
---|
| 499 | |
---|
| 500 | |
---|
| 501 | int |
---|
[dcec5a4] | 502 | __rtems_lseek( |
---|
[b06e68ef] | 503 | int fd, |
---|
| 504 | rtems_libio_offset_t offset, |
---|
| 505 | int whence |
---|
| 506 | ) |
---|
| 507 | { |
---|
[e2d79559] | 508 | rtems_libio_t *iop; |
---|
| 509 | |
---|
| 510 | if (rtems_file_descriptor_type(fd)) { |
---|
| 511 | int (*fp)(int fd, rtems_libio_offset_t offset, int whence); |
---|
[b06e68ef] | 512 | |
---|
[e2d79559] | 513 | fp = handlers[rtems_file_descriptor_type_index(fd)].lseek; |
---|
| 514 | if (fp == NULL) { |
---|
| 515 | errno = EBADF; |
---|
| 516 | return -1; |
---|
| 517 | } |
---|
| 518 | return (*fp)(fd, offset, whence); |
---|
| 519 | } |
---|
| 520 | iop = rtems_libio_iop(fd); |
---|
[b06e68ef] | 521 | rtems_libio_check_fd(fd); |
---|
| 522 | |
---|
| 523 | switch (whence) |
---|
| 524 | { |
---|
| 525 | case SEEK_SET: |
---|
| 526 | iop->offset = offset; |
---|
| 527 | break; |
---|
| 528 | |
---|
| 529 | case SEEK_CUR: |
---|
| 530 | iop->offset += offset; |
---|
| 531 | break; |
---|
| 532 | |
---|
| 533 | case SEEK_END: |
---|
| 534 | iop->offset = iop->size - offset; |
---|
| 535 | break; |
---|
| 536 | |
---|
| 537 | default: |
---|
| 538 | errno = EINVAL; |
---|
| 539 | return -1; |
---|
| 540 | } |
---|
| 541 | return 0; |
---|
| 542 | } |
---|