int rtems_rfs_file_seek (rtems_rfs_file_handle* handle, rtems_rfs_pos pos, rtems_rfs_pos* new_pos) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO)) printf ("rtems-rfs: file-seek: new=%" PRIu64 "\n", pos); /* * This call only sets the position if it is in a valid part of the file. The * user can request past the end of the file then write to extend the * file. The lseek entry states: * * "Although lseek() may position the file offset beyond the end of the * file, this function does not itself extend the size of the file." * * This means the file needs to set the file size to the pos only when a * write occurs. */ if (pos < rtems_rfs_file_shared_get_size (rtems_rfs_file_fs (handle), handle->shared)) { rtems_rfs_file_set_bpos (handle, pos); /* * If the file has a block check if it maps to the current position and it * does not release it. That will force us to get the block at the new * position when the I/O starts. */ if (rtems_rfs_buffer_handle_has_block (&handle->buffer)) { rtems_rfs_buffer_block block; int rc; rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle), rtems_rfs_file_map (handle), rtems_rfs_file_bpos (handle), &block); if (rc > 0) return rc; if (rtems_rfs_buffer_bnum (&handle->buffer) != block) { rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle), rtems_rfs_file_buffer (handle)); if (rc > 0) return rc; } } } else { /* * The seek is outside the current file so release any buffer. A write will * extend the file. */ int rc = rtems_rfs_file_io_release (handle); if (rc > 0) return rc; } *new_pos = pos; return 0; }
/** * This routine processes the write() system call. * * @param iop * @param buffer * @param count * @return ssize_t */ static ssize_t rtems_rfs_rtems_file_write (rtems_libio_t* iop, const void* buffer, size_t count) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); rtems_rfs_pos pos; rtems_rfs_pos file_size; const uint8_t* data = buffer; ssize_t write = 0; int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_WRITE)) printf("rtems-rfs: file-write: handle:%p count:%zd\n", file, count); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); pos = iop->offset; file_size = rtems_rfs_file_size (file); if (pos > file_size) { /* * If the iop position is past the physical end of the file we need to set * the file size to the new length before writing. The * rtems_rfs_file_io_end() will grow the file subsequently. */ rc = rtems_rfs_file_set_size (file, pos); if (rc) { rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return rtems_rfs_rtems_error ("file-write: write extend", rc); } rtems_rfs_file_set_bpos (file, pos); } else if (pos < file_size && rtems_libio_iop_is_append(iop)) { pos = file_size; rc = rtems_rfs_file_seek (file, pos, &pos); if (rc) { rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return rtems_rfs_rtems_error ("file-write: write append seek", rc); } } while (count) { size_t size = count; rc = rtems_rfs_file_io_start (file, &size, false); if (rc) { /* * If we have run out of space and have written some data return that * amount first as the inode will have accounted for it. This means * there was no error and the return code from can be ignored. */ if (!write) write = rtems_rfs_rtems_error ("file-write: write open", rc); break; } if (size > count) size = count; memcpy (rtems_rfs_file_data (file), data, size); data += size; count -= size; write += size; rc = rtems_rfs_file_io_end (file, size, false); if (rc) { write = rtems_rfs_rtems_error ("file-write: write close", rc); break; } } if (write >= 0) iop->offset = pos + write; rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return write; }
/** * This routine processes the write() system call. * * @param iop * @param buffer * @param count * @return ssize_t */ static ssize_t rtems_rfs_rtems_file_write (rtems_libio_t* iop, const void* buffer, size_t count) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); rtems_rfs_pos pos; const uint8_t* data = buffer; ssize_t write = 0; int rc; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_WRITE)) printf("rtems-rfs: file-write: handle:%p count:%zd\n", file, count); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); pos = iop->offset; /* * If the iop position is past the physical end of the file we need to set * the file size to the new length before writing. If the position equals the * size of file we are still past the end of the file as positions number * from 0. For a specific position we need a file that has a length of one * more. */ if (pos >= rtems_rfs_file_size (file)) { rc = rtems_rfs_file_set_size (file, pos + 1); if (rc) { rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return rtems_rfs_rtems_error ("file-write: write extend", rc); } } rtems_rfs_file_set_bpos (file, pos); while (count) { size_t size = count; rc = rtems_rfs_file_io_start (file, &size, false); if (rc) { write = rtems_rfs_rtems_error ("file-write: write open", rc); break; } if (size > count) size = count; memcpy (rtems_rfs_file_data (file), data, size); data += size; count -= size; write += size; rc = rtems_rfs_file_io_end (file, size, false); if (rc) { write = rtems_rfs_rtems_error ("file-write: write close", rc); break; } } iop->size = rtems_rfs_file_size (file); rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); return write; }