diff --git a/ecllibrary/std/File.ecl b/ecllibrary/std/File.ecl index 4371f36dfa7..022882aa363 100644 --- a/ecllibrary/std/File.ecl +++ b/ecllibrary/std/File.ecl @@ -358,9 +358,10 @@ EXPORT RfsAction(varstring server, varstring query) := * @param location The IP address of the remote machine. * @param frompath The path/name of the file to move. * @param topath The path/name of the target file. + * @param planename The name of the data plane containing the file. */ -EXPORT MoveExternalFile(varstring location, varstring frompath, varstring topath) := - lib_fileservices.FileServices.MoveExternalFile(location, frompath, topath); +EXPORT MoveExternalFile(varstring location, varstring frompath, varstring topath, varstring planename) := + lib_fileservices.FileServices.MoveExternalFile(location, frompath, topath, planename); /** * Removes a single physical file from a remote machine. The diff --git a/plugins/fileservices/fileservices.cpp b/plugins/fileservices/fileservices.cpp index b32257f26b6..1cefa81bec6 100644 --- a/plugins/fileservices/fileservices.cpp +++ b/plugins/fileservices/fileservices.cpp @@ -2726,7 +2726,7 @@ FILESERVICES_API char * FILESERVICES_CALL fsfResolveHostName(const char *hostna return ret.detach(); } -static void checkExternalFileRights(ICodeContext *ctx, CDfsLogicalFileName &lfn, bool rd,bool wr) +static void checkExternalFileRights(ICodeContext *ctx,CDfsLogicalFileName &lfn,bool checkScopePermissions,bool rd,bool wr) { Linked udesc = ctx->queryUserDescriptor(); unsigned auditflags = 0; @@ -2734,7 +2734,11 @@ static void checkExternalFileRights(ICodeContext *ctx, CDfsLogicalFileName &lfn, auditflags |= (DALI_LDAP_AUDIT_REPORT|DALI_LDAP_READ_WANTED); if (wr) auditflags |= (DALI_LDAP_AUDIT_REPORT|DALI_LDAP_WRITE_WANTED); - SecAccessFlags perm = queryDistributedFileDirectory().getFilePermissions(lfn.get(),udesc,auditflags); + SecAccessFlags perm = SecAccess_Unavailable; + if (!checkScopePermissions) + perm = queryDistributedFileDirectory().getFilePermissions(lfn.get(),udesc,auditflags); + else + perm = queryDistributedFileDirectory().getFScopePermissions(lfn.get(),udesc,auditflags); if (wr) { if (!HASWRITEPERMISSION(perm)) { throw MakeStringException(-1,"Write permission denied for %s", lfn.get()); @@ -2747,21 +2751,60 @@ static void checkExternalFileRights(ICodeContext *ctx, CDfsLogicalFileName &lfn, } } -FILESERVICES_API void FILESERVICES_CALL fsMoveExternalFile(ICodeContext * ctx,const char *location,const char *frompath,const char *topath) +static void checkExternalFilePath(ICodeContext *ctx,IPropertyTree *plane,const char *host, + const char *path,bool checkScopePermissionIfDir,bool rd,bool wr,RemoteFilename &rfn) { - SocketEndpoint ep(location); + if (containsRelPaths(path)) //Detect a path like: a/../../../f + throw makeStringExceptionV(-1,"Invalid file path %s",path); + + CDfsLogicalFileName dlfn; + if (plane) + { + //allow relative path if a plane name is specified. + if (isAbsolutePath(path)) + { + const char *relativePath = getRelativePath(path,plane->queryProp("@prefix")); + if (nullptr == relativePath) + throw makeStringExceptionV(-1,"Invalid plane path %s.",path); + path = relativePath; + } + dlfn.setPlaneExternal(plane->queryProp("@name"),path); + } + else + dlfn.setExternal(host,path); //for backward compatibility + dlfn.getExternalFilename(rfn); + + if (checkScopePermissionIfDir) + { + Owned f = createIFile(rfn); + checkScopePermissionIfDir = f->isDirectory()==fileBool::foundYes; + } + checkExternalFileRights(ctx,dlfn,checkScopePermissionIfDir,rd,wr); +} + +static IPropertyTree *checkPlaneOrHost(const char *planeName,const char *host) +{ + if (!isEmptyString(planeName)) + { + Owned plane = getDropZonePlane(planeName); //Only support DropZone for now. + if (!plane) + throw makeStringExceptionV(-1,"DropZone %s not found.",planeName); + return plane.getClear(); + } + SocketEndpoint ep(host); if (ep.isNull()) - throw MakeStringException(-1,"fsMoveExternalFile: Cannot resolve location %s",location); - CDfsLogicalFileName from; - from.setExternal(location,frompath); - CDfsLogicalFileName to; - to.setExternal(location,topath); - checkExternalFileRights(ctx,from,true,true); - checkExternalFileRights(ctx,to,false,true); - RemoteFilename fromrfn; - fromrfn.setPath(ep,frompath); - RemoteFilename torfn; - torfn.setPath(ep,topath); + throw makeStringExceptionV(-1,"Cannot resolve host %s",host); + return nullptr; +} + +static void implementMoveExternalFile(ICodeContext *ctx,const char *location, + const char *frompath,const char *topath,const char *planename) +{ + Owned plane = checkPlaneOrHost(planename,location); + RemoteFilename fromrfn,torfn; + checkExternalFilePath(ctx,plane,location,frompath,true,true,true,fromrfn); + checkExternalFilePath(ctx,plane,location,topath,false,false,true,torfn); + Owned fileto = createIFile(torfn); if (fileto->exists()) throw MakeStringException(-1,"fsMoveExternalFile: Destination %s already exists", topath); @@ -2774,6 +2817,17 @@ FILESERVICES_API void FILESERVICES_CALL fsMoveExternalFile(ICodeContext * ctx,c AuditMessage(ctx,"MoveExternalFile",frompath,topath); } +FILESERVICES_API void FILESERVICES_CALL fsMoveExternalFile(ICodeContext *ctx,const char *location,const char *frompath,const char *topath) +{ + implementMoveExternalFile(ctx,location,frompath,topath,nullptr); +} + +FILESERVICES_API void FILESERVICES_CALL fsMoveExternalFile_v2(ICodeContext *ctx,const char *location, + const char *frompath,const char *topath,const char *planename) +{ + implementMoveExternalFile(ctx,location,frompath,topath,planename); +} + FILESERVICES_API void FILESERVICES_CALL fsDeleteExternalFile(ICodeContext * ctx,const char *location,const char *path) { SocketEndpoint ep(location); @@ -2781,7 +2835,7 @@ FILESERVICES_API void FILESERVICES_CALL fsDeleteExternalFile(ICodeContext * ctx throw MakeStringException(-1,"fsDeleteExternalFile: Cannot resolve location %s",location); CDfsLogicalFileName lfn; lfn.setExternal(location,path); - checkExternalFileRights(ctx,lfn,false,true); + checkExternalFileRights(ctx,lfn,false,false,true); //The path could be a directory. So, it may need to be checked as a scope. Will re-visit this when adding plane name here. RemoteFilename rfn; rfn.setPath(ep,path); Owned file = createIFile(rfn); @@ -2805,7 +2859,7 @@ FILESERVICES_API void FILESERVICES_CALL fsCreateExternalDirectory(ICodeContext if (isPathSepChar(path.charAt(path.length()-1))) path.remove(path.length()-1, 1); lfn.setExternal(location,path); - checkExternalFileRights(ctx,lfn,false,true); + checkExternalFileRights(ctx,lfn,false,false,true); RemoteFilename rfn; rfn.setPath(ep,path); Owned file = createIFile(rfn); diff --git a/plugins/fileservices/fileservices.hpp b/plugins/fileservices/fileservices.hpp index db1c52a049f..432e655a862 100644 --- a/plugins/fileservices/fileservices.hpp +++ b/plugins/fileservices/fileservices.hpp @@ -183,6 +183,7 @@ FILESERVICES_API void FILESERVICES_CALL fsRfsAction(const char *server, const ch FILESERVICES_API char * FILESERVICES_CALL fsfGetHostName(const char *ipaddress); FILESERVICES_API char * FILESERVICES_CALL fsfResolveHostName(const char *hostname); FILESERVICES_API void FILESERVICES_CALL fsMoveExternalFile(ICodeContext * ctx,const char *location,const char *frompath,const char *topath); +FILESERVICES_API void FILESERVICES_CALL fsMoveExternalFile_v2(ICodeContext *ctx,const char *location,const char *frompath,const char *topath,const char *planename); FILESERVICES_API void FILESERVICES_CALL fsDeleteExternalFile(ICodeContext * ctx,const char *location,const char *path); FILESERVICES_API void FILESERVICES_CALL fsCreateExternalDirectory(ICodeContext * ctx,const char *location,const char *path); FILESERVICES_API char * FILESERVICES_CALL fsfGetLogicalFileAttribute(ICodeContext * ctx,const char *lfn,const char *attrname); diff --git a/plugins/proxies/lib_fileservices.ecllib b/plugins/proxies/lib_fileservices.ecllib index 33e8412ce2e..cf1a85c9f39 100644 --- a/plugins/proxies/lib_fileservices.ecllib +++ b/plugins/proxies/lib_fileservices.ecllib @@ -99,7 +99,7 @@ export FileServices := SERVICE : plugin('fileservices'), time RfsAction( const varstring server, const varstring query): c,entrypoint='fsRfsAction'; varstring GetHostName( const varstring ipaddress ): c,entrypoint='fsfGetHostName'; varstring ResolveHostName( const varstring hostname ): c,entrypoint='fsfResolveHostName'; - MoveExternalFile(const varstring location, const varstring frompath, const varstring topath): c,action,context,entrypoint='fsMoveExternalFile'; + MoveExternalFile(const varstring location, const varstring frompath, const varstring topath, const varstring planename=''): c,action,context,entrypoint='fsMoveExternalFile_v2'; DeleteExternalFile(const varstring location, const varstring path): c,action,context,entrypoint='fsDeleteExternalFile'; CreateExternalDirectory(const varstring location, const varstring path): c,action,context,entrypoint='fsCreateExternalDirectory'; varstring GetLogicalFileAttribute(const varstring lfn,const varstring attrname) : c,context,entrypoint='fsfGetLogicalFileAttribute';