├── irods ├── session │ └── address_resolver.go ├── common │ ├── tracker.go │ ├── response_code.go │ ├── object_type.go │ ├── constants.go │ └── operation_type.go ├── types │ ├── transfer_data_block.go │ ├── object_type.go │ ├── quota.go │ ├── zone.go │ ├── column.go │ ├── file_lock_handle.go │ ├── file_handle.go │ ├── collection.go │ ├── data_object.go │ ├── resource.go │ ├── process.go │ ├── replica.go │ ├── data_object_checksum.go │ ├── data_object_lock.go │ ├── auth.go │ ├── user.go │ ├── version.go │ ├── duration.go │ ├── meta.go │ └── file_redirection_info.go ├── message │ ├── api.go │ ├── sql_result.go │ ├── binbytesbuf.go │ ├── opened_data_object_request.go │ ├── byte_data.go │ ├── resource_server_cookie.go │ ├── int.go │ ├── portal_response.go │ ├── touch_response.go │ ├── admin_response.go │ ├── resource_server_transfer_header.go │ ├── user_admin_response.go │ ├── ticket_admin_response.go │ ├── modify_access_response.go │ ├── auth_request.go │ ├── end_transaction_response.go │ ├── modify_metadata_response.go │ ├── move_collection_response.go │ ├── copy_data_object_response.go │ ├── make_collection_response.go │ ├── move_data_object_response.go │ ├── trim_data_object_response.go │ ├── close_data_object_response.go │ ├── write_data_object_response.go │ ├── modify_collection_response.go │ ├── remove_data_object_response.go │ ├── remove_collection_response.go │ ├── unlock_data_object_response.go │ ├── operation_complete_response.go │ ├── extract_struct_file_response.go │ ├── truncate_data_object_response.go │ ├── replicate_data_object_response.go │ ├── modify_access_inherit_response.go │ ├── get_data_object_complete_response.go │ ├── read_data_object_response.go │ ├── close_data_object_replica_response.go │ ├── disconnect.go │ ├── lock_data_object_response.go │ ├── open_data_object_response.go │ ├── create_data_object_response.go │ ├── auth_result.go │ ├── data_object_request.go │ ├── seek_data_object_response.go │ ├── ssl_sharedsecret.go │ ├── resource_server_transfer_encryption_header.go │ ├── host.go │ ├── get_data_object_stat_request.go │ ├── get_data_object_response.go │ ├── put_data_object_response.go │ ├── new_auth_plugin_response.go │ ├── auth_pam_response.go │ ├── auth_plugin_response.go │ ├── checksum_response.go │ ├── operation_complete_request.go │ ├── query_special_collection.go │ ├── get_data_object_complete_request.go │ ├── auth_plugin_request.go │ ├── auth_pam_request.go │ ├── query_response.go │ ├── ssl_settings.go │ ├── end_transaction_request.go │ ├── keyval_pair.go │ ├── admin_add_group_member_request.go │ ├── admin_remove_group_member_request.go │ ├── admin_remove_user_request.go │ ├── admin_change_password_request.go │ ├── modify_collection_request.go │ ├── admin_set_user_resource_quota_request.go │ ├── admin_change_user_type_request.go │ ├── admin_set_group_resource_quota_request.go │ ├── close_data_object_request.go │ ├── get_file_stat_response.go │ └── read_data_object_request.go ├── util │ ├── xml.go │ ├── random.go │ ├── irods_time.go │ ├── local_path.go │ ├── tasks.go │ ├── wildcard.go │ ├── timeout_wait.go │ └── io.go ├── auth │ └── native.go ├── connection │ ├── auth.go │ └── native_auth.go └── fs │ ├── checksum.go │ ├── struct_file.go │ └── touch.go ├── examples ├── search │ ├── account.yml │ └── search.go ├── upload │ └── account.yml ├── version │ ├── account.yml │ └── version.go ├── get_ticket │ ├── account.yml │ └── get_ticket.go ├── list_acls │ ├── account.yml │ └── list_acls.go ├── list_dir │ ├── account.yml │ └── list_dir.go ├── list_ticket │ └── account.yml ├── list_user │ └── account.yml ├── make_dir │ ├── account.yml │ └── make_dir.go ├── delete_dir │ ├── account.yml │ └── delete_dir.go ├── delete_file │ ├── account.yml │ └── delete_file.go ├── download │ └── account.yml ├── get_ticket_anon │ ├── account.yml │ └── get_ticket_anon.go ├── upload_parallel │ └── account.yml ├── create_ticket │ ├── account.yml │ └── create_ticket.go ├── download_parallel │ └── account.yml ├── download_resumable │ └── account.yml ├── list_dir_via_ticket │ ├── account.yml │ └── list_dir.go ├── download_parallel_resumable │ └── account.yml └── ssl_list_dir │ ├── account.yml │ └── list_dir.go ├── test ├── testcases │ ├── util.go │ ├── lowlevel_process_test.go │ ├── util_error_test.go │ ├── util_encoding_test.go │ ├── util_password_obfuscation_test.go │ ├── type_duration_test.go │ ├── highlevel_filesystem_cache_test.go │ └── lowlevel_connection_test.go └── server │ ├── irods_4.2.8 │ └── docker-compose.yml │ ├── irods_4.3.3 │ └── docker-compose.yml │ ├── irods_4.2.11 │ └── docker-compose.yml │ └── irods_4.3.3_pam │ └── docker-compose.yml ├── .gitignore ├── tools ├── format.sh └── lint.sh ├── fs ├── fs_process.go ├── fs_ticket_restrictions.go ├── fs_system.go └── fs_structfile.go ├── python └── pam.py ├── LICENSE └── Makefile /irods/session/address_resolver.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | type AddressResolver func(address string) string 4 | -------------------------------------------------------------------------------- /irods/common/tracker.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | type TransferTrackerCallback func(taskName string, processed int64, total int64) 4 | -------------------------------------------------------------------------------- /examples/search/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/upload/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/version/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/get_ticket/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/list_acls/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/list_dir/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/list_ticket/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/list_user/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/make_dir/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /irods/types/transfer_data_block.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // TransferDataBlock is a struct that maintains transfer data block info. 4 | type TransferDataBlock struct { 5 | Offset int64 6 | Length int64 7 | } 8 | -------------------------------------------------------------------------------- /test/testcases/util.go: -------------------------------------------------------------------------------- 1 | package testcases 2 | 3 | import "testing" 4 | 5 | func FailError(t *testing.T, err error) { 6 | if err != nil { 7 | t.Errorf("%+v", err) 8 | t.FailNow() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/delete_dir/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | 8 | -------------------------------------------------------------------------------- /examples/delete_file/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | 8 | -------------------------------------------------------------------------------- /examples/download/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | 8 | -------------------------------------------------------------------------------- /examples/get_ticket_anon/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/upload_parallel/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/create_ticket/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | 8 | -------------------------------------------------------------------------------- /examples/download_parallel/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | 8 | -------------------------------------------------------------------------------- /examples/download_resumable/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/list_dir_via_ticket/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /examples/download_parallel_resumable/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "native" 2 | irods_host: "data.cyverse.org" 3 | irods_port: 1247 4 | irods_user_name: "" 5 | irods_user_password: "" 6 | irods_zone_name: "iplant" 7 | -------------------------------------------------------------------------------- /irods/common/response_code.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | // ResponseCode ... 4 | type ResponseCode int 5 | 6 | // response codes 7 | const ( 8 | SYS_SVR_TO_CLI_COLL_STAT ResponseCode = 99999996 9 | SYS_CLI_TO_SVR_COLL_STAT_REPLY ResponseCode = 99999997 10 | ) 11 | -------------------------------------------------------------------------------- /irods/common/object_type.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | type ObjectType int 4 | 5 | const ( 6 | UNKNOWN_OBJECT_TYPE ObjectType = iota 7 | DATA_OBJECT_TYPE 8 | COLLECTION_OBJECT_TYPE 9 | UNKNOWN_FILE_TYPE 10 | LOCAL_FILE_TYPE 11 | LOCAL_DIR_TYPE 12 | NO_INPUT_TYPE 13 | ) 14 | -------------------------------------------------------------------------------- /irods/message/api.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | const ( 4 | // RODS_MESSAGE_API_REQ_TYPE is a type for api request 5 | RODS_MESSAGE_API_REQ_TYPE MessageType = "RODS_API_REQ" 6 | // RODS_MESSAGE_API_REPLY_TYPE is a type for api response 7 | RODS_MESSAGE_API_REPLY_TYPE MessageType = "RODS_API_REPLY" 8 | ) 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | .vscode -------------------------------------------------------------------------------- /irods/message/sql_result.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import "encoding/xml" 4 | 5 | // IRODSMessageSQLResult .. 6 | type IRODSMessageSQLResult struct { 7 | XMLName xml.Name `xml:"SqlResult_PI"` 8 | AttributeIndex int `xml:"attriInx"` 9 | ResultLen int `xml:"reslen"` 10 | Values []string `xml:"value,omitempty"` 11 | } 12 | -------------------------------------------------------------------------------- /irods/message/binbytesbuf.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | // IRODSMessageBinBytesBuf stores bytes buffer 8 | type IRODSMessageBinBytesBuf struct { 9 | XMLName xml.Name `xml:"BinBytesBuf_PI"` 10 | 11 | Length int `xml:"buflen"` 12 | Data string `xml:"buf"` // data is base64 encoded 13 | 14 | Result int 15 | } 16 | -------------------------------------------------------------------------------- /irods/util/xml.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "bytes" 5 | "encoding/xml" 6 | ) 7 | 8 | // EscapeXMLSpecialChars escape special chars for XML 9 | func EscapeXMLSpecialChars(in string) string { 10 | var buf bytes.Buffer 11 | err := xml.EscapeText(&buf, []byte(in)) 12 | if err != nil { 13 | return in 14 | } 15 | 16 | return buf.String() 17 | } 18 | -------------------------------------------------------------------------------- /irods/types/object_type.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // ObjectType determines if the object is data object or collection in irods 4 | type ObjectType string 5 | 6 | const ( 7 | // ObjectTypeDataObject is for DataObject 8 | ObjectTypeDataObject ObjectType = "data" 9 | // ObjectTypeCollection is for Collection 10 | ObjectTypeCollection ObjectType = "collection" 11 | ) 12 | -------------------------------------------------------------------------------- /tools/format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Exit upon failure 4 | set -e 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 7 | 8 | 9 | for PACKAGE in "fs" "irods" "test" 10 | do 11 | PACKAGE_DIR="$SCRIPT_DIR/../$PACKAGE" 12 | gofmt -s -l -d $PACKAGE_DIR | tee /tmp/format_output.txt 13 | test $(cat /tmp/format_output.txt | wc -l) -eq 0 14 | done 15 | -------------------------------------------------------------------------------- /irods/types/quota.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // IRODSQuota describes a resource quota 8 | type IRODSQuota struct { 9 | RescName string `json:"resc_name"` 10 | Limit int64 `json:"limit"` 11 | } 12 | 13 | // ToString stringifies the object 14 | func (q *IRODSQuota) ToString() string { 15 | return fmt.Sprintf("", q.RescName, q.Limit) 16 | } 17 | -------------------------------------------------------------------------------- /irods/types/zone.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "fmt" 4 | 5 | // IRODSZone contains irods zone information 6 | type IRODSZone struct { 7 | ID string `json:"id"` 8 | Name string `json:"name"` 9 | Type string `json:"type"` 10 | } 11 | 12 | // ToString stringifies the object 13 | func (zone *IRODSZone) ToString() string { 14 | return fmt.Sprintf("", zone.ID, zone.Name, zone.Type) 15 | } 16 | -------------------------------------------------------------------------------- /irods/util/random.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | var ( 9 | letters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 10 | ) 11 | 12 | // MakeRandomString returns a random string 13 | func MakeRandomString(size int) string { 14 | r := rand.New(rand.NewSource(time.Now().UnixNano())) 15 | 16 | b := make([]rune, size) 17 | for i := 0; i < size; i++ { 18 | b[i] = letters[r.Intn(len(letters))] 19 | } 20 | 21 | bs := string(b) 22 | return bs 23 | } 24 | -------------------------------------------------------------------------------- /examples/ssl_list_dir/account.yml: -------------------------------------------------------------------------------- 1 | irods_authentication_scheme: "pam" 2 | irods_client_server_negotiation: "request_server_negotiation" 3 | irods_client_server_policy: "CS_NEG_REQUIRE" 4 | irods_host: "ssldata.cyverse.org" 5 | irods_port: 1247 6 | irods_user_name: "" 7 | irods_user_password: "" 8 | irods_zone_name: "iplant" 9 | irods_encryption_algorithm: "AES-256-CBC" 10 | irods_encryption_key_size: 32 11 | irods_encryption_salt_size: 8 12 | irods_encryption_num_hash_rounds: 16 13 | irods_ssl_ca_certificate_file: "/etc/ssl/certs/ca-bundle.crt" 14 | -------------------------------------------------------------------------------- /irods/types/column.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // ColumnType is a type of iRODS Column 4 | type ColumnType string 5 | 6 | const ( 7 | // ColumnTypeInteger is for integer column 8 | ColumnTypeInteger ColumnType = "Integer" 9 | // ColumnTypeString is for string column 10 | ColumnTypeString ColumnType = "String" 11 | // ColumnTypeDateTime is for datetime column 12 | ColumnTypeDateTime ColumnType = "DateTime" 13 | ) 14 | 15 | // IRODSColumn is a struct holding a column 16 | type IRODSColumn struct { 17 | Type ColumnType 18 | ICatKey string 19 | ICatID int 20 | } 21 | -------------------------------------------------------------------------------- /irods/common/constants.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | // constants 4 | const ( 5 | // VERSION 6 | IRODSVersionRelease string = "4.3.0" 7 | IRODSVersionAPI string = "d" 8 | 9 | // Magic Numbers 10 | MaxQueryRows int = 500 11 | MaxPasswordLength int = 50 12 | MaxNameLength int = 64 13 | ReadWriteBufferSize int = 1024 * 1024 * 4 // 4MB 14 | 15 | /* 16 | MAX_SQL_ATTR int = 50 17 | MAX_PATH_ALLOWED int = 1024 18 | MAX_NAME_LEN int = MAX_PATH_ALLOWED + 64 19 | MAX_SQL_ROWS int = 256 20 | */ 21 | ) 22 | -------------------------------------------------------------------------------- /irods/types/file_lock_handle.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // IRODSFileLockHandle contains file lock handle 8 | type IRODSFileLockHandle struct { 9 | FileDescriptor int 10 | // Path has an absolute path to the data object 11 | Path string 12 | OpenMode FileOpenMode 13 | Type DataObjectLockType 14 | Command DataObjectLockCommand 15 | } 16 | 17 | // ToString stringifies the object 18 | func (handle *IRODSFileLockHandle) ToString() string { 19 | return fmt.Sprintf("", handle.FileDescriptor, handle.Path, handle.OpenMode, handle.Type, handle.Command) 20 | } 21 | -------------------------------------------------------------------------------- /fs/fs_process.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | irods_fs "github.com/cyverse/go-irodsclient/irods/fs" 5 | "github.com/cyverse/go-irodsclient/irods/types" 6 | ) 7 | 8 | // StatProcess stats processes 9 | func (fs *FileSystem) StatProcess(address string, zoneName string) ([]*types.IRODSProcess, error) { 10 | conn, err := fs.metadataSession.AcquireConnection(true) 11 | if err != nil { 12 | return nil, err 13 | } 14 | defer fs.metadataSession.ReturnConnection(conn) //nolint 15 | 16 | processes, err := irods_fs.StatProcess(conn, address, zoneName) 17 | if err != nil { 18 | return nil, err 19 | } 20 | 21 | return processes, err 22 | } 23 | -------------------------------------------------------------------------------- /irods/types/file_handle.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cyverse/go-irodsclient/irods/common" 7 | ) 8 | 9 | // IRODSFileHandle contains file handle 10 | type IRODSFileHandle struct { 11 | FileDescriptor int 12 | // Path has an absolute path to the data object 13 | Path string 14 | OpenMode FileOpenMode 15 | Resource string 16 | Oper common.OperationType 17 | } 18 | 19 | // ToString stringifies the object 20 | func (handle *IRODSFileHandle) ToString() string { 21 | return fmt.Sprintf("", handle.FileDescriptor, handle.Path, handle.OpenMode, handle.Resource, handle.Oper) 22 | } 23 | -------------------------------------------------------------------------------- /irods/message/opened_data_object_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import "encoding/xml" 4 | 5 | // IRODSMessageOpenedDataObjectRequest ... 6 | type IRODSMessageOpenedDataObjectRequest struct { 7 | XMLName xml.Name `xml:"OpenedDataObjInp_PI"` 8 | FileDescriptor int `xml:"l1descInx"` 9 | Size int64 `xml:"len"` 10 | Whence int `xml:"whence"` 11 | OperationType int `xml:"oprType"` 12 | Offset int64 `xml:"offset"` 13 | BytesWritten int64 `xml:"bytesWritten"` 14 | KeyVals IRODSMessageSSKeyVal `xml:"KeyValPair_PI"` 15 | } 16 | -------------------------------------------------------------------------------- /irods/message/byte_data.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | // IRODSMessageByteData stores byte data 4 | type IRODSMessageByteData struct { 5 | Type MessageType 6 | Data []byte 7 | } 8 | 9 | // NewIRODSMessageByteData creates a IRODSMessageByteData message 10 | func NewIRODSMessageByteData(msgType MessageType, data []byte) *IRODSMessageByteData { 11 | return &IRODSMessageByteData{ 12 | Type: msgType, 13 | Data: data, 14 | } 15 | } 16 | 17 | // GetMessageBody builds a message body 18 | func (msg *IRODSMessageByteData) GetMessageBody() (*IRODSMessageBody, error) { 19 | return &IRODSMessageBody{ 20 | Type: msg.Type, 21 | Message: msg.Data, 22 | Error: nil, 23 | Bs: nil, 24 | IntInfo: 0, 25 | }, nil 26 | } 27 | -------------------------------------------------------------------------------- /fs/fs_ticket_restrictions.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // IRODSTicketRestrictions contains irods ticket restriction information 8 | type IRODSTicketRestrictions struct { 9 | // AllowedHosts is a list of allowed hosts 10 | AllowedHosts []string `json:"allowed_hosts"` 11 | // AllowedUserName is a list of allowed user names 12 | AllowedUserNames []string `json:"allowed_user_names"` 13 | // AllowedGroupNames is a list of allowed group names 14 | AllowedGroupNames []string `json:"allowed_group_names"` 15 | } 16 | 17 | // ToString stringifies the object 18 | func (ticket *IRODSTicketRestrictions) ToString() string { 19 | return fmt.Sprintf("", ticket.AllowedHosts, ticket.AllowedUserNames, ticket.AllowedGroupNames) 20 | } 21 | -------------------------------------------------------------------------------- /irods/util/irods_time.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "strconv" 5 | "time" 6 | 7 | "github.com/cockroachdb/errors" 8 | ) 9 | 10 | // GetIRODSDateTime returns time struct from string IRODS time 11 | func GetIRODSDateTime(timestring string) (time.Time, error) { 12 | i64, err := strconv.ParseInt(timestring, 10, 64) 13 | if err != nil { 14 | return time.Time{}, errors.Errorf("cannot parse IRODS time string %q", timestring) 15 | } 16 | 17 | if i64 <= 0 { 18 | return time.Time{}, nil 19 | } 20 | 21 | return time.Unix(i64, 0), nil 22 | } 23 | 24 | // GetIRODSDateTimeStringForTicket returns IRODS time string from time struct 25 | func GetIRODSDateTimeStringForTicket(t time.Time) string { 26 | if t.IsZero() { 27 | return "0" 28 | } 29 | 30 | return t.UTC().Format("2006-01-02.15:04:05") 31 | } 32 | -------------------------------------------------------------------------------- /fs/fs_system.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | irods_fs "github.com/cyverse/go-irodsclient/irods/fs" 5 | "github.com/cyverse/go-irodsclient/irods/types" 6 | ) 7 | 8 | // ListProcesses lists all processes 9 | func (fs *FileSystem) ListProcesses(address string, zoneName string) ([]*types.IRODSProcess, error) { 10 | conn, err := fs.metadataSession.AcquireConnection(true) 11 | if err != nil { 12 | return nil, err 13 | } 14 | defer fs.metadataSession.ReturnConnection(conn) //nolint 15 | 16 | processes, err := irods_fs.StatProcess(conn, address, zoneName) 17 | if err != nil { 18 | return nil, err 19 | } 20 | 21 | return processes, nil 22 | } 23 | 24 | // ListAllProcesses lists all processes 25 | func (fs *FileSystem) ListAllProcesses() ([]*types.IRODSProcess, error) { 26 | return fs.ListProcesses("", "") 27 | } 28 | -------------------------------------------------------------------------------- /python/pam.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | from irods.session import iRODSSession 4 | import irods.client_configuration as cfg 5 | try: 6 | env_file = os.environ['IRODS_ENVIRONMENT_FILE'] 7 | auth_file = os.environ['IRODS_AUTHENTICATION_FILE'] 8 | except KeyError: 9 | env_file = os.path.expanduser('~/.irods/irods_environment.json') 10 | auth_file = os.path.expanduser('~/.irods/.irodsA') 11 | 12 | logging.basicConfig(level=logging.DEBUG) 13 | 14 | cfg.load() 15 | 16 | ssl_settings = {} # Or, optionally: {'ssl_context': } 17 | session = iRODSSession(irods_env_file=env_file, **ssl_settings) 18 | session.pool.account._auth_file = auth_file 19 | coll = session.collections.get("/%s/home/%s" % (session.zone, session.username)) 20 | 21 | for obj in coll.data_objects: 22 | print(obj) 23 | -------------------------------------------------------------------------------- /irods/types/collection.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // IRODSCollection contains irods collection information 9 | type IRODSCollection struct { 10 | ID int64 `json:"id"` 11 | // Path has an absolute path to the collection 12 | Path string `json:"path"` 13 | // Name has only the name part of the path 14 | Name string `json:"name"` 15 | // Owner has the owner's name 16 | Owner string `json:"owner"` 17 | // CreateTime has creation time 18 | CreateTime time.Time `json:"create_time"` 19 | // ModifyTime has last modified time 20 | ModifyTime time.Time `json:"modify_time"` 21 | } 22 | 23 | // ToString stringifies the object 24 | func (coll *IRODSCollection) ToString() string { 25 | return fmt.Sprintf("", coll.ID, coll.Path, coll.CreateTime, coll.ModifyTime) 26 | } 27 | -------------------------------------------------------------------------------- /irods/message/resource_server_cookie.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/binary" 5 | 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageResourceServerAuth stores resource server authentication message 10 | type IRODSMessageResourceServerAuth struct { 11 | Cookie int 12 | } 13 | 14 | // NewIRODSMessageResourceServerAuth creates a IRODSMessageResourceServerAuth message 15 | func NewIRODSMessageResourceServerAuth(redirectionInfo *types.IRODSRedirectionInfo) *IRODSMessageResourceServerAuth { 16 | return &IRODSMessageResourceServerAuth{ 17 | Cookie: redirectionInfo.Cookie, 18 | } 19 | } 20 | 21 | // GetBytes returns byte array 22 | func (msg *IRODSMessageResourceServerAuth) GetBytes() ([]byte, error) { 23 | buf := make([]byte, 4) 24 | binary.BigEndian.PutUint32(buf, uint32(msg.Cookie)) 25 | return buf, nil 26 | } 27 | -------------------------------------------------------------------------------- /test/server/irods_4.2.8/docker-compose.yml: -------------------------------------------------------------------------------- 1 | name: irods-test-docker-4-2-8 2 | 3 | services: 4 | irods-catalog: 5 | image: cyverse/irods-test-docker-catalog:v4.2.8 6 | environment: 7 | - POSTGRES_PASSWORD=testpassword 8 | restart: always 9 | 10 | irods-catalog-provider: 11 | image: cyverse/irods-test-docker-catalog-provider:v4.2.8 12 | shm_size: 500mb 13 | healthcheck: 14 | test: ["CMD", "su", "-", "irods", "-c", "./irodsctl status | grep Process"] 15 | interval: 10s 16 | timeout: 10s 17 | retries: 3 18 | start_period: 20s 19 | start_interval: 10s 20 | restart: always 21 | ports: 22 | - "1247:1247" 23 | - "20000-20199:20000-20199" 24 | depends_on: 25 | - irods-catalog 26 | -------------------------------------------------------------------------------- /test/server/irods_4.3.3/docker-compose.yml: -------------------------------------------------------------------------------- 1 | name: irods-test-docker-4-3-3 2 | 3 | services: 4 | irods-catalog: 5 | image: cyverse/irods-test-docker-catalog:v4.3.3 6 | environment: 7 | - POSTGRES_PASSWORD=testpassword 8 | restart: always 9 | 10 | irods-catalog-provider: 11 | image: cyverse/irods-test-docker-catalog-provider:v4.3.3 12 | shm_size: 500mb 13 | healthcheck: 14 | test: ["CMD", "su", "-", "irods", "-c", "./irodsctl status | grep Process"] 15 | interval: 10s 16 | timeout: 10s 17 | retries: 3 18 | start_period: 20s 19 | start_interval: 10s 20 | restart: always 21 | ports: 22 | - "1247:1247" 23 | - "20000-20199:20000-20199" 24 | depends_on: 25 | - irods-catalog 26 | -------------------------------------------------------------------------------- /test/server/irods_4.2.11/docker-compose.yml: -------------------------------------------------------------------------------- 1 | name: irods-test-docker-4-2-11 2 | 3 | services: 4 | irods-catalog: 5 | image: cyverse/irods-test-docker-catalog:v4.2.11 6 | environment: 7 | - POSTGRES_PASSWORD=testpassword 8 | restart: always 9 | 10 | irods-catalog-provider: 11 | image: cyverse/irods-test-docker-catalog-provider:v4.2.11 12 | shm_size: 500mb 13 | healthcheck: 14 | test: ["CMD", "su", "-", "irods", "-c", "./irodsctl status | grep Process"] 15 | interval: 10s 16 | timeout: 10s 17 | retries: 3 18 | start_period: 20s 19 | start_interval: 10s 20 | restart: always 21 | ports: 22 | - "1247:1247" 23 | - "20000-20199:20000-20199" 24 | depends_on: 25 | - irods-catalog 26 | -------------------------------------------------------------------------------- /irods/types/data_object.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // IRODSDataObject contains irods data object information 8 | type IRODSDataObject struct { 9 | ID int64 `json:"id"` 10 | CollectionID int64 `json:"collection_id"` 11 | // Path has an absolute path to the data object 12 | Path string `json:"path"` 13 | // Name has only the name part of the path 14 | Name string `json:"name"` 15 | // Size has the file size 16 | Size int64 `json:"size"` 17 | // DataType has the type of the file, 18 | DataType string `json:"data_type"` 19 | // Replicas has replication information 20 | Replicas []*IRODSReplica `json:"replicas,omitempty"` 21 | } 22 | 23 | // ToString stringifies the object 24 | func (obj *IRODSDataObject) ToString() string { 25 | return fmt.Sprintf("", obj.ID, obj.Path, obj.Size, obj.DataType) 26 | } 27 | -------------------------------------------------------------------------------- /test/server/irods_4.3.3_pam/docker-compose.yml: -------------------------------------------------------------------------------- 1 | name: irods-test-docker-4-3-3-pam 2 | 3 | services: 4 | irods-catalog: 5 | image: cyverse/irods-test-docker-catalog:v4.3.3_pam 6 | environment: 7 | - POSTGRES_PASSWORD=testpassword 8 | restart: always 9 | 10 | irods-catalog-provider: 11 | image: cyverse/irods-test-docker-catalog-provider:v4.3.3_pam 12 | shm_size: 500mb 13 | healthcheck: 14 | test: ["CMD", "su", "-", "irods", "-c", "./irodsctl status | grep Process"] 15 | interval: 10s 16 | timeout: 10s 17 | retries: 3 18 | start_period: 20s 19 | start_interval: 10s 20 | restart: always 21 | ports: 22 | - "1247:1247" 23 | - "20000-20199:20000-20199" 24 | depends_on: 25 | - irods-catalog 26 | -------------------------------------------------------------------------------- /irods/types/resource.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // IRODSResource describes a resource host 9 | type IRODSResource struct { 10 | RescID int64 `json:"resc_id"` 11 | Name string `json:"name"` 12 | Zone string `json:"zone"` 13 | Type string `json:"type"` 14 | Class string `json:"class"` 15 | Location string `json:"location"` 16 | 17 | // Path has the path string of the resource 18 | Path string `json:"path"` 19 | 20 | // Context has the context string 21 | Context string `json:"context"` 22 | 23 | // CreateTime has creation time 24 | CreateTime time.Time `json:"create_time"` 25 | // ModifyTime has last modified time 26 | ModifyTime time.Time `json:"modify_time"` 27 | } 28 | 29 | // ToString stringifies the object 30 | func (res *IRODSResource) ToString() string { 31 | return fmt.Sprintf("", res.Name, res) 32 | } 33 | -------------------------------------------------------------------------------- /irods/auth/native.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "crypto/md5" 5 | "encoding/base64" 6 | 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | const ( 11 | challengeLen int = 64 12 | authResponseLen int = 16 13 | ) 14 | 15 | // GenerateAuthResponse returns auth response 16 | func GenerateAuthResponse(challenge []byte, password string) string { 17 | paddedPassword := make([]byte, common.MaxPasswordLength) 18 | copy(paddedPassword, []byte(password)) 19 | 20 | m := md5.New() 21 | m.Write(challenge[:challengeLen]) 22 | m.Write(paddedPassword) 23 | encodedPassword := m.Sum(nil) 24 | 25 | // replace 0x00 to 0x01 26 | for idx := 0; idx < len(encodedPassword); idx++ { 27 | if encodedPassword[idx] == 0 { 28 | encodedPassword[idx] = 1 29 | } 30 | } 31 | 32 | b64encodedPassword := base64.StdEncoding.EncodeToString(encodedPassword[:authResponseLen]) 33 | return b64encodedPassword 34 | } 35 | -------------------------------------------------------------------------------- /irods/types/process.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // IRODSProcess contains irods process information 9 | type IRODSProcess struct { 10 | ID int64 `json:"id"` 11 | StartTime time.Time `json:"start_time"` 12 | ProxyUser string `json:"proxy_user"` 13 | ProxyZone string `json:"proxy_zone"` 14 | ClientUser string `json:"client_user"` 15 | ClientZone string `json:"client_zone"` 16 | ClientAddress string `json:"client_address"` 17 | ServerAddress string `json:"server_address"` 18 | ClientProgram string `json:"client_program"` 19 | } 20 | 21 | // ToString stringifies the object 22 | func (obj *IRODSProcess) ToString() string { 23 | return fmt.Sprintf("", obj.ID, obj.StartTime, obj.ProxyUser, obj.ProxyZone, obj.ClientUser, obj.ClientZone, obj.ClientAddress, obj.ServerAddress, obj.ClientProgram) 24 | } 25 | -------------------------------------------------------------------------------- /irods/message/int.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | ) 8 | 9 | // IRODSMessageInt stores int message 10 | type IRODSMessageInt struct { 11 | XMLName xml.Name `xml:"INT_PI"` 12 | Value int `xml:"myInt"` 13 | } 14 | 15 | // NewIRODSMessageInt creates a IRODSMessageInt message 16 | func NewIRODSMessageInt(intValue int) (*IRODSMessageInt, error) { 17 | return &IRODSMessageInt{ 18 | Value: intValue, 19 | }, nil 20 | } 21 | 22 | // GetBytes returns byte array 23 | func (msg *IRODSMessageInt) GetBytes() ([]byte, error) { 24 | xmlBytes, err := xml.Marshal(msg) 25 | if err != nil { 26 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 27 | } 28 | return xmlBytes, nil 29 | } 30 | 31 | // FromBytes returns struct from bytes 32 | func (msg *IRODSMessageInt) FromBytes(bytes []byte) error { 33 | err := xml.Unmarshal(bytes, msg) 34 | if err != nil { 35 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 36 | } 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /irods/message/portal_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | // IRODSMessagePortalResponse stores portal response 8 | type IRODSMessagePortalResponse struct { 9 | XMLName xml.Name `xml:"PortalOprOut_PI"` 10 | Status int `xml:"status"` 11 | FileDescriptor int `xml:"l1descInx"` 12 | Threads int `xml:"numThreads"` 13 | CheckSum string `xml:"chksum"` 14 | PortList *IRODSMessagePortList `xml:"PortList_PI"` 15 | // stores error return 16 | // error if result < 0 17 | // data is included if result == 0 18 | // any value >= 0 is fine 19 | Result int `xml:"-"` 20 | } 21 | 22 | type IRODSMessagePortList struct { 23 | XMLName xml.Name `xml:"PortList_PI"` 24 | Port int `xml:"portNum"` 25 | Cookie int `xml:"cookie"` 26 | ServerSocket int `xml:"sock"` // server's sock number 27 | WindowSize int `xml:"windowSize"` 28 | HostAddress string `xml:"hostAddr"` 29 | } 30 | -------------------------------------------------------------------------------- /tools/lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Exit upon failure 4 | set -e 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 7 | export PATH=$PATH:$GOPATH/bin 8 | 9 | if ! command -v golangci-lint &> /dev/null ; then 10 | # binary will be $(go env GOPATH)/bin/golangci-lint 11 | curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.61.0 12 | fi 13 | 14 | if ! command -v ineffassign &> /dev/null ; then 15 | go get github.com/gordonklaus/ineffassign 16 | go install github.com/gordonklaus/ineffassign 17 | fi 18 | 19 | if ! command -v misspell &> /dev/null ; then 20 | go get github.com/client9/misspell/cmd/misspell 21 | go install github.com/client9/misspell/cmd/misspell 22 | fi 23 | 24 | go mod tidy 25 | 26 | 27 | for PACKAGE in "config" "examples" "fs" "irods" "test" 28 | do 29 | PACKAGE_DIR="$SCRIPT_DIR/../$PACKAGE" 30 | golangci-lint run $PACKAGE_DIR/... 31 | ineffassign $PACKAGE_DIR/... 32 | misspell -error $PACKAGE_DIR 33 | done 34 | -------------------------------------------------------------------------------- /test/testcases/lowlevel_process_test.go: -------------------------------------------------------------------------------- 1 | package testcases 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/cyverse/go-irodsclient/irods/connection" 7 | "github.com/cyverse/go-irodsclient/irods/fs" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func getLowlevelProcessTest() Test { 12 | return Test{ 13 | Name: "Lowlevel_Process", 14 | Func: lowlevelProcessTest, 15 | } 16 | } 17 | 18 | func lowlevelProcessTest(t *testing.T, test *Test) { 19 | t.Run("ProcessStat", testProcessStat) 20 | } 21 | 22 | func testProcessStat(t *testing.T) { 23 | test := GetCurrentTest() 24 | server := test.GetCurrentServer() 25 | 26 | account, err := server.GetAccount() 27 | FailError(t, err) 28 | 29 | conn, err := connection.NewIRODSConnection(account, server.GetConnectionConfig()) 30 | FailError(t, err) 31 | 32 | err = conn.Connect() 33 | FailError(t, err) 34 | defer func() { 35 | _ = conn.Disconnect() 36 | }() 37 | 38 | processes, err := fs.StatProcess(conn, "", "") 39 | FailError(t, err) 40 | 41 | assert.GreaterOrEqual(t, len(processes), 1) 42 | } 43 | -------------------------------------------------------------------------------- /irods/message/touch_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageTouchResponse stores touch response 10 | type IRODSMessageTouchResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageTouchResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageTouchResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageTouchResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/admin_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageAdminResponse stores alter metadata response 10 | type IRODSMessageAdminResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageAdminResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageAdminResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageAdminResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/resource_server_transfer_header.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/binary" 5 | 6 | "github.com/cockroachdb/errors" 7 | ) 8 | 9 | // IRODSMessageResourceServerTransferHeader stores resource server transfer header message 10 | type IRODSMessageResourceServerTransferHeader struct { 11 | OperationType int 12 | Flags int 13 | Offset int64 14 | Length int64 15 | } 16 | 17 | // FromBytes returns struct from bytes 18 | func (msg *IRODSMessageResourceServerTransferHeader) FromBytes(bytes []byte) error { 19 | if len(bytes) < 24 { 20 | return errors.Errorf("failed to read transfer header, header must be 24 bytes, but received %d", len(bytes)) 21 | } 22 | 23 | msg.OperationType = int(binary.BigEndian.Uint32(bytes[0:4])) 24 | msg.Flags = int(binary.BigEndian.Uint32(bytes[4:8])) 25 | msg.Offset = int64(binary.BigEndian.Uint64(bytes[8:16])) 26 | msg.Length = int64(binary.BigEndian.Uint64(bytes[16:24])) 27 | return nil 28 | } 29 | 30 | // SizeOf returns struct size in bytes 31 | func (msg *IRODSMessageResourceServerTransferHeader) SizeOf() int { 32 | return 24 33 | } 34 | -------------------------------------------------------------------------------- /irods/message/user_admin_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageUserAdminResponse stores alter metadata response 10 | type IRODSMessageUserAdminResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageUserAdminResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageUserAdminResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageUserAdminResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/ticket_admin_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageTicketAdminResponse stores ticket admin response 10 | type IRODSMessageTicketAdminResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageTicketAdminResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageTicketAdminResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageTicketAdminResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/util/local_path.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | 7 | "github.com/cockroachdb/errors" 8 | ) 9 | 10 | // GetCorrectLocalPath corrects the path 11 | func GetCorrectLocalPath(p string) string { 12 | return filepath.Clean(p) 13 | } 14 | 15 | // ExpandHomeDir expands ~/ 16 | func ExpandHomeDir(path string) (string, error) { 17 | if len(path) == 0 { 18 | return "", nil 19 | } 20 | 21 | if path[0] != '~' { 22 | return filepath.Abs(path) 23 | } 24 | 25 | homedir, err := os.UserHomeDir() 26 | if err != nil { 27 | return "", errors.Wrapf(err, "failed to get user home dir") 28 | } 29 | 30 | // resolve "~" 31 | if len(path) == 1 { 32 | return filepath.Abs(homedir) 33 | } 34 | 35 | // resolve "~/" 36 | if path[1] == '/' { 37 | path = filepath.Join(homedir, path[2:]) 38 | return filepath.Abs(path) 39 | } 40 | 41 | return filepath.Abs(path) 42 | } 43 | 44 | // ExistFile checks if file exists 45 | func ExistFile(path string) bool { 46 | st, err := os.Stat(path) 47 | if err != nil { 48 | return false 49 | } 50 | 51 | if !st.IsDir() { 52 | return true 53 | } 54 | return false 55 | } 56 | -------------------------------------------------------------------------------- /irods/message/modify_access_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageModifyAccessResponse stores alter modify access response 10 | type IRODSMessageModifyAccessResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageModifyAccessResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageModifyAccessResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageModifyAccessResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/auth_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cyverse/go-irodsclient/irods/common" 5 | ) 6 | 7 | // IRODSMessageAuthRequest stores authentication request 8 | type IRODSMessageAuthRequest struct { 9 | // empty structure 10 | } 11 | 12 | // NewIRODSMessageAuthRequest creates a IRODSMessageAuthRequest message 13 | func NewIRODSMessageAuthRequest() *IRODSMessageAuthRequest { 14 | return &IRODSMessageAuthRequest{} 15 | } 16 | 17 | // GetMessage builds a message 18 | func (msg *IRODSMessageAuthRequest) GetMessage() (*IRODSMessage, error) { 19 | msgHeader := IRODSMessageHeader{ 20 | Type: RODS_MESSAGE_API_REQ_TYPE, 21 | MessageLen: 0, 22 | ErrorLen: 0, 23 | BsLen: 0, 24 | IntInfo: int32(common.AUTH_REQUEST_AN), 25 | } 26 | 27 | return &IRODSMessage{ 28 | Header: &msgHeader, 29 | Body: nil, 30 | }, nil 31 | } 32 | 33 | // FromMessage returns struct from IRODSMessage 34 | func (msg *IRODSMessageAuthRequest) FromMessage(msgIn *IRODSMessage) error { 35 | return nil 36 | } 37 | 38 | func (msg *IRODSMessageAuthRequest) GetXMLCorrector() XMLCorrector { 39 | return GetXMLCorrectorForRequest() 40 | } 41 | -------------------------------------------------------------------------------- /irods/message/end_transaction_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageEndTransactionResponse stores end transaction response 10 | type IRODSMessageEndTransactionResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageEndTransactionResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageEndTransactionResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageEndTransactionResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/modify_metadata_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageModifyMetadataResponse stores alter metadata response 10 | type IRODSMessageModifyMetadataResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageModifyMetadataResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageModifyMetadataResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageModifyMetadataResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/move_collection_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageMoveCollectionResponse stores collection move response 10 | type IRODSMessageMoveCollectionResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageMoveCollectionResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageMoveCollectionResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageMoveCollectionResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/copy_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageCopyDataObjectResponse stores data object copy response 10 | type IRODSMessageCopyDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageCopyDataObjectResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageCopyDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageCopyDataObjectResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/make_collection_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageMakeCollectionResponse stores collection creation response 10 | type IRODSMessageMakeCollectionResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageMakeCollectionResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageMakeCollectionResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageMakeCollectionResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/move_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageMoveDataObjectResponse stores data object move response 10 | type IRODSMessageMoveDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageMoveDataObjectResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageMoveDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageMoveDataObjectResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/trim_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageTrimDataObjectResponse stores data object trim response 10 | type IRODSMessageTrimDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageTrimDataObjectResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageTrimDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageTrimDataObjectResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/types/replica.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // IRODSReplica contains irods data object replication information 9 | type IRODSReplica struct { 10 | Number int64 `json:"number"` 11 | 12 | // Owner has the owner's name 13 | Owner string `json:"owner"` 14 | 15 | Checksum *IRODSChecksum `json:"checksum,omitempty"` 16 | Status string `json:"status"` 17 | ResourceName string `json:"resource_name"` 18 | 19 | // Path has an absolute path to the data object 20 | Path string `json:"path"` 21 | ResourceHierarchy string `json:"resource_hierarchy"` 22 | 23 | // CreateTime has creation time 24 | CreateTime time.Time `json:"create_time"` 25 | // ModifyTime has last modified time 26 | ModifyTime time.Time `json:"modify_time"` 27 | // AccessTime has last access time 28 | AccessTime time.Time `json:"access_time"` // iRODS 5+ 29 | } 30 | 31 | // ToString stringifies the object 32 | func (obj *IRODSReplica) ToString() string { 33 | return fmt.Sprintf("", obj.Number, obj.Status, obj.ResourceName, obj.CreateTime, obj.ModifyTime, obj.AccessTime) 34 | } 35 | -------------------------------------------------------------------------------- /irods/message/close_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageCloseDataObjectResponse stores data object close response 10 | type IRODSMessageCloseDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageCloseDataObjectResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageCloseDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageCloseDataObjectResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/write_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageWriteDataObjectResponse stores data object write response 10 | type IRODSMessageWriteDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageWriteDataObjectResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageWriteDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageWriteDataObjectResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/util/tasks.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | const ( 4 | // TransferTaskMinLength is a minimum data length of a task for parallel data transfer 5 | TransferTaskMinLength int64 = 32 * 1024 * 1024 // 32MB 6 | // TransferTaskMaxNum is a maximum number of tasks for parallel data transfer 7 | TransferTaskMaxNum int = 16 8 | // TransferBlockSize is a block size of a task 9 | TransferBlockSize int64 = 1024 * 1024 // 1MB 10 | ) 11 | 12 | // GetNumTasksForParallelTransfer returns the number transfer tasks to be used 13 | func GetNumTasksForParallelTransfer(dataObjectLength int64) int { 14 | if dataObjectLength <= TransferTaskMinLength { 15 | return 1 16 | } 17 | 18 | numTasks := int(dataObjectLength / TransferTaskMinLength) 19 | if dataObjectLength%TransferTaskMinLength > 0 { 20 | numTasks++ 21 | } 22 | 23 | if numTasks <= 1 { 24 | return 1 25 | } else if numTasks > TransferTaskMaxNum { 26 | // too many tasks 27 | return TransferTaskMaxNum 28 | } 29 | 30 | return numTasks 31 | } 32 | 33 | // GetBlockSizeForParallelTransfer returns the block size 34 | func GetBlockSizeForParallelTransfer(dataObjectLength int64) int64 { 35 | return TransferBlockSize 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/modify_collection_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageModifyCollectionResponse stores alter metadata response 10 | type IRODSMessageModifyCollectionResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageModifyCollectionResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageModifyCollectionResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageModifyCollectionResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/remove_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageRemoveDataObjectResponse stores data object deletion response 10 | type IRODSMessageRemoveDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageRemoveDataObjectResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageRemoveDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | msg.Result = int(msgIn.Body.IntInfo) 29 | return nil 30 | } 31 | 32 | // GetXMLCorrector returns XML corrector for this message 33 | func (msg *IRODSMessageRemoveDataObjectResponse) GetXMLCorrector() XMLCorrector { 34 | return GetXMLCorrectorForResponse() 35 | } 36 | -------------------------------------------------------------------------------- /irods/message/remove_collection_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageRemoveCollectionResponse stores collection deletion response 10 | type IRODSMessageRemoveCollectionResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageRemoveCollectionResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageRemoveCollectionResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageRemoveCollectionResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/unlock_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageUnlockDataObjectResponse stores data object unlock response 10 | type IRODSMessageUnlockDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageUnlockDataObjectResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageUnlockDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageUnlockDataObjectResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/operation_complete_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageOperationCompleteResponse stores operation complete response 10 | type IRODSMessageOperationCompleteResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageOperationCompleteResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageOperationCompleteResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageOperationCompleteResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/extract_struct_file_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageExtractStructFileResponse stores struct file extraction response 10 | type IRODSMessageExtractStructFileResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageExtractStructFileResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageExtractStructFileResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageExtractStructFileResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/truncate_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageTruncateDataObjectResponse stores data object truncation response 10 | type IRODSMessageTruncateDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageTruncateDataObjectResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageTruncateDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageTruncateDataObjectResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/replicate_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageReplicateDataObjectResponse stores data object replication response 10 | type IRODSMessageReplicateDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageReplicateDataObjectResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageReplicateDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageReplicateDataObjectResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/modify_access_inherit_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageModifyAccessInheritResponse stores alter modify access inheritance response 10 | type IRODSMessageModifyAccessInheritResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageModifyAccessInheritResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageModifyAccessInheritResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageModifyAccessInheritResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/get_data_object_complete_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageGetDataObjectCompleteResponse stores get data object complete response 10 | type IRODSMessageGetDataObjectCompleteResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageGetDataObjectCompleteResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageGetDataObjectCompleteResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageGetDataObjectCompleteResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/read_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageReadDataObjectResponse stores data object read response 10 | type IRODSMessageReadDataObjectResponse struct { 11 | // empty structure 12 | Result int 13 | Data []byte 14 | } 15 | 16 | // CheckError returns error if server returned an error 17 | func (msg *IRODSMessageReadDataObjectResponse) CheckError() error { 18 | if msg.Result < 0 { 19 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 20 | } 21 | return nil 22 | } 23 | 24 | // FromMessage returns struct from IRODSMessage 25 | func (msg *IRODSMessageReadDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 26 | if msgIn.Body == nil { 27 | return errors.Errorf("empty message body") 28 | } 29 | 30 | msg.Result = int(msgIn.Body.IntInfo) 31 | msg.Data = msgIn.Body.Bs 32 | return nil 33 | } 34 | 35 | // GetXMLCorrector returns XML corrector for this message 36 | func (msg *IRODSMessageReadDataObjectResponse) GetXMLCorrector() XMLCorrector { 37 | return GetXMLCorrectorForResponse() 38 | } 39 | -------------------------------------------------------------------------------- /irods/message/close_data_object_replica_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageCloseDataObjectReplicaResponse stores data object replica close response 10 | type IRODSMessageCloseDataObjectReplicaResponse struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageCloseDataObjectReplicaResponse) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // FromMessage returns struct from IRODSMessage 24 | func (msg *IRODSMessageCloseDataObjectReplicaResponse) FromMessage(msgIn *IRODSMessage) error { 25 | if msgIn.Body == nil { 26 | return errors.Errorf("empty message body") 27 | } 28 | 29 | msg.Result = int(msgIn.Body.IntInfo) 30 | return nil 31 | } 32 | 33 | // GetXMLCorrector returns XML corrector for this message 34 | func (msg *IRODSMessageCloseDataObjectReplicaResponse) GetXMLCorrector() XMLCorrector { 35 | return GetXMLCorrectorForResponse() 36 | } 37 | -------------------------------------------------------------------------------- /irods/message/disconnect.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | const ( 4 | // RODS_MESSAGE_DISCONNECT_TYPE is a message type for disconnecting 5 | RODS_MESSAGE_DISCONNECT_TYPE MessageType = "RODS_DISCONNECT" 6 | ) 7 | 8 | // IRODSMessageDisconnect stores disconnect request 9 | type IRODSMessageDisconnect struct { 10 | // empty structure 11 | } 12 | 13 | // NewIRODSMessageDisconnect creates a IRODSMessageAuthRequest message 14 | func NewIRODSMessageDisconnect() *IRODSMessageDisconnect { 15 | return &IRODSMessageDisconnect{} 16 | } 17 | 18 | // GetMessage builds a message 19 | func (msg *IRODSMessageDisconnect) GetMessage() (*IRODSMessage, error) { 20 | msgHeader := IRODSMessageHeader{ 21 | Type: RODS_MESSAGE_DISCONNECT_TYPE, 22 | MessageLen: 0, 23 | ErrorLen: 0, 24 | BsLen: 0, 25 | IntInfo: 0, 26 | } 27 | 28 | return &IRODSMessage{ 29 | Header: &msgHeader, 30 | Body: nil, 31 | }, nil 32 | } 33 | 34 | // FromMessage returns struct from IRODSMessage 35 | func (msg *IRODSMessageDisconnect) FromMessage(msgIn *IRODSMessage) error { 36 | return nil 37 | } 38 | 39 | // GetXMLCorrector returns XML corrector for this message 40 | func (msg *IRODSMessageDisconnect) GetXMLCorrector() XMLCorrector { 41 | return GetXMLCorrectorForRequest() 42 | } 43 | -------------------------------------------------------------------------------- /fs/fs_structfile.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | irods_fs "github.com/cyverse/go-irodsclient/irods/fs" 5 | "github.com/cyverse/go-irodsclient/irods/types" 6 | "github.com/cyverse/go-irodsclient/irods/util" 7 | ) 8 | 9 | // ExtractStructFile extracts a struct file 10 | func (fs *FileSystem) ExtractStructFile(path string, targetCollection string, resource string, dataType types.DataType, force bool, bulkReg bool) error { 11 | irodsPath := util.GetCorrectIRODSPath(path) 12 | targetIrodsPath := util.GetCorrectIRODSPath(targetCollection) 13 | 14 | // we create a new connection for extraction because iRODS has a bug that does not clear file descriptors, causing SYS_OUT_OF_FILE_DESC error. 15 | // create a fresh connection and throw out after use. 16 | conn, err := fs.metadataSession.AcquireConnection(false) 17 | if err != nil { 18 | return err 19 | } 20 | 21 | // discard the connection after use to avoid file descriptor error. 22 | defer fs.metadataSession.DiscardConnection(conn) 23 | 24 | err = irods_fs.ExtractStructFile(conn, irodsPath, targetIrodsPath, resource, dataType, force, bulkReg) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | fs.invalidateCacheForDirExtract(targetIrodsPath) 30 | fs.cachePropagation.PropagateDirExtract(targetIrodsPath) 31 | 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /irods/types/data_object_checksum.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cockroachdb/errors" 7 | ) 8 | 9 | // IRODSChecksum contains data object hash information 10 | type IRODSChecksum struct { 11 | IRODSChecksumString string `json:"irods_checksum_string"` 12 | Algorithm ChecksumAlgorithm `json:"algorithm"` 13 | Checksum []byte `json:"-"` 14 | } 15 | 16 | // CreateIRODSChecksum creates IRODSChecksum from checksum string 17 | func CreateIRODSChecksum(checksumString string) (*IRODSChecksum, error) { 18 | if len(checksumString) == 0 { 19 | // completely normal 20 | return &IRODSChecksum{ 21 | IRODSChecksumString: "", 22 | Algorithm: "", 23 | Checksum: nil, 24 | }, nil 25 | } 26 | 27 | algorithm, checksum, err := ParseIRODSChecksumString(checksumString) 28 | if err != nil { 29 | return nil, errors.Wrapf(err, "failed to split data object checksum") 30 | } 31 | 32 | return &IRODSChecksum{ 33 | IRODSChecksumString: checksumString, 34 | Algorithm: algorithm, 35 | Checksum: checksum, 36 | }, nil 37 | } 38 | 39 | // ToString stringifies the object 40 | func (checksum *IRODSChecksum) ToString() string { 41 | return fmt.Sprintf("", checksum.Algorithm, checksum.Checksum) 42 | } 43 | -------------------------------------------------------------------------------- /irods/util/wildcard.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | 7 | "github.com/dlclark/regexp2" 8 | ) 9 | 10 | func HasWildcards(input string) bool { 11 | return (regexp.MustCompile(`(?:[^\\])(?:\\\\)*[?*]`).MatchString(input) || 12 | regexp.MustCompile(`^(?:\\\\)*[?*]`).MatchString(input) || 13 | regexp.MustCompile(`(?:[^\\])(?:\\\\)*\[.*?(?:[^\\])(?:\\\\)*\]`).MatchString(input) || 14 | regexp.MustCompile(`^(?:\\\\)*\[.*?(?:[^\\])(?:\\\\)*\]`).MatchString(input)) 15 | } 16 | 17 | func UnixWildcardsToSQLWildcards(input string) string { 18 | output := input 19 | length := len(input) 20 | // Use regexp2 rather than regexp here in order to be able to use lookbehind assertions 21 | // 22 | // Escape SQL wildcard characters 23 | output = strings.ReplaceAll(output, "%", `\%`) 24 | output = strings.ReplaceAll(output, "_", `\_`) 25 | // Replace ranges with a wildcard 26 | output, _ = regexp2.MustCompile(`(? 0 { 26 | wg.done = make(chan struct{}) 27 | } 28 | 29 | wg.counter += i 30 | wg.wg.Add(i) 31 | 32 | if wg.counter == 0 { 33 | close(wg.done) 34 | } 35 | } 36 | 37 | func (wg *TimeoutWaitGroup) Done() { 38 | wg.mutex.Lock() 39 | defer wg.mutex.Unlock() 40 | 41 | wg.counter-- 42 | if wg.counter == 0 { 43 | close(wg.done) 44 | } 45 | 46 | wg.wg.Done() 47 | } 48 | 49 | func (wg *TimeoutWaitGroup) Wait() { 50 | wg.wg.Wait() 51 | } 52 | 53 | func (wg *TimeoutWaitGroup) WaitTimeout(timeout time.Duration) bool { 54 | wg.mutex.Lock() 55 | if wg.counter == 0 { 56 | wg.mutex.Unlock() 57 | return true 58 | } 59 | done := wg.done 60 | wg.mutex.Unlock() 61 | 62 | timer := time.NewTimer(timeout) 63 | defer timer.Stop() 64 | 65 | select { 66 | case <-done: 67 | return true 68 | case <-timer.C: 69 | return false 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /irods/message/lock_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageLockDataObjectResponse stores data object lock response 10 | type IRODSMessageLockDataObjectResponse struct { 11 | // empty structure 12 | FileDescriptor int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageLockDataObjectResponse) CheckError() error { 17 | if msg.FileDescriptor < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.FileDescriptor)) 19 | } 20 | return nil 21 | } 22 | 23 | // GetFileDescriptor returns file descriptor 24 | func (msg *IRODSMessageLockDataObjectResponse) GetFileDescriptor() int { 25 | return msg.FileDescriptor 26 | } 27 | 28 | // FromMessage returns struct from IRODSMessage 29 | func (msg *IRODSMessageLockDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 30 | if msgIn.Body == nil { 31 | return errors.Errorf("empty message body") 32 | } 33 | 34 | msg.FileDescriptor = int(msgIn.Body.IntInfo) 35 | return nil 36 | } 37 | 38 | // GetXMLCorrector returns XML corrector for this message 39 | func (msg *IRODSMessageLockDataObjectResponse) GetXMLCorrector() XMLCorrector { 40 | return GetXMLCorrectorForResponse() 41 | } 42 | -------------------------------------------------------------------------------- /irods/message/open_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageOpenDataObjectResponse stores data object open response 10 | type IRODSMessageOpenDataObjectResponse struct { 11 | // empty structure 12 | FileDescriptor int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageOpenDataObjectResponse) CheckError() error { 17 | if msg.FileDescriptor < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.FileDescriptor)) 19 | } 20 | return nil 21 | } 22 | 23 | // GetFileDescriptor returns file descriptor 24 | func (msg *IRODSMessageOpenDataObjectResponse) GetFileDescriptor() int { 25 | return msg.FileDescriptor 26 | } 27 | 28 | // FromMessage returns struct from IRODSMessage 29 | func (msg *IRODSMessageOpenDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 30 | if msgIn.Body == nil { 31 | return errors.Errorf("empty message body") 32 | } 33 | 34 | msg.FileDescriptor = int(msgIn.Body.IntInfo) 35 | return nil 36 | } 37 | 38 | // GetXMLCorrector returns XML corrector for this message 39 | func (msg *IRODSMessageOpenDataObjectResponse) GetXMLCorrector() XMLCorrector { 40 | return GetXMLCorrectorForResponse() 41 | } 42 | -------------------------------------------------------------------------------- /irods/message/create_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageCreateDataObjectResponse stores data object creation response 10 | type IRODSMessageCreateDataObjectResponse struct { 11 | // empty structure 12 | FileDescriptor int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageCreateDataObjectResponse) CheckError() error { 17 | if msg.FileDescriptor < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.FileDescriptor)) 19 | } 20 | return nil 21 | } 22 | 23 | // GetFileDescriptor returns file descriptor 24 | func (msg *IRODSMessageCreateDataObjectResponse) GetFileDescriptor() int { 25 | return msg.FileDescriptor 26 | } 27 | 28 | // FromMessage returns struct from IRODSMessage 29 | func (msg *IRODSMessageCreateDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 30 | if msgIn.Body == nil { 31 | return errors.Errorf("empty message body") 32 | } 33 | 34 | msg.FileDescriptor = int(msgIn.Body.IntInfo) 35 | return nil 36 | } 37 | 38 | // GetXMLCorrector returns XML corrector for this message 39 | func (msg *IRODSMessageCreateDataObjectResponse) GetXMLCorrector() XMLCorrector { 40 | return GetXMLCorrectorForResponse() 41 | } 42 | -------------------------------------------------------------------------------- /irods/types/data_object_lock.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // DataObjectLockType is a type for data object lock type 4 | type DataObjectLockType string 5 | 6 | const ( 7 | // DataObjectLockTypeRead is for read lock 8 | DataObjectLockTypeRead DataObjectLockType = "readLockType" 9 | // DataObjectLockTypeWrite is for write lock 10 | DataObjectLockTypeWrite DataObjectLockType = "writeLockType" 11 | // DataObjectLockTypeWrite is for write lock 12 | DataObjectLockTypeUnlock DataObjectLockType = "unlockType" 13 | ) 14 | 15 | // GetFileOpenMode returns FileOpenMode 16 | func (t DataObjectLockType) GetFileOpenMode() FileOpenMode { 17 | switch t { 18 | case DataObjectLockTypeRead: 19 | return FileOpenModeReadOnly 20 | case DataObjectLockTypeWrite: 21 | return FileOpenModeWriteOnly 22 | default: 23 | return FileOpenModeReadOnly 24 | } 25 | } 26 | 27 | // DataObjectLockCommand is a type for data object lock command 28 | type DataObjectLockCommand string 29 | 30 | const ( 31 | // DataObjectLockCommandSetLock is for set lock command 32 | DataObjectLockCommandSetLock DataObjectLockCommand = "setLockCmd" 33 | // DataObjectLockCommandSetLockWait is for set lock wait command 34 | DataObjectLockCommandSetLockWait DataObjectLockCommand = "setLockWaitCmd" 35 | // DataObjectLockCommandGetLock is for get lock command 36 | DataObjectLockCommandGetLock DataObjectLockCommand = "getLockCmd" 37 | ) 38 | -------------------------------------------------------------------------------- /test/testcases/util_error_test.go: -------------------------------------------------------------------------------- 1 | package testcases 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/cyverse/go-irodsclient/irods/common" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func getUtilErrorTest() Test { 11 | return Test{ 12 | Name: "Util_Error", 13 | Func: utilErrorTest, 14 | } 15 | } 16 | 17 | func utilErrorTest(t *testing.T, test *Test) { 18 | t.Run("ErrorCode", testErrorCode) 19 | } 20 | 21 | func testErrorCode(t *testing.T) { 22 | errcode := common.REMOTE_SERVER_AUTHENTICATION_FAILURE 23 | 24 | // test - value 25 | errstr := common.GetIRODSErrorString(errcode) 26 | assert.Contains(t, errstr, "REMOTE_SERVER_AUTHENTICATION_FAILURE") 27 | 28 | // test + value 29 | errstr = common.GetIRODSErrorString(common.ErrorCode(-1 * int(errcode))) 30 | assert.Contains(t, errstr, "REMOTE_SERVER_AUTHENTICATION_FAILURE") 31 | 32 | // test sub value 33 | errcode = common.ErrorCode(int(common.REMOTE_SERVER_AUTHENTICATION_FAILURE) - int(common.EIO)) 34 | assert.Equal(t, int(errcode), -910005) 35 | 36 | mainErrcode, subErrcode := common.SplitIRODSErrorCode(errcode) 37 | assert.Equal(t, common.REMOTE_SERVER_AUTHENTICATION_FAILURE, mainErrcode) 38 | assert.Equal(t, -1*common.EIO, subErrcode) 39 | 40 | errstr = common.GetIRODSErrorString(errcode) 41 | assert.Contains(t, errstr, "REMOTE_SERVER_AUTHENTICATION_FAILURE") 42 | assert.Contains(t, errstr, "I/O error") 43 | 44 | } 45 | -------------------------------------------------------------------------------- /examples/delete_file/delete_file.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func main() { 15 | logger := log.WithFields(log.Fields{}) 16 | 17 | // Parse cli parameters 18 | flag.Parse() 19 | args := flag.Args() 20 | 21 | if len(args) != 1 { 22 | fmt.Fprintf(os.Stderr, "Give an iRODS path!\n") 23 | os.Exit(1) 24 | } 25 | 26 | inputPath := args[0] 27 | 28 | // Read account configuration from YAML file 29 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 30 | if err != nil { 31 | logger.Error(err) 32 | panic(err) 33 | } 34 | 35 | account := cfg.ToIRODSAccount() 36 | logger.Debugf("Account : %v", account.GetRedacted()) 37 | 38 | // Create a file system 39 | appName := "delete_file" 40 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 41 | if err != nil { 42 | logger.Error(err) 43 | panic(err) 44 | } 45 | 46 | defer filesystem.Release() 47 | 48 | err = filesystem.RemoveFile(inputPath, true) 49 | if err != nil { 50 | logger.Error(err) 51 | panic(err) 52 | } 53 | 54 | if !filesystem.ExistsFile(inputPath) { 55 | fmt.Printf("Successfully deleted file %q\n", inputPath) 56 | } else { 57 | fmt.Printf("Could not delete file %q\n", inputPath) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /irods/types/auth.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | // AuthScheme defines Authentication Scheme 8 | type AuthScheme string 9 | 10 | const ( 11 | // AuthSchemeNative uses Native authentication scheme 12 | AuthSchemeNative AuthScheme = "native" 13 | // AuthSchemeGSI uses GSI authentication scheme 14 | AuthSchemeGSI AuthScheme = "gsi" 15 | // AuthSchemePAM uses PAM authentication scheme 16 | AuthSchemePAM AuthScheme = "pam" 17 | // AuthSchemePAMPasswordAuthScheme uses PAM authentication scheme 18 | AuthSchemePAMPassword AuthScheme = "pam_password" 19 | // AuthSchemeUnknown is unknown scheme 20 | AuthSchemeUnknown AuthScheme = "" 21 | ) 22 | 23 | // GetAuthScheme returns AuthScheme value from string 24 | func GetAuthScheme(authScheme string) AuthScheme { 25 | switch strings.TrimSpace(strings.ToLower(authScheme)) { 26 | case string(AuthSchemeNative): 27 | return AuthSchemeNative 28 | case string(AuthSchemeGSI): 29 | return AuthSchemeGSI 30 | case string(AuthSchemePAM): 31 | return AuthSchemePAM 32 | case string(AuthSchemePAMPassword): 33 | return AuthSchemePAMPassword 34 | case string(AuthSchemeUnknown): 35 | fallthrough 36 | default: 37 | return AuthSchemeUnknown 38 | } 39 | } 40 | 41 | // IsPAM checks if the auth scheme is pam or pam_password 42 | func (authScheme AuthScheme) IsPAM() bool { 43 | return authScheme == AuthSchemePAM || authScheme == AuthSchemePAMPassword 44 | } 45 | -------------------------------------------------------------------------------- /examples/create_ticket/create_ticket.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | "github.com/cyverse/go-irodsclient/irods/types" 11 | 12 | log "github.com/sirupsen/logrus" 13 | ) 14 | 15 | func main() { 16 | logger := log.WithFields(log.Fields{}) 17 | 18 | // Parse cli parameters 19 | flag.Parse() 20 | args := flag.Args() 21 | 22 | if len(args) < 2 { 23 | fmt.Fprintf(os.Stderr, "Give a ticket type and an iRODS path!\n") 24 | os.Exit(1) 25 | } 26 | 27 | ticketType := args[0] 28 | irodsPath := args[1] 29 | ticketName := "" 30 | if len(args) >= 3 { 31 | ticketName = args[2] 32 | } 33 | 34 | // Read account configuration from YAML file 35 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 36 | if err != nil { 37 | logger.Error(err) 38 | panic(err) 39 | } 40 | 41 | account := cfg.ToIRODSAccount() 42 | logger.Debugf("Account : %v", account.GetRedacted()) 43 | 44 | // Create a file system 45 | appName := "create_ticket" 46 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 47 | if err != nil { 48 | logger.Error(err) 49 | panic(err) 50 | } 51 | 52 | defer filesystem.Release() 53 | 54 | err = filesystem.CreateTicket(ticketName, types.TicketType(ticketType), irodsPath) 55 | if err != nil { 56 | logger.Error(err) 57 | panic(err) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /irods/message/auth_result.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/types" 7 | ) 8 | 9 | // IRODSMessageAuthResult stores authentication result 10 | type IRODSMessageAuthResult struct { 11 | // empty structure 12 | Result int 13 | } 14 | 15 | // CheckError returns error if server returned an error 16 | func (msg *IRODSMessageAuthResult) CheckError() error { 17 | if msg.Result < 0 { 18 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 19 | } 20 | return nil 21 | } 22 | 23 | // GetMessage builds a message 24 | func (msg *IRODSMessageAuthResult) GetMessage() (*IRODSMessage, error) { 25 | msgHeader := IRODSMessageHeader{ 26 | Type: RODS_MESSAGE_API_REPLY_TYPE, 27 | MessageLen: 0, 28 | ErrorLen: 0, 29 | BsLen: 0, 30 | IntInfo: int32(msg.Result), 31 | } 32 | 33 | return &IRODSMessage{ 34 | Header: &msgHeader, 35 | Body: nil, 36 | }, nil 37 | } 38 | 39 | // FromMessage returns struct from IRODSMessage 40 | func (msg *IRODSMessageAuthResult) FromMessage(msgIn *IRODSMessage) error { 41 | if msgIn.Body == nil { 42 | return errors.Errorf("empty message body") 43 | } 44 | 45 | msg.Result = int(msgIn.Body.IntInfo) 46 | return nil 47 | } 48 | 49 | // GetXMLCorrector returns XML corrector for this message 50 | func (msg *IRODSMessageAuthResult) GetXMLCorrector() XMLCorrector { 51 | return GetXMLCorrectorForResponse() 52 | } 53 | -------------------------------------------------------------------------------- /examples/make_dir/make_dir.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func main() { 15 | logger := log.WithFields(log.Fields{}) 16 | 17 | recurse := false 18 | // Parse cli parameters 19 | flag.BoolVar(&recurse, "p", false, "create parent directories if not exist") 20 | flag.Parse() 21 | args := flag.Args() 22 | 23 | if len(args) != 1 { 24 | fmt.Fprintf(os.Stderr, "Give an iRODS path!\n") 25 | os.Exit(1) 26 | } 27 | 28 | inputPath := args[0] 29 | 30 | // Read account configuration from YAML file 31 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 32 | if err != nil { 33 | logger.Error(err) 34 | panic(err) 35 | } 36 | 37 | account := cfg.ToIRODSAccount() 38 | logger.Debugf("Account : %v", account.GetRedacted()) 39 | 40 | // Create a file system 41 | appName := "make_dir" 42 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 43 | if err != nil { 44 | logger.Error(err) 45 | panic(err) 46 | } 47 | 48 | defer filesystem.Release() 49 | 50 | err = filesystem.MakeDir(inputPath, recurse) 51 | if err != nil { 52 | logger.Error(err) 53 | panic(err) 54 | } 55 | 56 | if filesystem.ExistsDir(inputPath) { 57 | fmt.Printf("Successfully made dir %q\n", inputPath) 58 | } else { 59 | fmt.Printf("Could not make dir %q\n", inputPath) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/delete_dir/delete_dir.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func main() { 15 | logger := log.WithFields(log.Fields{}) 16 | 17 | recurse := false 18 | // Parse cli parameters 19 | flag.BoolVar(&recurse, "recurse", false, "recursive") 20 | flag.BoolVar(&recurse, "r", false, "recursive") 21 | flag.Parse() 22 | args := flag.Args() 23 | 24 | if len(args) != 1 { 25 | fmt.Fprintf(os.Stderr, "Give an iRODS path!\n") 26 | os.Exit(1) 27 | } 28 | 29 | inputPath := args[0] 30 | 31 | // Read account configuration from YAML file 32 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 33 | if err != nil { 34 | logger.Error(err) 35 | panic(err) 36 | } 37 | 38 | account := cfg.ToIRODSAccount() 39 | logger.Debugf("Account : %v", account.GetRedacted()) 40 | 41 | // Create a file system 42 | appName := "delete_dir" 43 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 44 | if err != nil { 45 | logger.Error(err) 46 | panic(err) 47 | } 48 | 49 | defer filesystem.Release() 50 | 51 | err = filesystem.RemoveDir(inputPath, recurse, true) 52 | if err != nil { 53 | logger.Error(err) 54 | panic(err) 55 | } 56 | 57 | if !filesystem.ExistsDir(inputPath) { 58 | fmt.Printf("Successfully deleted dir %q\n", inputPath) 59 | } else { 60 | fmt.Printf("Could not delete dir %q\n", inputPath) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /irods/message/data_object_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import "encoding/xml" 4 | 5 | // IRODSMessageDataObjectRequest ... 6 | type IRODSMessageDataObjectRequest struct { 7 | XMLName xml.Name `xml:"DataObjInp_PI"` 8 | Path string `xml:"objPath"` 9 | CreateMode int `xml:"createMode"` 10 | OpenFlags int `xml:"openFlags"` 11 | Offset int64 `xml:"offset"` 12 | Size int64 `xml:"dataSize"` 13 | Threads int `xml:"numThreads"` 14 | OperationType int `xml:"oprType"` 15 | SpecialCollectionPointer *IRODSMessageSpecialCollection `xml:"SpecColl_PI"` 16 | KeyVals IRODSMessageSSKeyVal `xml:"KeyValPair_PI"` 17 | } 18 | 19 | type IRODSMessageSpecialCollection struct { 20 | XMLName xml.Name `xml:"SpecColl_PI"` 21 | CollectionClass int `xml:"collClass"` 22 | Type int `xml:"type"` 23 | Collection string `xml:"collection"` 24 | ObjectPath string `xml:"objPath"` 25 | Resource string `xml:"resource"` 26 | ResourceHierarchy string `xml:"rescHier"` 27 | PhysicalPath string `xml:"phyPath"` 28 | CacheDirectory string `xml:"cacheDir"` 29 | CacheDirty int `xml:"cacheDirty"` 30 | ReplicationNumber int `xml:"replNum"` 31 | } 32 | -------------------------------------------------------------------------------- /test/testcases/util_encoding_test.go: -------------------------------------------------------------------------------- 1 | package testcases 2 | 3 | import ( 4 | "encoding/hex" 5 | "testing" 6 | 7 | irods_util "github.com/cyverse/go-irodsclient/irods/util" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func getUtilEncodingTest() Test { 12 | return Test{ 13 | Name: "Util_Encoding", 14 | Func: utilEncodingTest, 15 | } 16 | } 17 | 18 | func utilEncodingTest(t *testing.T, test *Test) { 19 | t.Run("EncoderRing", testEncoderRing) 20 | t.Run("Scramble", testScramble) 21 | t.Run("ClientSignature", testClientSignature) 22 | } 23 | 24 | func testEncoderRing(t *testing.T) { 25 | ring := irods_util.GetEncoderRing("def") 26 | ringHex := hex.EncodeToString(ring) 27 | assert.Equal(t, "5fbabc5bfd2ef4f4d65024d364c3241a71c71aae827a91b654e9de55e62f3cb23840a894e36c7149ddd8963a1b228df43840a894e36c7149ddd8963a1b228df4", ringHex) 28 | } 29 | 30 | func testScramble(t *testing.T) { 31 | scrPass1 := irods_util.Scramble(";.ObfV2test_password", "06fed401fb79f864272a421835486736", "", false) 32 | assert.Equal(t, ";EBo$tJuoAY_RigHonj-", scrPass1) 33 | 34 | scrPass2 := irods_util.Scramble(";.ObfV2test_password", "06fed401fb79f864272a421835486736", "", true) 35 | assert.Equal(t, ";E3O&GDl4!&_$3GBd+B\"", scrPass2) 36 | } 37 | 38 | func testClientSignature(t *testing.T) { 39 | test := GetCurrentTest() 40 | server := test.GetCurrentServer() 41 | 42 | sess, err := server.GetSession() 43 | FailError(t, err) 44 | defer sess.Release() 45 | 46 | conn, err := sess.AcquireConnection(true) 47 | FailError(t, err) 48 | 49 | signature := conn.GetClientSignature() 50 | assert.Equal(t, 32, len(signature)) 51 | } 52 | -------------------------------------------------------------------------------- /irods/types/user.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "fmt" 4 | 5 | // IRODSUserType is a type of iRODS User 6 | type IRODSUserType string 7 | 8 | const ( 9 | // IRODSUserRodsGroup is for a group 10 | IRODSUserRodsGroup IRODSUserType = "rodsgroup" 11 | // IRODSUserRodsUser is for a user 12 | IRODSUserRodsUser IRODSUserType = "rodsuser" 13 | // IRODSUserRodsAdmin is for an admin user 14 | IRODSUserRodsAdmin IRODSUserType = "rodsadmin" 15 | // IRODSUserGroupAdmin is for an admin group 16 | IRODSUserGroupAdmin IRODSUserType = "groupadmin" 17 | ) 18 | 19 | // IRODSUser contains irods user information 20 | type IRODSUser struct { 21 | ID int64 `json:"id"` 22 | Name string `json:"name"` 23 | Zone string `json:"zone"` 24 | Type IRODSUserType `json:"type"` 25 | } 26 | 27 | // IsGroup returns true if type is IRODSUserRodsGroup 28 | func (user *IRODSUser) IsGroup() bool { 29 | return user.Type == IRODSUserRodsGroup 30 | } 31 | 32 | // IsUser returns true if type is IRODSUserRodsUser 33 | func (user *IRODSUser) IsUser() bool { 34 | return user.Type == IRODSUserRodsUser 35 | } 36 | 37 | // IsAdminGroup returns true if type is IRODSUserGroupAdmin 38 | func (user *IRODSUser) IsAdminGroup() bool { 39 | return user.Type == IRODSUserGroupAdmin 40 | } 41 | 42 | // IsAdminUser returns true if type is IRODSUserRodsAdmin 43 | func (user *IRODSUser) IsAdminUser() bool { 44 | return user.Type == IRODSUserRodsAdmin 45 | } 46 | 47 | // ToString stringifies the object 48 | func (user *IRODSUser) ToString() string { 49 | return fmt.Sprintf("", user.ID, user.Name, user.Zone, string(user.Type)) 50 | } 51 | -------------------------------------------------------------------------------- /examples/get_ticket/get_ticket.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | "github.com/cyverse/go-irodsclient/irods/session" 11 | 12 | log "github.com/sirupsen/logrus" 13 | ) 14 | 15 | func main() { 16 | logger := log.WithFields(log.Fields{}) 17 | 18 | // Parse cli parameters 19 | flag.Parse() 20 | args := flag.Args() 21 | 22 | if len(args) != 1 { 23 | fmt.Fprintf(os.Stderr, "Give an iRODS ticket!\n") 24 | os.Exit(1) 25 | } 26 | 27 | ticketName := args[0] 28 | 29 | // Read account configuration from YAML file 30 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 31 | if err != nil { 32 | logger.Error(err) 33 | panic(err) 34 | } 35 | 36 | account := cfg.ToIRODSAccount() 37 | logger.Debugf("Account : %v", account.GetRedacted()) 38 | 39 | // Create a file system 40 | appName := "get_ticket" 41 | config := fs.NewFileSystemConfig(appName) 42 | sessConfig := config.ToMetadataSessionConfig() 43 | sess, err := session.NewIRODSSession(account, sessConfig) 44 | if err != nil { 45 | logger.Error(err) 46 | panic(err) 47 | } 48 | 49 | defer sess.Release() 50 | 51 | /* 52 | conn, err := sess.AcquireConnection(true) 53 | if err != nil { 54 | logger.Error(err) 55 | panic(err) 56 | } 57 | 58 | ticket, err := irods_fs.GetTicket(conn, ticketName) 59 | if err != nil { 60 | logger.Error(err) 61 | panic(err) 62 | } 63 | */ 64 | fmt.Printf("> Ticket: %s\n", ticketName) 65 | /* 66 | fmt.Printf("%s\n", ticket.ToString()) 67 | */ 68 | } 69 | -------------------------------------------------------------------------------- /examples/ssl_list_dir/list_dir.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func main() { 15 | logger := log.WithFields(log.Fields{}) 16 | 17 | // Parse cli parameters 18 | flag.Parse() 19 | args := flag.Args() 20 | 21 | if len(args) != 1 { 22 | fmt.Fprintf(os.Stderr, "Give an iRODS path!\n") 23 | os.Exit(1) 24 | } 25 | 26 | inputPath := args[0] 27 | 28 | // Read account configuration from YAML file 29 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 30 | if err != nil { 31 | logger.Error(err) 32 | panic(err) 33 | } 34 | 35 | account := cfg.ToIRODSAccount() 36 | logger.Debugf("Account : %v", account.GetRedacted()) 37 | 38 | // Create a file system 39 | appName := "list_dir" 40 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 41 | if err != nil { 42 | logger.Error(err) 43 | panic(err) 44 | } 45 | 46 | defer filesystem.Release() 47 | 48 | entries, err := filesystem.List(inputPath) 49 | if err != nil { 50 | logger.Error(err) 51 | panic(err) 52 | } 53 | 54 | if len(entries) == 0 { 55 | fmt.Printf("Found no entries in the directory %q\n", inputPath) 56 | } else { 57 | fmt.Printf("DIR: %s\n", inputPath) 58 | for _, entry := range entries { 59 | if entry.Type == fs.FileEntry { 60 | fmt.Printf("> FILE:\t%s\t%d\n", entry.Path, entry.Size) 61 | } else { 62 | // dir 63 | fmt.Printf("> DIRECTORY:\t%s\n", entry.Path) 64 | } 65 | 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/list_dir_via_ticket/list_dir.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func main() { 15 | logger := log.WithFields(log.Fields{}) 16 | 17 | // Parse cli parameters 18 | flag.Parse() 19 | args := flag.Args() 20 | 21 | if len(args) != 1 { 22 | fmt.Fprintf(os.Stderr, "Give an iRODS path!\n") 23 | os.Exit(1) 24 | } 25 | 26 | inputPath := args[0] 27 | 28 | // Read account configuration from YAML file 29 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 30 | if err != nil { 31 | logger.Error(err) 32 | panic(err) 33 | } 34 | 35 | account := cfg.ToIRODSAccount() 36 | logger.Debugf("Account : %v", account.GetRedacted()) 37 | 38 | // Create a file system 39 | appName := "list_dir_ticket" 40 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 41 | if err != nil { 42 | logger.Error(err) 43 | panic(err) 44 | } 45 | 46 | defer filesystem.Release() 47 | 48 | entries, err := filesystem.List(inputPath) 49 | if err != nil { 50 | logger.Error(err) 51 | panic(err) 52 | } 53 | 54 | if len(entries) == 0 { 55 | fmt.Printf("Found no entries in the directory %q\n", inputPath) 56 | } else { 57 | fmt.Printf("DIR: %s\n", inputPath) 58 | for _, entry := range entries { 59 | if entry.Type == fs.FileEntry { 60 | fmt.Printf("> FILE:\t%s\t%d\n", entry.Path, entry.Size) 61 | } else { 62 | // dir 63 | fmt.Printf("> DIRECTORY:\t%s\n", entry.Path) 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/list_dir/list_dir.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func main() { 15 | logger := log.WithFields(log.Fields{}) 16 | 17 | // Parse cli parameters 18 | flag.Parse() 19 | args := flag.Args() 20 | 21 | if len(args) != 1 { 22 | fmt.Fprintf(os.Stderr, "Give an iRODS path!\n") 23 | os.Exit(1) 24 | } 25 | 26 | inputPath := args[0] 27 | 28 | // Read account configuration from YAML file 29 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 30 | if err != nil { 31 | logger.Error(err) 32 | panic(err) 33 | } 34 | 35 | account := cfg.ToIRODSAccount() 36 | logger.Debugf("Account : %v", account.GetRedacted()) 37 | 38 | // Create a file system 39 | appName := "list_dir" 40 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 41 | if err != nil { 42 | logger.Error(err) 43 | panic(err) 44 | } 45 | 46 | defer filesystem.Release() 47 | 48 | entries, err := filesystem.List(inputPath) 49 | if err != nil { 50 | logger.Error(err) 51 | panic(err) 52 | } 53 | 54 | if len(entries) == 0 { 55 | fmt.Printf("Found no entries in the directory %q\n", inputPath) 56 | } else { 57 | fmt.Printf("DIR: %s\n", inputPath) 58 | for _, entry := range entries { 59 | if entry.Type == fs.FileEntry { 60 | fmt.Printf("> FILE:\t%d\t%s\t%d\n", entry.ID, entry.Path, entry.Size) 61 | } else { 62 | // dir 63 | fmt.Printf("> DIRECTORY:\t%d\t%s\n", entry.ID, entry.Path) 64 | } 65 | 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/search/search.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func main() { 15 | logger := log.WithFields(log.Fields{}) 16 | 17 | // Parse cli parameters 18 | flag.Parse() 19 | args := flag.Args() 20 | 21 | if len(args) != 1 { 22 | fmt.Fprintf(os.Stderr, "Give an iRODS path with wildcard!\n") 23 | os.Exit(1) 24 | } 25 | 26 | inputPath := args[0] 27 | 28 | // Read account configuration from YAML file 29 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 30 | if err != nil { 31 | logger.Error(err) 32 | panic(err) 33 | } 34 | 35 | account := cfg.ToIRODSAccount() 36 | logger.Debugf("Account : %v", account.GetRedacted()) 37 | 38 | // Create a file system 39 | appName := "search" 40 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 41 | if err != nil { 42 | logger.Error(err) 43 | panic(err) 44 | } 45 | 46 | defer filesystem.Release() 47 | 48 | entries, err := filesystem.SearchUnixWildcard(inputPath) 49 | if err != nil { 50 | logger.Error(err) 51 | panic(err) 52 | } 53 | 54 | if len(entries) == 0 { 55 | fmt.Printf("Found no entries in the directory %q\n", inputPath) 56 | } else { 57 | fmt.Printf("DIR: %s\n", inputPath) 58 | for _, entry := range entries { 59 | if entry.Type == fs.FileEntry { 60 | fmt.Printf("> FILE:\t%d\t%s\t%d\n", entry.ID, entry.Path, entry.Size) 61 | } else { 62 | // dir 63 | fmt.Printf("> DIRECTORY:\t%d\t%s\n", entry.ID, entry.Path) 64 | } 65 | 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /irods/message/seek_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // IRODSMessageSeekDataObjectResponse stores data object seek response 12 | type IRODSMessageSeekDataObjectResponse struct { 13 | XMLName xml.Name `xml:"fileLseekOut_PI"` 14 | Offset int64 `xml:"offset"` 15 | } 16 | 17 | // FromBytes returns struct from bytes 18 | func (msg *IRODSMessageSeekDataObjectResponse) FromBytes(bytes []byte) error { 19 | err := xml.Unmarshal(bytes, msg) 20 | if err != nil { 21 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 22 | } 23 | return nil 24 | } 25 | 26 | // CheckError returns error if server returned an error 27 | func (msg *IRODSMessageSeekDataObjectResponse) CheckError() error { 28 | if msg.Offset < 0 { 29 | return types.NewIRODSError(common.ErrorCode(msg.Offset)) 30 | } 31 | return nil 32 | } 33 | 34 | // FromMessage returns struct from IRODSMessage 35 | func (msg *IRODSMessageSeekDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 36 | if msgIn.Body == nil { 37 | return errors.Errorf("empty message body") 38 | } 39 | 40 | if msgIn.Body.Message != nil { 41 | err := msg.FromBytes(msgIn.Body.Message) 42 | if err != nil { 43 | return errors.Wrapf(err, "failed to get irods message from message body") 44 | } 45 | } 46 | 47 | return nil 48 | } 49 | 50 | // GetXMLCorrector returns XML corrector for this message 51 | func (msg *IRODSMessageSeekDataObjectResponse) GetXMLCorrector() XMLCorrector { 52 | return GetXMLCorrectorForResponse() 53 | } 54 | -------------------------------------------------------------------------------- /irods/message/ssl_sharedsecret.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | ) 6 | 7 | const ( 8 | // RODS_MESSAGE_SSL_SHARED_SECRET_TYPE is a message type for shared secret used in SSL connection establishment 9 | RODS_MESSAGE_SSL_SHARED_SECRET_TYPE MessageType = "SHARED_SECRET" 10 | ) 11 | 12 | // IRODSMessageSSLSharedSecret stores shared secret data 13 | type IRODSMessageSSLSharedSecret struct { 14 | SharedSecret []byte 15 | } 16 | 17 | // NewIRODSMessageSSLSharedSecret creates a IRODSMessageSSLSharedSecret message 18 | func NewIRODSMessageSSLSharedSecret(sharedSecret []byte) *IRODSMessageSSLSharedSecret { 19 | return &IRODSMessageSSLSharedSecret{ 20 | SharedSecret: sharedSecret, 21 | } 22 | } 23 | 24 | // GetMessage builds a message 25 | func (msg *IRODSMessageSSLSharedSecret) GetMessage() (*IRODSMessage, error) { 26 | msgBody := IRODSMessageBody{ 27 | Type: RODS_MESSAGE_SSL_SHARED_SECRET_TYPE, 28 | Message: msg.SharedSecret, 29 | Error: nil, 30 | Bs: nil, 31 | IntInfo: 0, 32 | } 33 | 34 | msgHeader, err := msgBody.BuildHeader() 35 | if err != nil { 36 | return nil, errors.Wrapf(err, "failed to build header from irods message") 37 | } 38 | 39 | return &IRODSMessage{ 40 | Header: msgHeader, 41 | Body: &msgBody, 42 | }, nil 43 | } 44 | 45 | // FromMessage returns struct from IRODSMessage 46 | func (msg *IRODSMessageSSLSharedSecret) FromMessage(msgIn *IRODSMessage) error { 47 | if msgIn.Body == nil { 48 | return errors.Errorf("empty message body") 49 | } 50 | 51 | msg.SharedSecret = msgIn.Body.Message 52 | 53 | return nil 54 | } 55 | 56 | func (msg *IRODSMessageSSLSharedSecret) GetXMLCorrector() XMLCorrector { 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /irods/message/resource_server_transfer_encryption_header.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/binary" 5 | 6 | "github.com/cockroachdb/errors" 7 | ) 8 | 9 | // IRODSMessageResourceServerTransferEncryptionHeader stores resource server transfer encryption header message 10 | type IRODSMessageResourceServerTransferEncryptionHeader struct { 11 | Length int 12 | IV []byte 13 | 14 | ivSize int // internal, must be set before calling FromBytes 15 | } 16 | 17 | // NewIRODSMessageResourceServerTransferEncryptionHeader creates IRODSMessageResourceServerTransferEncryptionHeader 18 | func NewIRODSMessageResourceServerTransferEncryptionHeader(ivSize int) *IRODSMessageResourceServerTransferEncryptionHeader { 19 | return &IRODSMessageResourceServerTransferEncryptionHeader{ 20 | ivSize: ivSize, 21 | } 22 | } 23 | 24 | // GetBytes returns byte array 25 | func (msg *IRODSMessageResourceServerTransferEncryptionHeader) GetBytes() ([]byte, error) { 26 | buf := make([]byte, 4+msg.ivSize) 27 | binary.LittleEndian.PutUint32(buf, uint32(msg.Length)) 28 | copy(buf[4:4+msg.ivSize], msg.IV) 29 | return buf, nil 30 | } 31 | 32 | // FromBytes returns struct from bytes 33 | func (msg *IRODSMessageResourceServerTransferEncryptionHeader) FromBytes(bytes []byte) error { 34 | if len(bytes) < 4+msg.ivSize { 35 | return errors.Errorf("failed to read transfer encryption header, header must be %d bytes, but received %d", 4+msg.ivSize, len(bytes)) 36 | } 37 | 38 | msg.Length = int(binary.LittleEndian.Uint32(bytes[0:4])) 39 | msg.IV = bytes[4 : 4+msg.ivSize] 40 | return nil 41 | } 42 | 43 | // SizeOf returns struct size in bytes 44 | func (msg *IRODSMessageResourceServerTransferEncryptionHeader) SizeOf() int { 45 | return 4 + msg.ivSize 46 | } 47 | -------------------------------------------------------------------------------- /irods/connection/auth.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/types" 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | func AuthenticateClient(conn *IRODSConnection, authPlugin IRODSAuthPlugin, requestContext *IRODSAuthContext) error { 10 | logger := log.WithFields(log.Fields{}) 11 | 12 | logger.Debug("authentication start") 13 | 14 | if authPlugin == nil { 15 | return types.NewAuthFlowError("no authentication plugin provided") 16 | } 17 | 18 | nextOp := AUTH_CLIENT_START 19 | 20 | requestContext.Set("scheme", authPlugin.GetName()) 21 | requestContext.Set(AUTH_NEXT_OPERATION, nextOp) 22 | 23 | for { 24 | logger.Debugf("server request context: %v", requestContext.GetRedacted()) 25 | 26 | responseContext, err := authPlugin.Execute(conn, nextOp, requestContext) 27 | if err != nil { 28 | return errors.Join(err, types.NewAuthFlowError("authentication plugin execution failed")) 29 | } 30 | 31 | logger.Debugf("server response context: %v", responseContext.GetRedacted()) 32 | 33 | if conn.IsLoggedIn() { 34 | break 35 | } 36 | 37 | authNextOperation, ok := responseContext.Get(AUTH_NEXT_OPERATION) 38 | if !ok { 39 | return types.NewAuthFlowError("authentication response did not return next operation") 40 | } 41 | 42 | if authNextOperationString, ok := authNextOperation.(string); ok { 43 | nextOp = authNextOperationString 44 | } 45 | 46 | if len(nextOp) == 0 || nextOp == AUTH_FLOW_COMPLETE { 47 | // invalid 48 | return types.NewAuthFlowError("authentication did not complete successfully") 49 | } 50 | 51 | requestContext = responseContext 52 | } 53 | 54 | logger.Debug("authentication complete") 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /irods/types/version.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | ) 7 | 8 | // IRODSVersion contains irods version information 9 | type IRODSVersion struct { 10 | ReleaseVersion string // e.g., "rods4.2.8" 11 | APIVersion string 12 | ReconnectPort int 13 | ReconnectAddr string 14 | Cookie int 15 | } 16 | 17 | // GetReleaseVersion returns version parts (major, minor, patch) 18 | func (ver *IRODSVersion) GetReleaseVersion() (int, int, int) { 19 | major := 0 20 | minor := 0 21 | patch := 0 22 | 23 | releaseVersion := strings.ToLower(ver.ReleaseVersion) 24 | releaseVersion = strings.TrimPrefix(releaseVersion, "rods") 25 | 26 | vers := strings.Split(releaseVersion, ".") 27 | if len(vers) >= 1 { 28 | m, err := strconv.Atoi(vers[0]) 29 | if err == nil { 30 | major = m 31 | } 32 | } 33 | 34 | if len(vers) >= 2 { 35 | m, err := strconv.Atoi(vers[1]) 36 | if err == nil { 37 | minor = m 38 | } 39 | } 40 | 41 | if len(vers) >= 3 { 42 | p, err := strconv.Atoi(vers[2]) 43 | if err == nil { 44 | patch = p 45 | } 46 | } 47 | 48 | return major, minor, patch 49 | } 50 | 51 | // HasHigherVersionThan returns if given version is higher or equal than current version 52 | func (ver *IRODSVersion) HasHigherVersionThan(major int, minor int, patch int) bool { 53 | smajor, sminor, spatch := ver.GetReleaseVersion() 54 | if smajor > major { 55 | return true 56 | } 57 | if smajor < major { 58 | return false 59 | } 60 | // major is equal 61 | if sminor > minor { 62 | return true 63 | } 64 | if sminor < minor { 65 | return false 66 | } 67 | // minor is equal 68 | if spatch > patch { 69 | return true 70 | } 71 | if spatch < patch { 72 | return false 73 | } 74 | return true 75 | } 76 | -------------------------------------------------------------------------------- /irods/message/host.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | "net" 6 | "strconv" 7 | "strings" 8 | 9 | "github.com/cockroachdb/errors" 10 | "github.com/cyverse/go-irodsclient/irods/types" 11 | ) 12 | 13 | // IRODSMessageHost stores startup message 14 | type IRODSMessageHost struct { 15 | XMLName xml.Name `xml:"RHostAddr_PI"` 16 | Addr string `xml:"hostAddr"` 17 | Zone string `xml:"rodsZone"` 18 | Port int `xml:"port"` 19 | DummyInt int `xml:"dummyInt"` 20 | } 21 | 22 | // NewIRODSMessageHost creates a IRODSMessageHost message 23 | func NewIRODSMessageHost(resource *types.IRODSResource) (*IRODSMessageHost, error) { 24 | addr := resource.Location 25 | port := 1247 26 | 27 | if strings.Contains(resource.Location, ":") { 28 | newAddr, portStr, err := net.SplitHostPort(resource.Location) 29 | if err != nil { 30 | return nil, errors.Wrapf(err, "failed to split host port") 31 | } 32 | 33 | port, err = strconv.Atoi(portStr) 34 | if err != nil { 35 | return nil, errors.Wrapf(err, "failed to convert ascii %q to int", portStr) 36 | } 37 | 38 | addr = newAddr 39 | } 40 | 41 | return &IRODSMessageHost{ 42 | Addr: addr, 43 | Zone: resource.Zone, 44 | Port: port, 45 | }, nil 46 | } 47 | 48 | // GetBytes returns byte array 49 | func (msg *IRODSMessageHost) GetBytes() ([]byte, error) { 50 | xmlBytes, err := xml.Marshal(msg) 51 | if err != nil { 52 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 53 | } 54 | return xmlBytes, nil 55 | } 56 | 57 | // FromBytes returns struct from bytes 58 | func (msg *IRODSMessageHost) FromBytes(bytes []byte) error { 59 | err := xml.Unmarshal(bytes, msg) 60 | if err != nil { 61 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 62 | } 63 | return nil 64 | } 65 | -------------------------------------------------------------------------------- /test/testcases/util_password_obfuscation_test.go: -------------------------------------------------------------------------------- 1 | package testcases 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/cyverse/go-irodsclient/config" 8 | "github.com/sethvargo/go-password/password" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func getUtilPasswordObfuscationTest() Test { 13 | return Test{ 14 | Name: "Util_PasswordObfuscation", 15 | Func: utilPasswordObfuscation, 16 | } 17 | } 18 | 19 | func utilPasswordObfuscation(t *testing.T, test *Test) { 20 | t.Run("StaticPasswords", testStaticPasswords) 21 | t.Run("RandomPasswords", testRandomPasswords) 22 | 23 | } 24 | 25 | func testStaticPasswords(t *testing.T) { 26 | obf := config.NewPasswordObfuscator() 27 | 28 | mypassword := "mypassword_1234_!@#$" 29 | encodedPassword := obf.Encode([]byte(mypassword)) 30 | decodedPassword := obf.Decode(encodedPassword) 31 | assert.Equal(t, mypassword, string(decodedPassword)) 32 | 33 | mypassword = "MicceLecos!@99" 34 | encodedPassword = obf.Encode([]byte(mypassword)) 35 | decodedPassword = obf.Decode(encodedPassword) 36 | 37 | assert.Equal(t, mypassword, string(decodedPassword)) 38 | 39 | for i := 0; i < 99; i++ { 40 | mypassword = fmt.Sprintf("loLLeooelef!@%d", i) 41 | encodedPassword := obf.Encode([]byte(mypassword)) 42 | decodedPassword := obf.Decode(encodedPassword) 43 | 44 | assert.Equal(t, mypassword, string(decodedPassword)) 45 | } 46 | } 47 | 48 | func testRandomPasswords(t *testing.T) { 49 | obf := config.NewPasswordObfuscator() 50 | 51 | for i := 0; i < 100000; i++ { 52 | mypassword, err := password.Generate(20, 10, 10, false, true) 53 | if err != nil { 54 | t.Fatal(err) 55 | } 56 | 57 | encodedPassword := obf.Encode([]byte(mypassword)) 58 | decodedPassword := obf.Decode(encodedPassword) 59 | 60 | assert.Equal(t, mypassword, string(decodedPassword)) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /irods/types/duration.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "encoding/json" 5 | "time" 6 | 7 | "github.com/cockroachdb/errors" 8 | ) 9 | 10 | // Duration is a replacement of time.Duration that supports JSON 11 | type Duration time.Duration 12 | 13 | // MarshalJSON ... 14 | func (d *Duration) MarshalJSON() ([]byte, error) { 15 | return json.Marshal(time.Duration(*d).String()) 16 | } 17 | 18 | // UnmarshalJSON ... 19 | func (d *Duration) UnmarshalJSON(b []byte) error { 20 | var v interface{} 21 | if err := json.Unmarshal(b, &v); err != nil { 22 | return errors.Wrapf(err, "failed to parse %q to time.Duration", string(b)) 23 | } 24 | switch value := v.(type) { 25 | case float64: 26 | *d = Duration(time.Duration(value)) 27 | return nil 28 | case string: 29 | tmp, err := time.ParseDuration(value) 30 | if err != nil { 31 | return errors.Wrapf(err, "failed to parse %q to time.Duration", string(b)) 32 | } 33 | *d = Duration(tmp) 34 | return nil 35 | default: 36 | return errors.Errorf("failed to parse %q to time.Duration", string(b)) 37 | } 38 | } 39 | 40 | // bug in YAMLv2, fixed in YAMLv3 41 | // // MarshalYAML ... 42 | // func (d *Duration) MarshalYAML() (interface{}, error) { 43 | // return time.Duration(*d).String(), nil 44 | // } 45 | 46 | // UnmarshalYAML ... 47 | func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error { 48 | var tm string 49 | if err := unmarshal(&tm); err != nil { 50 | return errors.Wrapf(err, "failed to parse %q to time.Duration", tm) 51 | } 52 | 53 | lastChar := byte(tm[len(tm)-1]) 54 | if lastChar >= '0' && lastChar <= '9' { 55 | // ends with number, no units 56 | tm = tm + "ns" 57 | } 58 | 59 | td, err := time.ParseDuration(tm) 60 | if err != nil { 61 | return errors.Wrapf(err, "failed to parse %q to time.Duration", tm) 62 | } 63 | 64 | *d = Duration(td) 65 | return nil 66 | } 67 | -------------------------------------------------------------------------------- /irods/message/get_data_object_stat_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageGetDataObjectStatRequest stores file stat request 11 | type IRODSMessageGetDataObjectStatRequest IRODSMessageDataObjectRequest 12 | 13 | // GetBytes returns byte array 14 | func (msg *IRODSMessageGetDataObjectStatRequest) GetBytes() ([]byte, error) { 15 | xmlBytes, err := xml.Marshal(msg) 16 | if err != nil { 17 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 18 | } 19 | return xmlBytes, nil 20 | } 21 | 22 | // FromBytes returns struct from bytes 23 | func (msg *IRODSMessageGetDataObjectStatRequest) FromBytes(bytes []byte) error { 24 | err := xml.Unmarshal(bytes, msg) 25 | if err != nil { 26 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 27 | } 28 | return nil 29 | } 30 | 31 | // GetMessage builds a message 32 | func (msg *IRODSMessageGetDataObjectStatRequest) GetMessage() (*IRODSMessage, error) { 33 | bytes, err := msg.GetBytes() 34 | if err != nil { 35 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 36 | } 37 | 38 | msgBody := IRODSMessageBody{ 39 | Type: RODS_MESSAGE_API_REQ_TYPE, 40 | Message: bytes, 41 | Error: nil, 42 | Bs: nil, 43 | IntInfo: int32(common.OBJ_STAT_AN), 44 | } 45 | 46 | msgHeader, err := msgBody.BuildHeader() 47 | if err != nil { 48 | return nil, errors.Wrapf(err, "failed to build header from irods message") 49 | } 50 | 51 | return &IRODSMessage{ 52 | Header: msgHeader, 53 | Body: &msgBody, 54 | }, nil 55 | } 56 | 57 | // GetXMLCorrector returns XML corrector for this message 58 | func (msg *IRODSMessageGetDataObjectStatRequest) GetXMLCorrector() XMLCorrector { 59 | return GetXMLCorrectorForRequest() 60 | } 61 | -------------------------------------------------------------------------------- /irods/types/meta.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/cockroachdb/errors" 8 | ) 9 | 10 | // IRODSMetaItemType describes a type to set metadata on 11 | type IRODSMetaItemType string 12 | 13 | const ( 14 | // IRODSDataObjectMetaItemType is a type for data object meta 15 | IRODSDataObjectMetaItemType IRODSMetaItemType = "-d" 16 | // IRODSCollectionMetaItemType is a type for collection meta 17 | IRODSCollectionMetaItemType IRODSMetaItemType = "-C" 18 | // IRODSResourceMetaItemType is a type for resource meta 19 | IRODSResourceMetaItemType IRODSMetaItemType = "-R" 20 | // IRODSUserMetaItemType is a type for user meta 21 | IRODSUserMetaItemType IRODSMetaItemType = "-u" 22 | ) 23 | 24 | // GetIRODSMetaItemType gets the irods metadata item type from an object. 25 | func GetIRODSMetaItemType(data interface{}) (IRODSMetaItemType, error) { 26 | switch data.(type) { 27 | case IRODSDataObject: 28 | return IRODSDataObjectMetaItemType, nil 29 | case IRODSCollection: 30 | return IRODSCollectionMetaItemType, nil 31 | case IRODSUser: 32 | return IRODSUserMetaItemType, nil 33 | default: 34 | return "", errors.Errorf("unknown irods metadata item type") 35 | } 36 | } 37 | 38 | // IRODSMeta contains irods metadata 39 | type IRODSMeta struct { 40 | AVUID int64 `json:"avu_id"` // is ignored on metadata operations (set, add, mod, rm) 41 | Name string `json:"name"` 42 | Value string `json:"value"` 43 | Units string `json:"units"` 44 | // CreateTime has creation time 45 | CreateTime time.Time `json:"create_time"` 46 | // ModifyTime has last modified time 47 | ModifyTime time.Time `json:"modify_time"` 48 | } 49 | 50 | // ToString stringifies the object 51 | func (meta *IRODSMeta) ToString() string { 52 | return fmt.Sprintf("", meta.AVUID, meta.Name, meta.Value, meta.Units, meta.CreateTime, meta.ModifyTime) 53 | } 54 | -------------------------------------------------------------------------------- /test/testcases/type_duration_test.go: -------------------------------------------------------------------------------- 1 | package testcases 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/cyverse/go-irodsclient/irods/types" 8 | "github.com/stretchr/testify/assert" 9 | "gopkg.in/yaml.v2" 10 | ) 11 | 12 | func getTypeDurationTest() Test { 13 | return Test{ 14 | Name: "Type_Duration", 15 | Func: typeDurationTest, 16 | } 17 | } 18 | 19 | func typeDurationTest(t *testing.T, test *Test) { 20 | t.Run("MarshalToYAML", testDurationMarshalToYAML) 21 | t.Run("UnmarshalFromYAMLWithoutUnits", testDurationUnmarshalFromYAMLWithoutUnits) 22 | t.Run("UnmarshalFromYAML", testDurationUnmarshalFromYAML) 23 | } 24 | 25 | func testDurationMarshalToYAML(t *testing.T) { 26 | d1 := types.Duration(5 * time.Minute) 27 | 28 | yamlBytes, err := yaml.Marshal(d1) 29 | assert.NoError(t, err) 30 | assert.NotEmpty(t, string(yamlBytes)) 31 | 32 | var d2 types.Duration 33 | err = yaml.Unmarshal(yamlBytes, &d2) 34 | assert.NoError(t, err) 35 | assert.Equal(t, d1, d2) 36 | } 37 | 38 | func testDurationUnmarshalFromYAMLWithoutUnits(t *testing.T) { 39 | v1 := []byte("60000000000") 40 | 41 | var d1 types.Duration 42 | err := yaml.Unmarshal(v1, &d1) 43 | assert.NoError(t, err) 44 | assert.Equal(t, 1*time.Minute, time.Duration(d1)) 45 | 46 | v2 := []byte("6h60000000000") 47 | 48 | var d2 types.Duration 49 | err = yaml.Unmarshal(v2, &d2) 50 | assert.NoError(t, err) 51 | assert.Equal(t, 6*time.Hour+1*time.Minute, time.Duration(d2)) 52 | } 53 | 54 | func testDurationUnmarshalFromYAML(t *testing.T) { 55 | v1 := []byte("6m") 56 | 57 | var d1 types.Duration 58 | err := yaml.Unmarshal(v1, &d1) 59 | assert.NoError(t, err) 60 | assert.Equal(t, 6*time.Minute, time.Duration(d1)) 61 | 62 | v2 := []byte("6h6m") 63 | 64 | var d2 types.Duration 65 | err = yaml.Unmarshal(v2, &d2) 66 | assert.NoError(t, err) 67 | assert.Equal(t, 6*time.Hour+6*time.Minute, time.Duration(d2)) 68 | } 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2021, The Arizona Board of Regents on behalf of The University of Arizona 2 | 3 | All rights reserved. 4 | 5 | Developed by: CyVerse as a collaboration between participants at BIO5 at The University of Arizona (the primary hosting institution), Cold Spring Harbor Laboratory, The University of Texas at Austin, and individual contributors. Find out more at http://www.cyverse.org/. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 11 | * Neither the name of CyVerse, BIO5, The University of Arizona, Cold Spring Harbor Laboratory, The University of Texas at Austin, nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | -------------------------------------------------------------------------------- /irods/message/get_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // IRODSMessageGetDataObjectResponse stores file get response 12 | type IRODSMessageGetDataObjectResponse IRODSMessagePortalResponse 13 | 14 | // GetBytes returns byte array 15 | func (msg *IRODSMessageGetDataObjectResponse) GetBytes() ([]byte, error) { 16 | xmlBytes, err := xml.Marshal(msg) 17 | if err != nil { 18 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 19 | } 20 | return xmlBytes, nil 21 | } 22 | 23 | // CheckError returns error if server returned an error 24 | func (msg *IRODSMessageGetDataObjectResponse) CheckError() error { 25 | if msg.Result < 0 { 26 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 27 | } 28 | return nil 29 | } 30 | 31 | // FromBytes returns struct from bytes 32 | func (msg *IRODSMessageGetDataObjectResponse) FromBytes(bytes []byte) error { 33 | err := xml.Unmarshal(bytes, msg) 34 | if err != nil { 35 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 36 | } 37 | return nil 38 | } 39 | 40 | // FromMessage returns struct from IRODSMessage 41 | func (msg *IRODSMessageGetDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 42 | if msgIn.Body == nil { 43 | return errors.Errorf("empty message body") 44 | } 45 | 46 | msg.Result = int(msgIn.Body.IntInfo) 47 | 48 | if msgIn.Body.Message != nil { 49 | err := msg.FromBytes(msgIn.Body.Message) 50 | if err != nil { 51 | return errors.Wrapf(err, "failed to get irods message from message body") 52 | } 53 | } 54 | 55 | return nil 56 | } 57 | 58 | // GetXMLCorrector returns XML corrector for this message 59 | func (msg *IRODSMessageGetDataObjectResponse) GetXMLCorrector() XMLCorrector { 60 | return GetXMLCorrectorForResponse() 61 | } 62 | -------------------------------------------------------------------------------- /irods/message/put_data_object_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // IRODSMessagePutDataObjectResponse stores file put response 12 | type IRODSMessagePutDataObjectResponse IRODSMessagePortalResponse 13 | 14 | // GetBytes returns byte array 15 | func (msg *IRODSMessagePutDataObjectResponse) GetBytes() ([]byte, error) { 16 | xmlBytes, err := xml.Marshal(msg) 17 | if err != nil { 18 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 19 | } 20 | return xmlBytes, nil 21 | } 22 | 23 | // CheckError returns error if server returned an error 24 | func (msg *IRODSMessagePutDataObjectResponse) CheckError() error { 25 | if msg.Result < 0 { 26 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 27 | } 28 | return nil 29 | } 30 | 31 | // FromBytes returns struct from bytes 32 | func (msg *IRODSMessagePutDataObjectResponse) FromBytes(bytes []byte) error { 33 | err := xml.Unmarshal(bytes, msg) 34 | if err != nil { 35 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 36 | } 37 | return nil 38 | } 39 | 40 | // FromMessage returns struct from IRODSMessage 41 | func (msg *IRODSMessagePutDataObjectResponse) FromMessage(msgIn *IRODSMessage) error { 42 | if msgIn.Body == nil { 43 | return errors.Errorf("empty message body") 44 | } 45 | 46 | msg.Result = int(msgIn.Body.IntInfo) 47 | 48 | if msgIn.Body.Message != nil { 49 | err := msg.FromBytes(msgIn.Body.Message) 50 | if err != nil { 51 | return errors.Wrapf(err, "failed to get irods message from message body") 52 | } 53 | } 54 | 55 | return nil 56 | } 57 | 58 | // GetXMLCorrector returns XML corrector for this message 59 | func (msg *IRODSMessagePutDataObjectResponse) GetXMLCorrector() XMLCorrector { 60 | return GetXMLCorrectorForResponse() 61 | } 62 | -------------------------------------------------------------------------------- /irods/connection/native_auth.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "encoding/hex" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/auth" 8 | "github.com/cyverse/go-irodsclient/irods/message" 9 | "github.com/cyverse/go-irodsclient/irods/types" 10 | ) 11 | 12 | func AuthenticateNative(conn *IRODSConnection, password string) error { 13 | timeout := conn.GetOperationTimeout() 14 | 15 | authRequest := message.NewIRODSMessageAuthRequest() 16 | authChallenge := message.IRODSMessageAuthChallengeResponse{} 17 | err := conn.RequestAndCheck(authRequest, &authChallenge, nil, timeout) 18 | if err != nil { 19 | newErr := errors.Join(err, types.NewAuthError(conn.account)) 20 | return errors.Wrapf(newErr, "failed to receive authentication challenge message body") 21 | } 22 | 23 | challengeBytes, err := authChallenge.GetChallenge() 24 | if err != nil { 25 | newErr := errors.Join(err, types.NewAuthError(conn.account)) 26 | return errors.Wrapf(newErr, "failed to get authentication challenge") 27 | } 28 | 29 | // save client signature 30 | conn.clientSignature = generateClientSignature(challengeBytes) 31 | 32 | encodedPassword := auth.GenerateAuthResponse(challengeBytes, password) 33 | 34 | authResponse := message.NewIRODSMessageAuthResponse(encodedPassword, conn.account.ProxyUser, conn.account.ProxyZone) 35 | authResult := message.IRODSMessageAuthResult{} 36 | err = conn.RequestAndCheck(authResponse, &authResult, nil, timeout) 37 | if err != nil { 38 | newErr := errors.Join(err, types.NewAuthError(conn.account)) 39 | return errors.Wrapf(newErr, "received irods authentication error") 40 | } 41 | 42 | conn.loggedIn = true 43 | 44 | return nil 45 | } 46 | 47 | // generateClientSignature generates a client signature from auth challenge 48 | func generateClientSignature(challenge []byte) string { 49 | if len(challenge) > 16 { 50 | challenge = challenge[:16] 51 | } 52 | 53 | signature := hex.EncodeToString(challenge) 54 | return signature 55 | } 56 | -------------------------------------------------------------------------------- /irods/types/file_redirection_info.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cockroachdb/errors" 7 | ) 8 | 9 | // IRODSFileOpenRedirectionHandle contains file open redirection handle 10 | type IRODSFileOpenRedirectionHandle struct { 11 | FileDescriptor int 12 | // Path has an absolute path to the data object 13 | Path string 14 | Resource string 15 | Threads int 16 | CheckSum string 17 | RedirectionInfo *IRODSRedirectionInfo 18 | } 19 | 20 | // IRODSRedirectionInfo contains redirection info 21 | type IRODSRedirectionInfo struct { 22 | Port int 23 | Cookie int 24 | ServerSocket int 25 | WindowSize int 26 | Host string 27 | } 28 | 29 | // ToString stringifies the object 30 | func (info *IRODSFileOpenRedirectionHandle) ToString() string { 31 | return fmt.Sprintf("", info.FileDescriptor, info.Path, info.Resource, info.Threads, info.CheckSum, info.RedirectionInfo.ToString()) 32 | } 33 | 34 | // ToString stringifies the object 35 | func (info *IRODSRedirectionInfo) ToString() string { 36 | return fmt.Sprintf("", info.Port, info.Cookie, info.ServerSocket, info.WindowSize, info.Host) 37 | } 38 | 39 | // Validate validates redirection info 40 | func (info *IRODSRedirectionInfo) Validate() error { 41 | if len(info.Host) == 0 { 42 | newErr := NewResourceServerConnectionConfigError(info) 43 | return errors.Wrapf(newErr, "empty host") 44 | } 45 | 46 | if info.Port <= 0 { 47 | newErr := NewResourceServerConnectionConfigError(info) 48 | return errors.Wrapf(newErr, "empty port") 49 | } 50 | 51 | if info.Cookie <= 0 { 52 | newErr := NewResourceServerConnectionConfigError(info) 53 | return errors.Wrapf(newErr, "empty cookie") 54 | } 55 | 56 | if info.ServerSocket <= 0 { 57 | newErr := NewResourceServerConnectionConfigError(info) 58 | return errors.Wrapf(newErr, "empty server socket") 59 | } 60 | 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /examples/get_ticket_anon/get_ticket_anon.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | irods_fs "github.com/cyverse/go-irodsclient/irods/fs" 11 | "github.com/cyverse/go-irodsclient/irods/session" 12 | 13 | log "github.com/sirupsen/logrus" 14 | ) 15 | 16 | func main() { 17 | logger := log.WithFields(log.Fields{}) 18 | 19 | // Parse cli parameters 20 | flag.Parse() 21 | args := flag.Args() 22 | 23 | if len(args) != 1 { 24 | fmt.Fprintf(os.Stderr, "Give an iRODS ticket!\n") 25 | os.Exit(1) 26 | } 27 | 28 | ticketName := args[0] 29 | 30 | // Read account configuration from YAML file 31 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 32 | if err != nil { 33 | logger.Error(err) 34 | panic(err) 35 | } 36 | 37 | account := cfg.ToIRODSAccount() 38 | logger.Debugf("Account : %v", account.GetRedacted()) 39 | 40 | // Create a file system 41 | appName := "get_ticket_anon" 42 | config := fs.NewFileSystemConfig(appName) 43 | sessConfig := config.ToMetadataSessionConfig() 44 | sess, err := session.NewIRODSSession(account, sessConfig) 45 | if err != nil { 46 | logger.Error(err) 47 | panic(err) 48 | } 49 | 50 | defer sess.Release() 51 | 52 | conn, err := sess.AcquireConnection(true) 53 | if err != nil { 54 | logger.Error(err) 55 | panic(err) 56 | } 57 | 58 | ticket, err := irods_fs.GetTicketForAnonymousAccess(conn, ticketName) 59 | if err != nil { 60 | logger.Error(err) 61 | panic(err) 62 | } 63 | 64 | /* 65 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 66 | if err != nil { 67 | logger.Error(err) 68 | panic(err) 69 | } 70 | 71 | defer filesystem.Release() 72 | 73 | 74 | entries, err := filesystem.List(inputPath) 75 | if err != nil { 76 | logger.Error(err) 77 | panic(err) 78 | } 79 | */ 80 | 81 | fmt.Printf("> Ticket: %s\n", ticketName) 82 | fmt.Printf("%s\n", ticket.ToString()) 83 | } 84 | -------------------------------------------------------------------------------- /irods/message/new_auth_plugin_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "encoding/json" 7 | "encoding/xml" 8 | 9 | "github.com/cockroachdb/errors" 10 | "github.com/cyverse/go-irodsclient/irods/common" 11 | "github.com/cyverse/go-irodsclient/irods/types" 12 | ) 13 | 14 | // IRODSMessageNewAuthPluginResponse stores new authentication plugin response 15 | type IRODSMessageNewAuthPluginResponse struct { 16 | AuthContext map[string]interface{} 17 | Result int 18 | } 19 | 20 | // CheckError returns error if server returned an error 21 | func (msg *IRODSMessageNewAuthPluginResponse) CheckError() error { 22 | if msg.Result < 0 { 23 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 24 | } 25 | return nil 26 | } 27 | 28 | // FromMessage returns struct from IRODSMessage 29 | func (msg *IRODSMessageNewAuthPluginResponse) FromMessage(msgIn *IRODSMessage) error { 30 | if msgIn.Header == nil { 31 | return errors.Errorf("empty message header") 32 | } 33 | 34 | msg.Result = int(msgIn.Header.IntInfo) 35 | 36 | if msgIn.Body == nil { 37 | return nil 38 | } 39 | 40 | binBytesBuf := IRODSMessageBinBytesBuf{} 41 | err := xml.Unmarshal(msgIn.Body.Message, &binBytesBuf) 42 | if err != nil { 43 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 44 | } 45 | 46 | dataJson, err := base64.StdEncoding.DecodeString(string(binBytesBuf.Data)) 47 | if err != nil { 48 | return errors.Wrapf(err, "failed to decode base64 message") 49 | } 50 | 51 | nullIndex := bytes.IndexByte(dataJson, '\x00') 52 | if nullIndex >= 0 { 53 | dataJson = dataJson[:nullIndex] 54 | } 55 | 56 | err = json.Unmarshal(dataJson, &msg.AuthContext) 57 | if err != nil { 58 | return errors.Wrapf(err, "failed to unmarshal json to auth context") 59 | } 60 | 61 | return nil 62 | } 63 | 64 | // GetXMLCorrector returns XML corrector for this message 65 | func (msg *IRODSMessageNewAuthPluginResponse) GetXMLCorrector() XMLCorrector { 66 | return GetXMLCorrectorForResponse() 67 | } 68 | -------------------------------------------------------------------------------- /examples/list_acls/list_acls.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/cyverse/go-irodsclient/config" 9 | "github.com/cyverse/go-irodsclient/fs" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func main() { 15 | logger := log.WithFields(log.Fields{}) 16 | 17 | log.SetLevel(log.DebugLevel) 18 | 19 | // Parse cli parameters 20 | flag.Parse() 21 | args := flag.Args() 22 | 23 | if len(args) != 1 { 24 | fmt.Fprintf(os.Stderr, "Give an iRODS path!\n") 25 | os.Exit(1) 26 | } 27 | 28 | inputPath := args[0] 29 | 30 | // Read account configuration from YAML file 31 | cfg, err := config.NewConfigFromYAMLFile(config.GetDefaultConfig(), "account.yml") 32 | if err != nil { 33 | logger.Error(err) 34 | panic(err) 35 | } 36 | 37 | account := cfg.ToIRODSAccount() 38 | logger.Debugf("Account : %v", account.GetRedacted()) 39 | 40 | // Create a file system 41 | appName := "list_acls" 42 | filesystem, err := fs.NewFileSystemWithDefault(account, appName) 43 | if err != nil { 44 | logger.Error(err) 45 | panic(err) 46 | } 47 | 48 | defer filesystem.Release() 49 | 50 | stat, err := filesystem.Stat(inputPath) 51 | if err != nil { 52 | logger.Error(err) 53 | panic(err) 54 | } 55 | 56 | if stat.Type == fs.DirectoryEntry { 57 | inherit, err := filesystem.GetDirACLInheritance(inputPath) 58 | if err != nil { 59 | logger.Error(err) 60 | panic(err) 61 | } 62 | 63 | if inherit.Inheritance { 64 | fmt.Printf("Inheritance - Enabled\n") 65 | } else { 66 | fmt.Printf("Inheritance - Disabled\n") 67 | } 68 | } 69 | 70 | accesses, err := filesystem.ListACLs(inputPath) 71 | if err != nil { 72 | logger.Error(err) 73 | panic(err) 74 | } 75 | 76 | if len(accesses) == 0 { 77 | fmt.Printf("Found no acls for path %q\n", inputPath) 78 | } else { 79 | fmt.Printf("%s\n", inputPath) 80 | for _, access := range accesses { 81 | fmt.Printf("> User: %s (%s) = %s\n", access.UserName, access.UserType, access.AccessLevel) 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /test/testcases/highlevel_filesystem_cache_test.go: -------------------------------------------------------------------------------- 1 | package testcases 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/cyverse/go-irodsclient/fs" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func getHighlevelFilesystemCacheTest() Test { 12 | return Test{ 13 | Name: "Highlevel_FilesystemCache", 14 | Func: highlevelFilesystemCacheTest, 15 | } 16 | } 17 | 18 | func highlevelFilesystemCacheTest(t *testing.T, test *Test) { 19 | t.Run("MakeDirCacheEvent", testMakeDirCacheEvent) 20 | } 21 | 22 | func testMakeDirCacheEvent(t *testing.T) { 23 | test := GetCurrentTest() 24 | server := test.GetCurrentServer() 25 | 26 | filesystem, err := server.GetFileSystem() 27 | FailError(t, err) 28 | defer filesystem.Release() 29 | 30 | eventTypesReceived := []fs.FilesystemCacheEventType{} 31 | eventPathsReceived := []string{} 32 | eventHandler := func(path string, eventType fs.FilesystemCacheEventType) { 33 | eventTypesReceived = append(eventTypesReceived, eventType) 34 | eventPathsReceived = append(eventPathsReceived, path) 35 | } 36 | 37 | filesystem.AddCacheEventHandler(eventHandler) 38 | 39 | homeDir, err := test.GetTestHomeDir() 40 | FailError(t, err) 41 | 42 | for i := 0; i < 10; i++ { 43 | newDir := fmt.Sprintf("%s/cache_test_dir_%d", homeDir, i) 44 | 45 | // create test 46 | err = filesystem.MakeDir(newDir, false) 47 | FailError(t, err) 48 | 49 | exist := filesystem.ExistsDir(newDir) 50 | assert.True(t, exist) 51 | 52 | // delete test 53 | err = filesystem.RemoveDir(newDir, true, true) 54 | FailError(t, err) 55 | 56 | assert.Equal(t, 2, len(eventTypesReceived)) 57 | assert.Equal(t, 2, len(eventPathsReceived)) 58 | 59 | assert.Equal(t, newDir, eventPathsReceived[0]) 60 | assert.Equal(t, fs.FilesystemCacheDirCreateEvent, eventTypesReceived[0]) 61 | assert.Equal(t, newDir, eventPathsReceived[1]) 62 | assert.Equal(t, fs.FilesystemCacheDirRemoveEvent, eventTypesReceived[1]) 63 | 64 | eventTypesReceived = []fs.FilesystemCacheEventType{} 65 | eventPathsReceived = []string{} 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /irods/message/auth_pam_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // IRODSMessagePamAuthResponse stores auth challenge 12 | type IRODSMessagePamAuthResponse struct { 13 | XMLName xml.Name `xml:"pamAuthRequestOut_PI"` 14 | GeneratedPassword string `xml:"irodsPamPassword"` 15 | // stores error return 16 | Result int `xml:"-"` 17 | } 18 | 19 | // CheckError returns error if server returned an error 20 | func (msg *IRODSMessagePamAuthResponse) CheckError() error { 21 | if msg.Result < 0 { 22 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 23 | } 24 | return nil 25 | } 26 | 27 | // GetBytes returns byte array 28 | func (msg *IRODSMessagePamAuthResponse) GetBytes() ([]byte, error) { 29 | xmlBytes, err := xml.Marshal(msg) 30 | if err != nil { 31 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 32 | } 33 | return xmlBytes, nil 34 | } 35 | 36 | // FromBytes returns struct from bytes 37 | func (msg *IRODSMessagePamAuthResponse) FromBytes(bytes []byte) error { 38 | err := xml.Unmarshal(bytes, msg) 39 | if err != nil { 40 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 41 | } 42 | return nil 43 | } 44 | 45 | // FromMessage returns struct from IRODSMessage 46 | func (msg *IRODSMessagePamAuthResponse) FromMessage(msgIn *IRODSMessage) error { 47 | if msgIn.Body == nil { 48 | return errors.Errorf("empty message body") 49 | } 50 | 51 | msg.Result = int(msgIn.Body.IntInfo) 52 | 53 | if msgIn.Body.Message != nil { 54 | err := msg.FromBytes(msgIn.Body.Message) 55 | if err != nil { 56 | return errors.Wrapf(err, "failed to get irods message from message body") 57 | } 58 | } 59 | 60 | return nil 61 | } 62 | 63 | // GetXMLCorrector returns XML corrector for this message 64 | func (msg *IRODSMessagePamAuthResponse) GetXMLCorrector() XMLCorrector { 65 | return GetXMLCorrectorForResponse() 66 | } 67 | -------------------------------------------------------------------------------- /irods/fs/checksum.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/connection" 7 | "github.com/cyverse/go-irodsclient/irods/message" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // GetDataObjectChecksum returns a data object checksum for the path 12 | func GetDataObjectChecksum(conn *connection.IRODSConnection, path string, resource string) (*types.IRODSChecksum, error) { 13 | if conn == nil || !conn.IsConnected() { 14 | return nil, errors.Errorf("connection is nil or disconnected") 15 | } 16 | 17 | metrics := conn.GetMetrics() 18 | if metrics != nil { 19 | metrics.IncreaseCounterForStat(1) 20 | } 21 | 22 | // lock the connection 23 | conn.Lock() 24 | defer conn.Unlock() 25 | 26 | // use default resource when resource param is empty 27 | if len(resource) == 0 { 28 | account := conn.GetAccount() 29 | resource = account.DefaultResource 30 | } 31 | 32 | request := message.NewIRODSMessageChecksumRequest(path, resource) 33 | response := message.IRODSMessageChecksumResponse{} 34 | err := conn.RequestAndCheck(request, &response, nil, conn.GetOperationTimeout()) 35 | if err != nil { 36 | if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND || types.GetIRODSErrorCode(err) == common.CAT_UNKNOWN_FILE { 37 | newErr := errors.Join(err, types.NewFileNotFoundError(path)) 38 | return nil, errors.Wrapf(newErr, "failed to find the data object for path %q", path) 39 | } else if types.GetIRODSErrorCode(err) == common.CAT_UNKNOWN_COLLECTION { 40 | newErr := errors.Join(err, types.NewFileNotFoundError(path)) 41 | return nil, errors.Wrapf(newErr, "failed to find the collection for path %q", path) 42 | } 43 | 44 | return nil, errors.Wrapf(err, "failed to get data object checksum") 45 | } 46 | 47 | checksum, err := types.CreateIRODSChecksum(response.Checksum) 48 | if err != nil { 49 | return nil, errors.Wrapf(err, "failed to create iRODS checksum") 50 | } 51 | 52 | return checksum, nil 53 | } 54 | -------------------------------------------------------------------------------- /irods/fs/struct_file.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/connection" 7 | "github.com/cyverse/go-irodsclient/irods/message" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // ExtractStructFile extracts a struct file for the path 12 | func ExtractStructFile(conn *connection.IRODSConnection, path string, target string, resource string, dataType types.DataType, force bool, bulkReg bool) error { 13 | if conn == nil || !conn.IsConnected() { 14 | return errors.Errorf("connection is nil or disconnected") 15 | } 16 | 17 | // lock the connection 18 | conn.Lock() 19 | defer conn.Unlock() 20 | 21 | switch dataType { 22 | case types.TAR_FILE_DT, types.GZIP_TAR_DT, types.BZIP2_TAR_DT, types.ZIP_FILE_DT: 23 | // pass 24 | default: 25 | return errors.Errorf("failed to extract content from unsupported data type %q", dataType) 26 | } 27 | 28 | // use default resource when resource param is empty 29 | if len(resource) == 0 { 30 | account := conn.GetAccount() 31 | resource = account.DefaultResource 32 | } 33 | 34 | request := message.NewIRODSMessageExtractStructFileRequest(path, target, resource, dataType, force, bulkReg) 35 | response := message.IRODSMessageExtractStructFileResponse{} 36 | err := conn.RequestAndCheck(request, &response, nil, conn.GetLongResponseOperationTimeout()) 37 | if err != nil { 38 | if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND || types.GetIRODSErrorCode(err) == common.CAT_UNKNOWN_FILE { 39 | newErr := errors.Join(err, types.NewFileNotFoundError(path)) 40 | return errors.Wrapf(newErr, "failed to find the data object for path %q", path) 41 | } else if types.GetIRODSErrorCode(err) == common.CAT_UNKNOWN_COLLECTION { 42 | newErr := errors.Join(err, types.NewFileNotFoundError(path)) 43 | return errors.Wrapf(newErr, "failed to find the collection for path %q", path) 44 | } 45 | 46 | return errors.Wrapf(err, "received extract struct file error") 47 | } 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /irods/message/auth_plugin_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // IRODSMessageAuthPluginResponse stores auth plugin info 12 | type IRODSMessageAuthPluginResponse struct { 13 | XMLName xml.Name `xml:"authPlugReqOut_PI"` 14 | GeneratedPassword []byte `xml:"result_"` 15 | // stores error return 16 | Result int `xml:"-"` 17 | } 18 | 19 | // CheckError returns error if server returned an error 20 | func (msg *IRODSMessageAuthPluginResponse) CheckError() error { 21 | if msg.Result < 0 { 22 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 23 | } 24 | return nil 25 | } 26 | 27 | // GetBytes returns byte array 28 | func (msg *IRODSMessageAuthPluginResponse) GetBytes() ([]byte, error) { 29 | xmlBytes, err := xml.Marshal(msg) 30 | if err != nil { 31 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 32 | } 33 | return xmlBytes, nil 34 | } 35 | 36 | // FromBytes returns struct from bytes 37 | func (msg *IRODSMessageAuthPluginResponse) FromBytes(b []byte) error { 38 | err := xml.Unmarshal(b, msg) 39 | if err != nil { 40 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 41 | } 42 | 43 | return nil 44 | } 45 | 46 | // FromMessage returns struct from IRODSMessage 47 | func (msg *IRODSMessageAuthPluginResponse) FromMessage(msgIn *IRODSMessage) error { 48 | if msgIn.Body == nil { 49 | return errors.Errorf("empty message body") 50 | } 51 | 52 | msg.Result = int(msgIn.Body.IntInfo) 53 | 54 | if msgIn.Body.Message != nil { 55 | err := msg.FromBytes(msgIn.Body.Message) 56 | if err != nil { 57 | return errors.Wrapf(err, "failed to get irods message from message body") 58 | } 59 | } 60 | 61 | return nil 62 | } 63 | 64 | // GetXMLCorrector returns XML corrector for this message 65 | func (msg *IRODSMessageAuthPluginResponse) GetXMLCorrector() XMLCorrector { 66 | return GetXMLCorrectorForPasswordResponse() 67 | } 68 | -------------------------------------------------------------------------------- /irods/message/checksum_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // IRODSMessageChecksumResponse stores data object checksum response 12 | type IRODSMessageChecksumResponse struct { 13 | Checksum string `xml:"myStr"` 14 | // stores error return 15 | Result int `xml:"-"` 16 | } 17 | 18 | type STRI_PI struct { 19 | } 20 | 21 | // GetBytes returns byte array 22 | func (msg *IRODSMessageChecksumResponse) GetBytes() ([]byte, error) { 23 | xmlBytes, err := xml.Marshal(msg) 24 | if err != nil { 25 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 26 | } 27 | return xmlBytes, nil 28 | } 29 | 30 | // CheckError returns error if server returned an error 31 | func (msg *IRODSMessageChecksumResponse) CheckError() error { 32 | if len(msg.Checksum) == 0 { 33 | return errors.Errorf("checksum not present in response message") 34 | } 35 | 36 | if msg.Result < 0 { 37 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 38 | } 39 | 40 | return nil 41 | } 42 | 43 | // FromBytes returns struct from bytes 44 | func (msg *IRODSMessageChecksumResponse) FromBytes(bytes []byte) error { 45 | err := xml.Unmarshal(bytes, msg) 46 | if err != nil { 47 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 48 | } 49 | return nil 50 | } 51 | 52 | // FromMessage returns struct from IRODSMessage 53 | func (msg *IRODSMessageChecksumResponse) FromMessage(msgIn *IRODSMessage) error { 54 | if msgIn.Body == nil { 55 | return errors.Errorf("empty message body") 56 | } 57 | 58 | msg.Result = int(msgIn.Body.IntInfo) 59 | 60 | if msgIn.Body.Message != nil { 61 | err := msg.FromBytes(msgIn.Body.Message) 62 | if err != nil { 63 | return errors.Wrapf(err, "failed to get irods message from message body") 64 | } 65 | } 66 | 67 | return nil 68 | } 69 | 70 | // GetXMLCorrector returns XML corrector for this message 71 | func (msg *IRODSMessageChecksumResponse) GetXMLCorrector() XMLCorrector { 72 | return GetXMLCorrectorForResponse() 73 | } 74 | -------------------------------------------------------------------------------- /irods/message/operation_complete_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageOperationCompleteRequest stores operation complete request 11 | type IRODSMessageOperationCompleteRequest IRODSMessageInt 12 | 13 | // NewIRODSMessageOperationCompleteRequest creates a IRODSMessageOperationCompleteRequest message 14 | func NewIRODSMessageOperationCompleteRequest(value int) *IRODSMessageOperationCompleteRequest { 15 | request := &IRODSMessageOperationCompleteRequest{ 16 | Value: value, 17 | } 18 | 19 | return request 20 | } 21 | 22 | // GetBytes returns byte array 23 | func (msg *IRODSMessageOperationCompleteRequest) GetBytes() ([]byte, error) { 24 | xmlBytes, err := xml.Marshal(msg) 25 | if err != nil { 26 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 27 | } 28 | return xmlBytes, nil 29 | } 30 | 31 | // FromBytes returns struct from bytes 32 | func (msg *IRODSMessageOperationCompleteRequest) FromBytes(bytes []byte) error { 33 | err := xml.Unmarshal(bytes, msg) 34 | if err != nil { 35 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 36 | } 37 | return nil 38 | } 39 | 40 | // GetMessage builds a message 41 | func (msg *IRODSMessageOperationCompleteRequest) GetMessage() (*IRODSMessage, error) { 42 | bytes, err := msg.GetBytes() 43 | if err != nil { 44 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 45 | } 46 | 47 | msgBody := IRODSMessageBody{ 48 | Type: RODS_MESSAGE_API_REQ_TYPE, 49 | Message: bytes, 50 | Error: nil, 51 | Bs: nil, 52 | IntInfo: int32(common.OPR_COMPLETE_AN), 53 | } 54 | 55 | msgHeader, err := msgBody.BuildHeader() 56 | if err != nil { 57 | return nil, errors.Wrapf(err, "failed to build header from irods message") 58 | } 59 | 60 | return &IRODSMessage{ 61 | Header: msgHeader, 62 | Body: &msgBody, 63 | }, nil 64 | } 65 | 66 | // GetXMLCorrector returns XML corrector for this message 67 | func (msg *IRODSMessageOperationCompleteRequest) GetXMLCorrector() XMLCorrector { 68 | return GetXMLCorrectorForRequest() 69 | } 70 | -------------------------------------------------------------------------------- /irods/message/query_special_collection.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | type IRODSMessageQuerySpecialCollection IRODSMessageDataObjectRequest 11 | 12 | // GetBytes returns byte array 13 | func (msg *IRODSMessageQuerySpecialCollection) GetBytes() ([]byte, error) { 14 | xmlBytes, err := xml.Marshal(msg) 15 | if err != nil { 16 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 17 | } 18 | return xmlBytes, nil 19 | } 20 | 21 | // FromBytes returns struct from bytes 22 | func (msg *IRODSMessageQuerySpecialCollection) FromBytes(bytes []byte) error { 23 | err := xml.Unmarshal(bytes, msg) 24 | if err != nil { 25 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 26 | } 27 | return nil 28 | } 29 | 30 | // GetMessage builds a message 31 | func (msg *IRODSMessageQuerySpecialCollection) GetMessage() (*IRODSMessage, error) { 32 | bytes, err := msg.GetBytes() 33 | if err != nil { 34 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 35 | } 36 | 37 | msgBody := IRODSMessageBody{ 38 | Type: RODS_MESSAGE_API_REQ_TYPE, 39 | Message: bytes, 40 | Error: nil, 41 | Bs: nil, 42 | IntInfo: int32(common.QUERY_SPEC_COLL_AN), 43 | } 44 | 45 | msgHeader, err := msgBody.BuildHeader() 46 | if err != nil { 47 | return nil, errors.Wrapf(err, "failed to build header from irods message") 48 | } 49 | 50 | return &IRODSMessage{ 51 | Header: msgHeader, 52 | Body: &msgBody, 53 | }, nil 54 | } 55 | 56 | // FromMessage returns struct from IRODSMessage 57 | func (msg *IRODSMessageQuerySpecialCollection) FromMessage(msgIn *IRODSMessage) error { 58 | if msgIn.Body == nil { 59 | return errors.Errorf("empty message body") 60 | } 61 | 62 | err := msg.FromBytes(msgIn.Body.Message) 63 | if err != nil { 64 | return errors.Wrapf(err, "failed to get irods message from message body") 65 | } 66 | return nil 67 | } 68 | 69 | // GetXMLCorrector returns XML corrector for this message 70 | func (msg *IRODSMessageQuerySpecialCollection) GetXMLCorrector() XMLCorrector { 71 | return GetXMLCorrectorForRequest() 72 | } 73 | -------------------------------------------------------------------------------- /irods/message/get_data_object_complete_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageGetDataObjectCompleteRequest stores get data object complete request 11 | type IRODSMessageGetDataObjectCompleteRequest IRODSMessageInt 12 | 13 | // NewIRODSMessageGetDataObjectCompleteRequest creates a IRODSMessageGetDataObjectCompleteRequest message 14 | func NewIRODSMessageGetDataObjectCompleteRequest(desc int) *IRODSMessageGetDataObjectCompleteRequest { 15 | request := &IRODSMessageGetDataObjectCompleteRequest{ 16 | Value: desc, 17 | } 18 | 19 | return request 20 | } 21 | 22 | // GetBytes returns byte array 23 | func (msg *IRODSMessageGetDataObjectCompleteRequest) GetBytes() ([]byte, error) { 24 | xmlBytes, err := xml.Marshal(msg) 25 | if err != nil { 26 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 27 | } 28 | return xmlBytes, nil 29 | } 30 | 31 | // FromBytes returns struct from bytes 32 | func (msg *IRODSMessageGetDataObjectCompleteRequest) FromBytes(bytes []byte) error { 33 | err := xml.Unmarshal(bytes, msg) 34 | if err != nil { 35 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 36 | } 37 | return nil 38 | } 39 | 40 | // GetMessage builds a message 41 | func (msg *IRODSMessageGetDataObjectCompleteRequest) GetMessage() (*IRODSMessage, error) { 42 | bytes, err := msg.GetBytes() 43 | if err != nil { 44 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 45 | } 46 | 47 | msgBody := IRODSMessageBody{ 48 | Type: RODS_MESSAGE_API_REQ_TYPE, 49 | Message: bytes, 50 | Error: nil, 51 | Bs: nil, 52 | IntInfo: int32(common.OPR_COMPLETE_AN), 53 | } 54 | 55 | msgHeader, err := msgBody.BuildHeader() 56 | if err != nil { 57 | return nil, errors.Wrapf(err, "failed to build header from irods message") 58 | } 59 | 60 | return &IRODSMessage{ 61 | Header: msgHeader, 62 | Body: &msgBody, 63 | }, nil 64 | } 65 | 66 | // GetXMLCorrector returns XML corrector for this message 67 | func (msg *IRODSMessageGetDataObjectCompleteRequest) GetXMLCorrector() XMLCorrector { 68 | return GetXMLCorrectorForRequest() 69 | } 70 | -------------------------------------------------------------------------------- /irods/message/auth_plugin_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageAuthPluginRequest stores auth plugin request 11 | type IRODSMessageAuthPluginRequest struct { 12 | XMLName xml.Name `xml:"authPlugReqInp_PI"` 13 | AuthScheme string `xml:"auth_scheme_"` 14 | Context string `xml:"context_"` 15 | } 16 | 17 | // NewIRODSMessageAuthPluginRequest creates a IRODSMessageAuthPluginRequest 18 | func NewIRODSMessageAuthPluginRequest(authScheme string, context string) *IRODSMessageAuthPluginRequest { 19 | return &IRODSMessageAuthPluginRequest{ 20 | AuthScheme: authScheme, 21 | Context: context, 22 | } 23 | } 24 | 25 | // GetBytes returns byte array 26 | func (msg *IRODSMessageAuthPluginRequest) GetBytes() ([]byte, error) { 27 | xmlBytes, err := xml.Marshal(msg) 28 | if err != nil { 29 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 30 | } 31 | return xmlBytes, nil 32 | } 33 | 34 | // FromBytes returns struct from bytes 35 | func (msg *IRODSMessageAuthPluginRequest) FromBytes(bytes []byte) error { 36 | err := xml.Unmarshal(bytes, msg) 37 | if err != nil { 38 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 39 | } 40 | return nil 41 | } 42 | 43 | // GetMessage builds a message 44 | func (msg *IRODSMessageAuthPluginRequest) GetMessage() (*IRODSMessage, error) { 45 | bytes, err := msg.GetBytes() 46 | if err != nil { 47 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 48 | } 49 | 50 | msgBody := IRODSMessageBody{ 51 | Type: RODS_MESSAGE_API_REQ_TYPE, 52 | Message: bytes, 53 | Error: nil, 54 | Bs: nil, 55 | IntInfo: int32(common.AUTH_PLUG_REQ_AN), 56 | } 57 | 58 | msgHeader, err := msgBody.BuildHeader() 59 | if err != nil { 60 | return nil, errors.Wrapf(err, "failed to build header from irods message") 61 | } 62 | 63 | return &IRODSMessage{ 64 | Header: msgHeader, 65 | Body: &msgBody, 66 | }, nil 67 | } 68 | 69 | // GetXMLCorrector returns XML corrector for this message 70 | func (msg *IRODSMessageAuthPluginRequest) GetXMLCorrector() XMLCorrector { 71 | return GetXMLCorrectorForRequest() 72 | } 73 | -------------------------------------------------------------------------------- /irods/message/auth_pam_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessagePamAuthRequest stores auth response 11 | type IRODSMessagePamAuthRequest struct { 12 | XMLName xml.Name `xml:"pamAuthRequestInp_PI"` 13 | Username string `xml:"pamUser"` 14 | Password string `xml:"pamPassword"` 15 | TTL int `xml:"timeToLive"` 16 | } 17 | 18 | // NewIRODSMessagePamAuthRequest creates a IRODSMessagePamAuthRequest message 19 | func NewIRODSMessagePamAuthRequest(username, password string, ttl int) *IRODSMessagePamAuthRequest { 20 | return &IRODSMessagePamAuthRequest{ 21 | Username: username, 22 | Password: password, 23 | TTL: ttl, 24 | } 25 | } 26 | 27 | // GetBytes returns byte array 28 | func (msg *IRODSMessagePamAuthRequest) GetBytes() ([]byte, error) { 29 | xmlBytes, err := xml.Marshal(msg) 30 | if err != nil { 31 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 32 | } 33 | return xmlBytes, nil 34 | } 35 | 36 | // FromBytes returns struct from bytes 37 | func (msg *IRODSMessagePamAuthRequest) FromBytes(bytes []byte) error { 38 | err := xml.Unmarshal(bytes, msg) 39 | if err != nil { 40 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 41 | } 42 | return nil 43 | } 44 | 45 | // GetMessage builds a message 46 | func (msg *IRODSMessagePamAuthRequest) GetMessage() (*IRODSMessage, error) { 47 | bytes, err := msg.GetBytes() 48 | if err != nil { 49 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 50 | } 51 | 52 | msgBody := IRODSMessageBody{ 53 | Type: RODS_MESSAGE_API_REQ_TYPE, 54 | Message: bytes, 55 | Error: nil, 56 | Bs: nil, 57 | IntInfo: int32(common.PAM_AUTH_REQUEST_AN), 58 | } 59 | 60 | msgHeader, err := msgBody.BuildHeader() 61 | if err != nil { 62 | return nil, errors.Wrapf(err, "failed to build header from irods message") 63 | } 64 | 65 | return &IRODSMessage{ 66 | Header: msgHeader, 67 | Body: &msgBody, 68 | }, nil 69 | } 70 | 71 | // GetXMLCorrector returns XML corrector for this message 72 | func (msg *IRODSMessagePamAuthRequest) GetXMLCorrector() XMLCorrector { 73 | return GetXMLCorrectorForRequest() 74 | } 75 | -------------------------------------------------------------------------------- /irods/message/query_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // IRODSMessageQueryResponse stores query result 12 | type IRODSMessageQueryResponse struct { 13 | XMLName xml.Name `xml:"GenQueryOut_PI"` 14 | RowCount int `xml:"rowCnt"` 15 | AttributeCount int `xml:"attriCnt"` 16 | ContinueIndex int `xml:"continueInx"` 17 | TotalRowCount int `xml:"totalRowCount"` 18 | SQLResult []IRODSMessageSQLResult `xml:"SqlResult_PI"` 19 | 20 | // stores error result 21 | Result int `xml:"-"` 22 | } 23 | 24 | // GetBytes returns byte array 25 | func (msg *IRODSMessageQueryResponse) GetBytes() ([]byte, error) { 26 | xmlBytes, err := xml.Marshal(msg) 27 | if err != nil { 28 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 29 | } 30 | return xmlBytes, nil 31 | } 32 | 33 | // CheckError returns error if server returned an error 34 | func (msg *IRODSMessageQueryResponse) CheckError() error { 35 | if msg.Result < 0 { 36 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 37 | } 38 | return nil 39 | } 40 | 41 | // FromBytes returns struct from bytes 42 | func (msg *IRODSMessageQueryResponse) FromBytes(bytes []byte) error { 43 | err := xml.Unmarshal(bytes, msg) 44 | if err != nil { 45 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 46 | } 47 | return nil 48 | } 49 | 50 | // FromMessage returns struct from IRODSMessage 51 | func (msg *IRODSMessageQueryResponse) FromMessage(msgIn *IRODSMessage) error { 52 | if msgIn.Body == nil { 53 | return errors.Errorf("empty message body") 54 | } 55 | 56 | msg.Result = int(msgIn.Body.IntInfo) 57 | 58 | if msgIn.Body.Message != nil { 59 | err := msg.FromBytes(msgIn.Body.Message) 60 | if err != nil { 61 | return errors.Wrapf(err, "failed to get irods message from message body") 62 | } 63 | } 64 | 65 | return nil 66 | } 67 | 68 | // GetXMLCorrector returns XML corrector for this message 69 | func (msg *IRODSMessageQueryResponse) GetXMLCorrector() XMLCorrector { 70 | return GetXMLCorrectorForResponse() 71 | } 72 | -------------------------------------------------------------------------------- /irods/common/operation_type.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | // OperationType ... 4 | type OperationType int 5 | 6 | // operation types 7 | const ( 8 | OPER_TYPE_NONE OperationType = 0 9 | OPER_TYPE_PUT_DATA_OBJ OperationType = 1 10 | OPER_TYPE_GET_DATA_OBJ OperationType = 2 11 | OPER_TYPE_SAME_HOST_COPY_OBJ OperationType = 3 12 | OPER_TYPE_COPY_TO_LOCAL_OBJ OperationType = 4 13 | OPER_TYPE_COPY_TO_REMOTE_OBJ OperationType = 5 14 | OPER_TYPE_REPLICATE_DATA_OBJ OperationType = 6 15 | OPER_TYPE_REPLICATE_DATA_OBJ_DEST OperationType = 7 16 | OPER_TYPE_REPLICATE_DATA_OBJ_SRC OperationType = 8 17 | OPER_TYPE_COPY_DATA_OBJ_DEST OperationType = 9 18 | OPER_TYPE_COPY_DATA_OBJ_SRC OperationType = 10 19 | OPER_TYPE_RENAME_DATA_OBJ OperationType = 11 20 | OPER_TYPE_RENAME_COLL OperationType = 12 21 | OPER_TYPE_MOVE OperationType = 13 22 | OPER_TYPE_RSYNC OperationType = 14 23 | OPER_TYPE_PHYMV OperationType = 15 24 | OPER_TYPE_PHYMV_SRC OperationType = 16 25 | OPER_TYPE_PHYMV_DEST OperationType = 17 26 | OPER_TYPE_QUERY_DATA_OBJ OperationType = 18 27 | OPER_TYPE_QUERY_DATA_OBJ_RECUR OperationType = 19 28 | OPER_TYPE_QUERY_COLL_OBJ OperationType = 20 29 | OPER_TYPE_QUERY_COLL_OBJ_RECUR OperationType = 21 30 | OPER_TYPE_RENAME_UNKNOWN_TYPE OperationType = 22 31 | OPER_TYPE_REMOTE_ZONE OperationType = 24 32 | OPER_TYPE_UNREG OperationType = 26 33 | OPER_TYPE_DONE OperationType = 9999 34 | 35 | // flag for oprType of dataObjInp_t and structFileOprInp_t 36 | OPER_TYPE_PURGE_STRUCT_FILE_CACHE OperationType = 1 37 | OPER_TYPE_DELETE_STRUCT_FILE OperationType = 2 38 | OPER_TYPE_NO_REG_COLL_INFO OperationType = 4 39 | OPER_TYPE_LOGICAL_BUNDLE OperationType = 8 40 | OPER_TYPE_CREATE_TAR OperationType = 0 41 | OPER_TYPE_ADD_TO_TAR OperationType = 16 42 | OPER_TYPE_PRESERVE_COLL_PATH OperationType = 32 43 | OPER_TYPE_PRESERVE_DIR_CONT OperationType = 64 44 | 45 | /* definition for openType in l1desc_t */ 46 | OPER_TYPE_CREATE_TYPE OperationType = 1 47 | OPER_TYPE_OPEN_FOR_READ OperationType = 2 48 | OPER_TYPE_OPEN_FOR_WRITE OperationType = 3 49 | ) 50 | -------------------------------------------------------------------------------- /irods/message/ssl_settings.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | ) 8 | 9 | // IRODSMessageSSLSettings stores ssl settings 10 | type IRODSMessageSSLSettings struct { 11 | EncryptionAlgorithm string 12 | EncryptionKeySize uint32 13 | SaltSize uint32 14 | HashRounds uint32 15 | } 16 | 17 | // NewIRODSMessageSSLSettings creates a IRODSMessageSSLSettings message 18 | func NewIRODSMessageSSLSettings(algorithm string, keySize int, saltSize int, hashRounds int) *IRODSMessageSSLSettings { 19 | return &IRODSMessageSSLSettings{ 20 | EncryptionAlgorithm: algorithm, 21 | EncryptionKeySize: uint32(keySize), 22 | SaltSize: uint32(saltSize), 23 | HashRounds: uint32(hashRounds), 24 | } 25 | } 26 | 27 | // GetBytes returns byte array 28 | func (msg *IRODSMessageSSLSettings) GetBytes() ([]byte, error) { 29 | xmlBytes, err := xml.Marshal(msg) 30 | if err != nil { 31 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 32 | } 33 | return xmlBytes, nil 34 | } 35 | 36 | // FromBytes returns struct from bytes 37 | func (msg *IRODSMessageSSLSettings) FromBytes(bytes []byte) error { 38 | err := xml.Unmarshal(bytes, msg) 39 | if err != nil { 40 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 41 | } 42 | return nil 43 | } 44 | 45 | // GetMessage builds a message 46 | func (msg *IRODSMessageSSLSettings) GetMessage() (*IRODSMessage, error) { 47 | msgHeader := IRODSMessageHeader{ 48 | Type: MessageType(msg.EncryptionAlgorithm), 49 | MessageLen: msg.EncryptionKeySize, 50 | ErrorLen: msg.SaltSize, 51 | BsLen: msg.HashRounds, 52 | IntInfo: 0, 53 | } 54 | 55 | return &IRODSMessage{ 56 | Header: &msgHeader, 57 | Body: nil, 58 | }, nil 59 | } 60 | 61 | // FromMessage returns struct from IRODSMessage 62 | func (msg *IRODSMessageSSLSettings) FromMessage(msgIn *IRODSMessage) error { 63 | if msgIn.Body == nil { 64 | return errors.Errorf("empty message body") 65 | } 66 | 67 | msg.EncryptionAlgorithm = string(msgIn.Header.Type) 68 | msg.EncryptionKeySize = msgIn.Header.MessageLen 69 | msg.SaltSize = msgIn.Header.ErrorLen 70 | msg.HashRounds = msgIn.Header.BsLen 71 | 72 | return nil 73 | } 74 | 75 | func (msg *IRODSMessageSSLSettings) GetXMLCorrector() XMLCorrector { 76 | return GetXMLCorrectorForRequest() 77 | } 78 | -------------------------------------------------------------------------------- /irods/message/end_transaction_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageEndTransactionRequest stores collection creation request 11 | type IRODSMessageEndTransactionRequest struct { 12 | XMLName xml.Name `xml:"endTransactionInp_PI"` 13 | Action string `xml:"arg0"` 14 | Argument string `xml:"arg1"` // unused 15 | } 16 | 17 | // NewIRODSMessageEndTransactionRequest creates a IRODSMessageEndTransactionRequest message 18 | func NewIRODSMessageEndTransactionRequest(commit bool) *IRODSMessageEndTransactionRequest { 19 | var action string 20 | 21 | if commit { 22 | action = "commit" 23 | } else { 24 | action = "rollback" 25 | } 26 | 27 | return &IRODSMessageEndTransactionRequest{ 28 | Action: action, 29 | } 30 | } 31 | 32 | // GetBytes returns byte array 33 | func (msg *IRODSMessageEndTransactionRequest) GetBytes() ([]byte, error) { 34 | xmlBytes, err := xml.Marshal(msg) 35 | if err != nil { 36 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 37 | } 38 | return xmlBytes, nil 39 | } 40 | 41 | // FromBytes returns struct from bytes 42 | func (msg *IRODSMessageEndTransactionRequest) FromBytes(bytes []byte) error { 43 | err := xml.Unmarshal(bytes, msg) 44 | if err != nil { 45 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 46 | } 47 | return nil 48 | } 49 | 50 | // GetMessage builds a message 51 | func (msg *IRODSMessageEndTransactionRequest) GetMessage() (*IRODSMessage, error) { 52 | bytes, err := msg.GetBytes() 53 | if err != nil { 54 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 55 | } 56 | 57 | msgBody := IRODSMessageBody{ 58 | Type: RODS_MESSAGE_API_REQ_TYPE, 59 | Message: bytes, 60 | Error: nil, 61 | Bs: nil, 62 | IntInfo: int32(common.END_TRANSACTION_AN), 63 | } 64 | 65 | msgHeader, err := msgBody.BuildHeader() 66 | if err != nil { 67 | return nil, errors.Wrapf(err, "failed to build header from irods message") 68 | } 69 | 70 | return &IRODSMessage{ 71 | Header: msgHeader, 72 | Body: &msgBody, 73 | }, nil 74 | } 75 | 76 | // GetXMLCorrector returns XML corrector for this message 77 | func (msg *IRODSMessageEndTransactionRequest) GetXMLCorrector() XMLCorrector { 78 | return GetXMLCorrectorForRequest() 79 | } 80 | -------------------------------------------------------------------------------- /irods/message/keyval_pair.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import "encoding/xml" 4 | 5 | // IRODSMessageRawString ... 6 | type IRODSMessageRawString struct { 7 | Value string `xml:",innerxml"` 8 | } 9 | 10 | // IRODSMessageSSKeyVal .. 11 | type IRODSMessageSSKeyVal struct { 12 | XMLName xml.Name `xml:"KeyValPair_PI"` 13 | Length int `xml:"ssLen"` 14 | Keys []string `xml:"keyWord,omitempty"` 15 | Values []IRODSMessageRawString `xml:"svalue,omitempty"` 16 | } 17 | 18 | // IRODSMessageIIKeyVal .. 19 | type IRODSMessageIIKeyVal struct { 20 | XMLName xml.Name `xml:"InxIvalPair_PI"` 21 | Length int `xml:"iiLen"` 22 | Keys []int `xml:"inx,omitempty"` 23 | Values []int `xml:"ivalue,omitempty"` 24 | } 25 | 26 | // IRODSMessageISKeyVal .. 27 | type IRODSMessageISKeyVal struct { 28 | XMLName xml.Name `xml:"InxValPair_PI"` 29 | Length int `xml:"isLen"` 30 | Keys []int `xml:"inx,omitempty"` 31 | Values []IRODSMessageRawString `xml:"svalue,omitempty"` 32 | } 33 | 34 | // NewIRODSMessageSSKeyVal creates a new IRODSMessageSSKeyVal 35 | func NewIRODSMessageSSKeyVal() *IRODSMessageSSKeyVal { 36 | return &IRODSMessageSSKeyVal{ 37 | Length: 0, 38 | } 39 | } 40 | 41 | // Add adds a key-val pair 42 | func (kv *IRODSMessageSSKeyVal) Add(key string, val string) { 43 | kv.Keys = append(kv.Keys, key) 44 | kv.Values = append(kv.Values, IRODSMessageRawString{ 45 | Value: val, 46 | }) 47 | kv.Length = len(kv.Keys) 48 | } 49 | 50 | // NewIRODSMessageIIKeyVal creates a new IRODSMessageIIKeyVal 51 | func NewIRODSMessageIIKeyVal() *IRODSMessageIIKeyVal { 52 | return &IRODSMessageIIKeyVal{ 53 | Length: 0, 54 | } 55 | } 56 | 57 | // Add adds a key-val pair 58 | func (kv *IRODSMessageIIKeyVal) Add(key int, val int) { 59 | kv.Keys = append(kv.Keys, key) 60 | kv.Values = append(kv.Values, val) 61 | kv.Length = len(kv.Keys) 62 | } 63 | 64 | // NewIRODSMessageISKeyVal creates a new IRODSMessageISKeyVal 65 | func NewIRODSMessageISKeyVal() *IRODSMessageISKeyVal { 66 | return &IRODSMessageISKeyVal{ 67 | Length: 0, 68 | } 69 | } 70 | 71 | // Add adds a key-val pair 72 | func (kv *IRODSMessageISKeyVal) Add(key int, val string) { 73 | kv.Keys = append(kv.Keys, key) 74 | kv.Values = append(kv.Values, IRODSMessageRawString{ 75 | Value: val, 76 | }) 77 | kv.Length = len(kv.Keys) 78 | } 79 | -------------------------------------------------------------------------------- /irods/message/admin_add_group_member_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageAdminAddGroupMemberRequest stores add group member request 11 | type IRODSMessageAdminAddGroupMemberRequest IRODSMessageAdminRequest 12 | 13 | // NewIRODSMessageAdminAddGroupMemberRequest creates a new IRODSMessageAdminAddGroupMemberRequest 14 | func NewIRODSMessageAdminAddGroupMemberRequest(groupName string, username string, zoneName string) *IRODSMessageAdminAddGroupMemberRequest { 15 | request := &IRODSMessageAdminAddGroupMemberRequest{ 16 | Action: "modify", 17 | Target: "group", 18 | } 19 | 20 | request.Arg2 = groupName 21 | request.Arg3 = "add" 22 | request.Arg4 = username 23 | request.Arg5 = zoneName 24 | 25 | return request 26 | } 27 | 28 | // GetBytes returns byte array 29 | func (msg *IRODSMessageAdminAddGroupMemberRequest) GetBytes() ([]byte, error) { 30 | xmlBytes, err := xml.Marshal(msg) 31 | if err != nil { 32 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 33 | } 34 | return xmlBytes, nil 35 | } 36 | 37 | // FromBytes returns struct from bytes 38 | func (msg *IRODSMessageAdminAddGroupMemberRequest) FromBytes(bytes []byte) error { 39 | err := xml.Unmarshal(bytes, msg) 40 | if err != nil { 41 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 42 | } 43 | return nil 44 | } 45 | 46 | // GetMessage builds a message 47 | func (msg *IRODSMessageAdminAddGroupMemberRequest) GetMessage() (*IRODSMessage, error) { 48 | bytes, err := msg.GetBytes() 49 | if err != nil { 50 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 51 | } 52 | 53 | msgBody := IRODSMessageBody{ 54 | Type: RODS_MESSAGE_API_REQ_TYPE, 55 | Message: bytes, 56 | Error: nil, 57 | Bs: nil, 58 | IntInfo: int32(common.GENERAL_ADMIN_AN), 59 | } 60 | 61 | msgHeader, err := msgBody.BuildHeader() 62 | if err != nil { 63 | return nil, errors.Wrapf(err, "failed to build header from irods message") 64 | } 65 | 66 | return &IRODSMessage{ 67 | Header: msgHeader, 68 | Body: &msgBody, 69 | }, nil 70 | } 71 | 72 | // GetXMLCorrector returns XML corrector for this message 73 | func (msg *IRODSMessageAdminAddGroupMemberRequest) GetXMLCorrector() XMLCorrector { 74 | return GetXMLCorrectorForRequest() 75 | } 76 | -------------------------------------------------------------------------------- /test/testcases/lowlevel_connection_test.go: -------------------------------------------------------------------------------- 1 | package testcases 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/cyverse/go-irodsclient/irods/connection" 7 | log "github.com/sirupsen/logrus" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func getLowlevelConnectionTest() Test { 12 | return Test{ 13 | Name: "Lowlevel_Connection", 14 | Func: lowlevelConnectionTest, 15 | DoNotCreateHomeDir: true, 16 | } 17 | } 18 | 19 | func lowlevelConnectionTest(t *testing.T, test *Test) { 20 | t.Run("Connection", testConnection) 21 | t.Run("InvalidUsername", testInvalidUsername) 22 | t.Run("ManyConnections", testManyConnections) 23 | } 24 | 25 | func testConnection(t *testing.T) { 26 | test := GetCurrentTest() 27 | server := test.GetCurrentServer() 28 | 29 | account, err := server.GetAccount() 30 | FailError(t, err) 31 | 32 | t.Logf("account info: %+v", account) 33 | 34 | conn, err := connection.NewIRODSConnection(account, server.GetConnectionConfig()) 35 | FailError(t, err) 36 | 37 | t.Logf("Log level set to %q", log.GetLevel().String()) 38 | 39 | err = conn.Connect() 40 | FailError(t, err) 41 | defer func() { 42 | _ = conn.Disconnect() 43 | }() 44 | 45 | ver := conn.GetVersion() 46 | verMajor, _, _ := ver.GetReleaseVersion() 47 | assert.GreaterOrEqual(t, 4, verMajor) 48 | } 49 | 50 | func testInvalidUsername(t *testing.T) { 51 | test := GetCurrentTest() 52 | server := test.GetCurrentServer() 53 | 54 | account, err := server.GetAccount() 55 | FailError(t, err) 56 | account.ProxyUser = "test$def" 57 | account.ClientUser = "" 58 | 59 | conn, err := connection.NewIRODSConnection(account, server.GetConnectionConfig()) 60 | assert.Error(t, err) 61 | assert.Nil(t, conn) 62 | } 63 | 64 | func testManyConnections(t *testing.T) { 65 | test := GetCurrentTest() 66 | server := test.GetCurrentServer() 67 | 68 | account, err := server.GetAccount() 69 | FailError(t, err) 70 | 71 | for i := 0; i < 10; i++ { 72 | conn, err := connection.NewIRODSConnection(account, server.GetConnectionConfig()) 73 | FailError(t, err) 74 | 75 | err = conn.Connect() 76 | FailError(t, err) 77 | defer func() { 78 | _ = conn.Disconnect() 79 | }() 80 | 81 | ver := conn.GetVersion() 82 | verMajor, _, _ := ver.GetReleaseVersion() 83 | assert.GreaterOrEqual(t, 4, verMajor) 84 | 85 | t.Logf("Connection %d: %s %s", i, conn.GetVersion().ReleaseVersion, conn.GetVersion().APIVersion) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /irods/message/admin_remove_group_member_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageAdminRemoveGroupMemberRequest stores remove group member request 11 | type IRODSMessageAdminRemoveGroupMemberRequest IRODSMessageAdminRequest 12 | 13 | // NewIRODSMessageAdminRemoveGroupMemberRequest creates a new IRODSMessageAdminRemoveGroupMemberRequest 14 | func NewIRODSMessageAdminRemoveGroupMemberRequest(groupName string, username string, zoneName string) *IRODSMessageAdminRemoveGroupMemberRequest { 15 | request := &IRODSMessageAdminRemoveGroupMemberRequest{ 16 | Action: "modify", 17 | Target: "group", 18 | } 19 | 20 | request.Arg2 = groupName 21 | request.Arg3 = "remove" 22 | request.Arg4 = username 23 | request.Arg5 = zoneName 24 | 25 | return request 26 | } 27 | 28 | // GetBytes returns byte array 29 | func (msg *IRODSMessageAdminRemoveGroupMemberRequest) GetBytes() ([]byte, error) { 30 | xmlBytes, err := xml.Marshal(msg) 31 | if err != nil { 32 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 33 | } 34 | return xmlBytes, nil 35 | } 36 | 37 | // FromBytes returns struct from bytes 38 | func (msg *IRODSMessageAdminRemoveGroupMemberRequest) FromBytes(bytes []byte) error { 39 | err := xml.Unmarshal(bytes, msg) 40 | if err != nil { 41 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 42 | } 43 | return nil 44 | } 45 | 46 | // GetMessage builds a message 47 | func (msg *IRODSMessageAdminRemoveGroupMemberRequest) GetMessage() (*IRODSMessage, error) { 48 | bytes, err := msg.GetBytes() 49 | if err != nil { 50 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 51 | } 52 | 53 | msgBody := IRODSMessageBody{ 54 | Type: RODS_MESSAGE_API_REQ_TYPE, 55 | Message: bytes, 56 | Error: nil, 57 | Bs: nil, 58 | IntInfo: int32(common.GENERAL_ADMIN_AN), 59 | } 60 | 61 | msgHeader, err := msgBody.BuildHeader() 62 | if err != nil { 63 | return nil, errors.Wrapf(err, "failed to build header from irods message") 64 | } 65 | 66 | return &IRODSMessage{ 67 | Header: msgHeader, 68 | Body: &msgBody, 69 | }, nil 70 | } 71 | 72 | // GetXMLCorrector returns XML corrector for this message 73 | func (msg *IRODSMessageAdminRemoveGroupMemberRequest) GetXMLCorrector() XMLCorrector { 74 | return GetXMLCorrectorForRequest() 75 | } 76 | -------------------------------------------------------------------------------- /irods/message/admin_remove_user_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // IRODSMessageAdminRemoveUserRequest stores remove user request 12 | type IRODSMessageAdminRemoveUserRequest IRODSMessageAdminRequest 13 | 14 | // NewIRODSMessageAdminRemoveUserRequest creates a new IRODSMessageAdminRemoveUserRequest 15 | func NewIRODSMessageAdminRemoveUserRequest(username string, zoneName string, userType types.IRODSUserType) *IRODSMessageAdminRemoveUserRequest { 16 | target := "user" 17 | 18 | //if userType == types.IRODSUserRodsGroup { 19 | // target = "group" 20 | //} 21 | 22 | request := &IRODSMessageAdminRemoveUserRequest{ 23 | Action: "rm", 24 | Target: target, 25 | } 26 | 27 | request.Arg2 = username 28 | request.Arg3 = zoneName 29 | 30 | return request 31 | } 32 | 33 | // GetBytes returns byte array 34 | func (msg *IRODSMessageAdminRemoveUserRequest) GetBytes() ([]byte, error) { 35 | xmlBytes, err := xml.Marshal(msg) 36 | if err != nil { 37 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 38 | } 39 | return xmlBytes, nil 40 | } 41 | 42 | // FromBytes returns struct from bytes 43 | func (msg *IRODSMessageAdminRemoveUserRequest) FromBytes(bytes []byte) error { 44 | err := xml.Unmarshal(bytes, msg) 45 | if err != nil { 46 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 47 | } 48 | return nil 49 | } 50 | 51 | // GetMessage builds a message 52 | func (msg *IRODSMessageAdminRemoveUserRequest) GetMessage() (*IRODSMessage, error) { 53 | bytes, err := msg.GetBytes() 54 | if err != nil { 55 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 56 | } 57 | 58 | msgBody := IRODSMessageBody{ 59 | Type: RODS_MESSAGE_API_REQ_TYPE, 60 | Message: bytes, 61 | Error: nil, 62 | Bs: nil, 63 | IntInfo: int32(common.GENERAL_ADMIN_AN), 64 | } 65 | 66 | msgHeader, err := msgBody.BuildHeader() 67 | if err != nil { 68 | return nil, errors.Wrapf(err, "failed to build header from irods message") 69 | } 70 | 71 | return &IRODSMessage{ 72 | Header: msgHeader, 73 | Body: &msgBody, 74 | }, nil 75 | } 76 | 77 | // GetXMLCorrector returns XML corrector for this message 78 | func (msg *IRODSMessageAdminRemoveUserRequest) GetXMLCorrector() XMLCorrector { 79 | return GetXMLCorrectorForRequest() 80 | } 81 | -------------------------------------------------------------------------------- /irods/message/admin_change_password_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | "fmt" 6 | 7 | "github.com/cockroachdb/errors" 8 | "github.com/cyverse/go-irodsclient/irods/common" 9 | ) 10 | 11 | // IRODSMessageAdminRequestIRODSMessageAdminChangePasswordRequest stores change password request 12 | type IRODSMessageAdminChangePasswordRequest IRODSMessageAdminRequest 13 | 14 | // NewIRODSMessageAdminChangePasswordRequest creates a new IRODSMessageAdminChangePasswordRequest 15 | func NewIRODSMessageAdminChangePasswordRequest(username string, zoneName string, password string) *IRODSMessageAdminChangePasswordRequest { 16 | request := &IRODSMessageAdminChangePasswordRequest{ 17 | Action: "modify", 18 | Target: "user", 19 | } 20 | 21 | request.Arg2 = fmt.Sprintf("%s#%s", username, zoneName) 22 | request.Arg3 = "password" 23 | request.Arg4 = password // password 24 | request.Arg5 = zoneName 25 | 26 | return request 27 | } 28 | 29 | // GetBytes returns byte array 30 | func (msg *IRODSMessageAdminChangePasswordRequest) GetBytes() ([]byte, error) { 31 | xmlBytes, err := xml.Marshal(msg) 32 | if err != nil { 33 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 34 | } 35 | return xmlBytes, nil 36 | } 37 | 38 | // FromBytes returns struct from bytes 39 | func (msg *IRODSMessageAdminChangePasswordRequest) FromBytes(bytes []byte) error { 40 | err := xml.Unmarshal(bytes, msg) 41 | if err != nil { 42 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 43 | } 44 | return nil 45 | } 46 | 47 | // GetMessage builds a message 48 | func (msg *IRODSMessageAdminChangePasswordRequest) GetMessage() (*IRODSMessage, error) { 49 | bytes, err := msg.GetBytes() 50 | if err != nil { 51 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 52 | } 53 | 54 | msgBody := IRODSMessageBody{ 55 | Type: RODS_MESSAGE_API_REQ_TYPE, 56 | Message: bytes, 57 | Error: nil, 58 | Bs: nil, 59 | IntInfo: int32(common.GENERAL_ADMIN_AN), 60 | } 61 | 62 | msgHeader, err := msgBody.BuildHeader() 63 | if err != nil { 64 | return nil, errors.Wrapf(err, "failed to build header from irods message") 65 | } 66 | 67 | return &IRODSMessage{ 68 | Header: msgHeader, 69 | Body: &msgBody, 70 | }, nil 71 | } 72 | 73 | // GetXMLCorrector returns XML corrector for this message 74 | func (msg *IRODSMessageAdminChangePasswordRequest) GetXMLCorrector() XMLCorrector { 75 | return GetXMLCorrectorForPasswordRequest() 76 | } 77 | -------------------------------------------------------------------------------- /irods/message/modify_collection_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageModifyCollectionRequest stores mod coll request 11 | type IRODSMessageModifyCollectionRequest IRODSMessageMakeCollectionRequest 12 | 13 | // NewIRODSMessageModifyCollectionRequest creates a IRODSMessageModifyCollectionRequest message 14 | func NewIRODSMessageModifyCollectionRequest(name string) *IRODSMessageModifyCollectionRequest { 15 | request := &IRODSMessageModifyCollectionRequest{ 16 | Name: name, 17 | Flags: 0, 18 | OperationType: 0, 19 | KeyVals: IRODSMessageSSKeyVal{ 20 | Length: 0, 21 | }, 22 | } 23 | 24 | return request 25 | } 26 | 27 | // AddKeyVal adds a key-value pair 28 | func (msg *IRODSMessageModifyCollectionRequest) AddKeyVal(key common.KeyWord, val string) { 29 | msg.KeyVals.Add(string(key), val) 30 | } 31 | 32 | // GetBytes returns byte array 33 | func (msg *IRODSMessageModifyCollectionRequest) GetBytes() ([]byte, error) { 34 | xmlBytes, err := xml.Marshal(msg) 35 | if err != nil { 36 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 37 | } 38 | return xmlBytes, nil 39 | } 40 | 41 | // FromBytes returns struct from bytes 42 | func (msg *IRODSMessageModifyCollectionRequest) FromBytes(bytes []byte) error { 43 | err := xml.Unmarshal(bytes, msg) 44 | if err != nil { 45 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 46 | } 47 | return nil 48 | } 49 | 50 | // GetMessage builds a message 51 | func (msg *IRODSMessageModifyCollectionRequest) GetMessage() (*IRODSMessage, error) { 52 | bytes, err := msg.GetBytes() 53 | if err != nil { 54 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 55 | } 56 | 57 | msgBody := IRODSMessageBody{ 58 | Type: RODS_MESSAGE_API_REQ_TYPE, 59 | Message: bytes, 60 | Error: nil, 61 | Bs: nil, 62 | IntInfo: int32(common.MOD_COLL_AN), 63 | } 64 | 65 | msgHeader, err := msgBody.BuildHeader() 66 | if err != nil { 67 | return nil, errors.Wrapf(err, "failed to build header from irods message") 68 | } 69 | 70 | return &IRODSMessage{ 71 | Header: msgHeader, 72 | Body: &msgBody, 73 | }, nil 74 | } 75 | 76 | // GetXMLCorrector returns XML corrector for this message 77 | func (msg *IRODSMessageModifyCollectionRequest) GetXMLCorrector() XMLCorrector { 78 | return GetXMLCorrectorForRequest() 79 | } 80 | -------------------------------------------------------------------------------- /irods/message/admin_set_user_resource_quota_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | "fmt" 6 | 7 | "github.com/cockroachdb/errors" 8 | "github.com/cyverse/go-irodsclient/irods/common" 9 | ) 10 | 11 | // IRODSMessageAdminSetUserResourceQuotaRequest stores set user resource quota request 12 | type IRODSMessageAdminSetUserResourceQuotaRequest IRODSMessageAdminRequest 13 | 14 | // NewIRODSMessageAdminSetUserResourceQuotaRequest creates a new IRODSMessageAdminSetUserResourceQuotaRequest 15 | func NewIRODSMessageAdminSetUserResourceQuotaRequest(username string, zoneName string, resource string, value string) *IRODSMessageAdminSetUserResourceQuotaRequest { 16 | request := &IRODSMessageAdminSetUserResourceQuotaRequest{ 17 | Action: "set-quota", 18 | Target: "user", 19 | } 20 | 21 | request.Arg2 = fmt.Sprintf("%s#%s", username, zoneName) 22 | request.Arg3 = resource 23 | request.Arg4 = value 24 | 25 | return request 26 | } 27 | 28 | // GetBytes returns byte array 29 | func (msg *IRODSMessageAdminSetUserResourceQuotaRequest) GetBytes() ([]byte, error) { 30 | xmlBytes, err := xml.Marshal(msg) 31 | if err != nil { 32 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 33 | } 34 | return xmlBytes, nil 35 | } 36 | 37 | // FromBytes returns struct from bytes 38 | func (msg *IRODSMessageAdminSetUserResourceQuotaRequest) FromBytes(bytes []byte) error { 39 | err := xml.Unmarshal(bytes, msg) 40 | if err != nil { 41 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 42 | } 43 | return nil 44 | } 45 | 46 | // GetMessage builds a message 47 | func (msg *IRODSMessageAdminSetUserResourceQuotaRequest) GetMessage() (*IRODSMessage, error) { 48 | bytes, err := msg.GetBytes() 49 | if err != nil { 50 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 51 | } 52 | 53 | msgBody := IRODSMessageBody{ 54 | Type: RODS_MESSAGE_API_REQ_TYPE, 55 | Message: bytes, 56 | Error: nil, 57 | Bs: nil, 58 | IntInfo: int32(common.GENERAL_ADMIN_AN), 59 | } 60 | 61 | msgHeader, err := msgBody.BuildHeader() 62 | if err != nil { 63 | return nil, errors.Wrapf(err, "failed to build header from irods message") 64 | } 65 | 66 | return &IRODSMessage{ 67 | Header: msgHeader, 68 | Body: &msgBody, 69 | }, nil 70 | } 71 | 72 | // GetXMLCorrector returns XML corrector for this message 73 | func (msg *IRODSMessageAdminSetUserResourceQuotaRequest) GetXMLCorrector() XMLCorrector { 74 | return GetXMLCorrectorForRequest() 75 | } 76 | -------------------------------------------------------------------------------- /irods/message/admin_change_user_type_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | "fmt" 6 | 7 | "github.com/cockroachdb/errors" 8 | "github.com/cyverse/go-irodsclient/irods/common" 9 | "github.com/cyverse/go-irodsclient/irods/types" 10 | ) 11 | 12 | // IRODSMessageAdminChangeUserTypeRequest stores chage user type request 13 | type IRODSMessageAdminChangeUserTypeRequest IRODSMessageAdminRequest 14 | 15 | // NewIRODSMessageAdminChangeUserTypeRequest creates a new IRODSMessageAdminChangeUserTypeRequest 16 | func NewIRODSMessageAdminChangeUserTypeRequest(username string, zoneName string, userType types.IRODSUserType) *IRODSMessageAdminChangeUserTypeRequest { 17 | request := &IRODSMessageAdminChangeUserTypeRequest{ 18 | Action: "modify", 19 | Target: "user", 20 | } 21 | 22 | request.Arg2 = fmt.Sprintf("%s#%s", username, zoneName) 23 | request.Arg3 = "type" 24 | request.Arg4 = string(userType) 25 | request.Arg5 = zoneName 26 | 27 | return request 28 | } 29 | 30 | // GetBytes returns byte array 31 | func (msg *IRODSMessageAdminChangeUserTypeRequest) GetBytes() ([]byte, error) { 32 | xmlBytes, err := xml.Marshal(msg) 33 | if err != nil { 34 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 35 | } 36 | return xmlBytes, nil 37 | } 38 | 39 | // FromBytes returns struct from bytes 40 | func (msg *IRODSMessageAdminChangeUserTypeRequest) FromBytes(bytes []byte) error { 41 | err := xml.Unmarshal(bytes, msg) 42 | if err != nil { 43 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 44 | } 45 | return nil 46 | } 47 | 48 | // GetMessage builds a message 49 | func (msg *IRODSMessageAdminChangeUserTypeRequest) GetMessage() (*IRODSMessage, error) { 50 | bytes, err := msg.GetBytes() 51 | if err != nil { 52 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 53 | } 54 | 55 | msgBody := IRODSMessageBody{ 56 | Type: RODS_MESSAGE_API_REQ_TYPE, 57 | Message: bytes, 58 | Error: nil, 59 | Bs: nil, 60 | IntInfo: int32(common.GENERAL_ADMIN_AN), 61 | } 62 | 63 | msgHeader, err := msgBody.BuildHeader() 64 | if err != nil { 65 | return nil, errors.Wrapf(err, "failed to build header from irods message") 66 | } 67 | 68 | return &IRODSMessage{ 69 | Header: msgHeader, 70 | Body: &msgBody, 71 | }, nil 72 | } 73 | 74 | // GetXMLCorrector returns XML corrector for this message 75 | func (msg *IRODSMessageAdminChangeUserTypeRequest) GetXMLCorrector() XMLCorrector { 76 | return GetXMLCorrectorForRequest() 77 | } 78 | -------------------------------------------------------------------------------- /irods/message/admin_set_group_resource_quota_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | "fmt" 6 | 7 | "github.com/cockroachdb/errors" 8 | "github.com/cyverse/go-irodsclient/irods/common" 9 | ) 10 | 11 | // IRODSMessageAdminSetGroupResourceQuotaRequest stores set group resource quota request 12 | type IRODSMessageAdminSetGroupResourceQuotaRequest IRODSMessageAdminRequest 13 | 14 | // NewIRODSMessageAdminSetGroupResourceQuotaRequest creates a new IRODSMessageAdminSetGroupResourceQuotaRequest 15 | func NewIRODSMessageAdminSetGroupResourceQuotaRequest(groupName string, zoneName string, resource string, value string) *IRODSMessageAdminSetGroupResourceQuotaRequest { 16 | request := &IRODSMessageAdminSetGroupResourceQuotaRequest{ 17 | Action: "set-quota", 18 | Target: "group", 19 | } 20 | 21 | request.Arg2 = fmt.Sprintf("%s#%s", groupName, zoneName) 22 | request.Arg3 = resource 23 | request.Arg4 = value 24 | 25 | return request 26 | } 27 | 28 | // GetBytes returns byte array 29 | func (msg *IRODSMessageAdminSetGroupResourceQuotaRequest) GetBytes() ([]byte, error) { 30 | xmlBytes, err := xml.Marshal(msg) 31 | if err != nil { 32 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 33 | } 34 | return xmlBytes, nil 35 | } 36 | 37 | // FromBytes returns struct from bytes 38 | func (msg *IRODSMessageAdminSetGroupResourceQuotaRequest) FromBytes(bytes []byte) error { 39 | err := xml.Unmarshal(bytes, msg) 40 | if err != nil { 41 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 42 | } 43 | return nil 44 | } 45 | 46 | // GetMessage builds a message 47 | func (msg *IRODSMessageAdminSetGroupResourceQuotaRequest) GetMessage() (*IRODSMessage, error) { 48 | bytes, err := msg.GetBytes() 49 | if err != nil { 50 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 51 | } 52 | 53 | msgBody := IRODSMessageBody{ 54 | Type: RODS_MESSAGE_API_REQ_TYPE, 55 | Message: bytes, 56 | Error: nil, 57 | Bs: nil, 58 | IntInfo: int32(common.GENERAL_ADMIN_AN), 59 | } 60 | 61 | msgHeader, err := msgBody.BuildHeader() 62 | if err != nil { 63 | return nil, errors.Wrapf(err, "failed to build header from irods message") 64 | } 65 | 66 | return &IRODSMessage{ 67 | Header: msgHeader, 68 | Body: &msgBody, 69 | }, nil 70 | } 71 | 72 | // GetXMLCorrector returns XML corrector for this message 73 | func (msg *IRODSMessageAdminSetGroupResourceQuotaRequest) GetXMLCorrector() XMLCorrector { 74 | return GetXMLCorrectorForRequest() 75 | } 76 | -------------------------------------------------------------------------------- /irods/message/close_data_object_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageCloseDataObjectRequest stores data object close request 11 | type IRODSMessageCloseDataObjectRequest IRODSMessageOpenedDataObjectRequest 12 | 13 | // NewIRODSMessageCloseDataObjectRequest creates a IRODSMessageCloseDataObjectRequest message 14 | func NewIRODSMessageCloseDataObjectRequest(desc int) *IRODSMessageCloseDataObjectRequest { 15 | request := &IRODSMessageCloseDataObjectRequest{ 16 | FileDescriptor: desc, 17 | Size: 0, 18 | Whence: 0, 19 | OperationType: 0, 20 | Offset: 0, 21 | BytesWritten: 0, 22 | KeyVals: IRODSMessageSSKeyVal{ 23 | Length: 0, 24 | }, 25 | } 26 | 27 | return request 28 | } 29 | 30 | // AddKeyVal adds a key-value pair 31 | func (msg *IRODSMessageCloseDataObjectRequest) AddKeyVal(key common.KeyWord, val string) { 32 | msg.KeyVals.Add(string(key), val) 33 | } 34 | 35 | // GetBytes returns byte array 36 | func (msg *IRODSMessageCloseDataObjectRequest) GetBytes() ([]byte, error) { 37 | xmlBytes, err := xml.Marshal(msg) 38 | if err != nil { 39 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 40 | } 41 | return xmlBytes, nil 42 | } 43 | 44 | // FromBytes returns struct from bytes 45 | func (msg *IRODSMessageCloseDataObjectRequest) FromBytes(bytes []byte) error { 46 | err := xml.Unmarshal(bytes, msg) 47 | if err != nil { 48 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 49 | } 50 | return nil 51 | } 52 | 53 | // GetMessage builds a message 54 | func (msg *IRODSMessageCloseDataObjectRequest) GetMessage() (*IRODSMessage, error) { 55 | bytes, err := msg.GetBytes() 56 | if err != nil { 57 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 58 | } 59 | 60 | msgBody := IRODSMessageBody{ 61 | Type: RODS_MESSAGE_API_REQ_TYPE, 62 | Message: bytes, 63 | Error: nil, 64 | Bs: nil, 65 | IntInfo: int32(common.DATA_OBJ_CLOSE_AN), 66 | } 67 | 68 | msgHeader, err := msgBody.BuildHeader() 69 | if err != nil { 70 | return nil, errors.Wrapf(err, "failed to build header from irods message") 71 | } 72 | 73 | return &IRODSMessage{ 74 | Header: msgHeader, 75 | Body: &msgBody, 76 | }, nil 77 | } 78 | 79 | // GetXMLCorrector returns XML corrector for this message 80 | func (msg *IRODSMessageCloseDataObjectRequest) GetXMLCorrector() XMLCorrector { 81 | return GetXMLCorrectorForRequest() 82 | } 83 | -------------------------------------------------------------------------------- /irods/message/get_file_stat_response.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // IRODSMessageGetFileStatResponse stores data object read response 12 | type IRODSMessageGetFileStatResponse struct { 13 | XMLName xml.Name `xml:"RODS_STAT_T_PI"` 14 | Size int64 `xml:"st_size"` 15 | Dev int `xml:"st_dev"` 16 | Ino int `xml:"st_ino"` 17 | Mode int `xml:"st_mode"` 18 | Links int `xml:"st_nlink"` 19 | UID int `xml:"st_uid"` 20 | GID int `xml:"st_gid"` 21 | Rdev int `xml:"st_rdev"` 22 | AccessTime int `xml:"st_atim"` 23 | ModifyTime int `xml:"st_mtim"` 24 | ChangeTime int `xml:"st_ctim"` 25 | BlkSize int `xml:"st_blksize"` 26 | Blocks int `xml:"st_blocks"` 27 | 28 | // stores error return 29 | Result int `xml:"-"` 30 | } 31 | 32 | // GetBytes returns byte array 33 | func (msg *IRODSMessageGetFileStatResponse) GetBytes() ([]byte, error) { 34 | xmlBytes, err := xml.Marshal(msg) 35 | if err != nil { 36 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 37 | } 38 | return xmlBytes, nil 39 | } 40 | 41 | // CheckError returns error if server returned an error 42 | func (msg *IRODSMessageGetFileStatResponse) CheckError() error { 43 | if msg.Result < 0 { 44 | return types.NewIRODSError(common.ErrorCode(msg.Result)) 45 | } 46 | return nil 47 | } 48 | 49 | // FromBytes returns struct from bytes 50 | func (msg *IRODSMessageGetFileStatResponse) FromBytes(bytes []byte) error { 51 | err := xml.Unmarshal(bytes, msg) 52 | if err != nil { 53 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 54 | } 55 | return nil 56 | } 57 | 58 | // FromMessage returns struct from IRODSMessage 59 | func (msg *IRODSMessageGetFileStatResponse) FromMessage(msgIn *IRODSMessage) error { 60 | if msgIn.Body == nil { 61 | return errors.Errorf("empty message body") 62 | } 63 | 64 | msg.Result = int(msgIn.Body.IntInfo) 65 | 66 | if msgIn.Body.Message != nil { 67 | err := msg.FromBytes(msgIn.Body.Message) 68 | if err != nil { 69 | return errors.Wrapf(err, "failed to get irods message from message body") 70 | } 71 | } 72 | 73 | return nil 74 | } 75 | 76 | // GetXMLCorrector returns XML corrector for this message 77 | func (msg *IRODSMessageGetFileStatResponse) GetXMLCorrector() XMLCorrector { 78 | return GetXMLCorrectorForResponse() 79 | } 80 | -------------------------------------------------------------------------------- /irods/message/read_data_object_request.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | "github.com/cockroachdb/errors" 7 | "github.com/cyverse/go-irodsclient/irods/common" 8 | ) 9 | 10 | // IRODSMessageReadDataObjectRequest stores data object read request 11 | type IRODSMessageReadDataObjectRequest IRODSMessageOpenedDataObjectRequest 12 | 13 | // NewIRODSMessageReadDataObjectRequest creates a IRODSMessageReadDataObjectRequest message 14 | func NewIRODSMessageReadDataObjectRequest(desc int, len int) *IRODSMessageReadDataObjectRequest { 15 | request := &IRODSMessageReadDataObjectRequest{ 16 | FileDescriptor: desc, 17 | Size: int64(len), 18 | Whence: 0, 19 | OperationType: 0, 20 | Offset: 0, 21 | BytesWritten: 0, 22 | KeyVals: IRODSMessageSSKeyVal{ 23 | Length: 0, 24 | }, 25 | } 26 | 27 | return request 28 | } 29 | 30 | // AddKeyVal adds a key-value pair 31 | func (msg *IRODSMessageReadDataObjectRequest) AddKeyVal(key common.KeyWord, val string) { 32 | msg.KeyVals.Add(string(key), val) 33 | } 34 | 35 | // GetBytes returns byte array 36 | func (msg *IRODSMessageReadDataObjectRequest) GetBytes() ([]byte, error) { 37 | xmlBytes, err := xml.Marshal(msg) 38 | if err != nil { 39 | return nil, errors.Wrapf(err, "failed to marshal irods message to xml") 40 | } 41 | return xmlBytes, nil 42 | } 43 | 44 | // FromBytes returns struct from bytes 45 | func (msg *IRODSMessageReadDataObjectRequest) FromBytes(bytes []byte) error { 46 | err := xml.Unmarshal(bytes, msg) 47 | if err != nil { 48 | return errors.Wrapf(err, "failed to unmarshal xml to irods message") 49 | } 50 | return nil 51 | } 52 | 53 | // GetMessage builds a message 54 | func (msg *IRODSMessageReadDataObjectRequest) GetMessage() (*IRODSMessage, error) { 55 | bytes, err := msg.GetBytes() 56 | if err != nil { 57 | return nil, errors.Wrapf(err, "failed to get bytes from irods message") 58 | } 59 | 60 | msgBody := IRODSMessageBody{ 61 | Type: RODS_MESSAGE_API_REQ_TYPE, 62 | Message: bytes, 63 | Error: nil, 64 | Bs: nil, 65 | IntInfo: int32(common.DATA_OBJ_READ_AN), 66 | } 67 | 68 | msgHeader, err := msgBody.BuildHeader() 69 | if err != nil { 70 | return nil, errors.Wrapf(err, "failed to build header from irods message") 71 | } 72 | 73 | return &IRODSMessage{ 74 | Header: msgHeader, 75 | Body: &msgBody, 76 | }, nil 77 | } 78 | 79 | // GetXMLCorrector returns XML corrector for this message 80 | func (msg *IRODSMessageReadDataObjectRequest) GetXMLCorrector() XMLCorrector { 81 | return GetXMLCorrectorForRequest() 82 | } 83 | -------------------------------------------------------------------------------- /irods/util/io.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "io" 5 | "net" 6 | 7 | "github.com/cockroachdb/errors" 8 | "github.com/cyverse/go-irodsclient/irods/common" 9 | ) 10 | 11 | // ReadBytes reads data from socket in a particular size 12 | func ReadBytes(socket net.Conn, buffer []byte, size int) (int, error) { 13 | readLen, err := ReadBytesWithTrackerCallBack(socket, buffer, size, nil) 14 | if err != nil { 15 | if err == io.EOF { 16 | return readLen, io.EOF 17 | } 18 | 19 | return readLen, errors.Wrapf(err, "failed to read bytes from socket") 20 | } 21 | return readLen, nil 22 | } 23 | 24 | // WriteBytes writes data to socket 25 | func WriteBytes(socket net.Conn, buffer []byte, size int) error { 26 | err := WriteBytesWithTrackerCallBack(socket, buffer, size, nil) 27 | if err != nil { 28 | return errors.Wrapf(err, "failed to write bytes to socket") 29 | } 30 | return nil 31 | } 32 | 33 | // ReadBytesWithTrackerCallBack reads data from socket in a particular size 34 | func ReadBytesWithTrackerCallBack(socket net.Conn, buffer []byte, size int, callback common.TransferTrackerCallback) (int, error) { 35 | totalSizeToRead := size 36 | sizeLeft := size 37 | actualRead := 0 38 | 39 | for sizeLeft > 0 { 40 | sizeRead, err := socket.Read(buffer[actualRead:size]) 41 | 42 | if sizeRead > 0 { 43 | sizeLeft -= sizeRead 44 | actualRead += sizeRead 45 | 46 | if callback != nil { 47 | callback("read", int64(actualRead), int64(totalSizeToRead)) 48 | } 49 | } 50 | 51 | if err != nil { 52 | if err == io.EOF { 53 | return actualRead, io.EOF 54 | } 55 | 56 | return actualRead, errors.Wrapf(err, "failed to read from socket") 57 | } 58 | } 59 | 60 | if sizeLeft < 0 { 61 | return actualRead, errors.Errorf("received more bytes than requested, %d requested, but %d read", size, actualRead) 62 | } 63 | 64 | return actualRead, nil 65 | } 66 | 67 | // WriteBytesWithTrackerCallBack writes data to socket 68 | func WriteBytesWithTrackerCallBack(socket net.Conn, buffer []byte, size int, callback common.TransferTrackerCallback) error { 69 | totalSizeToSend := size 70 | sizeLeft := size 71 | actualWrite := 0 72 | 73 | for sizeLeft > 0 { 74 | sizeWrite, err := socket.Write(buffer[actualWrite:size]) 75 | 76 | if sizeWrite > 0 { 77 | sizeLeft -= sizeWrite 78 | actualWrite += sizeWrite 79 | 80 | if callback != nil { 81 | callback("write", int64(actualWrite), int64(totalSizeToSend)) 82 | } 83 | } 84 | 85 | if err != nil { 86 | return errors.Wrapf(err, "failed to write to socket") 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GO111MODULE=on 2 | GOPROXY=direct 3 | GOPATH=$(shell go env GOPATH) 4 | 5 | .EXPORT_ALL_VARIABLES: 6 | 7 | .PHONY: lint 8 | lint: 9 | ./tools/lint.sh 10 | 11 | .PHONY: format 12 | format: 13 | ./tools/format.sh 14 | 15 | .PHONY: examples 16 | examples: 17 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/list_dir/list_dir.out ./examples/list_dir/list_dir.go 18 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/list_acls/list_acls.out ./examples/list_acls/list_acls.go 19 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/list_user/list_user.out ./examples/list_user/list_user.go 20 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/search/search.out ./examples/search/search.go 21 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/upload/upload.out ./examples/upload/upload.go 22 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/upload_parallel/upload_parallel.out ./examples/upload_parallel/upload_parallel.go 23 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/download/download.out ./examples/download/download.go 24 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/download_resumable/download_resumable.out ./examples/download_resumable/download_resumable.go 25 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/download_parallel/download_parallel.out ./examples/download_parallel/download_parallel.go 26 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/download_parallel_resumable/download_parallel_resumable.out ./examples/download_parallel_resumable/download_parallel_resumable.go 27 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/delete_file/delete_file.out ./examples/delete_file/delete_file.go 28 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/delete_dir/delete_dir.out ./examples/delete_dir/delete_dir.go 29 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/make_dir/make_dir.out ./examples/make_dir/make_dir.go 30 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/list_dir_via_ticket/list_dir.out ./examples/list_dir_via_ticket/list_dir.go 31 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/list_ticket/list_ticket.out ./examples/list_ticket/list_ticket.go 32 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/create_ticket/create_ticket.out ./examples/create_ticket/create_ticket.go 33 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/get_ticket/get_ticket.out ./examples/get_ticket/get_ticket.go 34 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/get_ticket_anon/get_ticket_anon.out ./examples/get_ticket_anon/get_ticket_anon.go 35 | CGO_ENABLED=0 GOOS=linux go build -o ./examples/version/version.out ./examples/version/version.go 36 | 37 | .PHONY: test 38 | test: 39 | LOG_LEVEL=debug go test -timeout 3000s -v -p 1 -count=1 ./... 40 | -------------------------------------------------------------------------------- /irods/fs/touch.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "github.com/cockroachdb/errors" 5 | "github.com/cyverse/go-irodsclient/irods/common" 6 | "github.com/cyverse/go-irodsclient/irods/connection" 7 | "github.com/cyverse/go-irodsclient/irods/message" 8 | "github.com/cyverse/go-irodsclient/irods/types" 9 | ) 10 | 11 | // Touch create an empty data object or update timestamp for the path 12 | func Touch(conn *connection.IRODSConnection, path string, resource string, noCreate bool, replicaNumber *int, referencePath string, secondsSinceEpoch *int) error { 13 | if conn == nil || !conn.IsConnected() { 14 | return errors.Errorf("connection is nil or disconnected") 15 | } 16 | 17 | // lock the connection 18 | conn.Lock() 19 | defer conn.Unlock() 20 | 21 | // use default resource when resource param is empty 22 | //if len(resource) == 0 { 23 | // account := conn.GetAccount() 24 | // resource = account.DefaultResource 25 | //} 26 | 27 | request := message.NewIRODSMessageTouchRequest(path) 28 | if noCreate { 29 | request.SetNoCreate(noCreate) 30 | } 31 | 32 | if replicaNumber != nil { 33 | replicaNumberVal := *replicaNumber 34 | request.SetReplicaNumber(replicaNumberVal) 35 | } 36 | 37 | if replicaNumber != nil && len(resource) > 0 { 38 | request.SetLeafResourceName(resource) 39 | } 40 | 41 | if len(referencePath) > 0 { 42 | request.SetReference(referencePath) 43 | } 44 | 45 | if len(referencePath) == 0 && secondsSinceEpoch != nil { 46 | secondsSinceEpochVal := *secondsSinceEpoch 47 | request.SetSecondsSinceEpoch(secondsSinceEpochVal) 48 | } 49 | 50 | response := message.IRODSMessageTouchResponse{} 51 | err := conn.RequestAndCheck(request, &response, nil, conn.GetOperationTimeout()) 52 | if err != nil { 53 | if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND || types.GetIRODSErrorCode(err) == common.CAT_UNKNOWN_FILE { 54 | newErr := errors.Join(err, types.NewFileNotFoundError(path)) 55 | return errors.Wrapf(newErr, "failed to find the data object for path %q", path) 56 | } else if types.GetIRODSErrorCode(err) == common.SYS_UNMATCHED_API_NUM { 57 | // not supported 58 | newErr := errors.Join(err, types.NewAPINotSupportedError(common.TOUCH_APN)) 59 | return errors.Wrapf(newErr, "failed to find the data object for path %q", path) 60 | } else if types.GetIRODSErrorCode(err) == common.CAT_UNKNOWN_COLLECTION { 61 | newErr := errors.Join(err, types.NewFileNotFoundError(path)) 62 | return errors.Wrapf(newErr, "failed to find the collection for path %q", path) 63 | } 64 | 65 | return errors.Wrapf(err, "failed to touch data object for path %q", path) 66 | } 67 | 68 | return nil 69 | } 70 | --------------------------------------------------------------------------------