1 /* This file contains file and directory reading file system call handlers.
3 * The entry points into this file are:
4 * do_read perform the READ file system call
5 * do_getdents perform the GETDENTS file system call
8 * April 2009 (D.C. van Moolenbroek)
15 /*===========================================================================*
17 *===========================================================================*/
18 ssize_t
do_read(ino_t ino_nr
, struct fsdriver_data
*data
, size_t count
,
21 /* Read data from a file.
28 if ((ino
= find_inode(ino_nr
)) == NULL
)
31 if (IS_DIR(ino
)) return EISDIR
;
33 if ((r
= get_handle(ino
)) != OK
)
38 /* Use the buffer from below to eliminate extra copying. */
39 size
= sffs_table
->t_readbuf(&ptr
);
43 chunk
= MIN(count
, size
);
45 if ((r
= sffs_table
->t_read(ino
->i_file
, ptr
, chunk
, pos
)) <= 0)
50 if ((r
= fsdriver_copyout(data
, off
, ptr
, chunk
)) != OK
)
64 /*===========================================================================*
66 *===========================================================================*/
67 ssize_t
do_getdents(ino_t ino_nr
, struct fsdriver_data
*data
, size_t bytes
,
70 /* Retrieve directory entries.
72 struct fsdriver_dentry fsdentry
;
73 char name
[NAME_MAX
+1];
74 struct inode
*ino
, *child
;
75 struct sffs_attr attr
;
78 /* must be at least sizeof(struct dirent) + NAME_MAX */
79 static char buf
[BLOCK_SIZE
];
81 if ((ino
= find_inode(ino_nr
)) == NULL
)
84 if (!IS_DIR(ino
)) return ENOTDIR
;
86 if (*posp
< 0 || *posp
>= ULONG_MAX
) return EINVAL
;
88 /* We are going to need at least one free inode to store children in. */
89 if (!have_free_inode()) return ENFILE
;
91 /* If we don't have a directory handle yet, get one now. */
92 if ((r
= get_handle(ino
)) != OK
)
95 fsdriver_dentry_init(&fsdentry
, data
, bytes
, buf
, sizeof(buf
));
97 /* We use the seek position as file index number. The first position is for
98 * the "." entry, the second position is for the ".." entry, and the next
99 * position numbers each represent a file in the directory.
102 /* Determine which inode and name to use for this entry.
103 * We have no idea whether the host will give us "." and/or "..",
104 * so generate our own and skip those from the host.
117 /* Entry for "..", but only when there is a parent. */
118 if (ino
->i_parent
== NULL
)
121 child
= ino
->i_parent
;
128 /* Any other entry, not being "." or "..". */
129 attr
.a_mask
= SFFS_ATTR_MODE
;
131 r
= sffs_table
->t_readdir(ino
->i_dir
, pos
- 2, name
,
132 sizeof(name
), &attr
);
135 /* No more entries? Then close the handle and stop. */
142 /* FIXME: what if the error is ENAMETOOLONG? */
146 if (!strcmp(name
, ".") || !strcmp(name
, ".."))
149 if ((child
= lookup_dentry(ino
, name
)) == NULL
) {
150 child
= get_free_inode();
152 /* We were promised a free inode! */
153 assert(child
!= NULL
);
155 child
->i_flags
= MODE_TO_DIRFLAG(attr
.a_mode
);
157 add_dentry(ino
, name
, child
);
161 r
= fsdriver_dentry_add(&fsdentry
, INODE_NR(child
), name
, strlen(name
),
162 IS_DIR(child
) ? DT_DIR
: DT_REG
);
172 return fsdriver_dentry_finish(&fsdentry
);