dfs_romfs.c 5.4 KB
Newer Older
B
bernard.xiong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
#include <rtthread.h>
#include <dfs.h>
#include <dfs_fs.h>
#include "dfs_romfs.h"

int dfs_romfs_mount(struct dfs_filesystem* fs, unsigned long rwflag, const void* data)
{
	struct romfs_dirent* root_dirent;

	if (data == RT_NULL) return -DFS_STATUS_EIO;

	root_dirent = (struct romfs_dirent*)data;
	fs->data = root_dirent;

	return DFS_STATUS_OK;
}

int dfs_romfs_unmount(struct dfs_filesystem* fs)
{
	return DFS_STATUS_OK;
}

int dfs_romfs_ioctl(struct dfs_fd* file, int cmd,	void* args)
{
	return -DFS_STATUS_EIO;
}

28
struct romfs_dirent* dfs_romfs_lookup(struct romfs_dirent* root_dirent, const char* path, rt_size_t *size)
B
bernard.xiong 已提交
29
{
30
	rt_size_t index, found;
B
bernard.xiong 已提交
31 32
	const char *subpath, *subpath_end;
	struct romfs_dirent* dirent;
33
	rt_size_t dirent_size;
B
bernard.xiong 已提交
34

35 36 37 38 39
	if (path[0] == '/' && path[1] == '\0') 
	{
		*size = root_dirent->size;
		return root_dirent;
	}
B
bernard.xiong 已提交
40

41 42 43
	/* goto root directy entries */
	dirent = (struct romfs_dirent*)root_dirent->data;
	dirent_size = root_dirent->size;
B
bernard.xiong 已提交
44 45 46 47 48 49 50 51 52 53

	/* get the end position of this subpath */
	subpath_end = path;
	/* skip /// */
	while (*subpath_end && *subpath_end == '/') subpath_end ++;
	subpath = subpath_end;
	while ((*subpath_end != '/') && *subpath_end) subpath_end ++;

	while (dirent != RT_NULL)
	{
54 55
		found = 0;
		
B
bernard.xiong 已提交
56
		/* search in folder */
57
		for (index = 0; index < dirent_size; index ++)
B
bernard.xiong 已提交
58 59 60
		{
			if (rt_strncmp(dirent[index].name, subpath, (subpath_end - subpath)) == 0)
			{
61 62
				dirent_size = dirent[index].size;

B
bernard.xiong 已提交
63 64 65 66 67
				/* skip /// */
				while (*subpath_end && *subpath_end == '/') subpath_end ++;
				subpath = subpath_end;
				while ((*subpath_end != '/') && *subpath_end) subpath_end ++;

68 69 70 71 72
				if (!(*subpath))
				{
					*size = dirent_size;
					return &dirent[index];
				}
B
bernard.xiong 已提交
73 74 75

				if (dirent[index].type == ROMFS_DIRENT_DIR)
				{
76
					/* enter directory */
B
bernard.xiong 已提交
77
					dirent = (struct romfs_dirent*)dirent[index].data;
78
					found = 1;
B
bernard.xiong 已提交
79 80
					break;
				}
81 82 83 84 85
				else 
				{
					/* return file dirent */
					return &dirent[index];
				}
B
bernard.xiong 已提交
86 87
			}
		}
88 89

		if (!found) break; /* not found */
B
bernard.xiong 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
	}

	/* not found */
	return RT_NULL;
}

int dfs_romfs_read(struct dfs_fd* file, void *buf, rt_size_t count)
{
	rt_size_t length;
	struct romfs_dirent* dirent;

	dirent = (struct romfs_dirent *)file->data;
	RT_ASSERT(dirent != RT_NULL);

	if (count < file->size - file->pos)
		length = count;
	else
		length = file->size - file->pos;

	if (length > 0)
		memcpy(buf, &(dirent->data[file->pos]), length);

112 113 114
	/* update file current position */
	file->pos += length;

B
bernard.xiong 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
	return length;
}

int dfs_romfs_lseek(struct dfs_fd* file, rt_off_t offset)
{
	if (offset < file->size)
	{
		file->pos = offset;
		return file->pos;
	}

	return -DFS_STATUS_EIO;
}

int dfs_romfs_close(struct dfs_fd* file)
{
	file->data = RT_NULL;
	return DFS_STATUS_OK;
}

int dfs_romfs_open(struct dfs_fd* file)
{
137
	rt_size_t size;
B
bernard.xiong 已提交
138
	struct romfs_dirent* dirent;
139
	struct romfs_dirent* root_dirent;
B
bernard.xiong 已提交
140 141 142

	root_dirent = (struct romfs_dirent*)file->fs->data;

B
bernard.xiong 已提交
143
	if (file->flags & (DFS_O_CREAT | DFS_O_WRONLY | DFS_O_APPEND | DFS_O_TRUNC | DFS_O_RDWR))
B
bernard.xiong 已提交
144 145
		return -DFS_STATUS_EINVAL;

146
	dirent = dfs_romfs_lookup(root_dirent, file->path, &size);
B
bernard.xiong 已提交
147 148
	if (dirent == RT_NULL) return -DFS_STATUS_ENOENT;

149 150
	file->data = dirent;
	file->size = size;
B
bernard.xiong 已提交
151
	file->pos = 0;
152

B
bernard.xiong 已提交
153 154 155
	return DFS_STATUS_OK;
}

156
int dfs_romfs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
B
bernard.xiong 已提交
157
{
158
	rt_size_t size;
B
bernard.xiong 已提交
159
	struct romfs_dirent* dirent;
160
	struct romfs_dirent* root_dirent;
B
bernard.xiong 已提交
161 162

	root_dirent = (struct romfs_dirent*)fs->data;
163
	dirent = dfs_romfs_lookup(root_dirent, path, &size);
B
bernard.xiong 已提交
164 165 166 167

	if (dirent == RT_NULL) return -DFS_STATUS_ENOENT;

	st->st_dev = 0;
B
bernard.xiong@gmail.com 已提交
168 169
	st->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH |
	DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH;
170

B
bernard.xiong 已提交
171
	if (dirent->type == ROMFS_DIRENT_DIR)
B
bernard.xiong@gmail.com 已提交
172
	{
173 174
		st->st_mode &= ~DFS_S_IFREG;
		st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH;
B
bernard.xiong 已提交
175 176 177 178 179 180 181 182 183
	}

	st->st_size = dirent->size;
	st->st_mtime = 0;
	st->st_blksize = 512;

	return DFS_STATUS_OK;
}

184
int dfs_romfs_getdents(struct dfs_fd* file, struct dirent* dirp, rt_uint32_t count)
B
bernard.xiong 已提交
185 186 187
{
	rt_size_t index;
	const char *name;
188
	struct dirent* d;
B
bernard.xiong 已提交
189 190 191
	struct romfs_dirent *dirent, *sub_dirent;

	dirent = (struct romfs_dirent*) file->data;
192
	RT_ASSERT(dirent->type == ROMFS_DIRENT_DIR);
B
bernard.xiong 已提交
193

194 195 196
	/* enter directory */
	dirent = (struct romfs_dirent*) dirent->data;
	
B
bernard.xiong 已提交
197
	/* make integer count */
198
	count = (count / sizeof(struct dirent));
B
bernard.xiong 已提交
199 200 201
	if ( count == 0 ) return -DFS_STATUS_EINVAL;
	
	index = 0;
202
	for (index = 0; index < count && file->pos < file->size; index ++)
B
bernard.xiong 已提交
203 204
	{
		d = dirp + index;
B
bernard.xiong@gmail.com 已提交
205

B
bernard.xiong 已提交
206 207 208 209
		sub_dirent = &dirent[file->pos];
		name = sub_dirent->name;

		/* fill dirent */
210 211 212 213 214
		if (sub_dirent->type == ROMFS_DIRENT_DIR)
			d->d_type = DFS_DT_DIR;
		else
			d->d_type = DFS_DT_REG;

B
bernard.xiong@gmail.com 已提交
215
		d->d_namlen = rt_strlen(name);
216 217
		d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
		rt_strncpy(d->d_name, name, rt_strlen(name) + 1);
B
bernard.xiong 已提交
218 219 220 221

		/* move to next position */
		++ file->pos; 
	}
222 223

	return index * sizeof(struct dirent);
B
bernard.xiong 已提交
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
}

static const struct dfs_filesystem_operation _romfs = 
{
	"rom",
	dfs_romfs_mount,
	dfs_romfs_unmount,
	RT_NULL,
	RT_NULL,

	dfs_romfs_open,
	dfs_romfs_close,
	dfs_romfs_ioctl,
	dfs_romfs_read,
	RT_NULL,
	RT_NULL,
	dfs_romfs_lseek,
	dfs_romfs_getdents,
	RT_NULL,
	dfs_romfs_stat,
	RT_NULL,
};

int dfs_romfs_init(void)
{
    /* register rom file system */
    dfs_register(&_romfs);
	return 0;
}