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