1 /****************************************************************************
2 * fs/vfs/fs_truncate64.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 ****************************************************************************/
59
file_truncate64(struct file * filep,off64_t length)60 static int file_truncate64(struct file *filep, off64_t length)
61 {
62 struct Vnode *vnode = NULL;
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->Truncate64)
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 err = vnode->vop->Truncate64(vnode, length);
90 if (err < 0)
91 {
92 goto errout;
93 }
94
95 return OK;
96
97 errout:
98 set_errno(-err);
99 return VFS_ERROR;
100 }
101
102 /****************************************************************************
103 * Name: ftruncate
104 *
105 * Description:
106 * The ftruncate() function causes the regular file referenced by fd to
107 * have a size of length bytes.
108 *
109 * If the file previously was larger than length, the extra data is
110 * discarded. If it was previously shorter than length, it is unspecified
111 * whether the file is changed or its size increased. If the file is
112 * extended, the extended area appears as if it were zero-filled. If fd
113 * references a shared memory object, ftruncate() sets the size of the
114 * shared memory object to length. If the file is not a regular file or
115 * a shared memory object, the result is unspecified.
116
117 * With ftruncate(), the file must be open for writing; for truncate(),
118 * the process must have write permission for the file.
119 *
120 * ftruncate() does not modify the file offset for any open file
121 * descriptions associated with the file.
122 *
123 * Input Parameters:
124 * fd - A reference to an open, regular file or shared memory object
125 * to be truncated.
126 * length - The new length of the file or shared memory object.
127 *
128 * Returned Value:
129 * On success, 0.
130 * On error, -1 is returned, and errno is set appro-priately:
131 *
132 *
133 ****************************************************************************/
134
ftruncate64(int fd,off64_t length)135 int ftruncate64(int fd, off64_t length)
136 {
137 #if CONFIG_NFILE_DESCRIPTORS > 0
138 struct file *filep = NULL;
139 #endif
140
141 /* Did we get a valid file descriptor? */
142
143 #if CONFIG_NFILE_DESCRIPTORS > 0
144 if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
145 #endif
146 {
147 set_errno(EBADF);
148 return VFS_ERROR;
149 }
150
151 #if CONFIG_NFILE_DESCRIPTORS > 0
152 /* The descriptor is in the right range to be a file descriptor... write
153 * to the file.
154 */
155
156 int ret = fs_getfilep(fd, &filep);
157 if (ret < 0)
158 {
159 /* The errno value has already been set */
160 return VFS_ERROR;
161 }
162
163 if (filep->f_oflags & O_DIRECTORY)
164 {
165 set_errno(EBADF);
166 return VFS_ERROR;
167 }
168
169 /* Perform the truncate operation using the file descriptor as an index */
170
171 return file_truncate64(filep, length);
172 #endif
173 }
174