import tput from NetBSD
[minix3.git] / lib / libsffs / write.c
blobbf70038a72f2ce0c4eb9580ade6c36b907732f64
1 /* This file contains file writing system call handlers.
3 * The entry points into this file are:
4 * do_write perform the WRITE file system call
5 * do_ftrunc perform the FTRUNC file system call
7 * Created:
8 * April 2009 (D.C. van Moolenbroek)
9 */
11 #include "inc.h"
13 static int write_file(struct inode *ino, u64_t *posp, size_t *countp,
14 cp_grant_id_t *grantp);
16 /*===========================================================================*
17 * write_file *
18 *===========================================================================*/
19 static int write_file(ino, posp, countp, grantp)
20 struct inode *ino;
21 u64_t *posp;
22 size_t *countp;
23 cp_grant_id_t *grantp;
25 /* Write data or zeroes to a file, depending on whether a valid pointer to
26 * a data grant was provided.
28 u64_t pos;
29 size_t count, size;
30 vir_bytes off;
31 char *ptr;
32 int r, chunk;
34 assert(!IS_DIR(ino));
36 if ((r = get_handle(ino)) != OK)
37 return r;
39 pos = *posp;
40 count = *countp;
42 assert(count > 0);
44 /* Use the buffer from below to eliminate extra copying. */
45 size = sffs_table->t_writebuf(&ptr);
46 off = 0;
48 while (count > 0) {
49 chunk = MIN(count, size);
51 if (grantp != NULL) {
52 r = sys_safecopyfrom(m_in.m_source, *grantp,
53 off, (vir_bytes) ptr, chunk);
55 if (r != OK)
56 break;
57 } else {
58 /* Do this every time. We don't know what happens below. */
59 memset(ptr, 0, chunk);
62 if ((r = sffs_table->t_write(ino->i_file, ptr, chunk, pos)) <= 0)
63 break;
65 count -= r;
66 off += r;
67 pos = add64u(pos, r);
70 if (r < 0)
71 return r;
73 *posp = pos;
74 *countp = off;
76 return OK;
79 /*===========================================================================*
80 * do_write *
81 *===========================================================================*/
82 int do_write()
84 /* Write data to a file.
86 struct inode *ino;
87 u64_t pos;
88 size_t count;
89 cp_grant_id_t grant;
90 int r;
92 if (state.s_read_only)
93 return EROFS;
95 if ((ino = find_inode(m_in.REQ_INODE_NR)) == NULL)
96 return EINVAL;
98 if (IS_DIR(ino)) return EISDIR;
100 pos = make64(m_in.REQ_SEEK_POS_LO, m_in.REQ_SEEK_POS_HI);
101 count = m_in.REQ_NBYTES;
102 grant = m_in.REQ_GRANT;
104 if (count == 0) return EINVAL;
106 if ((r = write_file(ino, &pos, &count, &grant)) != OK)
107 return r;
109 m_out.RES_SEEK_POS_HI = ex64hi(pos);
110 m_out.RES_SEEK_POS_LO = ex64lo(pos);
111 m_out.RES_NBYTES = count;
113 return OK;
116 /*===========================================================================*
117 * do_ftrunc *
118 *===========================================================================*/
119 int do_ftrunc()
121 /* Change file size or create file holes.
123 char path[PATH_MAX];
124 struct inode *ino;
125 struct sffs_attr attr;
126 u64_t start, end, delta;
127 size_t count;
128 int r;
130 if (state.s_read_only)
131 return EROFS;
133 if ((ino = find_inode(m_in.REQ_INODE_NR)) == NULL)
134 return EINVAL;
136 if (IS_DIR(ino)) return EISDIR;
138 start = make64(m_in.REQ_TRC_START_LO, m_in.REQ_TRC_START_HI);
139 end = make64(m_in.REQ_TRC_END_LO, m_in.REQ_TRC_END_HI);
141 if (cmp64u(end, 0) == 0) {
142 /* Truncate or expand the file. */
143 if ((r = verify_inode(ino, path, NULL)) != OK)
144 return r;
146 attr.a_mask = SFFS_ATTR_SIZE;
147 attr.a_size = start;
149 r = sffs_table->t_setattr(path, &attr);
150 } else {
151 /* Write zeroes to the file. We can't create holes. */
152 if (cmp64(end, start) <= 0) return EINVAL;
154 delta = sub64(end, start);
156 if (ex64hi(delta) != 0) return EINVAL;
158 count = ex64lo(delta);
160 r = write_file(ino, &start, &count, NULL);
163 return r;