2 * This is sample code generated by rpcgen.
3 * These are only templates and you can use them
4 * as a guideline for developing your own functions.
12 /* Check that a string is a valid file name. We require that it be valid
13 * UTF-8, that it not be empty, and that it not contain embedded forward
14 * slashes. Also checks that the length of the string is not more than the
15 * maximum allowed length. This function does allow the names "." and "..".
16 * Returns TRUE if the string is allowed as a filename. */
17 gboolean validate_filename(const char *filename)
19 if (filename == NULL || filename[0] == '\0')
21 if (strlen(filename) > 255)
23 if (!g_utf8_validate(filename, -1, NULL))
25 if (strchr(filename, '/') != NULL)
30 /* Arrange for a reference to an inode to be dropped when the RPC request
32 void schedule_inode_unref(RPCRequest *req, BlueSkyInode *inode)
34 struct cleanup_list *c = g_new(struct cleanup_list, 1);
35 c->func = (void (*)(void *))bluesky_inode_unref;
37 c->next = req->cleanup;
41 /* Look up a BlueSkyInode given an NFS filehandle. Returns NULL if the
42 * filehandle is invalid. */
43 BlueSkyInode *lookup_fh(RPCRequest *req, nfs_fh3 *fh)
45 BlueSkyInode *inode = NULL;
46 if (fh->data.data_len == 8) {
47 uint64_t inum = GUINT64_FROM_BE(*(uint64_t *)(fh->data.data_val));
48 inode = bluesky_get_inode(fs, inum);
50 schedule_inode_unref(req, inode);
55 int64_t decode_nfstime3(nfstime3 *time)
57 int64_t result = (int64_t)time->seconds * 1000000;
58 result += time->nseconds / 1000;
62 void set_attributes(BlueSkyInode *inode, sattr3 *attributes)
64 int64_t now = bluesky_get_current_time();
66 if (attributes->mode.set) {
67 inode->mode = attributes->mode.set_uint32_u.val;
70 if (attributes->uid.set) {
71 inode->uid = attributes->uid.set_uint32_u.val;
74 if (attributes->gid.set) {
75 inode->gid = attributes->gid.set_uint32_u.val;
78 if (attributes->size.set) {
79 if (inode->type == BLUESKY_REGULAR) {
80 bluesky_file_truncate(inode, attributes->size.set_uint64_u.val);
85 switch (attributes->atime.set) {
88 case SET_TO_SERVER_TIME:
91 case SET_TO_CLIENT_TIME:
92 inode->atime = decode_nfstime3(&attributes->atime.set_time_u.time);
96 switch (attributes->mtime.set) {
99 case SET_TO_SERVER_TIME:
102 case SET_TO_CLIENT_TIME:
103 inode->mtime = decode_nfstime3(&attributes->mtime.set_time_u.time);
108 inode->change_count++;
111 /* Copy inode attributes into NFS response. The BlueSkyInode should be locked
113 void encode_fattr3(struct fattr3 *result, BlueSkyInode *inode)
115 result->type = inode->type;
116 result->mode = inode->mode;
117 result->nlink = inode->nlink;
118 result->uid = inode->uid;
119 result->gid = inode->gid;
120 result->size = inode->size;
122 result->rdev.major = 0;
123 result->rdev.minor = 0;
125 result->fileid = inode->inum;
126 result->atime.seconds = inode->atime / 1000000;
127 result->atime.nseconds = (inode->atime % 1000000) * 1000;
128 result->mtime.seconds = inode->mtime / 1000000;
129 result->mtime.nseconds = (inode->mtime % 1000000) * 1000;
130 result->ctime.seconds = inode->ctime / 1000000;
131 result->ctime.nseconds = (inode->ctime % 1000000) * 1000;
133 switch (inode->type) {
134 case BLUESKY_SYMLINK:
135 result->size = strlen(inode->symlink_contents);
142 void encode_pre_wcc(struct wcc_data *wcc, BlueSkyInode *inode)
144 wcc->before.present = TRUE;
145 wcc->before.pre_op_attr_u.attributes.size = inode->size;
146 wcc->before.pre_op_attr_u.attributes.mtime.seconds = inode->mtime / 1000000;
147 wcc->before.pre_op_attr_u.attributes.mtime.nseconds = (inode->mtime % 1000000) * 1000;
148 wcc->before.pre_op_attr_u.attributes.ctime.seconds = inode->ctime / 1000000;
149 wcc->before.pre_op_attr_u.attributes.ctime.nseconds = (inode->ctime % 1000000) * 1000;
152 void nfsproc3_null_3_svc(void *argp, RPCRequest *req)
154 async_rpc_send_reply(req, NULL);
157 void nfsproc3_getattr_3_svc(nfs_fh3 *argp, RPCRequest *req)
160 memset(&result, 0, sizeof(result));
162 BlueSkyInode *inode = lookup_fh(req, argp);
164 result.status = NFS3_OK;
165 encode_fattr3(&result.getattr3res_u.attributes, inode);
167 result.status = NFS3ERR_STALE;
170 async_rpc_send_reply(req, &result);
173 void nfsproc3_setattr_3_svc(setattr3args *argp, RPCRequest *req)
176 memset(&result, 0, sizeof(result));
178 result.wccstat3_u.wcc.before.present = FALSE;
179 result.wccstat3_u.wcc.after.present = FALSE;
180 BlueSkyInode *inode = lookup_fh(req, &argp->object);
182 result.status = NFS3ERR_STALE;
183 async_rpc_send_reply(req, &result);
187 encode_pre_wcc(&result.wccstat3_u.wcc, inode);
188 if (argp->guard.check) {
189 if (inode->ctime != decode_nfstime3(&argp->guard.sattrguard3_u.ctime)) {
190 result.status = NFS3ERR_NOT_SYNC;
191 result.wccstat3_u.wcc.after.present = TRUE;
192 encode_fattr3(&result.wccstat3_u.wcc.after.post_op_attr_u.attributes, inode);
193 async_rpc_send_reply(req, &result);
198 set_attributes(inode, &argp->new_attributes);
200 result.wccstat3_u.wcc.after.present = TRUE;
201 encode_fattr3(&result.wccstat3_u.wcc.after.post_op_attr_u.attributes,
203 result.status = NFS3_OK;
205 async_rpc_send_reply(req, &result);
208 void nfsproc3_lookup_3_svc(diropargs3 *argp, RPCRequest *req)
211 memset(&result, 0, sizeof(result));
213 BlueSkyInode *dir = lookup_fh(req, &argp->dir);
215 result.status = NFS3ERR_STALE;
216 result.lookup3res_u.resfail.present = FALSE;
217 async_rpc_send_reply(req, &result);
221 result.lookup3res_u.resfail.present = TRUE;
222 encode_fattr3(&result.lookup3res_u.resfail.post_op_attr_u.attributes, dir);
223 if (!validate_filename(argp->name)) {
224 if (strlen(argp->name) > 255)
225 result.status = NFS3ERR_NAMETOOLONG;
227 result.status = NFS3ERR_NOENT;
228 async_rpc_send_reply(req, &result);
232 /* TODO: Special-case "." and "..". */
233 uint64_t inum = bluesky_directory_lookup(dir, argp->name);
235 result.status = NFS3ERR_NOENT;
236 async_rpc_send_reply(req, &result);
239 BlueSkyInode *inode = bluesky_get_inode(fs, inum);
241 result.status = NFS3ERR_NOENT;
242 async_rpc_send_reply(req, &result);
245 schedule_inode_unref(req, inode);
247 result.status = NFS3_OK;
248 result.lookup3res_u.resok.dir_attributes.present = TRUE;
249 encode_fattr3(&result.lookup3res_u.resok.dir_attributes.post_op_attr_u.attributes, dir);
250 result.lookup3res_u.resok.obj_attributes.present = TRUE;
251 encode_fattr3(&result.lookup3res_u.resok.obj_attributes.post_op_attr_u.attributes, inode);
254 fh_bytes = GUINT64_TO_BE(inum);
255 result.lookup3res_u.resok.object.data.data_len = 8;
256 result.lookup3res_u.resok.object.data.data_val = (char *)&fh_bytes;
258 async_rpc_send_reply(req, &result);
261 void nfsproc3_access_3_svc(access3args *argp, RPCRequest *req)
264 memset(&result, 0, sizeof(result));
266 BlueSkyInode *inode = lookup_fh(req, &argp->object);
268 result.status = NFS3ERR_STALE;
269 result.access3res_u.resfail.present = FALSE;
270 async_rpc_send_reply(req, &result);
274 result.status = NFS3_OK;
275 result.access3res_u.resok.obj_attributes.present = TRUE;
276 encode_fattr3(&result.access3res_u.resok.obj_attributes.post_op_attr_u.attributes, inode);
277 result.access3res_u.resok.access = argp->access;
279 async_rpc_send_reply(req, &result);
282 void nfsproc3_readlink_3_svc(nfs_fh3 *argp, RPCRequest *req)
285 memset(&result, 0, sizeof(result));
287 BlueSkyInode *inode = lookup_fh(req, argp);
289 if (inode->type == BLUESKY_SYMLINK) {
290 result.status = NFS3_OK;
291 result.readlink3res_u.resok.symlink_attributes.present = TRUE;
292 encode_fattr3(&result.readlink3res_u.resok.symlink_attributes.post_op_attr_u.attributes, inode);
293 result.readlink3res_u.resok.data = inode->symlink_contents;
295 result.status = NFS3ERR_INVAL;
296 result.readlink3res_u.resfail.present = TRUE;
297 encode_fattr3(&result.readlink3res_u.resfail.post_op_attr_u.attributes, inode);
300 result.status = NFS3ERR_STALE;
303 async_rpc_send_reply(req, &result);
306 void nfsproc3_read_3_svc(read3args *argp, RPCRequest *req)
309 memset(&result, 0, sizeof(result));
312 BlueSkyInode *inode = lookup_fh(req, &argp->file);
314 result.status = NFS3ERR_STALE;
315 result.read3res_u.resfail.present = FALSE;
316 async_rpc_send_reply(req, &result);
320 int count = argp->count;
321 if (argp->offset >= inode->size) {
323 result.read3res_u.resok.eof = TRUE;
325 count = MIN(count, inode->size - argp->offset);
326 if (argp->offset + count == inode->size)
327 result.read3res_u.resok.eof = TRUE;
329 result.read3res_u.resok.eof = FALSE;
331 bluesky_file_read(inode, argp->offset, buf, count);
334 result.status = NFS3_OK;
335 result.read3res_u.resok.file_attributes.present = TRUE;
336 encode_fattr3(&result.read3res_u.resok.file_attributes.post_op_attr_u.attributes, inode);
337 result.read3res_u.resok.count = count;
338 result.read3res_u.resok.data.data_val = buf;
339 result.read3res_u.resok.data.data_len = count;
341 async_rpc_send_reply(req, &result);
344 void nfsproc3_write_3_svc(write3args *argp, RPCRequest *req)
347 memset(&result, 0, sizeof(result));
349 memset(&wcc, 0, sizeof(wcc));
351 BlueSkyInode *inode = lookup_fh(req, &argp->file);
353 result.status = NFS3ERR_STALE;
354 result.write3res_u.resfail = wcc;
355 async_rpc_send_reply(req, &result);
359 encode_pre_wcc(&wcc, inode);
360 if (inode->type != BLUESKY_REGULAR) {
361 result.status = NFS3ERR_INVAL;
362 result.write3res_u.resfail = wcc;
363 async_rpc_send_reply(req, &result);
367 uint64_t lastbyte = argp->offset + argp->count;
368 if (lastbyte > inode->size) {
369 bluesky_file_truncate(inode, lastbyte);
372 if (argp->data.data_len < argp->count) {
375 bluesky_file_write(inode, argp->offset,
376 argp->data.data_val, argp->count);
379 wcc.after.present = TRUE;
380 encode_fattr3(&wcc.after.post_op_attr_u.attributes, inode);
381 result.write3res_u.resok.file_wcc = wcc;
382 result.write3res_u.resok.count = argp->count;
383 result.write3res_u.resok.committed = FILE_SYNC;
385 async_rpc_send_reply(req, &result);
388 void nfsproc3_create_3_svc(create3args *argp, RPCRequest *req)
391 memset(&result, 0, sizeof(result));
393 memset(&wcc, 0, sizeof(wcc));
395 BlueSkyInode *dir = lookup_fh(req, &argp->where.dir);
397 result.status = NFS3ERR_STALE;
398 result.diropres3_u.resfail = wcc;
399 async_rpc_send_reply(req, &result);
403 encode_pre_wcc(&wcc, dir);
404 if (dir->type != BLUESKY_DIRECTORY) {
405 result.status = NFS3ERR_NOTDIR;
406 result.diropres3_u.resfail = wcc;
407 async_rpc_send_reply(req, &result);
411 if (!validate_filename(argp->where.name)
412 || strcmp(argp->where.name, ".") == 0
413 || strcmp(argp->where.name, "..") == 0)
415 result.status = NFS3ERR_EXIST;
416 result.diropres3_u.resfail = wcc;
417 async_rpc_send_reply(req, &result);
422 file = bluesky_new_inode(bluesky_fs_alloc_inode(fs), fs, BLUESKY_REGULAR);
425 int64_t time = bluesky_get_current_time();
426 printf("time: %"PRIi64"\n", time);
431 bluesky_insert_inode(fs, file);
432 bluesky_directory_insert(dir, argp->where.name, file->inum);
434 dir->mtime = dir->ctime = bluesky_get_current_time();
437 wcc.after.present = TRUE;
438 encode_fattr3(&wcc.after.post_op_attr_u.attributes, dir);
439 result.diropres3_u.resok.obj_attributes.present = TRUE;
440 encode_fattr3(&result.diropres3_u.resok.obj_attributes.post_op_attr_u.attributes, file);
441 result.diropres3_u.resok.dir_wcc = wcc;
444 fh_bytes = GUINT64_TO_BE(file->inum);
445 result.diropres3_u.resok.obj.present = TRUE;
446 result.diropres3_u.resok.obj.post_op_fh3_u.handle.data.data_len = 8;
447 result.diropres3_u.resok.obj.post_op_fh3_u.handle.data.data_val = (char *)&fh_bytes;
449 async_rpc_send_reply(req, &result);
452 void nfsproc3_mkdir_3_svc(mkdir3args *argp, RPCRequest *req)
455 memset(&result, 0, sizeof(result));
457 memset(&wcc, 0, sizeof(wcc));
459 BlueSkyInode *dir = lookup_fh(req, &argp->where.dir);
461 result.status = NFS3ERR_STALE;
462 result.diropres3_u.resfail = wcc;
463 async_rpc_send_reply(req, &result);
467 encode_pre_wcc(&wcc, dir);
468 if (dir->type != BLUESKY_DIRECTORY) {
469 result.status = NFS3ERR_NOTDIR;
470 result.diropres3_u.resfail = wcc;
471 async_rpc_send_reply(req, &result);
475 if (!validate_filename(argp->where.name)
476 || strcmp(argp->where.name, ".") == 0
477 || strcmp(argp->where.name, "..") == 0)
479 result.status = NFS3ERR_EXIST;
480 result.diropres3_u.resfail = wcc;
481 async_rpc_send_reply(req, &result);
486 file = bluesky_new_inode(bluesky_fs_alloc_inode(fs), fs, BLUESKY_DIRECTORY);
489 int64_t time = bluesky_get_current_time();
494 bluesky_insert_inode(fs, file);
495 bluesky_directory_insert(dir, argp->where.name, file->inum);
496 set_attributes(file, &argp->attributes);
498 dir->mtime = dir->ctime = bluesky_get_current_time();
501 wcc.after.present = TRUE;
502 encode_fattr3(&wcc.after.post_op_attr_u.attributes, dir);
503 result.diropres3_u.resok.obj_attributes.present = TRUE;
504 encode_fattr3(&result.diropres3_u.resok.obj_attributes.post_op_attr_u.attributes, file);
505 result.diropres3_u.resok.dir_wcc = wcc;
508 fh_bytes = GUINT64_TO_BE(file->inum);
509 result.diropres3_u.resok.obj.present = TRUE;
510 result.diropres3_u.resok.obj.post_op_fh3_u.handle.data.data_len = 8;
511 result.diropres3_u.resok.obj.post_op_fh3_u.handle.data.data_val = (char *)&fh_bytes;
513 async_rpc_send_reply(req, &result);
516 void nfsproc3_symlink_3_svc(symlink3args *argp, RPCRequest *req)
519 memset(&result, 0, sizeof(result));
521 memset(&wcc, 0, sizeof(wcc));
523 BlueSkyInode *dir = lookup_fh(req, &argp->where.dir);
525 result.status = NFS3ERR_STALE;
526 result.diropres3_u.resfail = wcc;
527 async_rpc_send_reply(req, &result);
531 encode_pre_wcc(&wcc, dir);
532 if (dir->type != BLUESKY_DIRECTORY) {
533 result.status = NFS3ERR_NOTDIR;
534 result.diropres3_u.resfail = wcc;
535 async_rpc_send_reply(req, &result);
539 if (!validate_filename(argp->where.name)
540 || strcmp(argp->where.name, ".") == 0
541 || strcmp(argp->where.name, "..") == 0)
543 result.status = NFS3ERR_EXIST;
544 result.diropres3_u.resfail = wcc;
545 async_rpc_send_reply(req, &result);
550 file = bluesky_new_inode(bluesky_fs_alloc_inode(fs), fs, BLUESKY_SYMLINK);
553 int64_t time = bluesky_get_current_time();
558 file->symlink_contents = g_strdup(argp->symlink.symlink_data);
559 bluesky_insert_inode(fs, file);
560 bluesky_directory_insert(dir, argp->where.name, file->inum);
562 dir->mtime = dir->ctime = bluesky_get_current_time();
565 wcc.after.present = TRUE;
566 encode_fattr3(&wcc.after.post_op_attr_u.attributes, dir);
567 result.diropres3_u.resok.obj_attributes.present = TRUE;
568 encode_fattr3(&result.diropres3_u.resok.obj_attributes.post_op_attr_u.attributes, file);
569 result.diropres3_u.resok.dir_wcc = wcc;
572 fh_bytes = GUINT64_TO_BE(file->inum);
573 result.diropres3_u.resok.obj.present = TRUE;
574 result.diropres3_u.resok.obj.post_op_fh3_u.handle.data.data_len = 8;
575 result.diropres3_u.resok.obj.post_op_fh3_u.handle.data.data_val = (char *)&fh_bytes;
577 async_rpc_send_reply(req, &result);
580 void nfsproc3_mknod_3_svc(mknod3args *argp, RPCRequest *req)
583 memset(&result, 0, sizeof(result));
585 result.status = NFS3ERR_NOTSUPP;
587 async_rpc_send_reply(req, &result);
590 void nfsproc3_remove_3_svc(diropargs3 *argp, RPCRequest *req)
593 memset(&result, 0, sizeof(result));
595 BlueSkyInode *dir = lookup_fh(req, &argp->dir);
597 result.status = NFS3ERR_STALE;
598 async_rpc_send_reply(req, &result);
602 encode_pre_wcc(&result.wccstat3_u.wcc, dir);
604 if (!validate_filename(argp->name)
605 || strcmp(argp->name, ".") == 0
606 || strcmp(argp->name, "..") == 0)
608 result.status = NFS3ERR_NOENT;
609 async_rpc_send_reply(req, &result);
613 /* TODO: Decrement link count, deallocate inode if needed. */
615 bluesky_directory_remove(dir, argp->name);
617 result.status = NFS3_OK;
618 result.wccstat3_u.wcc.after.present = TRUE;
619 encode_fattr3(&result.wccstat3_u.wcc.after.post_op_attr_u.attributes,
622 async_rpc_send_reply(req, &result);
625 void nfsproc3_rmdir_3_svc(diropargs3 *argp, RPCRequest *req)
628 memset(&result, 0, sizeof(result));
630 BlueSkyInode *dir = lookup_fh(req, &argp->dir);
632 result.status = NFS3ERR_STALE;
633 async_rpc_send_reply(req, &result);
637 encode_pre_wcc(&result.wccstat3_u.wcc, dir);
639 if (!validate_filename(argp->name)
640 || strcmp(argp->name, ".") == 0
641 || strcmp(argp->name, "..") == 0)
643 result.status = NFS3ERR_NOENT;
644 async_rpc_send_reply(req, &result);
648 uint64_t inum = bluesky_directory_lookup(dir, argp->name);
649 BlueSkyInode *inode = bluesky_get_inode(fs, inum);
651 result.status = NFS3ERR_NOENT;
652 async_rpc_send_reply(req, &result);
655 schedule_inode_unref(req, inode);
657 if (inode->type != BLUESKY_DIRECTORY) {
658 result.status = NFS3ERR_NOTDIR;
659 async_rpc_send_reply(req, &result);
662 if (g_sequence_get_length(inode->dirents) > 0) {
663 printf("Directory not empty: %d entries\n",
664 g_sequence_get_length(inode->dirents));
665 result.status = NFS3ERR_NOTEMPTY;
666 async_rpc_send_reply(req, &result);
670 /* TODO: Decrement link count, deallocate inode if needed. */
672 bluesky_directory_remove(dir, argp->name);
674 result.status = NFS3_OK;
675 result.wccstat3_u.wcc.after.present = TRUE;
676 encode_fattr3(&result.wccstat3_u.wcc.after.post_op_attr_u.attributes,
679 async_rpc_send_reply(req, &result);
682 void nfsproc3_rename_3_svc(rename3args *argp, RPCRequest *req)
685 memset(&result, 0, sizeof(result));
686 wcc_data *wcc1 = &result.rename3res_u.res.fromdir_wcc;
687 wcc_data *wcc2 = &result.rename3res_u.res.todir_wcc;
689 BlueSkyInode *dir1 = lookup_fh(req, &argp->from.dir);
691 result.status = NFS3ERR_STALE;
692 async_rpc_send_reply(req, &result);
695 encode_pre_wcc(wcc1, dir1);
697 BlueSkyInode *dir2 = lookup_fh(req, &argp->to.dir);
699 result.status = NFS3ERR_STALE;
700 async_rpc_send_reply(req, &result);
703 encode_pre_wcc(wcc2, dir1);
705 gboolean status = bluesky_rename(dir1, argp->from.name,
709 wcc1->after.present = TRUE;
710 encode_fattr3(&wcc1->after.post_op_attr_u.attributes, dir1);
711 wcc2->after.present = TRUE;
712 encode_fattr3(&wcc2->after.post_op_attr_u.attributes, dir2);
714 result.status = NFS3_OK;
716 result.status = NFS3ERR_PERM;
718 async_rpc_send_reply(req, &result);
721 void nfsproc3_link_3_svc(link3args *argp, RPCRequest *req)
724 memset(&result, 0, sizeof(result));
726 memset(&wcc, 0, sizeof(wcc));
728 BlueSkyInode *inode = lookup_fh(req, &argp->file);
730 result.status = NFS3ERR_STALE;
731 result.link3res_u.res.linkdir_wcc = wcc;
732 async_rpc_send_reply(req, &result);
736 BlueSkyInode *dir = lookup_fh(req, &argp->link.dir);
738 result.status = NFS3ERR_STALE;
739 result.link3res_u.res.linkdir_wcc = wcc;
740 async_rpc_send_reply(req, &result);
744 encode_pre_wcc(&wcc, dir);
745 if (dir->type != BLUESKY_DIRECTORY) {
746 result.status = NFS3ERR_NOTDIR;
747 result.link3res_u.res.linkdir_wcc = wcc;
748 async_rpc_send_reply(req, &result);
752 if (!validate_filename(argp->link.name)
753 || strcmp(argp->link.name, ".") == 0
754 || strcmp(argp->link.name, "..") == 0
755 || bluesky_directory_lookup(dir, argp->link.name) != 0)
757 result.status = NFS3ERR_EXIST;
758 result.link3res_u.res.linkdir_wcc = wcc;
759 async_rpc_send_reply(req, &result);
763 if (!bluesky_directory_insert(dir, argp->link.name, inode->inum)) {
764 result.status = NFS3ERR_EXIST;
765 result.link3res_u.res.linkdir_wcc = wcc;
766 async_rpc_send_reply(req, &result);
770 bluesky_inode_update_ctime(inode, 0);
772 result.status = NFS3_OK;
773 wcc.after.present = TRUE;
774 encode_fattr3(&wcc.after.post_op_attr_u.attributes, dir);
775 result.link3res_u.res.file_attributes.present = TRUE;
776 encode_fattr3(&result.link3res_u.res.file_attributes.post_op_attr_u.attributes, inode);
777 result.link3res_u.res.linkdir_wcc = wcc;
779 async_rpc_send_reply(req, &result);
782 gint bluesky_dirent_compare(gconstpointer a, gconstpointer b,
785 #define MAX_READDIR_DIRENTS 64
786 void nfsproc3_readdir_3_svc(readdir3args *argp, RPCRequest *req)
789 memset(&result, 0, sizeof(result));
791 BlueSkyInode *dir = lookup_fh(req, &argp->dir);
793 result.status = NFS3ERR_STALE;
794 result.readdir3res_u.resfail.present = FALSE;
795 async_rpc_send_reply(req, &result);
799 result.status = NFS3_OK;
800 result.readdir3res_u.resok.dir_attributes.present = TRUE;
801 encode_fattr3(&result.readdir3res_u.resok.dir_attributes.post_op_attr_u.attributes, dir);
802 memset(result.readdir3res_u.resok.cookieverf, 0,
803 sizeof(result.readdir3res_u.resok.cookieverf));
805 entry3 dirents[MAX_READDIR_DIRENTS];
808 BlueSkyDirent start = {NULL, NULL, argp->cookie, 0};
809 GSequenceIter *i = g_sequence_search(dir->dirents, &start,
810 bluesky_dirent_compare, NULL);
812 while (count < MAX_READDIR_DIRENTS && !g_sequence_iter_is_end(i)) {
813 BlueSkyDirent *d = g_sequence_get(i);
814 dirents[count].fileid = d->inum;
815 dirents[count].name = d->name;
816 dirents[count].cookie = d->cookie;
817 dirents[count].nextentry = NULL;
819 dirents[count - 1].nextentry = &dirents[count];
820 i = g_sequence_iter_next(i);
825 result.readdir3res_u.resok.reply.entries = &dirents[0];
827 result.readdir3res_u.resok.reply.entries = NULL;
828 result.readdir3res_u.resok.reply.eof = g_sequence_iter_is_end(i);
830 async_rpc_send_reply(req, &result);
833 void nfsproc3_readdirplus_3_svc(readdirplus3args *argp, RPCRequest *req)
835 /* XDR-encoded sizes:
836 * post_op_attr: 88 bytes
837 * base readdirplus3resok: 88 + 16 bytes
838 * base directory entry: 24 bytes + filename
839 * attributes/fh3: 88 + 8 + filehandle size
841 size_t dircount = 88 + 16, attrcount = 0;
842 readdirplus3res result;
843 memset(&result, 0, sizeof(result));
845 BlueSkyInode *dir = lookup_fh(req, &argp->dir);
847 result.status = NFS3ERR_STALE;
848 result.readdirplus3res_u.resfail.present = FALSE;
849 async_rpc_send_reply(req, &result);
853 result.status = NFS3_OK;
854 result.readdirplus3res_u.resok.dir_attributes.present = TRUE;
855 encode_fattr3(&result.readdirplus3res_u.resok.dir_attributes.post_op_attr_u.attributes, dir);
856 memset(result.readdirplus3res_u.resok.cookieverf, 0,
857 sizeof(result.readdirplus3res_u.resok.cookieverf));
859 entryplus3 dirents[MAX_READDIR_DIRENTS];
860 uint64_t fh_bytes[MAX_READDIR_DIRENTS];
863 /* TODO: Handle dircount, maxcount arguments from client. */
865 BlueSkyDirent start = {NULL, NULL, argp->cookie, 0};
866 GSequenceIter *i = g_sequence_search(dir->dirents, &start,
867 bluesky_dirent_compare, NULL);
869 while (count < MAX_READDIR_DIRENTS && !g_sequence_iter_is_end(i)) {
870 BlueSkyDirent *d = g_sequence_get(i);
871 BlueSkyInode *inode = bluesky_get_inode(fs, d->inum);
873 dircount += 24 + ((strlen(d->name) + 3) & ~3);
874 attrcount += 88 + 8 + 8;
875 if (dircount > argp->dircount
876 || dircount + attrcount > argp->maxcount)
878 dirents[count].fileid = d->inum;
879 dirents[count].name = d->name;
880 dirents[count].cookie = d->cookie;
881 dirents[count].nextentry = NULL;
882 dirents[count].name_attributes.present = TRUE;
883 encode_fattr3(&dirents[count].name_attributes.post_op_attr_u.attributes, inode);
884 fh_bytes[count] = GUINT64_TO_BE(d->inum);
885 dirents[count].name_handle.present = TRUE;
886 dirents[count].name_handle.post_op_fh3_u.handle.data.data_len = 8;
887 dirents[count].name_handle.post_op_fh3_u.handle.data.data_val
888 = (char *)&fh_bytes[count];
890 dirents[count - 1].nextentry = &dirents[count];
892 bluesky_inode_unref(inode);
894 i = g_sequence_iter_next(i);
898 result.readdirplus3res_u.resok.reply.entries = &dirents[0];
900 result.readdirplus3res_u.resok.reply.entries = NULL;
901 result.readdirplus3res_u.resok.reply.eof = g_sequence_iter_is_end(i);
903 async_rpc_send_reply(req, &result);
906 void nfsproc3_fsstat_3_svc(nfs_fh3 *argp, RPCRequest *req)
909 memset(&result, 0, sizeof(result));
911 BlueSkyInode *inode = lookup_fh(req, argp);
913 result.status = NFS3ERR_STALE;
914 result.fsstat3res_u.resfail.present = FALSE;
915 async_rpc_send_reply(req, &result);
919 result.status = NFS3_OK;
920 result.fsstat3res_u.resok.obj_attributes.present = TRUE;
921 encode_fattr3(&result.fsstat3res_u.resok.obj_attributes.post_op_attr_u.attributes, inode);
923 result.fsstat3res_u.resok.tbytes = (1 << 30);
924 result.fsstat3res_u.resok.fbytes = (1 << 30);
925 result.fsstat3res_u.resok.abytes = (1 << 30);
926 result.fsstat3res_u.resok.tfiles = 0;
927 result.fsstat3res_u.resok.ffiles = 0;
928 result.fsstat3res_u.resok.afiles = 0;
929 result.fsstat3res_u.resok.invarsec = 0;
931 async_rpc_send_reply(req, &result);
934 void nfsproc3_fsinfo_3_svc(nfs_fh3 *argp, RPCRequest *req)
937 memset(&result, 0, sizeof(result));
939 BlueSkyInode *inode = bluesky_get_inode(fs, 1);
940 result.status = NFS3_OK;
941 result.fsinfo3res_u.resok.obj_attributes.present = TRUE;
942 encode_fattr3(&result.fsinfo3res_u.resok.obj_attributes.post_op_attr_u.attributes, inode);
943 result.fsinfo3res_u.resok.rtmax = 32768;
944 result.fsinfo3res_u.resok.rtpref = 32768;
945 result.fsinfo3res_u.resok.rtmult = 4096;
946 result.fsinfo3res_u.resok.wtmax = 32768;
947 result.fsinfo3res_u.resok.wtpref = 32768;
948 result.fsinfo3res_u.resok.wtmult = 4096;
949 result.fsinfo3res_u.resok.dtpref = 4096;
950 result.fsinfo3res_u.resok.maxfilesize = 0x7fffffffffffffffULL;
951 result.fsinfo3res_u.resok.time_delta.seconds = 0;
952 result.fsinfo3res_u.resok.time_delta.nseconds = 1000;
953 result.fsinfo3res_u.resok.properties
954 = FSF3_LINK | FSF3_SYMLINK | FSF3_HOMOGENEOUS | FSF3_CANSETTIME;
955 bluesky_inode_unref(inode);
957 async_rpc_send_reply(req, &result);
960 void nfsproc3_pathconf_3_svc(nfs_fh3 *argp, RPCRequest *req)
963 memset(&result, 0, sizeof(result));
965 BlueSkyInode *inode = bluesky_get_inode(fs, 1);
966 result.status = NFS3_OK;
967 result.pathconf3res_u.resok.obj_attributes.present = TRUE;
968 encode_fattr3(&result.pathconf3res_u.resok.obj_attributes.post_op_attr_u.attributes, inode);
969 result.pathconf3res_u.resok.linkmax = 0xffffffff;
970 result.pathconf3res_u.resok.name_max = 255;
971 result.pathconf3res_u.resok.no_trunc = TRUE;
972 result.pathconf3res_u.resok.chown_restricted = TRUE;
973 result.pathconf3res_u.resok.case_insensitive = FALSE;
974 result.pathconf3res_u.resok.case_preserving = TRUE;
975 bluesky_inode_unref(inode);
977 async_rpc_send_reply(req, &result);
980 void nfsproc3_commit_3_svc(commit3args *argp, RPCRequest *req)
983 memset(&result, 0, sizeof(result));
985 result.status = NFS3ERR_NOTSUPP;
987 async_rpc_send_reply(req, &result);