dfs_romfs.c 5.8 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
				else 
				{
					/* return file dirent */
84 85
					if (subpath != RT_NULL) break; /* not the end of path */
					
86 87
					return &dirent[index];
				}
B
bernard.xiong 已提交
88 89
			}
		}
90 91

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

	/* 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);

114 115 116
	/* update file current position */
	file->pos += length;

B
bernard.xiong 已提交
117 118 119 120 121
	return length;
}

int dfs_romfs_lseek(struct dfs_fd* file, rt_off_t offset)
{
B
bernard.xiong 已提交
122
	if (offset <= file->size)
B
bernard.xiong 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
	{
		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)
{
139
	rt_size_t size;
B
bernard.xiong 已提交
140
	struct romfs_dirent* dirent;
141
	struct romfs_dirent* root_dirent;
B
bernard.xiong 已提交
142 143 144

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

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

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

151 152 153 154 155 156 157 158 159 160 161 162
	/* entry is a directory file type */
	if (dirent->type == ROMFS_DIRENT_DIR)
	{
		if (!(file->flags & DFS_O_DIRECTORY) )
			return -DFS_STATUS_ENOENT;
	}
	else
	{
		/* entry is a file, but open it as a directory */
		if (file->flags & DFS_O_DIRECTORY)
			return -DFS_STATUS_ENOENT;
	}
163

164 165
	file->data = dirent;
	file->size = size;
B
bernard.xiong 已提交
166
	file->pos = 0;
167

B
bernard.xiong 已提交
168 169 170
	return DFS_STATUS_OK;
}

171
int dfs_romfs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
B
bernard.xiong 已提交
172
{
173
	rt_size_t size;
B
bernard.xiong 已提交
174
	struct romfs_dirent* dirent;
175
	struct romfs_dirent* root_dirent;
B
bernard.xiong 已提交
176 177

	root_dirent = (struct romfs_dirent*)fs->data;
178
	dirent = dfs_romfs_lookup(root_dirent, path, &size);
B
bernard.xiong 已提交
179 180 181 182

	if (dirent == RT_NULL) return -DFS_STATUS_ENOENT;

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

B
bernard.xiong 已提交
186
	if (dirent->type == ROMFS_DIRENT_DIR)
B
bernard.xiong@gmail.com 已提交
187
	{
188 189
		st->st_mode &= ~DFS_S_IFREG;
		st->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH;
B
bernard.xiong 已提交
190 191 192 193 194 195 196 197 198
	}

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

	return DFS_STATUS_OK;
}

199
int dfs_romfs_getdents(struct dfs_fd* file, struct dirent* dirp, rt_uint32_t count)
B
bernard.xiong 已提交
200 201 202
{
	rt_size_t index;
	const char *name;
203
	struct dirent* d;
B
bernard.xiong 已提交
204 205 206
	struct romfs_dirent *dirent, *sub_dirent;

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

209 210 211
	/* enter directory */
	dirent = (struct romfs_dirent*) dirent->data;
	
B
bernard.xiong 已提交
212
	/* make integer count */
213
	count = (count / sizeof(struct dirent));
B
bernard.xiong 已提交
214 215 216
	if ( count == 0 ) return -DFS_STATUS_EINVAL;
	
	index = 0;
217
	for (index = 0; index < count && file->pos < file->size; index ++)
B
bernard.xiong 已提交
218 219
	{
		d = dirp + index;
B
bernard.xiong@gmail.com 已提交
220

B
bernard.xiong 已提交
221 222 223 224
		sub_dirent = &dirent[file->pos];
		name = sub_dirent->name;

		/* fill dirent */
225 226 227 228 229
		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 已提交
230
		d->d_namlen = rt_strlen(name);
231 232
		d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
		rt_strncpy(d->d_name, name, rt_strlen(name) + 1);
B
bernard.xiong 已提交
233 234 235 236

		/* move to next position */
		++ file->pos; 
	}
237 238

	return index * sizeof(struct dirent);
B
bernard.xiong 已提交
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
}

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;
}