# # Parser for XML-RPC call and response # # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # $Id$ # require "date" require "xmlrpc/base64" require "xmlrpc/datetime" # add some methods to NQXML::Node module NQXML class Node def removeChild(node) @children.delete(node) end def childNodes @children end def hasChildNodes not @children.empty? end def [] (index) @children[index] end def nodeType if @entity.instance_of? NQXML::Text then :TEXT elsif @entity.instance_of? NQXML::Comment then :COMMENT #elsif @entity.instance_of? NQXML::Element then :ELEMENT elsif @entity.instance_of? NQXML::Tag then :ELEMENT else :ELSE end end def nodeValue #TODO: error when wrong Entity-type @entity.text end def nodeName #TODO: error when wrong Entity-type @entity.name end end # class Node end # module NQXML module XMLRPC class FaultException < StandardError attr_reader :faultCode, :faultString def initialize(faultCode, faultString) @faultCode = faultCode @faultString = faultString end # returns a hash def to_h {"faultCode" => @faultCode, "faultString" => @faultString} end end module Convert def self.int(str) str.to_i end def self.boolean(str) case str when "0" then false when "1" then true else raise "RPC-value of type boolean is wrong" end end def self.double(str) str.to_f end def self.dateTime(str) if str =~ /^(-?\d\d\d\d)(\d\d)(\d\d)T(\d\d):(\d\d):(\d\d)$/ then # TODO: Time.gm ??? .local ??? a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i} XMLRPC::DateTime.new(*a) #if a[0] >= 1970 then # Time.gm(*a) #else # Date.new(*a[0,3]) #end else raise "wrong dateTime.iso8601 format" end end def self.base64(str) XMLRPC::Base64.decode(str) end def self.struct(hash) # convert to marhalled object klass = hash["___class___"] if klass.nil? or Config::ENABLE_MARSHALLING == false hash else begin mod = Module klass.split("::").each {|const| mod = mod.const_get(const.strip)} Thread.critical = true # let initialize take 0 parameters mod.module_eval %{ begin alias __initialize initialize rescue NameError end def initialize; end } obj = mod.new # restore old initialize mod.module_eval %{ undef initialize begin alias initialize __initialize rescue NameError end } Thread.critical = false hash.delete "___class___" hash.each {|k,v| obj.__set_instance_variable(k, v) } obj rescue hash end end end def self.fault(hash) if hash.kind_of? Hash and hash.size == 2 and hash.has_key? "faultCode" and hash.has_key? "faultString" and hash["faultCode"].kind_of? Integer and hash["faultString"].kind_of? String XMLRPC::FaultException.new(hash["faultCode"], hash["faultString"]) else raise "wrong fault-structure: #{hash.inspect}" end end end # module Convert module XMLParser class AbstractTreeParser def parseMethodResponse(str) methodResponse_document(createCleanedTree(str)) end def parseMethodCall(str) methodCall_document(createCleanedTree(str)) end private # # remove all whitespaces but in the tags i4, int, boolean.... # and all comments # def removeWhitespacesAndComments(node) remove = [] childs = node.childNodes.to_a childs.each do |nd| case _nodeType(nd) when :TEXT # TODO: add nil? unless %w(i4 int boolean string double dateTime.iso8601 base64).include? node.nodeName if node.nodeName == "value" if not node.childNodes.to_a.detect {|n| _nodeType(n) == :ELEMENT}.nil? remove << nd if nd.nodeValue.strip == "" end else remove << nd if nd.nodeValue.strip == "" end end when :COMMENT remove << nd else removeWhitespacesAndComments(nd) end end remove.each { |i| node.removeChild(i) } end def nodeMustBe(node, name) cmp = case name when Array name.include?(node.nodeName) when String name == node.nodeName else raise "error" end if not cmp then raise "wrong xml-rpc (name)" end node end # # returns, when successfully the only child-node # def hasOnlyOneChild(node, name=nil) if node.childNodes.to_a.size != 1 raise "wrong xml-rpc (size)" end if name != nil then nodeMustBe(node.firstChild, name) end end def assert(b) if not b then raise "assert-fail" end end # the node `node` has empty string or string def text_zero_one(node) nodes = node.childNodes.to_a.size if nodes == 1 text(node.firstChild) elsif nodes == 0 "" else raise "wrong xml-rpc (size)" end end def integer(node) #TODO: check string for float because to_i returnsa # 0 when wrong string nodeMustBe(node, %w(i4 int)) hasOnlyOneChild(node) Convert.int(text(node.firstChild)) end def boolean(node) nodeMustBe(node, "boolean") hasOnlyOneChild(node) Convert.boolean(text(node.firstChild)) end def v_nil(node) nodeMustBe(node, "nil") assert( node.childNodes.to_a.size == 0 ) nil end def string(node) nodeMustBe(node, "string") text_zero_one(node) end def double(node) #TODO: check string for float because to_f returnsa # 0.0 when wrong string nodeMustBe(node, "double") hasOnlyOneChild(node) Convert.double(text(node.firstChild)) end def dateTime(node) nodeMustBe(node, "dateTime.iso8601") hasOnlyOneChild(node) Convert.dateTime( text(node.firstChild) ) end def base64(node) nodeMustBe(node, "base64") #hasOnlyOneChild(node) Convert.base64(text_zero_one(node)) end def member(node) nodeMustBe(node, "member") assert( node.childNodes.to_a.size == 2 ) [ name(node[0]), value(node[1]) ] end def name(node) nodeMustBe(node, "name") #hasOnlyOneChild(node) text_zero_one(node) end def array(node) nodeMustBe(node, "array") hasOnlyOneChild(node, "data") data(node.firstChild) end def data(node) nodeMustBe(node, "data") node.childNodes.to_a.collect do |val| value(val) end end def param(node) nodeMustBe(node, "param") hasOnlyOneChild(node, "value") value(node.firstChild) end def methodResponse(node) nodeMustBe(node, "methodResponse") hasOnlyOneChild(node, %w(params fault)) child = node.firstChild case child.nodeName when "params" [ true, params(child,false) ] when "fault" [ false, fault(child) ] else raise "unexpected error" end end def methodName(node) nodeMustBe(node, "methodName") hasOnlyOneChild(node) text(node.firstChild) end def params(node, call=true) nodeMustBe(node, "params") if call node.childNodes.to_a.collect do |n| param(n) end else # response (only one param) hasOnlyOneChild(node) param(node.firstChild) end end def fault(node) nodeMustBe(node, "fault") hasOnlyOneChild(node, "value") f = value(node.firstChild) Convert.fault(f) end # _nodeType is defined in the subclass def text(node) assert( _nodeType(node) == :TEXT ) assert( node.hasChildNodes == false ) assert( node.nodeValue != nil ) node.nodeValue.to_s end def struct(node) nodeMustBe(node, "struct") hash = {} node.childNodes.to_a.each do |me| n, v = member(me) hash[n] = v end Convert.struct(hash) end def value(node) nodeMustBe(node, "value") nodes = node.childNodes.to_a.size if nodes == 0 return "" elsif nodes > 1 raise "wrong xml-rpc (size)" end child = node.firstChild case _nodeType(child) when :TEXT text_zero_one(node) when :ELEMENT case child.nodeName when "i4", "int" then integer(child) when "boolean" then boolean(child) when "string" then string(child) when "double" then double(child) when "dateTime.iso8601" then dateTime(child) when "base64" then base64(child) when "struct" then struct(child) when "array" then array(child) when "nil" if Config::ENABLE_NIL_PARSER v_nil(child) else raise "wrong/unknown XML-RPC type 'nil'" end else raise "wrong/unknown XML-RPC type" end else raise "wrong type of node" end end def methodCall(node) nodeMustBe(node, "methodCall") assert( (1..2).include?( node.childNodes.to_a.size ) ) name = methodName(node[0]) if node.childNodes.to_a.size == 2 then pa = params(node[1]) else # no parameters given pa = [] end [name, pa] end end # module TreeParserMixin class AbstractStreamParser def parseMethodResponse(str) parser = @parser_class.new parser.parse(str) raise "No valid method response!" if parser.method_name != nil if parser.fault != nil # is a fault structure [false, parser.fault] else # is a normal return value raise "Missing return value!" if parser.params.size == 0 raise "Too many return values. Only one allowed!" if parser.params.size > 1 [true, parser.params[0]] end end def parseMethodCall(str) parser = @parser_class.new parser.parse(str) raise "No valid method call - missing method name!" if parser.method_name.nil? [parser.method_name, parser.params] end end module StreamParserMixin attr_reader :params attr_reader :method_name attr_reader :fault def initialize(*a) super(*a) @params = [] @values = [] @val_stack = [] @names = [] @name = [] @structs = [] @struct = {} @method_name = nil @fault = nil @data = nil end def startElement(name, attrs=[]) @data = nil case name when "value" @value = nil when "nil" raise "wrong/unknown XML-RPC type 'nil'" unless Config::ENABLE_NIL_PARSER @value = :nil when "array" @val_stack << @values @values = [] when "struct" @names << @name @name = [] @structs << @struct @struct = {} end end def endElement(name) @data ||= "" case name when "string" @value = @data when "i4", "int" @value = Convert.int(@data) when "boolean" @value = Convert.boolean(@data) when "double" @value = Convert.double(@data) when "dateTime.iso8601" @value = Convert.dateTime(@data) when "base64" @value = Convert.base64(@data) when "value" @value = @data if @value.nil? @values << (@value == :nil ? nil : @value) when "array" @value = @values @values = @val_stack.pop when "struct" @value = Convert.struct(@struct) @name = @names.pop @struct = @structs.pop when "name" @name[0] = @data when "member" @struct[@name[0]] = @values.pop when "param" @params << @values[0] @values = [] when "fault" @fault = Convert.fault(@values[0]) when "methodName" @method_name = @data end @data = nil end def character(data) if @data @data << data else @data = data end end end # module StreamParserMixin # --------------------------------------------------------------------------- class XMLStreamParser < AbstractStreamParser def initialize require "xmlparser" eval %{ class XMLRPCParser < ::XMLParser include StreamParserMixin end } @parser_class = XMLRPCParser end end # class XMLStreamParser # --------------------------------------------------------------------------- class NQXMLStreamParser < AbstractStreamParser def initialize require "nqxml/streamingparser" @parser_class = XMLRPCParser end class XMLRPCParser include StreamParserMixin def parse(str) parser = NQXML::StreamingParser.new(str) parser.each do |ele| case ele when NQXML::Text @data = ele.text #character(ele.text) when NQXML::Tag if ele.isTagEnd endElement(ele.name) else startElement(ele.name, ele.attrs) end end end # do end # method parse end # class XMLRPCParser end # class NQXMLStreamParser # --------------------------------------------------------------------------- class XMLTreeParser < AbstractTreeParser def initialize require "xmltreebuilder" # The new XMLParser library (0.6.2+) uses a slightly different DOM implementation. # The following code removes the differences between both versions. if defined? XML::DOM::Builder return if defined? XML::DOM::Node::DOCUMENT # code below has been already executed klass = XML::DOM::Node klass.const_set("DOCUMENT", klass::DOCUMENT_NODE) klass.const_set("TEXT", klass::TEXT_NODE) klass.const_set("COMMENT", klass::COMMENT_NODE) klass.const_set("ELEMENT", klass::ELEMENT_NODE) end end private def _nodeType(node) tp = node.nodeType if tp == XML::SimpleTree::Node::TEXT then :TEXT elsif tp == XML::SimpleTree::Node::COMMENT then :COMMENT elsif tp == XML::SimpleTree::Node::ELEMENT then :ELEMENT else :ELSE end end def methodResponse_document(node) assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT ) hasOnlyOneChild(node, "methodResponse") methodResponse(node.firstChild) end def methodCall_document(node) assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT ) hasOnlyOneChild(node, "methodCall") methodCall(node.firstChild) end def createCleanedTree(str) doc = XML::SimpleTreeBuilder.new.parse(str) doc.documentElement.normalize removeWhitespacesAndComments(doc) doc end end # class XMLParser # --------------------------------------------------------------------------- class NQXMLTreeParser < AbstractTreeParser def initialize require "nqxml/treeparser" end private def _nodeType(node) node.nodeType end def methodResponse_document(node) methodResponse(node) end def methodCall_document(node) methodCall(node) end def createCleanedTree(str) doc = ::NQXML::TreeParser.new(str).document.rootNode removeWhitespacesAndComments(doc) doc end end # class NQXMLTreeParser # --------------------------------------------------------------------------- class REXMLStreamParser < AbstractStreamParser def initialize require "rexml/document" @parser_class = StreamListener end class StreamListener include StreamParserMixin alias :tag_start :startElement alias :tag_end :endElement alias :text :character alias :cdata :character def method_missing(*a) # ignore end def parse(str) parser = REXML::Document.parse_stream(str, self) end end end # --------------------------------------------------------------------------- class XMLScanStreamParser < AbstractStreamParser def initialize require "xmlscan/parser" @parser_class = XMLScanParser end class XMLScanParser include StreamParserMixin Entities = { "lt" => "<", "gt" => ">", "amp" => "&", "quot" => '"', "apos" => "'" } def parse(str) parser = XMLScan::XMLParser.new(self) parser.parse(str) end alias :on_stag :startElement alias :on_etag :endElement def on_stag_end(name); end def on_stag_end_empty(name) startElement(name) endElement(name) end def on_chardata(str) character(str) end def on_cdata(str) character(str) end def on_entityref(ent) str = Entities[ent] if str character(str) else raise "unknown entity" end end def on_charref(code) character(code.chr) end def on_charref_hex(code) character(code.chr) end def method_missing(*a) end # TODO: call/implement? # valid_name? # valid_chardata? # valid_char? # parse_error end end # --------------------------------------------------------------------------- XMLParser = XMLTreeParser NQXMLParser = NQXMLTreeParser Classes = [XMLStreamParser, XMLTreeParser, NQXMLStreamParser, NQXMLTreeParser, REXMLStreamParser, XMLScanStreamParser] end # module XMLParser end # module XMLRPC '#n416'>416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
/*
Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com>
This file is part of GlusterFS.
GlusterFS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
GlusterFS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
<http://www.gnu.org/licenses/>.
*/
#ifndef _PROTOCOL_H
#define _PROTOCOL_H
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include <inttypes.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <unistd.h>
#include <fcntl.h>
#include "byte-order.h"
/* Any changes in the protocol structure or adding new '[f,m]ops' needs to
* bump the protocol version by "0.1"
*/
#define GF_PROTOCOL_VERSION "2.1"
struct gf_stat {
uint64_t ino;
uint64_t size;
uint64_t blocks;
uint32_t dev;
uint32_t rdev;
uint32_t mode;
uint32_t nlink;
uint32_t uid;
uint32_t gid;
uint32_t blksize;
uint32_t atime;
uint32_t atime_nsec;
uint32_t mtime;
uint32_t mtime_nsec;
uint32_t ctime;
uint32_t ctime_nsec;
} __attribute__((packed));
static inline void
gf_stat_to_stat (struct gf_stat *gf_stat, struct stat *stat)
{
stat->st_dev = ntoh32 (gf_stat->dev);
stat->st_ino = ntoh64 (gf_stat->ino);
stat->st_mode = ntoh32 (gf_stat->mode);
stat->st_nlink = ntoh32 (gf_stat->nlink);
stat->st_uid = ntoh32 (gf_stat->uid);
stat->st_gid = ntoh32 (gf_stat->gid);
stat->st_rdev = ntoh32 (gf_stat->rdev);
stat->st_size = ntoh64 (gf_stat->size);
stat->st_blksize = ntoh32 (gf_stat->blksize);
stat->st_blocks = ntoh64 (gf_stat->blocks);
stat->st_atime = ntoh32 (gf_stat->atime);
stat->st_mtime = ntoh32 (gf_stat->mtime);
stat->st_ctime = ntoh32 (gf_stat->ctime);
/* TODO: handle nsec */
}
static inline void
gf_stat_from_stat (struct gf_stat *gf_stat, struct stat *stat)
{
gf_stat->dev = hton32 (stat->st_dev);
gf_stat->ino = hton64 (stat->st_ino);
gf_stat->mode = hton32 (stat->st_mode);
gf_stat->nlink = hton32 (stat->st_nlink);
gf_stat->uid = hton32 (stat->st_uid);
gf_stat->gid = hton32 (stat->st_gid);
gf_stat->rdev = hton32 (stat->st_rdev);
gf_stat->size = hton64 (stat->st_size);
gf_stat->blksize = hton32 (stat->st_blksize);
gf_stat->blocks = hton64 (stat->st_blocks);
gf_stat->atime = hton32 (stat->st_atime);
gf_stat->mtime = hton32 (stat->st_mtime);
gf_stat->ctime = hton32 (stat->st_ctime);
/* TODO: handle nsec */
}
struct gf_statfs {
uint64_t bsize;
uint64_t frsize;
uint64_t blocks;
uint64_t bfree;
uint64_t bavail;
uint64_t files;
uint64_t ffree;
uint64_t favail;
uint64_t fsid;
uint64_t flag;
uint64_t namemax;
} __attribute__((packed));
static inline void
gf_statfs_to_statfs (struct gf_statfs *gf_stat, struct statvfs *stat)
{
stat->f_bsize = ntoh64 (gf_stat->bsize);
stat->f_frsize = ntoh64 (gf_stat->frsize);
stat->f_blocks = ntoh64 (gf_stat->blocks);
stat->f_bfree = ntoh64 (gf_stat->bfree);
stat->f_bavail = ntoh64 (gf_stat->bavail);
stat->f_files = ntoh64 (gf_stat->files);
stat->f_ffree = ntoh64 (gf_stat->ffree);
stat->f_favail = ntoh64 (gf_stat->favail);
stat->f_fsid = ntoh64 (gf_stat->fsid);
stat->f_flag = ntoh64 (gf_stat->flag);
stat->f_namemax = ntoh64 (gf_stat->namemax);
}
static inline void
gf_statfs_from_statfs (struct gf_statfs *gf_stat, struct statvfs *stat)
{
gf_stat->bsize = hton64 (stat->f_bsize);
gf_stat->frsize = hton64 (stat->f_frsize);
gf_stat->blocks = hton64 (stat->f_blocks);
gf_stat->bfree = hton64 (stat->f_bfree);
gf_stat->bavail = hton64 (stat->f_bavail);
gf_stat->files = hton64 (stat->f_files);
gf_stat->ffree = hton64 (stat->f_ffree);
gf_stat->favail = hton64 (stat->f_favail);
gf_stat->fsid = hton64 (stat->f_fsid);
gf_stat->flag = hton64 (stat->f_flag);
gf_stat->namemax = hton64 (stat->f_namemax);
}
struct gf_flock {
uint16_t type;
uint16_t whence;
uint64_t start;
uint64_t len;
uint32_t pid;
} __attribute__((packed));
static inline void
gf_flock_to_flock (struct gf_flock *gf_flock, struct flock *flock)
{
flock->l_type = ntoh16 (gf_flock->type);
flock->l_whence = ntoh16 (gf_flock->whence);
flock->l_start = ntoh64 (gf_flock->start);
flock->l_len = ntoh64 (gf_flock->len);
flock->l_pid = ntoh32 (gf_flock->pid);
}
static inline void
gf_flock_from_flock (struct gf_flock *gf_flock, struct flock *flock)
{
gf_flock->type = hton16 (flock->l_type);
gf_flock->whence = hton16 (flock->l_whence);
gf_flock->start = hton64 (flock->l_start);
gf_flock->len = hton64 (flock->l_len);
gf_flock->pid = hton32 (flock->l_pid);
}
struct gf_timespec {
uint32_t tv_sec;
uint32_t tv_nsec;
} __attribute__((packed));
static inline void
gf_timespec_to_timespec (struct gf_timespec *gf_ts, struct timespec *ts)
{
ts[0].tv_sec = ntoh32 (gf_ts[0].tv_sec);
ts[0].tv_nsec = ntoh32 (gf_ts[0].tv_nsec);
ts[1].tv_sec = ntoh32 (gf_ts[1].tv_sec);
ts[1].tv_nsec = ntoh32 (gf_ts[1].tv_nsec);
}
static inline void
gf_timespec_from_timespec (struct gf_timespec *gf_ts, struct timespec *ts)
{
gf_ts[0].tv_sec = hton32 (ts[0].tv_sec);
gf_ts[0].tv_nsec = hton32 (ts[0].tv_nsec);
gf_ts[1].tv_sec = hton32 (ts[1].tv_sec);
gf_ts[1].tv_nsec = hton32 (ts[1].tv_nsec);
}
#define GF_O_ACCMODE 003
#define GF_O_RDONLY 00
#define GF_O_WRONLY 01
#define GF_O_RDWR 02
#define GF_O_CREAT 0100
#define GF_O_EXCL 0200
#define GF_O_NOCTTY 0400
#define GF_O_TRUNC 01000
#define GF_O_APPEND 02000
#define GF_O_NONBLOCK 04000
#define GF_O_SYNC 010000
#define GF_O_ASYNC 020000
#define GF_O_DIRECT 040000
#define GF_O_DIRECTORY 0200000
#define GF_O_NOFOLLOW 0400000
#define GF_O_NOATIME 01000000
#define GF_O_CLOEXEC 02000000
#define GF_O_LARGEFILE 0100000
#define XLATE_BIT(from, to, bit) do { \
if (from & bit) \
to = to | GF_##bit; \
} while (0)
#define UNXLATE_BIT(from, to, bit) do { \
if (from & GF_##bit) \
to = to | bit; \
} while (0)
#define XLATE_ACCESSMODE(from, to) do { \
switch (from & O_ACCMODE) { \
case O_RDONLY: to |= GF_O_RDONLY; \
break; \
case O_WRONLY: to |= GF_O_WRONLY; \
break; \
case O_RDWR: to |= GF_O_RDWR; \
break; \
} \
} while (0)
#define UNXLATE_ACCESSMODE(from, to) do { \
switch (from & GF_O_ACCMODE) { \
case GF_O_RDONLY: to |= O_RDONLY; \
break; \
case GF_O_WRONLY: to |= O_WRONLY; \
break; \
case GF_O_RDWR: to |= O_RDWR; \
break; \
} \
} while (0)
static inline uint32_t
gf_flags_from_flags (uint32_t flags)
{
uint32_t gf_flags = 0;
XLATE_ACCESSMODE (flags, gf_flags);
XLATE_BIT (flags, gf_flags, O_CREAT);
XLATE_BIT (flags, gf_flags, O_EXCL);
XLATE_BIT (flags, gf_flags, O_NOCTTY);
XLATE_BIT (flags, gf_flags, O_TRUNC);
XLATE_BIT (flags, gf_flags, O_APPEND);
XLATE_BIT (flags, gf_flags, O_NONBLOCK);
XLATE_BIT (flags, gf_flags, O_SYNC);
XLATE_BIT (flags, gf_flags, O_ASYNC);
XLATE_BIT (flags, gf_flags, O_DIRECT);
XLATE_BIT (flags, gf_flags, O_DIRECTORY);
XLATE_BIT (flags, gf_flags, O_NOFOLLOW);
#ifdef O_NOATIME
XLATE_BIT (flags, gf_flags, O_NOATIME);
#endif
#ifdef O_CLOEXEC
XLATE_BIT (flags, gf_flags, O_CLOEXEC);
#endif
XLATE_BIT (flags, gf_flags, O_LARGEFILE);
return gf_flags;
}
static inline uint32_t
gf_flags_to_flags (uint32_t gf_flags)
{
uint32_t flags = 0;
UNXLATE_ACCESSMODE (gf_flags, flags);
UNXLATE_BIT (gf_flags, flags, O_CREAT);
UNXLATE_BIT (gf_flags, flags, O_EXCL);
UNXLATE_BIT (gf_flags, flags, O_NOCTTY);
UNXLATE_BIT (gf_flags, flags, O_TRUNC);
UNXLATE_BIT (gf_flags, flags, O_APPEND);
UNXLATE_BIT (gf_flags, flags, O_NONBLOCK);
UNXLATE_BIT (gf_flags, flags, O_SYNC);
UNXLATE_BIT (gf_flags, flags, O_ASYNC);
UNXLATE_BIT (gf_flags, flags, O_DIRECT);
UNXLATE_BIT (gf_flags, flags, O_DIRECTORY);
UNXLATE_BIT (gf_flags, flags, O_NOFOLLOW);
#ifdef O_NOATIME
UNXLATE_BIT (gf_flags, flags, O_NOATIME);
#endif
#ifdef O_CLOEXEC
UNXLATE_BIT (gf_flags, flags, O_CLOEXEC);
#endif
UNXLATE_BIT (gf_flags, flags, O_LARGEFILE);
return flags;
}
typedef struct {
uint64_t ino;
char path[0]; /* NULL terminated */
} __attribute__((packed)) gf_fop_stat_req_t;;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_stat_rsp_t;
typedef struct {
uint64_t ino;
uint32_t size;
char path[0]; /* NULL terminated */
} __attribute__((packed)) gf_fop_readlink_req_t;
typedef struct {
char path[0]; /* NULL terminated */
} __attribute__((packed)) gf_fop_readlink_rsp_t;
typedef struct {
uint64_t par;
uint64_t dev;
uint32_t mode;
char path[0]; /* NULL terminated */
char bname[0]; /* NULL terminated */
} __attribute__((packed)) gf_fop_mknod_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_mknod_rsp_t;
typedef struct {
uint64_t par;
uint32_t mode;
char path[0]; /* NULL terminated */
char bname[0]; /* NULL terminated */
} __attribute__((packed)) gf_fop_mkdir_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_mkdir_rsp_t;
typedef struct {
uint64_t par;
char path[0]; /* NULL terminated */
char bname[0]; /* NULL terminated */
} __attribute__((packed)) gf_fop_unlink_req_t;
typedef struct {
} __attribute__((packed)) gf_fop_unlink_rsp_t;
typedef struct {
uint64_t par;
char path[0];
char bname[0]; /* NULL terminated */
} __attribute__((packed)) gf_fop_rmdir_req_t;
typedef struct {
} __attribute__((packed)) gf_fop_rmdir_rsp_t;
typedef struct {
uint64_t par;
char path[0];
char bname[0];
char linkname[0];
} __attribute__((packed)) gf_fop_symlink_req_t;
typedef struct {
struct gf_stat stat;
}__attribute__((packed)) gf_fop_symlink_rsp_t;
typedef struct {
uint64_t oldpar;
uint64_t newpar;
char oldpath[0];
char oldbname[0]; /* NULL terminated */
char newpath[0];
char newbname[0]; /* NULL terminated */
} __attribute__((packed)) gf_fop_rename_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_rename_rsp_t;
typedef struct {
uint64_t oldino;
uint64_t newpar;
char oldpath[0];
char newpath[0];
char newbname[0];
}__attribute__((packed)) gf_fop_link_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_link_rsp_t;
typedef struct {
uint64_t ino;
uint32_t mode;
char path[0];
} __attribute__((packed)) gf_fop_chmod_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_chmod_rsp_t;
typedef struct {
uint64_t ino;
uint32_t uid;
uint32_t gid;
char path[0];
} __attribute__((packed)) gf_fop_chown_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_chown_rsp_t;
typedef struct {
uint64_t ino;
uint64_t offset;
char path[0];
} __attribute__((packed)) gf_fop_truncate_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_truncate_rsp_t;
typedef struct {
uint64_t ino;
uint32_t flags;
char path[0];
} __attribute__((packed)) gf_fop_open_req_t;
typedef struct {
int64_t fd;
} __attribute__((packed)) gf_fop_open_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint64_t offset;
uint32_t size;
} __attribute__((packed)) gf_fop_read_req_t;
typedef struct {
struct gf_stat stat;
char buf[0];
} __attribute__((packed)) gf_fop_read_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint64_t offset;
uint32_t size;
} __attribute__((packed)) gf_fop_write_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_write_rsp_t;
typedef struct {
uint64_t ino;
char path[0];
} __attribute__((packed)) gf_fop_statfs_req_t;
typedef struct {
struct gf_statfs statfs;
} __attribute__((packed)) gf_fop_statfs_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
} __attribute__((packed)) gf_fop_flush_req_t;
typedef struct { } __attribute__((packed)) gf_fop_flush_rsp_t;
typedef struct fsync_req {
uint64_t ino;
int64_t fd;
uint32_t data;
} __attribute__((packed)) gf_fop_fsync_req_t;
typedef struct {
} __attribute__((packed)) gf_fop_fsync_rsp_t;
typedef struct {
uint64_t ino;
uint32_t flags;
uint32_t dict_len;
char dict[0];
char path[0];
} __attribute__((packed)) gf_fop_setxattr_req_t;
typedef struct { } __attribute__((packed)) gf_fop_setxattr_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint32_t flags;
uint32_t dict_len;
char dict[0];
} __attribute__((packed)) gf_fop_fsetxattr_req_t;
typedef struct { } __attribute__((packed)) gf_fop_fsetxattr_rsp_t;
typedef struct {
uint64_t ino;
uint32_t flags;
uint32_t dict_len;
char dict[0];
char path[0];
} __attribute__((packed)) gf_fop_xattrop_req_t;
typedef struct {
uint32_t dict_len;
char dict[0];
} __attribute__((packed)) gf_fop_xattrop_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint32_t flags;
uint32_t dict_len;
char dict[0];
} __attribute__((packed)) gf_fop_fxattrop_req_t;
typedef struct {
uint32_t dict_len;
char dict[0];
} __attribute__((packed)) gf_fop_fxattrop_rsp_t;
typedef struct {
uint64_t ino;
uint32_t namelen;
char path[0];
char name[0];
} __attribute__((packed)) gf_fop_getxattr_req_t;
typedef struct {
uint32_t dict_len;
char dict[0];
} __attribute__((packed)) gf_fop_getxattr_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint32_t namelen;
char name[0];
} __attribute__((packed)) gf_fop_fgetxattr_req_t;
typedef struct {
uint32_t dict_len;
char dict[0];
} __attribute__((packed)) gf_fop_fgetxattr_rsp_t;
typedef struct {
uint64_t ino;
char path[0];
char name[0];
} __attribute__((packed)) gf_fop_removexattr_req_t;
typedef struct { } __attribute__((packed)) gf_fop_removexattr_rsp_t;
typedef struct {
uint64_t ino;
char path[0];
} __attribute__((packed)) gf_fop_opendir_req_t;
typedef struct {
int64_t fd;
} __attribute__((packed)) gf_fop_opendir_rsp_t;
typedef struct fsyncdir_req {
uint64_t ino;
int64_t fd;
int32_t data;
} __attribute__((packed)) gf_fop_fsyncdir_req_t;
typedef struct {
} __attribute__((packed)) gf_fop_fsyncdir_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint64_t offset;
uint32_t size;
} __attribute__((packed)) gf_fop_readdir_req_t;
typedef struct {
uint32_t size;
char buf[0];
} __attribute__((packed)) gf_fop_readdir_rsp_t;
typedef struct {
uint64_t ino;
uint32_t mask;
char path[0];
} __attribute__((packed)) gf_fop_access_req_t;
typedef struct {
} __attribute__((packed)) gf_fop_access_rsp_t;
typedef struct {
uint64_t par;
uint32_t flags;
uint32_t mode;
char path[0];
char bname[0];
} __attribute__((packed)) gf_fop_create_req_t;
typedef struct {
struct gf_stat stat;
uint64_t fd;
} __attribute__((packed)) gf_fop_create_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint64_t offset;
} __attribute__((packed)) gf_fop_ftruncate_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_ftruncate_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
} __attribute__((packed)) gf_fop_fstat_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_fstat_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint32_t cmd;
uint32_t type;
struct gf_flock flock;
} __attribute__((packed)) gf_fop_lk_req_t;
typedef struct {
struct gf_flock flock;
} __attribute__((packed)) gf_fop_lk_rsp_t;
typedef struct {
uint64_t ino;
uint32_t cmd;
uint32_t type;
struct gf_flock flock;
char path[0];
char volume[0];
} __attribute__((packed)) gf_fop_inodelk_req_t;
typedef struct {
} __attribute__((packed)) gf_fop_inodelk_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint32_t cmd;
uint32_t type;
struct gf_flock flock;
char volume[0];
} __attribute__((packed)) gf_fop_finodelk_req_t;
typedef struct {
} __attribute__((packed)) gf_fop_finodelk_rsp_t;
typedef struct {
uint64_t ino;
uint32_t cmd;
uint32_t type;
uint64_t namelen;
char path[0];
char name[0];
char volume[0];
} __attribute__((packed)) gf_fop_entrylk_req_t;
typedef struct {
} __attribute__((packed)) gf_fop_entrylk_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint32_t cmd;
uint32_t type;
uint64_t namelen;
char name[0];
char volume[0];
} __attribute__((packed)) gf_fop_fentrylk_req_t;
typedef struct {
} __attribute__((packed)) gf_fop_fentrylk_rsp_t;
typedef struct {
uint64_t ino;
struct gf_timespec tv[2];
char path[0];
} __attribute__((packed)) gf_fop_utimens_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_utimens_rsp_t;
typedef struct {
uint64_t ino;
uint64_t fd;
uint32_t mode;
} __attribute__((packed)) gf_fop_fchmod_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_fchmod_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint32_t uid;
uint32_t gid;
} __attribute__((packed)) gf_fop_fchown_req_t;
typedef struct {
struct gf_stat stat;
} __attribute__((packed)) gf_fop_fchown_rsp_t;
typedef struct {
uint64_t ino; /* NOTE: used only in case of 'root' lookup */
uint64_t par;
uint32_t flags;
uint32_t dictlen;
char path[0];
char bname[0];
char dict[0];
} __attribute__((packed)) gf_fop_lookup_req_t;
typedef struct {
struct gf_stat stat;
uint32_t dict_len;
char dict[0];
} __attribute__((packed)) gf_fop_lookup_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint32_t flags;
uint32_t count;
char buf[0];
} __attribute__((packed)) gf_fop_setdents_req_t;
typedef struct { } __attribute__((packed)) gf_fop_setdents_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;
uint64_t offset;
uint32_t size;
uint32_t flags;
} __attribute__((packed)) gf_fop_getdents_req_t;
typedef struct {
uint32_t count;
char buf[0];
} __attribute__((packed)) gf_fop_getdents_rsp_t;
typedef struct {
uint64_t ino;
uint32_t flag;
char path[0];
} __attribute__((packed)) gf_fop_checksum_req_t;
typedef struct {
unsigned char fchecksum[0];
unsigned char dchecksum[0];
} __attribute__((packed)) gf_fop_checksum_rsp_t;
typedef struct {
uint64_t ino;
int32_t timeout;
} __attribute__((packed)) gf_fop_lock_notify_req_t;
typedef struct { } __attribute__((packed)) gf_fop_lock_notify_rsp_t;
typedef struct {
int64_t fd;
int32_t timeout;
} __attribute__((packed)) gf_fop_lock_fnotify_req_t;
typedef struct { } __attribute__((packed)) gf_fop_lock_fnotify_rsp_t;
typedef struct {
char name[0];
} __attribute__((packed)) gf_mop_lock_req_t;
typedef struct {} __attribute__((packed)) gf_mop_lock_rsp_t;
typedef struct {
char name[0];
} __attribute__((packed)) gf_mop_unlock_req_t;
typedef struct {} __attribute__((packed)) gf_mop_unlock_rsp_t;
typedef struct {
char pattern[0];
} __attribute__((packed)) gf_mop_listlocks_req_t;
typedef struct {} __attribute__((packed)) gf_mop_listlocks_rsp_t;
typedef struct {
uint32_t flags;
} __attribute__((packed)) gf_mop_stats_req_t;
typedef struct {
char buf[0];
} __attribute__((packed)) gf_mop_stats_rsp_t;
typedef struct {
uint32_t flags;
uint32_t keylen;
char key[0];
} __attribute__((packed)) gf_mop_getspec_req_t;
typedef struct {
char spec[0];
} __attribute__((packed)) gf_mop_getspec_rsp_t;
typedef struct {
uint32_t msglen;
char msg[0];
} __attribute__((packed)) gf_mop_log_req_t;
typedef struct {
} __attribute__((packed)) gf_mop_log_rsp_t;
typedef struct {
uint32_t dict_len;
char buf[0];
} __attribute__((packed)) gf_mop_setvolume_req_t;
typedef struct {
uint32_t dict_len;
char buf[0];
} __attribute__((packed)) gf_mop_setvolume_rsp_t;
typedef struct {
} __attribute__((packed)) gf_mop_ping_req_t;
typedef struct {
} __attribute__((packed)) gf_mop_ping_rsp_t;
typedef struct {
uint64_t ino;
int64_t fd;