• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/vfs/fs_truncate.c
3  *
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.  The
7  * ASF licenses this file to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance with the
9  * License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
16  * License for the specific language governing permissions and limitations
17  * under the License.
18  *
19  ****************************************************************************/
20 
21 /****************************************************************************
22  * Included Files
23  ****************************************************************************/
24 
25 #include "vfs_config.h"
26 #include "sys/types.h"
27 #include "unistd.h"
28 #include "fcntl.h"
29 #include "sched.h"
30 #include "assert.h"
31 #include "errno.h"
32 
33 #include "vnode.h"
34 
35 /****************************************************************************
36  * Name: file_truncate
37  *
38  * Description:
39  *   Equivalent to the standard ftruncate() function except that is accepts
40  *   a struct file instance instead of a file descriptor and it does not set
41  *   the errno variable.
42  *
43  ****************************************************************************/
file_truncate(struct file * filep,off_t length)44 static int file_truncate(struct file *filep, off_t length)
45 {
46   struct Vnode *vnode = NULL;
47   int ret;
48   int err;
49 
50   /* Was this file opened for write access? */
51 
52   if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY)
53     {
54       err = EACCES;
55       goto errout;
56     }
57 
58   /* Is this vnode a registered mountpoint? Does it support the
59    * truncate operations may be relevant to device drivers but only
60    * the mountpoint operations vtable contains a truncate method.
61    */
62 
63   vnode = filep->f_vnode;
64   if (!vnode || !vnode->vop || !vnode->vop->Truncate)
65     {
66       err = ENOSYS;
67       goto errout;
68     }
69 
70   /* Does the file system support the truncate method?  It should if it is
71    * a write-able file system.
72    */
73 
74   ret = vnode->vop->Truncate(vnode, length);
75   if (ret < 0)
76     {
77       err = -ret;
78       goto errout;
79     }
80 
81   return ret;
82 
83 errout:
84   set_errno(err);
85   return VFS_ERROR;
86 }
87 
88 /****************************************************************************
89  * Name: ftruncate
90  *
91  * Description:
92  *   The ftruncate() function causes the regular file referenced by fd to
93  *   have a size of length bytes.
94  *
95  *   If the file previously was larger than length, the extra data is
96  *   discarded.  If it was previously shorter than length, it is unspecified
97  *   whether the file is changed or its size increased.  If the file is
98  *   extended, the extended area appears as if it were zero-filled.  If fd
99  *   references a shared memory object, ftruncate() sets the size of the
100  *   shared memory object to length. If the file is not a regular file or
101  *   a shared memory object, the result is unspecified.
102 
103  *   With ftruncate(), the file must be open for writing; for truncate(),
104  *   the process must have write permission for the file.
105  *
106  *   ftruncate() does not modify the file offset for any open file
107  *   descriptions associated with the file.
108  *
109  * Input Parameters:
110  *   fd     - A reference to an open, regular file or shared memory object
111  *            to be truncated.
112  *   length - The new length of the file or shared memory object.
113  *
114  * Returned Value:
115  * On success, 0.
116  * On error, -1 is returned, and errno is set appro-priately:
117  *
118  *
119  ****************************************************************************/
120 
ftruncate(int fd,off_t length)121 int ftruncate(int fd, off_t length)
122 {
123 #if CONFIG_NFILE_DESCRIPTORS > 0
124   struct file *filep = NULL;
125 #endif
126 
127   /* Did we get a valid file descriptor? */
128 
129 #if CONFIG_NFILE_DESCRIPTORS > 0
130   if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
131 #endif
132     {
133       set_errno(EBADF);
134       return VFS_ERROR;
135     }
136 
137 #if CONFIG_NFILE_DESCRIPTORS > 0
138   /* The descriptor is in the right range to be a file descriptor... write
139    * to the file.
140    */
141 
142   int ret = fs_getfilep(fd, &filep);
143   if (ret < 0)
144     {
145       /* The errno value has already been set */
146 
147       return VFS_ERROR;
148     }
149 
150   if (filep->f_oflags & O_DIRECTORY)
151     {
152       set_errno(EBADF);
153       return VFS_ERROR;
154     }
155 
156   /* Perform the truncate operation using the file descriptor as an index */
157 
158   return file_truncate(filep, length);
159 #endif
160 }
161 
truncate(const char * path,off_t length)162 int truncate(const char *path, off_t length)
163 {
164   int fd;
165   int ret;
166 
167   fd = open(path, O_RDWR);
168   if (fd == VFS_ERROR)
169     {
170       /* The errno value has already been set */
171       return VFS_ERROR;
172     }
173 
174   ret = ftruncate(fd, length);
175   close(fd);
176 
177   return ret;
178 }
179