3 * Copyright (C) 2002 Florin Malita <mali@go.ro>
5 * This file is part of LUFS, a free userspace filesystem implementation.
6 * See http://lufs.sourceforge.net/ for updates.
8 * LUFS is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * LUFS is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <sys/types.h>
32 #include <sys/socket.h>
38 #include <lufs/proto.h>
44 #include "filesystem.h"
48 static struct message*
49 generic_umount(struct file_system *fs, struct message *msg){
50 TRACE("unmounting this filesystem");
52 if(!fs->fs_ops->umount)
55 fs->fs_ops->umount(fs->fs_context);
56 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
59 static struct message*
60 generic_readdir(struct file_system *fs, struct message *msg){
61 struct lufs_req_readdir *req;
62 struct directory *dir;
65 if(!fs->fs_ops->readdir)
68 req = (struct lufs_req_readdir*)msg->m_data;
70 TRACE("readdir %s, offset %d",req->dirname, req->offset);
72 if(lu_cache_readdir(fs->fs_cache, req->dirname, req->offset, fs->fs_buf, LU_MAXDATA) < 0){
73 if(!(dir = lu_cache_mkdir(req->dirname)))
76 if(fs->fs_ops->readdir(fs->fs_context, req->dirname, dir) < 0){
77 lu_cache_killdir(dir);
81 lu_cache_add_dir(fs->fs_cache, dir);
83 if(lu_cache_readdir(fs->fs_cache, req->dirname, req->offset, fs->fs_buf, LU_MAXDATA) < 0){
84 WARN("could not read directory!");
90 res = lu_makemsg(&fs->fs_msg, PTYPE_OK, fs->fs_buf, strlen(fs->fs_buf) + 1);
94 static struct message*
95 generic_illegal(struct file_system *fs, struct message *msg){
96 WARN("Illegal message type: %d", msg->m_hdr.msg_type);
100 static struct message*
101 generic_read(struct file_system *fs, struct message *msg){
102 struct lufs_req_rw *req;
106 if(!fs->fs_ops->read)
109 req = (struct lufs_req_rw*)msg->m_data;
111 TRACE("read %s, offset= %Ld, count= %d", req->name, req->offset, (int)req->count);
113 if((r = fs->fs_ops->read(fs->fs_context, req->name, req->offset, req->count, fs->fs_buf)) < 0){
114 TRACE("read failed\n");
117 if((unsigned)r < req->count)
118 memset(fs->fs_buf + r, 0, req->count - r);
119 res = lu_makemsg(&fs->fs_msg, PTYPE_OK, fs->fs_buf, req->count);
124 static struct message*
125 generic_write(struct file_system *fs, struct message *msg){
126 struct lufs_req_rw *req;
130 if(!fs->fs_ops->write)
133 req = (struct lufs_req_rw*)msg->m_data;
134 buf = req->name + strlen(req->name) + 1;
136 TRACE("write %s, offset=%Ld, count=%d", req->name, req->offset, (int)req->count);
138 if(fs->fs_ops->write(fs->fs_context, req->name, req->offset, req->count, buf) < 0){
139 TRACE("write failed\n");
142 res = lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
147 static struct message*
148 generic_stat(struct file_system *fs, struct message *msg){
149 struct lufs_fattr *fattr = (struct lufs_fattr*)fs->fs_buf;
151 if(!fs->fs_ops->stat)
154 TRACE("stat %s", msg->m_data);
156 memset(fattr, 0, sizeof(struct lufs_fattr));
158 if(lu_cache_lookup_file(fs->fs_cache, msg->m_data, fattr, NULL, 0) < 0){
159 TRACE("lookup failed on master");
161 if(strlen(msg->m_data) <= 1)
162 sprintf(msg->m_data, "/.");
164 if(fs->fs_ops->stat(fs->fs_context, msg->m_data , fattr) < 0){
165 TRACE("do_stat failed too");
170 return lu_makemsg(&fs->fs_msg, PTYPE_OK, (char*)fattr, sizeof(struct lufs_fattr));
173 static struct message*
174 generic_mkdir(struct file_system *fs, struct message *msg){
175 struct lufs_req_mkdir *req;
178 if(!fs->fs_ops->mkdir)
183 req = (struct lufs_req_mkdir*)msg->m_data;
185 if(fs->fs_ops->mkdir(fs->fs_context, req->dirname, req->mode) < 0){
186 TRACE("mkdir failed!");
190 lu_cache_invalidate(fs->fs_cache, req->dirname);
192 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
195 static struct message*
196 generic_rmdir(struct file_system *fs, struct message *msg){
198 if(!fs->fs_ops->rmdir)
203 if(fs->fs_ops->rmdir(fs->fs_context, msg->m_data) < 0){
204 TRACE("rmdir failed!");
208 lu_cache_invalidate(fs->fs_cache, msg->m_data);
210 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
213 static struct message*
214 generic_create(struct file_system *fs, struct message *msg){
215 struct lufs_req_mkdir *req;
217 if(!fs->fs_ops->create)
222 req = (struct lufs_req_mkdir*)msg->m_data;
224 if(fs->fs_ops->create(fs->fs_context, req->dirname, req->mode) < 0){
225 TRACE("create failed!");
229 lu_cache_invalidate(fs->fs_cache, req->dirname);
231 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
234 static struct message*
235 generic_unlink(struct file_system *fs, struct message *msg){
237 if(!fs->fs_ops->unlink)
242 if(fs->fs_ops->unlink(fs->fs_context, msg->m_data) < 0){
243 TRACE("unlink failed!");
247 lu_cache_invalidate(fs->fs_cache, msg->m_data);
249 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
252 static struct message*
253 generic_rename(struct file_system *fs, struct message *msg){
255 if(!fs->fs_ops->rename)
258 TRACE("old: %s, new: %s", msg->m_data, msg->m_data + strlen(msg->m_data) + 1);
260 if(fs->fs_ops->rename(fs->fs_context, msg->m_data, msg->m_data + strlen(msg->m_data) + 1) < 0){
261 TRACE("rename failed!");
265 lu_cache_invalidate(fs->fs_cache, msg->m_data);
266 lu_cache_invalidate(fs->fs_cache, msg->m_data + strlen(msg->m_data) + 1);
268 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
271 static struct message*
272 generic_open(struct file_system *fs, struct message *msg){
273 struct lufs_req_open *req;
275 if(!fs->fs_ops->open)
280 req = (struct lufs_req_open*)msg->m_data;
282 if(fs->fs_ops->open(fs->fs_context, req->name, req->mode) < 0){
283 TRACE("open failed!");
287 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
290 static struct message*
291 generic_release(struct file_system *fs, struct message *msg){
293 if(!fs->fs_ops->release)
298 if(fs->fs_ops->release(fs->fs_context, msg->m_data) < 0){
299 TRACE("release failed!");
303 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
307 static struct message*
308 generic_readlink(struct file_system *fs, struct message *msg){
309 struct lufs_fattr fattr;
312 if(!fs->fs_ops->readlink)
315 TRACE("readlink %s", msg->m_data);
317 /* try to get the link target from dircache first */
318 if(lu_cache_lookup_file(fs->fs_cache, msg->m_data, &fattr, fs->fs_buf, LU_MAXDATA) < 0)
321 if(strcmp(fs->fs_buf, "")){
322 TRACE("link target found in dircache.");
323 return lu_makemsg(&fs->fs_msg, PTYPE_OK, fs->fs_buf, strlen(fs->fs_buf) + 1);
329 if((len = fs->fs_ops->readlink(fs->fs_context, msg->m_data, fs->fs_buf, LU_MAXDATA)) < 0){
330 TRACE("readlink failed!");
334 fs->fs_buf[len++] = 0;
336 return lu_makemsg(&fs->fs_msg, PTYPE_OK, fs->fs_buf, len);
339 static struct message*
340 generic_link(struct file_system *fs, struct message *msg){
342 if(!fs->fs_ops->link)
345 TRACE("link %s %s", msg->m_data, &msg->m_data[strlen(msg->m_data)+1]);
347 if(fs->fs_ops->link(fs->fs_context, msg->m_data, &msg->m_data[strlen(msg->m_data) + 1]) < 0){
348 TRACE("link failed!");
352 lu_cache_invalidate(fs->fs_cache, msg->m_data);
353 lu_cache_invalidate(fs->fs_cache, &msg->m_data[strlen(msg->m_data) + 1]);
355 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
358 static struct message*
359 generic_symlink(struct file_system *fs, struct message *msg){
361 if(!fs->fs_ops->symlink)
364 TRACE("symlink %s %s", msg->m_data, &msg->m_data[strlen(msg->m_data)+1]);
366 if(fs->fs_ops->symlink(fs->fs_context, &msg->m_data[strlen(msg->m_data) + 1], msg->m_data) < 0){
367 TRACE("symlink failed!");
371 lu_cache_invalidate(fs->fs_cache, msg->m_data);
373 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
376 static struct message*
377 generic_setattr(struct file_system *fs, struct message *msg){
378 struct lufs_req_setattr *req = (struct lufs_req_setattr*)msg->m_data;
380 if(!fs->fs_ops->setattr)
383 TRACE("setattr %s", req->name);
385 if(fs->fs_ops->setattr(fs->fs_context, req->name, &req->fattr) < 0){
386 TRACE("setattr failed!");
390 lu_cache_invalidate(fs->fs_cache, req->name);
392 return lu_makemsg(&fs->fs_msg, PTYPE_OK, NULL, 0);
397 handle_fs(struct file_system *fs, int sock, pid_t pid){
398 struct message *msg, *rep;
399 struct message* (*handlers[PTYPE_MAX + 1])(struct file_system*, struct message*);
401 handlers[0] = generic_illegal; // PTYPE_OK
402 handlers[1] = generic_illegal; // PTYPE_MOUNT
403 handlers[2] = generic_read; // PTYPE_READ
404 handlers[3] = generic_write; // PTYPE_WRITE
405 handlers[4] = generic_readdir; // PTYPE_READDIR
406 handlers[5] = generic_stat; // PTYPE_STAT
407 handlers[6] = generic_umount; // PTYPE_UMOUNT
408 handlers[7] = generic_setattr; // PTYPE_SETATTR
409 handlers[8] = generic_mkdir; // PTYPE_MKDIR
410 handlers[9] = generic_rmdir; // PTYPE_RMDIR
411 handlers[10] = generic_create; // PTYPE_CREATE
412 handlers[11] = generic_unlink; // PTYPE_UNLINK
413 handlers[12] = generic_rename; // PTYPE_RENAME
414 handlers[13] = generic_open; // PTYPE_OPEN
415 handlers[14] = generic_release; // PTYPE_RELEASE
416 handlers[15] = generic_readlink; // PTYPE_READLINK
417 handlers[16] = generic_link; // PTYPE_LINK
418 handlers[17] = generic_symlink; // PTYPE_SYMLINK
421 TRACE("connecting the slot...");
423 if(!fs->fs_ops->mount(fs->fs_context)){
424 WARN("couldn't connect!");
429 signal(SIGPIPE, SIG_IGN);
431 TRACE("entering I/O loop...");
434 msg = lu_recvmsg(&fs->fs_msg, sock);
437 TRACE("oops, my kernel pair disconnected");
442 if(msg->m_hdr.msg_type <= PTYPE_MAX){
443 rep = (handlers[msg->m_hdr.msg_type])(fs, msg);
447 TRACE("operation failed, sending error reply...");
448 rep = lu_makemsg(&fs->fs_msg, PTYPE_ERROR, NULL, 0);
451 lu_sendmsg(rep, sock);