Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:18

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup rtems_rfs
0007  *
0008  * @brief RTEMS RFS File Handlers
0009  *
0010  * This file contains the set of handlers used to process operations on
0011  * RFS file nodes.
0012  */
0013 
0014 /*
0015  *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042 
0043 #include <inttypes.h>
0044 #include <rtems/inttypes.h>
0045 #include <string.h>
0046 
0047 #include <rtems/rfs/rtems-rfs-file.h>
0048 #include "rtems-rfs-rtems.h"
0049 
0050 /**
0051  * This routine processes the open() system call.  Note that there is nothing
0052  * special to be done at open() time.
0053  */
0054 
0055 static int
0056 rtems_rfs_rtems_file_open (rtems_libio_t* iop,
0057                            const char*    pathname,
0058                            int            oflag,
0059                            mode_t         mode)
0060 {
0061   rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
0062   rtems_rfs_ino          ino;
0063   rtems_rfs_file_handle* file;
0064   int                    flags;
0065   int                    rc;
0066 
0067   flags = 0;
0068 
0069   if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN))
0070     printf("rtems-rfs: file-open: path:%s ino:%" PRId32 " flags:%04i mode:%04" PRIu32 "\n",
0071            pathname, ino, flags, (uint32_t) mode);
0072 
0073   rtems_rfs_rtems_lock (fs);
0074 
0075   ino = rtems_rfs_rtems_get_iop_ino (iop);
0076 
0077   rc = rtems_rfs_file_open (fs, ino, flags, &file);
0078   if (rc > 0)
0079   {
0080     rtems_rfs_rtems_unlock (fs);
0081     return rtems_rfs_rtems_error ("file-open: open", rc);
0082   }
0083 
0084   if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN))
0085     printf("rtems-rfs: file-open: handle:%p\n", file);
0086 
0087   rtems_rfs_rtems_set_iop_file_handle (iop, file);
0088 
0089   rtems_rfs_rtems_unlock (fs);
0090   return 0;
0091 }
0092 
0093 /**
0094  * This routine processes the close() system call.  Note that there is nothing
0095  * to flush at this point.
0096  *
0097  * @param iop
0098  * @return int
0099  */
0100 static int
0101 rtems_rfs_rtems_file_close (rtems_libio_t* iop)
0102 {
0103   rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
0104   rtems_rfs_file_system* fs = rtems_rfs_file_fs (file);
0105   int                    rc;
0106 
0107   if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_CLOSE))
0108     printf("rtems-rfs: file-close: handle:%p\n", file);
0109 
0110   rtems_rfs_rtems_lock (fs);
0111 
0112   rc = rtems_rfs_file_close (fs, file);
0113   if (rc > 0)
0114     rc = rtems_rfs_rtems_error ("file-close: file close", rc);
0115 
0116   rtems_rfs_rtems_unlock (fs);
0117   return rc;
0118 }
0119 
0120 /**
0121  * This routine processes the read() system call.
0122  *
0123  * @param iop
0124  * @param buffer
0125  * @param count
0126  * @return int
0127  */
0128 static ssize_t
0129 rtems_rfs_rtems_file_read (rtems_libio_t* iop,
0130                            void*          buffer,
0131                            size_t         count)
0132 {
0133   rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
0134   rtems_rfs_pos          pos;
0135   uint8_t*               data = buffer;
0136   ssize_t                read = 0;
0137   int                    rc;
0138 
0139   if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_READ))
0140     printf("rtems-rfs: file-read: handle:%p count:%zd\n", file, count);
0141 
0142   rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
0143 
0144   pos = iop->offset;
0145 
0146   if (pos < rtems_rfs_file_size (file))
0147   {
0148     while (count)
0149     {
0150       size_t size;
0151 
0152       rc = rtems_rfs_file_io_start (file, &size, true);
0153       if (rc > 0)
0154       {
0155         read = rtems_rfs_rtems_error ("file-read: read: io-start", rc);
0156         break;
0157       }
0158 
0159       if (size == 0)
0160         break;
0161 
0162       if (size > count)
0163         size = count;
0164 
0165       memcpy (data, rtems_rfs_file_data (file), size);
0166 
0167       data  += size;
0168       count -= size;
0169       read  += size;
0170 
0171       rc = rtems_rfs_file_io_end (file, size, true);
0172       if (rc > 0)
0173       {
0174         read = rtems_rfs_rtems_error ("file-read: read: io-end", rc);
0175         break;
0176       }
0177     }
0178   }
0179 
0180   if (read >= 0)
0181     iop->offset = pos + read;
0182 
0183   rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
0184 
0185   return read;
0186 }
0187 
0188 /**
0189  * This routine processes the write() system call.
0190  *
0191  * @param iop
0192  * @param buffer
0193  * @param count
0194  * @return ssize_t
0195  */
0196 static ssize_t
0197 rtems_rfs_rtems_file_write (rtems_libio_t* iop,
0198                             const void*    buffer,
0199                             size_t         count)
0200 {
0201   rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
0202   rtems_rfs_pos          pos;
0203   rtems_rfs_pos          file_size;
0204   const uint8_t*         data = buffer;
0205   ssize_t                write = 0;
0206   int                    rc;
0207 
0208   if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_WRITE))
0209     printf("rtems-rfs: file-write: handle:%p count:%zd\n", file, count);
0210 
0211   rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
0212 
0213   pos = iop->offset;
0214   file_size = rtems_rfs_file_size (file);
0215   if (pos > file_size)
0216   {
0217     /*
0218      * If the iop position is past the physical end of the file we need to set
0219      * the file size to the new length before writing.  The
0220      * rtems_rfs_file_io_end() will grow the file subsequently.
0221      */
0222     rc = rtems_rfs_file_set_size (file, pos);
0223     if (rc)
0224     {
0225       rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
0226       return rtems_rfs_rtems_error ("file-write: write extend", rc);
0227     }
0228 
0229     rtems_rfs_file_set_bpos (file, pos);
0230   }
0231   else if (pos < file_size && rtems_libio_iop_is_append(iop))
0232   {
0233     pos = file_size;
0234     rc = rtems_rfs_file_seek (file, pos, &pos);
0235     if (rc)
0236     {
0237       rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
0238       return rtems_rfs_rtems_error ("file-write: write append seek", rc);
0239     }
0240   }
0241 
0242   while (count)
0243   {
0244     size_t size = count;
0245 
0246     rc = rtems_rfs_file_io_start (file, &size, false);
0247     if (rc)
0248     {
0249       /*
0250        * If we have run out of space and have written some data return that
0251        * amount first as the inode will have accounted for it. This means
0252        * there was no error and the return code from can be ignored.
0253        */
0254       if (!write)
0255         write = rtems_rfs_rtems_error ("file-write: write open", rc);
0256       break;
0257     }
0258 
0259     if (size > count)
0260       size = count;
0261 
0262     memcpy (rtems_rfs_file_data (file), data, size);
0263 
0264     data  += size;
0265     count -= size;
0266     write  += size;
0267 
0268     rc = rtems_rfs_file_io_end (file, size, false);
0269     if (rc)
0270     {
0271       write = rtems_rfs_rtems_error ("file-write: write close", rc);
0272       break;
0273     }
0274   }
0275 
0276   if (write >= 0)
0277     iop->offset = pos + write;
0278 
0279   rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
0280 
0281   return write;
0282 }
0283 
0284 /**
0285  * This routine processes the lseek() system call.
0286  *
0287  * @param iop
0288  * @param offset
0289  * @param whence
0290  * @return off_t
0291  */
0292 static off_t
0293 rtems_rfs_rtems_file_lseek (rtems_libio_t* iop,
0294                             off_t          offset,
0295                             int            whence)
0296 {
0297   rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
0298   off_t                  old_offset;
0299   off_t                  new_offset;
0300 
0301   if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK))
0302     printf("rtems-rfs: file-lseek: handle:%p offset:%" PRIdoff_t "\n", file, offset);
0303 
0304   rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
0305 
0306   old_offset = iop->offset;
0307   new_offset = rtems_filesystem_default_lseek_file (iop, offset, whence);
0308   if (new_offset != -1)
0309   {
0310     rtems_rfs_pos pos = iop->offset;
0311     int           rc = rtems_rfs_file_seek (file, pos, &pos);
0312 
0313     if (rc)
0314     {
0315       rtems_rfs_rtems_error ("file_lseek: lseek", rc);
0316       iop->offset = old_offset;
0317       new_offset = -1;
0318     }
0319   }
0320 
0321   rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
0322 
0323   return new_offset;
0324 }
0325 
0326 /**
0327  * This routine processes the ftruncate() system call.
0328  *
0329  * @param iop
0330  * @param length
0331  * @return int
0332  */
0333 static int
0334 rtems_rfs_rtems_file_ftruncate (rtems_libio_t* iop,
0335                                 off_t          length)
0336 {
0337   rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
0338   int                    rc;
0339 
0340   if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_FTRUNC))
0341     printf("rtems-rfs: file-ftrunc: handle:%p length:%" PRIdoff_t "\n", file, length);
0342 
0343   rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
0344 
0345   rc = rtems_rfs_file_set_size (file, length);
0346   if (rc)
0347     rc = rtems_rfs_rtems_error ("file_ftruncate: set size", rc);
0348 
0349   rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
0350 
0351   return rc;
0352 }
0353 
0354 /*
0355  *  Set of operations handlers for operations on RFS files.
0356  */
0357 
0358 const rtems_filesystem_file_handlers_r rtems_rfs_rtems_file_handlers = {
0359   .open_h      = rtems_rfs_rtems_file_open,
0360   .close_h     = rtems_rfs_rtems_file_close,
0361   .read_h      = rtems_rfs_rtems_file_read,
0362   .write_h     = rtems_rfs_rtems_file_write,
0363   .ioctl_h     = rtems_filesystem_default_ioctl,
0364   .lseek_h     = rtems_rfs_rtems_file_lseek,
0365   .fstat_h     = rtems_rfs_rtems_fstat,
0366   .ftruncate_h = rtems_rfs_rtems_file_ftruncate,
0367   .fsync_h     = rtems_rfs_rtems_fdatasync,
0368   .fdatasync_h = rtems_rfs_rtems_fdatasync,
0369   .fcntl_h     = rtems_filesystem_default_fcntl,
0370   .kqfilter_h  = rtems_filesystem_default_kqfilter,
0371   .mmap_h      = rtems_filesystem_default_mmap,
0372   .poll_h      = rtems_filesystem_default_poll,
0373   .readv_h     = rtems_filesystem_default_readv,
0374   .writev_h    = rtems_filesystem_default_writev
0375 };