/* * Get another pagefull of userspace buffer, and map it to kernel * address space, and lock request */ static int fuse_copy_fill(struct fuse_copy_state *cs) { unsigned long offset; int err; unlock_request(cs->fc, cs->req); fuse_copy_finish(cs); if (!cs->seglen) { BUG_ON(!cs->nr_segs); cs->seglen = cs->iov[0].iov_len; cs->addr = (unsigned long) cs->iov[0].iov_base; cs->iov ++; cs->nr_segs --; } down_read(¤t->mm->mmap_sem); err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, &cs->pg, NULL); up_read(¤t->mm->mmap_sem); if (err < 0) return err; BUG_ON(err != 1); offset = cs->addr % PAGE_SIZE; cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); cs->buf = cs->mapaddr + offset; cs->len = min(PAGE_SIZE - offset, cs->seglen); cs->seglen -= cs->len; cs->addr += cs->len; return lock_request(cs->fc, cs->req); }
int protocol_recv_request_send_reply (struct connection *conn) { int r; struct request request; uint16_t cmd, flags; uint32_t magic, count, error = 0; uint64_t offset; char *buf = NULL; CLEANUP_EXTENTS_FREE struct nbdkit_extents *extents = NULL; /* Read the request packet. */ { ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&conn->read_lock); r = connection_get_status (conn); if (r <= 0) return r; r = conn->recv (conn, &request, sizeof request); if (r == -1) { nbdkit_error ("read request: %m"); return connection_set_status (conn, -1); } if (r == 0) { debug ("client closed input socket, closing connection"); return connection_set_status (conn, 0); /* disconnect */ } magic = be32toh (request.magic); if (magic != NBD_REQUEST_MAGIC) { nbdkit_error ("invalid request: 'magic' field is incorrect (0x%x)", magic); return connection_set_status (conn, -1); } flags = be16toh (request.flags); cmd = be16toh (request.type); offset = be64toh (request.offset); count = be32toh (request.count); if (cmd == NBD_CMD_DISC) { debug ("client sent %s, closing connection", name_of_nbd_cmd (cmd)); return connection_set_status (conn, 0); /* disconnect */ } /* Validate the request. */ if (!validate_request (conn, cmd, flags, offset, count, &error)) { if (cmd == NBD_CMD_WRITE && skip_over_write_buffer (conn->sockin, count) < 0) return connection_set_status (conn, -1); goto send_reply; } /* Get the data buffer used for either read or write requests. * This is a common per-thread data buffer, it must not be freed. */ if (cmd == NBD_CMD_READ || cmd == NBD_CMD_WRITE) { buf = threadlocal_buffer ((size_t) count); if (buf == NULL) { error = ENOMEM; if (cmd == NBD_CMD_WRITE && skip_over_write_buffer (conn->sockin, count) < 0) return connection_set_status (conn, -1); goto send_reply; } } /* Allocate the extents list for block status only. */ if (cmd == NBD_CMD_BLOCK_STATUS) { extents = nbdkit_extents_new (offset, conn->exportsize); if (extents == NULL) { error = ENOMEM; goto send_reply; } } /* Receive the write data buffer. */ if (cmd == NBD_CMD_WRITE) { r = conn->recv (conn, buf, count); if (r == 0) { errno = EBADMSG; r = -1; } if (r == -1) { nbdkit_error ("read data: %s: %m", name_of_nbd_cmd (cmd)); return connection_set_status (conn, -1); } } } /* Perform the request. Only this part happens inside the request lock. */ if (quit || !connection_get_status (conn)) { error = ESHUTDOWN; } else { lock_request (conn); error = handle_request (conn, cmd, flags, offset, count, buf, extents); assert ((int) error >= 0); unlock_request (conn); } /* Send the reply packet. */ send_reply: if (connection_get_status (conn) < 0) return -1; if (error != 0) { /* Since we're about to send only the limited NBD_E* errno to the * client, don't lose the information about what really happened * on the server side. Make sure there is a way for the operator * to retrieve the real error. */ debug ("sending error reply: %s", strerror (error)); } /* Currently we prefer to send simple replies for everything except * where we have to (ie. NBD_CMD_READ and NBD_CMD_BLOCK_STATUS when * structured_replies have been negotiated). However this prevents * us from sending human-readable error messages to the client, so * we should reconsider this in future. */ if (conn->structured_replies && (cmd == NBD_CMD_READ || cmd == NBD_CMD_BLOCK_STATUS)) { if (!error) { if (cmd == NBD_CMD_READ) return send_structured_reply_read (conn, request.handle, cmd, buf, count, offset); else /* NBD_CMD_BLOCK_STATUS */ return send_structured_reply_block_status (conn, request.handle, cmd, flags, count, offset, extents); } else return send_structured_reply_error (conn, request.handle, cmd, flags, error); } else return send_simple_reply (conn, request.handle, cmd, buf, count, error); }
int main (int argc, char ** argv) { BOOL status = NO; Cmdline * opt = NULL; Cmdline * arg = NULL; /* Create a new premptive client */ Init(); /* Handle command line args */ if (argc >= 3) { arg = opt = handle_args (argc,argv); if (opt && arg) { HTPrint ("method: %c (func %d)\n",opt->method,opt->func); HTPrint ("\tDepth: %s \n\tTimeout: %s \n",(opt->D)?opt->D:"UNDEFINED", \ (opt->T)?opt->T:"UNDEFINED"); HTPrint ("\tIf: %s \n\tOverwrite: %c \n",(opt->I)?opt->I:"UNDEFINED",opt->O); HTPrint ("\tRequest URI: %s%s \n",(arg->base_str)?arg->base_str:"", \ arg->request_uri); HTPrint ("\t1° argument: %s \n\t2° argument: %s\n",(arg->arg1)?arg->arg1:"UNDEFINED", (arg->arg2)?arg->arg2:"UNDEFINED"); } else { HTPrint ("Bad argument\n"); return -1; } }//if argc>3 else { HTPrint ("Usage: \n"); HTPrint ("%s <method> <method_function> [options_headers] <function_arguments>\n\n",argv[0]); HTPrint ("methods are: -[lufpkcm]\n"); HTPrint ("method_function are: -[1-4] (see functions order in HTDAV.html)\n"); HTPrint ("options_headers are:\n"); HTPrint ("\t-D <depth_header_value> (for Depth header)\n"); HTPrint ("\t-T <timeout_header_value> (for Timeout header)\n"); HTPrint ("\t-I <if_header_value> (for If header)\n"); HTPrint ("\t-O <'T' | 'F'> (for Overwrite header)\n\n"); HTPrint ("function_arguments are: \n"); HTPrint ("for LOCK: %s -l -<[1-3]> [options] <dest-uri> <owner|\"REFRESH\"> \n",argv[0]); HTPrint ("\t %s -l -4 [options] <relative-uri> <base_uri> <owner|\"REFRESH\">\n",argv[0]); HTPrint ("\t example: %s -l -4 -D 0 /dav_collection/myfile.html http://foo.bar/ mailto:[email protected]\n\n",argv[0]); HTPrint ("for UNLOCK: %s -u -<[1-2]> [options] <dest-uri> <lock-token>\n",argv[0]); HTPrint ("\t %s -u -3 [options] <relative-uri> <base-uri> <lock-token> \n",argv[0]); HTPrint ("\t example: %s -u -3 /dav_collection/myfile.html http://foo.bar/ <opaquelocken:blablabla>\n\n",argv[0]); HTPrint ("for PROPFIND:%s -f -<[1-3]> [options] <dest-uri> [\"allprop\"|\"propname\"|xml body]\n",\ argv[0]); HTPrint ("\t %s -f -4 [options] <relative-uri> <base-uri> [\"allprop\"|\"propname\"|xml body]\n",\ argv[0]); HTPrint ("\t example: %s -f -4 -D 0 /dav_collection/myfile.html http://foo.bar/ allprop\n\n",argv[0]); HTPrint ("for PROPPATCH:%s -p -<[1-4]> [options] <dest-uri> <xml body>\n",argv[0]); HTPrint ("\t %s -p -4 [options] <relative-uri> <base-uri> <xml body>\n",argv[0]); HTPrint ("\t example: %s -p -4 -I <opaquelock:blablabla> /dav_collection/myfile.html http://foo.bar/\\ \n " "\"<?xml version='1.0'?>\n <D:propertyupdate xmlns:D='DAV:' xmlns:Z='http://foo.bar/propertydtd/'>\n" " <D:set>\n <D:prop>\n <Z:author> MyName </Z:author>\n </D:prop>\n <D:set>\n" "</D:propertyupdate>\" \n\n",argv[0]); HTPrint ("for MKCOL: %s -k -<[1-2]> [options] <dest-uri>\n",argv[0]); HTPrint ("\t %s -k -3 [options] <relative-uri> <base-uri>\n",argv[0]); HTPrint ("\t example: %s -k -3 /dav_collection/newcollection http://foo.bar/\n\n",argv[0]); HTPrint ("for COPY: %s -c -<[1-3]> [options] <src-uri> <dst-uri> <xml body|\"NOBODY\">\n",\ argv[0]); HTPrint ("\t %s -c -4 [options] <relative-uri> <base-uri> <dst-uri> <xml body|\"NOBODY\">\n",\ argv[0]); HTPrint ("\t example: %s -c -4 /dav_collection/myfile.html http://foo.bar/ http://foo.bar/copyfile.html NOBODY\n\n",argv[0]); HTPrint ("for MOVE: %s -m -<[1-3]> [options] <src-uri> <dst-uri> <xml body|\"NOBODY\">\n", argv[0]); HTPrint ("\t %s -m -4 [options] <relative-uri> <base-uri> <dst-uri> <xml body|\"NOBODY\">\n",\ argv[0]); HTPrint ("\t example: %s -m -4 /dav_collection/myfile.html http://foo.bar/ http://foo.bar/movefile.html NOBODY\n\n",argv[0]); HTPrint ("If, Depth and Timeout headers as defined in RFC2518 section 9\n"); HTPrint ("lock-token as defined in RFC2518 section 9.5\n"); HTPrint ("xml body as defined in RFC2518 section 12\n\n"); return -1; } if (arg) { switch (arg->method) { case 'l': HTPrint ("LOCK REQUEST\n"); if (arg->arg1) { arg->arg1 = (!strcasecomp(arg->arg1,"REFRESH"))?NULL:arg->arg1; status = lock_request (arg); } else HTPrint ("Bad argument! Please, execute %s for help\n",argv[0]); break; case 'u': HTPrint ("UNLOCK REQUEST\n"); status = unlock_request (arg); break; case 'f': HTPrint ("PROPFIND REQUEST\n"); status = propfind_request (arg); break; case 'p': HTPrint ("PROPPATCH REQUEST\n"); status = proppatch_request (arg); break; case 'k': HTPrint ("MKCOL REQUEST\n"); status = mkcol_request (arg); break; case 'c': HTPrint ("COPY REQUEST\n"); if (arg->arg1) { arg->arg2 = (!strcasecomp(arg->arg2,"NOBODY"))?NULL:arg->arg2; status = copy_request (arg); } else HTPrint ("Bad argument! Please, execute %s for help\n",argv[0]); break; case 'm': HTPrint ("MOVE REQUEST\n"); if (arg->arg1) { arg->arg2 = (!strcasecomp(arg->arg2,"NOBODY"))?NULL:arg->arg2; status = move_request (arg); } else HTPrint ("Bad argument! Please, execute %s for help...\n",argv[0]); break; } if (status) HTEventList_newLoop(); else HTPrint ("FAILED\n"); HT_FREE (arg); } return 0; }