Beispiel #1
0
/*
 * 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(&current->mm->mmap_sem);
	err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
			     &cs->pg, NULL);
	up_read(&current->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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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;
}