• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/vfs/fs_truncate.c
3  *
4  *   Copyright (C) 2018 Gregory Nutt. All rights reserved.
5  *   Author: Gregory Nutt <gnutt@nuttx.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name NuttX nor the names of its contributors may be
18  *    used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  ****************************************************************************/
35 
36 /****************************************************************************
37  * Included Files
38  ****************************************************************************/
39 
40 #include "vfs_config.h"
41 #include "sys/types.h"
42 #include "unistd.h"
43 #include "fcntl.h"
44 #include "sched.h"
45 #include "assert.h"
46 #include "errno.h"
47 
48 #include "vnode.h"
49 
50 /****************************************************************************
51  * Name: file_truncate
52  *
53  * Description:
54  *   Equivalent to the standard ftruncate() function except that is accepts
55  *   a struct file instance instead of a file descriptor and it does not set
56  *   the errno variable.
57  *
58  ****************************************************************************/
file_truncate(struct file * filep,off_t length)59 static int file_truncate(struct file *filep, off_t length)
60 {
61   struct Vnode *vnode = NULL;
62   int ret;
63   int err;
64 
65   /* Was this file opened for write access? */
66 
67   if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY)
68     {
69       err = EACCES;
70       goto errout;
71     }
72 
73   /* Is this vnode a registered mountpoint? Does it support the
74    * truncate operations may be relevant to device drivers but only
75    * the mountpoint operations vtable contains a truncate method.
76    */
77 
78   vnode = filep->f_vnode;
79   if (!vnode || !vnode->vop || !vnode->vop->Truncate)
80     {
81       err = ENOSYS;
82       goto errout;
83     }
84 
85   /* Does the file system support the truncate method?  It should if it is
86    * a write-able file system.
87    */
88 
89   ret = vnode->vop->Truncate(vnode, length);
90   if (ret < 0)
91     {
92       err = -ret;
93       goto errout;
94     }
95 
96   return ret;
97 
98 errout:
99   set_errno(err);
100   return VFS_ERROR;
101 }
102 
103 /****************************************************************************
104  * Name: ftruncate
105  *
106  * Description:
107  *   The ftruncate() function causes the regular file referenced by fd to
108  *   have a size of length bytes.
109  *
110  *   If the file previously was larger than length, the extra data is
111  *   discarded.  If it was previously shorter than length, it is unspecified
112  *   whether the file is changed or its size increased.  If the file is
113  *   extended, the extended area appears as if it were zero-filled.  If fd
114  *   references a shared memory object, ftruncate() sets the size of the
115  *   shared memory object to length. If the file is not a regular file or
116  *   a shared memory object, the result is unspecified.
117 
118  *   With ftruncate(), the file must be open for writing; for truncate(),
119  *   the process must have write permission for the file.
120  *
121  *   ftruncate() does not modify the file offset for any open file
122  *   descriptions associated with the file.
123  *
124  * Input Parameters:
125  *   fd     - A reference to an open, regular file or shared memory object
126  *            to be truncated.
127  *   length - The new length of the file or shared memory object.
128  *
129  * Returned Value:
130  * On success, 0.
131  * On error, -1 is returned, and errno is set appro-priately:
132  *
133  *
134  ****************************************************************************/
135 
ftruncate(int fd,off_t length)136 int ftruncate(int fd, off_t length)
137 {
138 #if CONFIG_NFILE_DESCRIPTORS > 0
139   struct file *filep = NULL;
140 #endif
141 
142   /* Did we get a valid file descriptor? */
143 
144 #if CONFIG_NFILE_DESCRIPTORS > 0
145   if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
146 #endif
147     {
148       set_errno(EBADF);
149       return VFS_ERROR;
150     }
151 
152 #if CONFIG_NFILE_DESCRIPTORS > 0
153   /* The descriptor is in the right range to be a file descriptor... write
154    * to the file.
155    */
156 
157   int ret = fs_getfilep(fd, &filep);
158   if (ret < 0)
159     {
160       /* The errno value has already been set */
161 
162       return VFS_ERROR;
163     }
164 
165   if (filep->f_oflags & O_DIRECTORY)
166     {
167       set_errno(EBADF);
168       return VFS_ERROR;
169     }
170 
171   /* Perform the truncate operation using the file descriptor as an index */
172 
173   return file_truncate(filep, length);
174 #endif
175 }
176 
truncate(const char * path,off_t length)177 int truncate(const char *path, off_t length)
178 {
179   int fd;
180   int ret;
181 
182   fd = open(path, O_RDWR);
183   if (fd == VFS_ERROR)
184     {
185       /* The errno value has already been set */
186       return VFS_ERROR;
187     }
188 
189   ret = ftruncate(fd, length);
190   close(fd);
191 
192   return ret;
193 }
194