Skip to content

Commit

Permalink
[Server] Implement user settable extended file attributes.
Browse files Browse the repository at this point in the history
  • Loading branch information
abh3 authored and osschar committed Oct 10, 2019
1 parent 051f5b7 commit 726971d
Show file tree
Hide file tree
Showing 17 changed files with 1,563 additions and 251 deletions.
7 changes: 5 additions & 2 deletions src/XProtocol/XProtocol.cc
Expand Up @@ -86,7 +86,9 @@ const char *errNames[kXR_ERRFENCE-kXR_ArgInvalid] =
"Request in progress", // kXR_inProgress
"Quota exceeded", // kXR_overQuota
"Invalid signature", // kXR_SigVerErr
"Decryption failed" // kXR_DecryptErr
"Decryption failed", // kXR_DecryptErr
"Overloaded", // kXR_Overloaded
"Invalid payload format" // kXR_BadPayload
};

const char *reqNames[kXR_REQFENCE-kXR_auth] =
Expand All @@ -97,7 +99,8 @@ const char *reqNames[kXR_REQFENCE-kXR_auth] =
"sync", "stat", "set", "write",
"admin", "prepare", "statx", "endsess",
"bind", "readv", "verifyw", "locate",
"truncate", "sigver", "decrypt", "writev"
"truncate", "sigver", "decrypt", "writev",
"fattr"
};

// Following value is used to determine if the error or request code is
Expand Down
106 changes: 72 additions & 34 deletions src/XProtocol/XProtocol.hh
Expand Up @@ -140,6 +140,7 @@ enum XRequestTypes {
kXR_sigver, // 3029
kXR_decrypt, // 3030
kXR_writev, // 3031
kXR_fattr, // 3032
kXR_REQFENCE // Always last valid request code +1
};

Expand Down Expand Up @@ -289,6 +290,24 @@ enum XSecCrypto {
kXR_rsaKey = 0x80 // The rsa key was used
};

// kXR_fattr subcodes
//
enum xfaSubCode {
kXR_fattrDel = 0,
kXR_fattrGet = 1,
kXR_fattrList = 2,
kXR_fattrSet = 3,
kXR_fatrrMaxSC = 3 // Highest valid subcode
};

// kXR_fattr limits
//
enum xfaLimits {
kXR_faMaxVars = 16,
kXR_faMaxNlen = 248,
kXR_faMaxVlen = 65536
};

//_______________________________________________
// PROTOCOL DEFINITION: SERVER'S RESPONSES TYPES
//_______________________________________________
Expand All @@ -310,47 +329,49 @@ enum XResponseType {
//_______________________________________________

enum XActionCode {
kXR_asyncab = 5000,
kXR_asyncdi,
kXR_asyncms,
kXR_asyncrd,
kXR_asyncwt,
kXR_asyncav,
kXR_asynunav,
kXR_asyncgo,
kXR_asynresp
kXR_asyncab = 5000,
kXR_asyncdi, // 5001
kXR_asyncms, // 5002
kXR_asyncrd, // 5003
kXR_asyncwt, // 5004
kXR_asyncav, // 5005
kXR_asynunav, // 5006
kXR_asyncgo, // 5007
kXR_asynresp // 5008
};

//_______________________________________________
// PROTOCOL DEFINITION: SERVER'S ERROR CODES
//_______________________________________________
//
enum XErrorCode {
kXR_ArgInvalid = 3000,
kXR_ArgMissing,
kXR_ArgTooLong,
kXR_FileLocked,
kXR_FileNotOpen,
kXR_FSError,
kXR_InvalidRequest,
kXR_IOError,
kXR_NoMemory,
kXR_NoSpace,
kXR_NotAuthorized,
kXR_NotFound,
kXR_ServerError,
kXR_Unsupported,
kXR_noserver,
kXR_NotFile,
kXR_isDirectory,
kXR_Cancelled,
kXR_ChkLenErr,
kXR_ChkSumErr,
kXR_inProgress,
kXR_overQuota,
kXR_SigVerErr,
kXR_DecryptErr,
kXR_Overloaded,
kXR_ArgInvalid = 3000,
kXR_ArgMissing, // 3001
kXR_ArgTooLong, // 3002
kXR_FileLocked, // 3003
kXR_FileNotOpen, // 3004
kXR_FSError, // 3005
kXR_InvalidRequest, // 3006
kXR_IOError, // 3007
kXR_NoMemory, // 3008
kXR_NoSpace, // 3009
kXR_NotAuthorized, // 3010
kXR_NotFound, // 3011
kXR_ServerError, // 3012
kXR_Unsupported, // 3013
kXR_noserver, // 3014
kXR_NotFile, // 3015
kXR_isDirectory, // 3016
kXR_Cancelled, // 3017
kXR_ChkLenErr, // 3018
kXR_ChkSumErr, // 3019
kXR_inProgress, // 3020
kXR_overQuota, // 3021
kXR_SigVerErr, // 3022
kXR_DecryptErr, // 3023
kXR_Overloaded, // 3024
kXR_fsReadOnly, // 3025
kXR_BadPayload, // 3026
kXR_ERRFENCE, // Always last valid errcode + 1
kXR_noErrorYet = 10000
};
Expand Down Expand Up @@ -425,6 +446,20 @@ struct ClientEndsessRequest {
kXR_char sessid[16];
kXR_int32 dlen;
};
struct ClientFattrRequest {
kXR_char streamid[2];
kXR_unt16 requestid;
kXR_char fhandle[4];
kXR_char subcode;
kXR_char numattr;
kXR_char options;
kXR_char reserved[9];
kXR_int32 dlen;

// Valid options:
//
static const int isNew = 0x01; // For set, the variable must not exist
};
struct ClientGetfileRequest {
kXR_char streamid[2];
kXR_unt16 requestid;
Expand Down Expand Up @@ -630,6 +665,7 @@ typedef union {
struct ClientDecryptRequest decrypt;
struct ClientDirlistRequest dirlist;
struct ClientEndsessRequest endsess;
struct ClientFattrRequest fattr;
struct ClientGetfileRequest getfile;
struct ClientLocateRequest locate;
struct ClientLoginRequest login;
Expand Down Expand Up @@ -923,6 +959,7 @@ static int mapError(int rc)
case EILSEQ: return kXR_SigVerErr;
case ERANGE: return kXR_DecryptErr;
case EUSERS: return kXR_Overloaded;
case EROFS: return kXR_fsReadOnly;
default: return kXR_FSError;
}
}
Expand Down Expand Up @@ -955,6 +992,7 @@ static int toErrno( int xerr )
case kXR_SigVerErr: return EILSEQ;
case kXR_DecryptErr: return ERANGE;
case kXR_Overloaded: return EUSERS;
case kXR_fsReadOnly: return EROFS;
default: return ENOMSG;
}
}
Expand Down
174 changes: 8 additions & 166 deletions src/XrdOfs/XrdOfs.cc
Expand Up @@ -42,6 +42,8 @@
#include <sys/time.h>
#include <sys/types.h>

#include "XProtocol/XProtocol.hh"

#include "XrdCks/XrdCks.hh"
#include "XrdCks/XrdCksConfig.hh"
#include "XrdCks/XrdCksData.hh"
Expand Down Expand Up @@ -141,6 +143,7 @@ XrdOfs::XrdOfs()
Finder = 0;
Balancer = 0;
evsObject = 0;
ossRPList = 0;
myRole = strdup("server");
OssIsProxy = 0;
ossRW =' ';
Expand Down Expand Up @@ -178,6 +181,11 @@ XrdOfs::XrdOfs()
//
tpcRdrHost= 0;
tpcRdrPort= 0;

// Eextended attribute limits
//
usxMaxNsz = kXR_faMaxNlen;
usxMaxVsz = kXR_faMaxVlen;
}

/******************************************************************************/
Expand Down Expand Up @@ -1557,172 +1565,6 @@ int XrdOfs::exists(const char *path, // In
return XrdOfsFS->Emsg(epname, einfo, retc, "locate", path);
}

/******************************************************************************/
/* f s c t l */
/******************************************************************************/

int XrdOfs::fsctl(const int cmd,
const char *args,
XrdOucErrInfo &einfo,
const XrdSecEntity *client)
/*
Function: Perform filesystem operations:
Input: cmd - Operation command (currently supported):
SFS_FSCTL_LOCATE - locate file
SFS_FSCTL_STATCC - return cluster config status
SFS_FSCTL_STATFS - return file system info (physical)
SFS_FSCTL_STATLS - return file system info (logical)
SFS_FSCTL_STATXA - return file extended attributes
arg - Command dependent argument:
- Locate: The path whose location is wanted
buf - The stat structure to hold the results
einfo - Error/Response information structure.
client - Authentication credentials, if any.
Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
*/
{
EPNAME("fsctl");
static int PrivTab[] = {XrdAccPriv_Delete, XrdAccPriv_Insert,
XrdAccPriv_Lock, XrdAccPriv_Lookup,
XrdAccPriv_Rename, XrdAccPriv_Read,
XrdAccPriv_Write};
static char PrivLet[] = {'d', 'i',
'k', 'l',
'n', 'r',
'w'};
static const int PrivNum = sizeof(PrivLet);

int retc, i, blen, privs, opcode = cmd & SFS_FSCTL_CMD;
const char *tident = einfo.getErrUser();
char *bP, *cP;
XTRACE(fsctl, args, "");

// Process the LOCATE request
//
if (opcode == SFS_FSCTL_LOCATE)
{static const int locMask = (SFS_O_FORCE|SFS_O_NOWAIT|SFS_O_RESET|
SFS_O_HNAME|SFS_O_RAWIO);
struct stat fstat;
char pbuff[1024], rType[3];
const char *Resp[2] = {rType, pbuff};
const char *locArg, *opq, *Path = Split(args,&opq,pbuff,sizeof(pbuff));
XrdNetIF::ifType ifType;
int Resp1Len;
int find_flag = SFS_O_LOCATE | (cmd & locMask);
XrdOucEnv loc_Env(opq ? opq+1 : 0,0,client);

if (cmd & SFS_O_TRUNC) locArg = (char *)"*";
else { if (*Path == '*') {locArg = Path; Path++;}
else locArg = Path;
AUTHORIZE(client,0,AOP_Stat,"locate",Path,einfo);
}
if (Finder && Finder->isRemote()
&& (retc = Finder->Locate(einfo, locArg, find_flag, &loc_Env)))
return fsError(einfo, retc);

if (cmd & SFS_O_TRUNC) {rType[0] = 'S'; rType[1] = ossRW;}
else {if ((retc = XrdOfsOss->Stat(Path, &fstat, 0, &loc_Env)))
return XrdOfsFS->Emsg(epname, einfo, retc, "locate", Path);
rType[0] = ((fstat.st_mode & S_IFBLK) == S_IFBLK ? 's' : 'S');
rType[1] = (fstat.st_mode & S_IWUSR ? 'w' : 'r');
}
rType[2] = '\0';

ifType = XrdNetIF::GetIFType((einfo.getUCap() & XrdOucEI::uIPv4) != 0,
(einfo.getUCap() & XrdOucEI::uIPv64) != 0,
(einfo.getUCap() & XrdOucEI::uPrip) != 0);
bool retHN = (cmd & SFS_O_HNAME) != 0;
if ((Resp1Len = myIF->GetDest(pbuff, sizeof(pbuff), ifType, retHN)))
{einfo.setErrInfo(Resp1Len+3, (const char **)Resp, 2);
return SFS_DATA;
}
return Emsg(epname, einfo, ENETUNREACH, "locate", Path);
}

// Process the STATFS request
//
if (opcode == SFS_FSCTL_STATFS)
{char pbuff[1024];
const char *opq, *Path = Split(args, &opq, pbuff, sizeof(pbuff));
XrdOucEnv fs_Env(opq ? opq+1 : 0,0,client);
AUTHORIZE(client,0,AOP_Stat,"statfs",Path,einfo);
if (Finder && Finder->isRemote()
&& (retc = Finder->Space(einfo, Path, &fs_Env)))
return fsError(einfo, retc);
bP = einfo.getMsgBuff(blen);
if ((retc = XrdOfsOss->StatFS(Path, bP, blen, &fs_Env)))
return XrdOfsFS->Emsg(epname, einfo, retc, "statfs", args);
einfo.setErrCode(blen+1);
return SFS_DATA;
}

// Process the STATLS request
//
if (opcode == SFS_FSCTL_STATLS)
{char pbuff[1024];
const char *opq, *Path = Split(args, &opq, pbuff, sizeof(pbuff));
XrdOucEnv statls_Env(opq ? opq+1 : 0,0,client);
AUTHORIZE(client,0,AOP_Stat,"statfs",Path,einfo);
if (Finder && Finder->isRemote())
{statls_Env.Put("cms.qvfs", "1");
if ((retc = Finder->Space(einfo, Path, &statls_Env)))
{if (retc == SFS_DATA) retc = Reformat(einfo);
return fsError(einfo, retc);
}
}
bP = einfo.getMsgBuff(blen);
if ((retc = XrdOfsOss->StatLS(statls_Env, Path, bP, blen)))
return XrdOfsFS->Emsg(epname, einfo, retc, "statls", Path);
einfo.setErrCode(blen+1);
return SFS_DATA;
}

// Process the STATXA request
//
if (opcode == SFS_FSCTL_STATXA)
{char pbuff[1024];
const char *opq, *Path = Split(args, &opq, pbuff, sizeof(pbuff));
XrdOucEnv xa_Env(opq ? opq+1 : 0,0,client);
AUTHORIZE(client,0,AOP_Stat,"statxa",Path,einfo);
if (Finder && Finder->isRemote()
&& (retc = Finder->Locate(einfo,Path,SFS_O_RDONLY|SFS_O_STAT,&xa_Env)))
return fsError(einfo, retc);
bP = einfo.getMsgBuff(blen);
if ((retc = XrdOfsOss->StatXA(Path, bP, blen, &xa_Env)))
return XrdOfsFS->Emsg(epname, einfo, retc, "statxa", Path);
if (!client || !XrdOfsFS->Authorization) privs = XrdAccPriv_All;
else privs = XrdOfsFS->Authorization->Access(client, Path, AOP_Any);
cP = bP + blen; strcpy(cP, "&ofs.ap="); cP += 8;
if (privs == XrdAccPriv_All) *cP++ = 'a';
else {for (i = 0; i < PrivNum; i++)
if (PrivTab[i] & privs) *cP++ = PrivLet[i];
if (cP == (bP + blen + 1)) *cP++ = '?';
}
*cP++ = '\0';
einfo.setErrCode(cP-bP+1);
return SFS_DATA;
}

// Process the STATCC request (this should always succeed)
//
if (opcode == SFS_FSCTL_STATCC)
{static const int lcc_flag = SFS_O_LOCATE | SFS_O_LOCAL;
XrdOucEnv lcc_Env(0,0,client);
if (Finder) retc = Finder ->Locate(einfo,".",lcc_flag,&lcc_Env);
else if (Balancer) retc = Balancer->Locate(einfo,".",lcc_flag,&lcc_Env);
else retc = SFS_ERROR;
if (retc != SFS_DATA) einfo.setErrInfo(5, "none|");
return fsError(einfo, SFS_DATA);
}

// Operation is not supported
//
return XrdOfsFS->Emsg(epname, einfo, ENOTSUP, "fsctl", args);

}

/******************************************************************************/
/* g e t S t a t s */
/******************************************************************************/
Expand Down

0 comments on commit 726971d

Please sign in to comment.