/* * resmgr_echo_bug.c * * Created on: 15.03.2012 */ #include #include #include #include #include #include #include #include #include const int MAX_CHILDS = 5; struct myentry{ const char* name; struct myentry** childs; int childcount; iofunc_attr_t attr; }; #define ALIGN_TO 4 #define AL_C (ALIGN_TO - 1) #define ALIGN_DIRENT(x) (((x) + AL_C) & ~AL_C) const int FIRST_DIR_NODEID = 1; struct myentry DIRENTRIES[] = {{"", NULL, 0}, {"test", NULL, 0}}; const int DIRENT_COUNT = sizeof(DIRENTRIES) / sizeof(DIRENTRIES[0]); struct myentry* root = DIRENTRIES; #define FIRST_FILE_NODEID (FIRST_DIR_NODEID + DIRENT_COUNT) struct myentry FILEENTRIES[] = {{"file1"}, {"test/f"}, {"test/ff"}}; const int FILEENT_COUNT = sizeof(FILEENTRIES) / sizeof(FILEENTRIES[0]); #define OUT_OF_RANGE (FIRST_FILE_NODEID + FILEENT_COUNT) //const char* ENTRIES_IN int dirent_size(const char* dirent_name){ int dnameoffs = offsetof(struct dirent, d_name) + strlen(dirent_name) + 1; return (ALIGN_DIRENT(dnameoffs)); } void addentry(struct myentry* parent, struct myentry* child, mode_t mode, int nodeid){ if (parent == NULL || child == NULL) return; if (parent->childs == NULL) parent->childs = (struct myentry**)malloc(sizeof(struct myentry) * MAX_CHILDS); if (parent->childcount >= MAX_CHILDS) return; parent->childs[parent->childcount++] = child; iofunc_attr_init(&child->attr, mode, NULL, NULL); child->attr.inode = nodeid; } struct dirent* dirent_fill (struct dirent *dp, int inode, int offset, const char *fname, int size){ dp->d_ino = inode; dp->d_offset = offset; strcpy (dp->d_name, fname); dp->d_namelen = strlen (dp->d_name); dp->d_reclen = size; printf("namelen %d reclen %d\n", dp->d_namelen, dp->d_reclen); return ((struct dirent *) ((char *) dp + size)); } int handle_readdir(resmgr_context_t *ctp, io_read_t *msg, iofunc_ocb_t* ocb, struct myentry* entry){ char* reply = (char*)malloc(msg->i.nbytes); if (reply == NULL) return ENOMEM; struct dirent* de = (struct dirent*)reply; int diritems = entry->childcount; int left = msg->i.nbytes; printf("request size: %d, diritems = %d offset = %d\n", left, diritems, (int)ocb->offset); while (ocb->offset < diritems){ struct myentry* se = entry->childs[ocb->offset]; const char* name = strrchr(se->name, '/'); const char* realname = (name == NULL) ? se->name : name + 1; int dsize = dirent_size(realname); printf("name %s, ocboffset %d inode %d\n", realname, (int)ocb->offset, (int)se->attr.inode); if (left - dsize < 0) break; left -= dsize; char* prev = (char*)de; de = dirent_fill(de, se->attr.inode, ocb->offset, realname, dsize); ocb->offset++; printf("dirent off %d, dirent size %d\n", (char*)de - prev, dsize); } int rsize = (char*)de - reply; printf("readdir reply size %d\n", rsize); const void * realrep = (rsize) ? reply : NULL; if (-1 == MsgReply(ctp->rcvid, rsize, realrep, rsize)){ perror("!!!!!readdir MsgReply"); } free(reply); return _RESMGR_NOREPLY; } int handle_readfile(resmgr_context_t *ctp, io_read_t *msg, iofunc_ocb_t* ocb, struct myentry* entry){ return ENOTSUP; } int io_read(resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *oc){ iofunc_ocb_t* ocb = (iofunc_ocb_t*)oc; struct myentry* entry; int err; if ((err = iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK) return err; //Получаем нашу entry из inode int inode = ocb->attr->inode; if (inode > OUT_OF_RANGE || inode <= 0) return EINVAL; if (inode > FIRST_FILE_NODEID){ entry = FILEENTRIES + (inode - FIRST_FILE_NODEID); return handle_readfile(ctp, msg, ocb, entry); } entry = DIRENTRIES + (inode - FIRST_DIR_NODEID); return handle_readdir(ctp, msg, ocb, entry); } iofunc_attr_t* find_attr(const char* path){ int i=0; for (i=0; iconnect.path; int ret; iofunc_attr_t* attr; printf("Open path %s\n", path); if ((attr = find_attr(path)) == NULL) return ENOENT; return iofunc_open_default(context, piopen, attr, parg); } int create_directory_resmgr(){ dispatch_t* tdisp; if (NULL == (tdisp = dispatch_create())){ perror("dispatch_create"); return 1; } resmgr_attr_t mattr; memset(&mattr, 0, sizeof(mattr)); mattr.msg_max_size = 1024 * 1024; mattr.nparts_max = 1; resmgr_connect_funcs_t mconfunc; resmgr_io_funcs_t miofunc; iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &mconfunc, _RESMGR_IO_NFUNCS, &miofunc); mconfunc.open = handle_ioopen; miofunc.read = io_read; memset(&root->attr, 0, sizeof(iofunc_attr_t)); iofunc_attr_init(&root->attr, S_IFDIR | 0555, 0, 0); root->attr.inode = FIRST_DIR_NODEID; int ret = resmgr_attach(tdisp, &mattr, "/dev/bucase", _FTYPE_ANY, _RESMGR_FLAG_DIR, &mconfunc, &miofunc, &root->attr); if (ret == -1){ perror("resmgr_attach"); return 1; } resmgr_context_t* mcontext = resmgr_context_alloc(tdisp); while(1){ if ((mcontext = resmgr_block(mcontext)) == NULL){ perror("resmgr_block"); return 1; } resmgr_handler(mcontext); } return 0; } void fill_entries(){ addentry(root, DIRENTRIES + 1, S_IFDIR | 0555, FIRST_DIR_NODEID + 1); addentry(root, FILEENTRIES, S_IFREG | 0666, FIRST_FILE_NODEID); addentry(DIRENTRIES + 1, FILEENTRIES + 1, S_IFREG | 0666, FIRST_FILE_NODEID + 1); addentry(DIRENTRIES + 1, FILEENTRIES + 2, S_IFREG | 0666, FIRST_FILE_NODEID + 2); } int main(){ fill_entries(); return create_directory_resmgr(); }