etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libsffs / write.c
blobd18a5831add5b58b217c0a654142507c11c741cf
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_trunc perform the TRUNC file system call
7 * Created:
8 * April 2009 (D.C. van Moolenbroek)
9 */
11 #include "inc.h"
13 /*===========================================================================*
14 * write_file *
15 *===========================================================================*/
16 static ssize_t write_file(struct inode *ino, off_t pos, size_t count,
17 struct fsdriver_data *data)
19 /* Write data or zeroes to a file, depending on whether a valid pointer to
20 * a data grant was provided.
22 size_t size, off, chunk;
23 char *ptr;
24 int r;
26 if (pos < 0)
27 return EINVAL;
29 assert(!IS_DIR(ino));
31 if ((r = get_handle(ino)) != OK)
32 return r;
34 assert(count > 0);
36 /* Use the buffer from below to eliminate extra copying. */
37 size = sffs_table->t_writebuf(&ptr);
38 off = 0;
40 while (count > 0) {
41 chunk = MIN(count, size);
43 if (data != NULL) {
44 if ((r = fsdriver_copyin(data, off, ptr, chunk)) != OK)
45 break;
46 } else {
47 /* Do this every time. We don't know what happens below. */
48 memset(ptr, 0, chunk);
51 if ((r = sffs_table->t_write(ino->i_file, ptr, chunk, pos)) <= 0)
52 break;
54 count -= r;
55 off += r;
56 pos += r;
59 if (r < 0)
60 return r;
62 return off;
65 /*===========================================================================*
66 * do_write *
67 *===========================================================================*/
68 ssize_t do_write(ino_t ino_nr, struct fsdriver_data *data, size_t count,
69 off_t pos, int call)
71 /* Write data to a file.
73 struct inode *ino;
75 if (read_only)
76 return EROFS;
78 if ((ino = find_inode(ino_nr)) == NULL)
79 return EINVAL;
81 if (IS_DIR(ino)) return EISDIR;
83 if (count == 0) return 0;
85 return write_file(ino, pos, count, data);
88 /*===========================================================================*
89 * do_trunc *
90 *===========================================================================*/
91 int do_trunc(ino_t ino_nr, off_t start, off_t end)
93 /* Change file size or create file holes.
95 char path[PATH_MAX];
96 struct inode *ino;
97 struct sffs_attr attr;
98 uint64_t delta;
99 ssize_t r;
101 if (read_only)
102 return EROFS;
104 if ((ino = find_inode(ino_nr)) == NULL)
105 return EINVAL;
107 if (IS_DIR(ino)) return EISDIR;
109 if (end == 0) {
110 /* Truncate or expand the file. */
111 if ((r = verify_inode(ino, path, NULL)) != OK)
112 return r;
114 attr.a_mask = SFFS_ATTR_SIZE;
115 attr.a_size = start;
117 r = sffs_table->t_setattr(path, &attr);
118 } else {
119 /* Write zeroes to the file. We can't create holes. */
120 if (end <= start) return EINVAL;
122 delta = (uint64_t)end - (uint64_t)start;
124 if (delta > SSIZE_MAX) return EINVAL;
126 if ((r = write_file(ino, start, (size_t)delta, NULL)) >= 0)
127 r = OK;
130 return r;