XRootD
Loading...
Searching...
No Matches
XrdClFS.cc
Go to the documentation of this file.
1//------------------------------------------------------------------------------
2// Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN)
3// Author: Lukasz Janyst <ljanyst@cern.ch>
4//------------------------------------------------------------------------------
5// This file is part of the XRootD software suite.
6//
7// XRootD is free software: you can redistribute it and/or modify
8// it under the terms of the GNU Lesser General Public License as published by
9// the Free Software Foundation, either version 3 of the License, or
10// (at your option) any later version.
11//
12// XRootD is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU Lesser General Public License
18// along with XRootD. If not, see <http://www.gnu.org/licenses/>.
19//
20// In applying this licence, CERN does not waive the privileges and immunities
21// granted to it by virtue of its status as an Intergovernmental Organization
22// or submit itself to any jurisdiction.
23//------------------------------------------------------------------------------
24
28#include "XrdCl/XrdClURL.hh"
29#include "XrdCl/XrdClLog.hh"
32#include "XrdCl/XrdClUtils.hh"
34#include "XrdCl/XrdClFile.hh"
38#include "XrdSys/XrdSysE2T.hh"
39
40#include <cstdlib>
41#include <cstdio>
42#include <iostream>
43#include <iomanip>
44#include <cmath>
45
46#ifdef HAVE_READLINE
47#include <readline/readline.h>
48#include <readline/history.h>
49#endif
50
51using namespace XrdCl;
52
53//------------------------------------------------------------------------------
54// Build a path
55//------------------------------------------------------------------------------
56XRootDStatus BuildPath( std::string &newPath, Env *env,
57 const std::string &path )
58{
59 if( path.empty() )
61
62 int noCwd = 0;
63 env->GetInt( "NoCWD", noCwd );
64
65 if( path[0] == '/' || noCwd )
66 {
67 newPath = path;
68 return XRootDStatus();
69 }
70
71 std::string cwd = "/";
72 env->GetString( "CWD", cwd );
73 newPath = cwd;
74 newPath += "/";
75 newPath += path;
76
77 //----------------------------------------------------------------------------
78 // Collapse the dots
79 //----------------------------------------------------------------------------
80 std::list<std::string> pathComponents;
81 std::list<std::string>::iterator it;
82 XrdCl::Utils::splitString( pathComponents, newPath, "/" );
83 newPath = "/";
84 for( it = pathComponents.begin(); it != pathComponents.end(); )
85 {
86 if( *it == "." )
87 {
88 it = pathComponents.erase( it );
89 continue;
90 }
91
92 if( *it == ".." )
93 {
94 if( it == pathComponents.begin() )
96 std::list<std::string>::iterator it1 = it;
97 --it1;
98 it = pathComponents.erase( it1 );
99 it = pathComponents.erase( it );
100 continue;
101 }
102 ++it;
103 }
104
105 newPath = "/";
106 for( it = pathComponents.begin(); it != pathComponents.end(); ++it )
107 {
108 newPath += *it;
109 newPath += "/";
110 }
111 if( newPath.length() > 1 )
112 newPath.erase( newPath.length()-1, 1 );
113
114 return XRootDStatus();
115}
116
117//------------------------------------------------------------------------------
118// Convert mode string to uint16_t
119//------------------------------------------------------------------------------
120XRootDStatus ConvertMode( Access::Mode &mode, const std::string &modeStr )
121{
122 if( modeStr.length() != 9 )
124
125 mode = Access::None;
126 for( int i = 0; i < 3; ++i )
127 {
128 if( modeStr[i] == 'r' )
129 mode |= Access::UR;
130 else if( modeStr[i] == 'w' )
131 mode |= Access::UW;
132 else if( modeStr[i] == 'x' )
133 mode |= Access::UX;
134 else if( modeStr[i] != '-' )
136 }
137 for( int i = 3; i < 6; ++i )
138 {
139 if( modeStr[i] == 'r' )
140 mode |= Access::GR;
141 else if( modeStr[i] == 'w' )
142 mode |= Access::GW;
143 else if( modeStr[i] == 'x' )
144 mode |= Access::GX;
145 else if( modeStr[i] != '-' )
147 }
148 for( int i = 6; i < 9; ++i )
149 {
150 if( modeStr[i] == 'r' )
151 mode |= Access::OR;
152 else if( modeStr[i] == 'w' )
153 mode |= Access::OW;
154 else if( modeStr[i] == 'x' )
155 mode |= Access::OX;
156 else if( modeStr[i] != '-' )
158 }
159 return XRootDStatus();
160}
161
162//------------------------------------------------------------------------------
163// Perform a cache operation
164//------------------------------------------------------------------------------
166 Env *env,
167 const FSExecutor::CommandParams &args )
168{
169 //----------------------------------------------------------------------------
170 // Check up the args
171 //----------------------------------------------------------------------------
172 Log *log = DefaultEnv::GetLog();
173 uint32_t argc = args.size();
174
175 if( argc != 3 )
176 {
177 log->Error( AppMsg, "Wrong number of arguments." );
179 "Wrong number of arguments." );
180 }
181
182 if( args[1] != "evict" && args[1] != "fevict")
183 {
184 log->Error( AppMsg, "Invalid cache operation." );
185 return XRootDStatus( stError, errInvalidArgs, 0, "Invalid cache operation." );
186 }
187
188 std::string fullPath;
189 if( !BuildPath( fullPath, env, args[2] ).IsOK() )
190 {
191 log->Error( AppMsg, "Invalid cache path." );
192 return XRootDStatus( stError, errInvalidArgs, 0, "Invalid cache path." );
193 }
194
195 //----------------------------------------------------------------------------
196 // Create the command
197 //----------------------------------------------------------------------------
198 std::string cmd = args[1];
199 cmd.append(" ");
200 cmd.append(fullPath);
201
202 //----------------------------------------------------------------------------
203 // Run the operation
204 //----------------------------------------------------------------------------
205 Buffer *response = 0;
206 XRootDStatus st = fs->SendCache( cmd, response );
207 if( !st.IsOK() )
208 {
209 log->Error( AppMsg, "Unable set cache %s: %s",
210 fullPath.c_str(),
211 st.ToStr().c_str() );
212 return st;
213 }
214
215 if( response )
216 {
217 std::cout << response->ToString() << '\n';
218 }
219
220 delete response;
221
222 return XRootDStatus();
223}
224//------------------------------------------------------------------------------
225// Change current working directory
226//------------------------------------------------------------------------------
228 Env *env,
229 const FSExecutor::CommandParams &args )
230{
231 //----------------------------------------------------------------------------
232 // Check up the args
233 //----------------------------------------------------------------------------
234 Log *log = DefaultEnv::GetLog();
235 if( args.size() != 2 )
236 {
237 log->Error( AppMsg, "Invalid arguments. Expected a path." );
239 }
240
241 //----------------------------------------------------------------------------
242 // cd excludes NoCWD
243 //----------------------------------------------------------------------------
244 env->PutInt( "NoCWD", 0 );
245
246 std::string newPath;
247 if( !BuildPath( newPath, env, args[1] ).IsOK() )
248 {
249 log->Error( AppMsg, "Invalid path." );
251 }
252
253 //----------------------------------------------------------------------------
254 // Check if the path exist and is not a directory
255 //----------------------------------------------------------------------------
256 StatInfo *info;
257 XRootDStatus st = fs->Stat( newPath, info );
258 if( !st.IsOK() )
259 {
260 log->Error( AppMsg, "Unable to stat the path: %s", st.ToStr().c_str() );
261 return st;
262 }
263
264 if( !info->TestFlags( StatInfo::IsDir ) )
265 {
266 log->Error( AppMsg, "%s is not a directory.", newPath.c_str() );
268 }
269
270 env->PutString( "CWD", newPath );
271 delete info;
272 return XRootDStatus();
273}
274
275//------------------------------------------------------------------------------
276// Helper function to calculate number of digits in a number
277//------------------------------------------------------------------------------
278uint32_t nbDigits( uint64_t nb )
279{
280 if( nb == 0 ) return 1;
281 return uint32_t( log10( double(nb) ) + 1);
282}
283
284
285void PrintDirListStatInfo( StatInfo *info, bool hascks = false, uint32_t ownerwidth = 0, uint32_t groupwidth = 0, uint32_t sizewidth = 0 )
286{
287 if( info->ExtendedFormat() )
288 {
289 if( info->TestFlags( StatInfo::IsDir ) )
290 std::cout << "d";
291 else
292 std::cout << "-";
293 std::cout << info->GetModeAsOctString();
294
295 std::cout << " " << std::setw( ownerwidth ) << info->GetOwner();
296 std::cout << " " << std::setw( groupwidth ) << info->GetGroup();
297 std::cout << " " << std::setw( sizewidth ) << info->GetSize();
298 if( hascks && info->HasChecksum() )
299 std::cout << " " << std::setw( sizewidth ) << info->GetChecksum();
300 std::cout << " " << info->GetModTimeAsString() << " ";
301 }
302 else
303 {
304 if( info->TestFlags( StatInfo::IsDir ) )
305 std::cout << "d";
306 else
307 std::cout << "-";
308
309 if( info->TestFlags( StatInfo::IsReadable ) )
310 std::cout << "r";
311 else
312 std::cout << "-";
313
314 if( info->TestFlags( StatInfo::IsWritable ) )
315 std::cout << "w";
316 else
317 std::cout << "-";
318
319 if( info->TestFlags( StatInfo::XBitSet ) )
320 std::cout << "x";
321 else
322 std::cout << "-";
323
324 std::cout << " " << info->GetModTimeAsString();
325
326 uint64_t size = info->GetSize();
327 int width = nbDigits( size ) + 2;
328 if( width < 12 ) width = 12;
329 std::cout << std::setw( width ) << info->GetSize() << " ";
330 }
331}
332
333//------------------------------------------------------------------------------
334// List a directory
335//------------------------------------------------------------------------------
337 Env *env,
338 const FSExecutor::CommandParams &args )
339{
340 //----------------------------------------------------------------------------
341 // Check up the args
342 //----------------------------------------------------------------------------
343 Log *log = DefaultEnv::GetLog();
344 uint32_t argc = args.size();
345 bool stats = false;
346 bool showUrls = false;
347 bool hascks = false;
348 std::string path;
350
351 if( argc > 6 )
352 {
353 log->Error( AppMsg, "Too many arguments." );
355 }
356
357 for( uint32_t i = 1; i < args.size(); ++i )
358 {
359 if( args[i] == "-l" )
360 {
361 stats = true;
362 flags |= DirListFlags::Stat;
363 }
364 else if( args[i] == "-u" )
365 showUrls = true;
366 else if( args[i] == "-R" )
367 {
369 }
370 else if( args[i] == "-D" )
371 {
372 // show duplicates
373 flags &= ~DirListFlags::Merge;
374 }
375 else if( args[i] == "-Z" )
376 {
377 // check if file is a ZIP archive if yes list content
378 flags |= DirListFlags::Zip;
379 }
380 else if( args[i] == "-C" )
381 {
382 // query checksum for each entry in the directory
383 hascks = true;
384 stats = true;
385 flags |= DirListFlags::Cksm;
386 }
387 else
388 path = args[i];
389 }
390
391 if( showUrls )
392 // we don't merge the duplicate entries
393 // in case we print the full URL
394 flags &= ~DirListFlags::Merge;
395
396 std::string newPath = "/";
397 if( path.empty() )
398 env->GetString( "CWD", newPath );
399 else
400 {
401 if( !BuildPath( newPath, env, path ).IsOK() )
402 {
403 log->Error( AppMsg, "Invalid arguments. Invalid path." );
405 }
406 }
407
408 //----------------------------------------------------------------------------
409 // Stat the entry so we know if it is a file or a directory
410 //----------------------------------------------------------------------------
411 log->Debug( AppMsg, "Attempting to stat: %s", newPath.c_str() );
412
413 StatInfo *info = 0;
414 XRootDStatus st = fs->Stat( newPath, info );
415 std::unique_ptr<StatInfo> ptr( info );
416 if( !st.IsOK() )
417 {
418 log->Error( AppMsg, "Unable to stat the path: %s", st.ToStr().c_str() );
419 return st;
420 }
421
422 if( !info->TestFlags( StatInfo::IsDir ) &&
423 !( flags & DirListFlags::Zip ) )
424 {
425 if( stats )
426 PrintDirListStatInfo( info );
427
428 if( showUrls )
429 {
430 std::string url;
431 fs->GetProperty( "LastURL", url );
432 std::cout << url;
433 }
434 std::cout << newPath << std::endl;
435 return XRootDStatus();
436 }
437
438
439 //----------------------------------------------------------------------------
440 // Ask for the list
441 //----------------------------------------------------------------------------
442 log->Debug( AppMsg, "Attempting to list: %s", newPath.c_str() );
443
444 DirectoryList *list;
445 st = fs->DirList( newPath, flags, list );
446 if( !st.IsOK() )
447 {
448 log->Error( AppMsg, "Unable to list the path: %s", st.ToStr().c_str() );
449 return st;
450 }
451
452 if( st.code == suPartial )
453 {
454 std::cerr << "[!] Some of the requests failed. The result may be ";
455 std::cerr << "incomplete." << std::endl;
456 }
457
458 uint32_t ownerwidth = 0, groupwidth = 0, sizewidth = 0, ckswidth = 0;
460 for( it = list->Begin(); it != list->End() && stats; ++it )
461 {
462 StatInfo *info = (*it)->GetStatInfo();
463 if( ownerwidth < info->GetOwner().size() )
464 ownerwidth = info->GetOwner().size();
465 if( groupwidth < info->GetGroup().size() )
466 groupwidth = info->GetGroup().size();
467 if( sizewidth < nbDigits( info->GetSize() ) )
468 sizewidth = nbDigits( info->GetSize() );
469 if( ckswidth < info->GetChecksum().size() )
470 ckswidth = info->GetChecksum().size();
471 }
472
473 //----------------------------------------------------------------------------
474 // Print the results
475 //----------------------------------------------------------------------------
476 for( it = list->Begin(); it != list->End(); ++it )
477 {
478 if( stats )
479 {
480 StatInfo *info = (*it)->GetStatInfo();
481 if( !info )
482 std::cout << "---- 0000-00-00 00:00:00 ? ";
483 else
484 PrintDirListStatInfo( info, hascks, ownerwidth, groupwidth, sizewidth );
485 }
486 if( showUrls )
487 std::cout << "root://" << (*it)->GetHostAddress() << "/";
488 std::cout << list->GetParentName() << (*it)->GetName() << std::endl;
489 }
490 delete list;
491 return XRootDStatus();
492}
493
494//------------------------------------------------------------------------------
495// Create a directory
496//------------------------------------------------------------------------------
498 Env *env,
499 const FSExecutor::CommandParams &args )
500{
501 //----------------------------------------------------------------------------
502 // Check up the args
503 //----------------------------------------------------------------------------
504 Log *log = DefaultEnv::GetLog();
505 uint32_t argc = args.size();
506
507 if( argc < 2 || argc > 4 )
508 {
509 log->Error( AppMsg, "Too few arguments." );
511 }
512
515 std::string modeStr = "rwxr-x---";
516 std::string path = "";
517
518 for( uint32_t i = 1; i < args.size(); ++i )
519 {
520 if( args[i] == "-p" )
521 flags |= MkDirFlags::MakePath;
522 else if( !args[i].compare( 0, 2, "-m" ) )
523 modeStr = args[i].substr( 2, 9 );
524 else
525 path = args[i];
526 }
527
528 XRootDStatus st = ConvertMode( mode, modeStr );
529 if( !st.IsOK() )
530 {
531 log->Error( AppMsg, "Invalid mode string." );
532 return st;
533 }
534
535 std::string newPath;
536 if( !BuildPath( newPath, env, path ).IsOK() )
537 {
538 log->Error( AppMsg, "Invalid path." );
540 }
541
542 //----------------------------------------------------------------------------
543 // Run the query
544 //----------------------------------------------------------------------------
545 st = fs->MkDir( newPath, flags, mode );
546 if( !st.IsOK() )
547 {
548 log->Error( AppMsg, "Unable create directory %s: %s",
549 newPath.c_str(),
550 st.ToStr().c_str() );
551 return st;
552 }
553
554 return XRootDStatus();
555}
556
557//------------------------------------------------------------------------------
558// Remove a directory
559//------------------------------------------------------------------------------
561 Env *env,
562 const FSExecutor::CommandParams &args )
563{
564 //----------------------------------------------------------------------------
565 // Check up the args
566 //----------------------------------------------------------------------------
567 Log *log = DefaultEnv::GetLog();
568 uint32_t argc = args.size();
569
570 if( argc != 2 )
571 {
572 log->Error( AppMsg, "Wrong number of arguments." );
574 }
575
576 std::string fullPath;
577 if( !BuildPath( fullPath, env, args[1] ).IsOK() )
578 {
579 log->Error( AppMsg, "Invalid path." );
581 }
582
583 //----------------------------------------------------------------------------
584 // Run the query
585 //----------------------------------------------------------------------------
586 XRootDStatus st = query->RmDir( fullPath );
587 if( !st.IsOK() )
588 {
589 log->Error( AppMsg, "Unable remove directory %s: %s",
590 fullPath.c_str(),
591 st.ToStr().c_str() );
592 return st;
593 }
594
595 return XRootDStatus();
596}
597
598//------------------------------------------------------------------------------
599// Move a file or directory
600//------------------------------------------------------------------------------
602 Env *env,
603 const FSExecutor::CommandParams &args )
604{
605 //----------------------------------------------------------------------------
606 // Check up the args
607 //----------------------------------------------------------------------------
608 Log *log = DefaultEnv::GetLog();
609 uint32_t argc = args.size();
610
611 if( argc != 3 )
612 {
613 log->Error( AppMsg, "Wrong number of arguments." );
615 }
616
617 std::string fullPath1;
618 if( !BuildPath( fullPath1, env, args[1] ).IsOK() )
619 {
620 log->Error( AppMsg, "Invalid source path." );
622 }
623
624 std::string fullPath2;
625 if( !BuildPath( fullPath2, env, args[2] ).IsOK() )
626 {
627 log->Error( AppMsg, "Invalid destination path." );
629 }
630
631 if( is_subdirectory(fullPath1, fullPath2) )
633 "cannot move directory to a subdirectory of itself." );
634
635 //----------------------------------------------------------------------------
636 // Run the query
637 //----------------------------------------------------------------------------
638 XRootDStatus st = fs->Mv( fullPath1, fullPath2 );
639 if( !st.IsOK() )
640 {
641 log->Error( AppMsg, "Unable move %s to %s: %s",
642 fullPath1.c_str(), fullPath2.c_str(),
643 st.ToStr().c_str() );
644 return st;
645 }
646
647 return XRootDStatus();
648}
649
650//------------------------------------------------------------------------------
651// Remove a file
652//------------------------------------------------------------------------------
654 Env *env,
655 const FSExecutor::CommandParams &args )
656{
657 //----------------------------------------------------------------------------
658 // Check up the args
659 //----------------------------------------------------------------------------
660 Log *log = DefaultEnv::GetLog();
661 uint32_t argc = args.size();
662
663 if( argc < 2 )
664 {
665 log->Error( AppMsg, "Wrong number of arguments." );
667 }
668
669 struct print_t
670 {
671 void print( const std::string &msg )
672 {
673 std::unique_lock<std::mutex> lck( mtx );
674 std::cout << msg << '\n';
675 }
676 std::mutex mtx;
677 };
678 std::shared_ptr<print_t> print;
679 if( argc - 1 > 0 )
680 print = std::make_shared<print_t>();
681
682 std::vector<Pipeline> rms;
683 rms.reserve( argc - 1 );
684 for( size_t i = 1; i < argc; ++i )
685 {
686 std::string fullPath;
687 if( !BuildPath( fullPath, env, args[i] ).IsOK() )
688 {
689 log->Error( AppMsg, "Invalid path: %s", fullPath.c_str() );
691 }
692 rms.emplace_back( Rm( fs, fullPath ) >>
693 [log, fullPath, print]( XRootDStatus &st )
694 {
695 if( !st.IsOK() )
696 {
697 log->Error( AppMsg, "Unable remove %s: %s",
698 fullPath.c_str(),
699 st.ToStr().c_str() );
700 }
701 if( print )
702 {
703 print->print( "rm " + fullPath + " : " + st.ToString() );
704 }
705 } );
706 }
707
708 //----------------------------------------------------------------------------
709 // Run the query:
710 // Parallel() will take the vector of Pipeline by reference and empty the
711 // vector, so rms.size() will change after the call.
712 //----------------------------------------------------------------------------
713 const size_t rs = rms.size();
714 XRootDStatus st = WaitFor( Parallel( rms ).AtLeast( rs ) );
715 if( !st.IsOK() )
716 return st;
717
718 return XRootDStatus();
719}
720
721//------------------------------------------------------------------------------
722// Truncate a file
723//------------------------------------------------------------------------------
725 Env *env,
726 const FSExecutor::CommandParams &args )
727{
728 //----------------------------------------------------------------------------
729 // Check up the args
730 //----------------------------------------------------------------------------
731 Log *log = DefaultEnv::GetLog();
732 uint32_t argc = args.size();
733
734 if( argc != 3 )
735 {
736 log->Error( AppMsg, "Wrong number of arguments." );
738 }
739
740 std::string fullPath;
741 if( !BuildPath( fullPath, env, args[1] ).IsOK() )
742 {
743 log->Error( AppMsg, "Invalid path." );
745 }
746
747 char *result;
748 uint64_t size = ::strtoll( args[2].c_str(), &result, 0 );
749 if( *result != 0 )
750 {
751 log->Error( AppMsg, "Size parameter needs to be an integer" );
753 }
754
755 //----------------------------------------------------------------------------
756 // Run the query
757 //----------------------------------------------------------------------------
758 XRootDStatus st = fs->Truncate( fullPath, size );
759 if( !st.IsOK() )
760 {
761 log->Error( AppMsg, "Unable truncate %s: %s",
762 fullPath.c_str(),
763 st.ToStr().c_str() );
764 return st;
765 }
766
767 return XRootDStatus();
768}
769
770//------------------------------------------------------------------------------
771// Change the access rights to a file
772//------------------------------------------------------------------------------
774 Env *env,
775 const FSExecutor::CommandParams &args )
776{
777 //----------------------------------------------------------------------------
778 // Check up the args
779 //----------------------------------------------------------------------------
780 Log *log = DefaultEnv::GetLog();
781 uint32_t argc = args.size();
782
783 if( argc != 3 )
784 {
785 log->Error( AppMsg, "Wrong number of arguments." );
787 }
788
789 std::string fullPath;
790 if( !BuildPath( fullPath, env, args[1] ).IsOK() )
791 {
792 log->Error( AppMsg, "Invalid path." );
794 }
795
797 XRootDStatus st = ConvertMode( mode, args[2] );
798 if( !st.IsOK() )
799 {
800 log->Error( AppMsg, "Invalid mode string." );
801 return st;
802 }
803
804 //----------------------------------------------------------------------------
805 // Run the query
806 //----------------------------------------------------------------------------
807 st = fs->ChMod( fullPath, mode );
808 if( !st.IsOK() )
809 {
810 log->Error( AppMsg, "Unable change mode of %s: %s",
811 fullPath.c_str(),
812 st.ToStr().c_str() );
813 return st;
814 }
815
816 return XRootDStatus();
817}
818
819//------------------------------------------------------------------------------
820// Locate a path
821//------------------------------------------------------------------------------
823 Env *env,
824 const FSExecutor::CommandParams &args )
825{
826 //----------------------------------------------------------------------------
827 // Check up the args
828 //----------------------------------------------------------------------------
829 Log *log = DefaultEnv::GetLog();
830 uint32_t argc = args.size();
831
832 if( argc > 4 )
833 {
834 log->Error( AppMsg, "Wrong number of arguments." );
836 }
837
839 std::string path;
840 bool hasPath = false;
841 bool doDeepLocate = false;
842 for( uint32_t i = 1; i < argc; ++i )
843 {
844 if( args[i] == "-n" )
845 flags |= OpenFlags::NoWait;
846 else if( args[i] == "-r" )
847 flags |= OpenFlags::Refresh;
848 else if( args[i] == "-m" || args[i] == "-h" )
849 flags |= OpenFlags::PrefName;
850 else if( args[i] == "-i" )
851 flags |= OpenFlags::Force;
852 else if( args[i] == "-d" )
853 doDeepLocate = true;
854 else if( args[i] == "-p" )
855 {
856 Env *env = DefaultEnv::GetEnv();
857 env->PutInt( "PreserveLocateTried", 0 );
858 }
859 else if( !hasPath )
860 {
861 path = args[i];
862 hasPath = true;
863 }
864 else
865 {
866 log->Error( AppMsg, "Invalid argument: %s.", args[i].c_str() );
868 }
869 }
870
871 std::string fullPath;
872 if( path[0] == '*' )
873 fullPath = path;
874 else
875 {
876 if( !BuildPath( fullPath, env, path ).IsOK() )
877 {
878 log->Error( AppMsg, "Invalid path." );
880 }
881 }
882
883 //----------------------------------------------------------------------------
884 // Run the query
885 //----------------------------------------------------------------------------
886 LocationInfo *info = 0;
887 XRootDStatus st;
888 if( doDeepLocate )
889 st = fs->DeepLocate( fullPath, flags, info );
890 else
891 st = fs->Locate( fullPath, flags, info );
892
893 if( !st.IsOK() )
894 {
895 log->Error( AppMsg, "Unable locate %s: %s",
896 fullPath.c_str(),
897 st.ToStr().c_str() );
898 return st;
899 }
900
901 //----------------------------------------------------------------------------
902 // Print the result
903 //----------------------------------------------------------------------------
904 if( st.code == suPartial )
905 {
906 std::cerr << "[!] Some of the requests failed. The result may be ";
907 std::cerr << "incomplete." << std::endl;
908 }
909
911 for( it = info->Begin(); it != info->End(); ++it )
912 {
913 std::cout << it->GetAddress() << " ";
914 switch( it->GetType() )
915 {
917 std::cout << "Manager ";
918 break;
920 std::cout << "ManagerPending ";
921 break;
923 std::cout << "Server ";
924 break;
926 std::cout << "ServerPending ";
927 break;
928 default:
929 std::cout << "Unknown ";
930 };
931
932 switch( it->GetAccessType() )
933 {
935 std::cout << "Read";
936 break;
938 std::cout << "ReadWrite ";
939 break;
940 default:
941 std::cout << "Unknown ";
942 };
943 std::cout << std::endl;
944 }
945
946 delete info;
947 return XRootDStatus();
948}
949
950//------------------------------------------------------------------------------
951// Process stat query
952//------------------------------------------------------------------------------
953XRootDStatus ProcessStatQuery( StatInfo &info, const std::string &query )
954{
955 Log *log = DefaultEnv::GetLog();
956
957 //----------------------------------------------------------------------------
958 // Process the query
959 //----------------------------------------------------------------------------
960 bool isOrQuery = false;
961 bool status = true;
962 if( query.find( '|' ) != std::string::npos )
963 {
964 isOrQuery = true;
965 status = false;
966 }
967 std::vector<std::string> queryFlags;
968 if( isOrQuery )
969 Utils::splitString( queryFlags, query, "|" );
970 else
971 Utils::splitString( queryFlags, query, "&" );
972
973 //----------------------------------------------------------------------------
974 // Initialize flag translation map and check the input flags
975 //----------------------------------------------------------------------------
976 std::map<std::string, StatInfo::Flags> flagMap;
977 flagMap["XBitSet"] = StatInfo::XBitSet;
978 flagMap["IsDir"] = StatInfo::IsDir;
979 flagMap["Other"] = StatInfo::Other;
980 flagMap["Offline"] = StatInfo::Offline;
981 flagMap["POSCPending"] = StatInfo::POSCPending;
982 flagMap["IsReadable"] = StatInfo::IsReadable;
983 flagMap["IsWritable"] = StatInfo::IsWritable;
984 flagMap["BackUpExists"] = StatInfo::BackUpExists;
985
986 std::vector<std::string>::iterator it;
987 for( it = queryFlags.begin(); it != queryFlags.end(); ++it )
988 if( flagMap.find( *it ) == flagMap.end() )
989 {
990 log->Error( AppMsg, "Flag '%s' is not recognized.", it->c_str() );
992 }
993
994 //----------------------------------------------------------------------------
995 // Process the query
996 //----------------------------------------------------------------------------
997 if( isOrQuery )
998 {
999 for( it = queryFlags.begin(); it != queryFlags.end(); ++it )
1000 if( info.TestFlags( flagMap[*it] ) )
1001 return XRootDStatus();
1002 }
1003 else
1004 {
1005 for( it = queryFlags.begin(); it != queryFlags.end(); ++it )
1006 if( !info.TestFlags( flagMap[*it] ) )
1008 }
1009
1010 if( status )
1011 return XRootDStatus();
1013}
1014
1015//------------------------------------------------------------------------------
1016// Stat a path
1017//------------------------------------------------------------------------------
1019 Env *env,
1020 const FSExecutor::CommandParams &args )
1021{
1022 //----------------------------------------------------------------------------
1023 // Check up the args
1024 //----------------------------------------------------------------------------
1025 Log *log = DefaultEnv::GetLog();
1026 uint32_t argc = args.size();
1027
1028 if( argc < 2 )
1029 {
1030 log->Error( AppMsg, "Wrong number of arguments." );
1032 }
1033
1034 std::vector<std::string> paths;
1035 std::string query;
1036
1037 for( uint32_t i = 1; i < args.size(); ++i )
1038 {
1039 if( args[i] == "-q" )
1040 {
1041 if( i < args.size()-1 )
1042 {
1043 query = args[i+1];
1044 ++i;
1045 }
1046 else
1047 {
1048 log->Error( AppMsg, "Parameter '-q' requires an argument." );
1050 }
1051 }
1052 else
1053 paths.emplace_back( args[i] );
1054 }
1055
1056 std::vector<XrdCl::Pipeline> stats;
1057 std::vector<std::tuple<std::future<StatInfo>, std::string>> results;
1058 for( auto &path : paths )
1059 {
1060 std::string fullPath;
1061 if( !BuildPath( fullPath, env, path ).IsOK() )
1062 {
1063 log->Error( AppMsg, "Invalid path." );
1065 }
1066 std::future<XrdCl::StatInfo> ftr;
1067 stats.emplace_back( XrdCl::Stat( fs, fullPath ) >> ftr );
1068 results.emplace_back( std::move( ftr ), std::move( fullPath ) );
1069 }
1070
1071 //----------------------------------------------------------------------------
1072 // Run the query
1073 //----------------------------------------------------------------------------
1074 XrdCl::Async( XrdCl::Parallel( stats ) );
1075
1076 //----------------------------------------------------------------------------
1077 // Print the result
1078 //----------------------------------------------------------------------------
1080 for( auto &tpl : results )
1081 {
1082 auto &ftr = std::get<0>( tpl );
1083 auto &fullPath = std::get<1>( tpl );
1084 std::cout << std::endl;
1085 try
1086 {
1087 XrdCl::StatInfo info( ftr.get() );
1088 std::string flags;
1089
1090 if( info.TestFlags( StatInfo::XBitSet ) )
1091 flags += "XBitSet|";
1092 if( info.TestFlags( StatInfo::IsDir ) )
1093 flags += "IsDir|";
1094 if( info.TestFlags( StatInfo::Other ) )
1095 flags += "Other|";
1096 if( info.TestFlags( StatInfo::Offline ) )
1097 flags += "Offline|";
1098 if( info.TestFlags( StatInfo::POSCPending ) )
1099 flags += "POSCPending|";
1100 if( info.TestFlags( StatInfo::IsReadable ) )
1101 flags += "IsReadable|";
1102 if( info.TestFlags( StatInfo::IsWritable ) )
1103 flags += "IsWritable|";
1104 if( info.TestFlags( StatInfo::BackUpExists ) )
1105 flags += "BackUpExists|";
1106
1107 if( !flags.empty() )
1108 flags.erase( flags.length()-1, 1 );
1109
1110 std::cout << "Path: " << fullPath << std::endl;
1111 std::cout << "Id: " << info.GetId() << std::endl;
1112 std::cout << "Size: " << info.GetSize() << std::endl;
1113 std::cout << "MTime: " << info.GetModTimeAsString() << std::endl;
1114 // if extended stat information is available we can print also
1115 // change time and access time
1116 if( info.ExtendedFormat() )
1117 {
1118 std::cout << "CTime: " << info.GetChangeTimeAsString() << std::endl;
1119 std::cout << "ATime: " << info.GetAccessTimeAsString() << std::endl;
1120 }
1121 std::cout << "Flags: " << info.GetFlags() << " (" << flags << ")";
1122
1123 // check if extended stat information is available
1124 if( info.ExtendedFormat() )
1125 {
1126 std::cout << "\nMode: " << info.GetModeAsString() << std::endl;
1127 std::cout << "Owner: " << info.GetOwner() << std::endl;
1128 std::cout << "Group: " << info.GetGroup();
1129 }
1130
1131 std::cout << std::endl;
1132
1133 if( query.length() != 0 )
1134 {
1135 XRootDStatus s = ProcessStatQuery( info, query );
1136 if( !s.IsOK() )
1137 st = s;
1138 std::cout << "Query: " << query << " " << std::endl;
1139 }
1140 }
1141 catch( XrdCl::PipelineException &ex )
1142 {
1143 st = ex.GetError();
1144 log->Error( AppMsg, "Unable stat %s: %s", fullPath.c_str(), st.ToStr().c_str() );
1145 }
1146 }
1147
1148 return st;
1149}
1150
1151//------------------------------------------------------------------------------
1152// Stat a VFS
1153//------------------------------------------------------------------------------
1155 Env *env,
1156 const FSExecutor::CommandParams &args )
1157{
1158 //----------------------------------------------------------------------------
1159 // Check up the args
1160 //----------------------------------------------------------------------------
1161 Log *log = DefaultEnv::GetLog();
1162 uint32_t argc = args.size();
1163
1164 if( argc != 2 )
1165 {
1166 log->Error( AppMsg, "Wrong number of arguments." );
1168 }
1169
1170 std::string fullPath;
1171 if( !BuildPath( fullPath, env, args[1] ).IsOK() )
1172 {
1173 log->Error( AppMsg, "Invalid path." );
1175 }
1176
1177 //----------------------------------------------------------------------------
1178 // Run the query
1179 //----------------------------------------------------------------------------
1180 StatInfoVFS *info = 0;
1181 XRootDStatus st = fs->StatVFS( fullPath, info );
1182
1183 if( !st.IsOK() )
1184 {
1185 log->Error( AppMsg, "Unable stat VFS at %s: %s",
1186 fullPath.c_str(),
1187 st.ToStr().c_str() );
1188 return st;
1189 }
1190
1191 //----------------------------------------------------------------------------
1192 // Print the result
1193 //----------------------------------------------------------------------------
1194 std::cout << "Path: ";
1195 std::cout << fullPath << std::endl;
1196 std::cout << "Nodes with RW space: ";
1197 std::cout << info->GetNodesRW() << std::endl;
1198 std::cout << "Size of largest RW space (MB): ";
1199 std::cout << info->GetFreeRW() << std::endl;
1200 std::cout << "Utilization of RW space (%): ";
1201 std::cout << (uint16_t)info->GetUtilizationRW() << std::endl;
1202 std::cout << "Nodes with staging space: ";
1203 std::cout << info->GetNodesStaging() << std::endl;
1204 std::cout << "Size of largest staging space (MB): ";
1205 std::cout << info->GetFreeStaging() << std::endl;
1206 std::cout << "Utilization of staging space (%): ";
1207 std::cout << (uint16_t)info->GetUtilizationStaging() << std::endl;
1208
1209 delete info;
1210 return XRootDStatus();
1211}
1212
1213//------------------------------------------------------------------------------
1214// Query the server
1215//------------------------------------------------------------------------------
1217 Env *env,
1218 const FSExecutor::CommandParams &args )
1219{
1220 //----------------------------------------------------------------------------
1221 // Check up the args
1222 //----------------------------------------------------------------------------
1223 Log *log = DefaultEnv::GetLog();
1224 uint32_t argc = args.size();
1225
1226 if( !( argc >= 3 ) )
1227 {
1228 log->Error( AppMsg, "Wrong number of arguments." );
1230 }
1231
1232 QueryCode::Code qCode;
1233 if( args[1] == "config" )
1234 qCode = QueryCode::Config;
1235 else if( args[1] == "checksumcancel" )
1237 else if( args[1] == "checksum" )
1238 qCode = QueryCode::Checksum;
1239 else if( args[1] == "opaque" )
1240 qCode = QueryCode::Opaque;
1241 else if( args[1] == "opaquefile" )
1242 qCode = QueryCode::OpaqueFile;
1243 else if( args[1] == "prepare" )
1244 qCode = QueryCode::Prepare;
1245 else if( args[1] == "space" )
1246 qCode = QueryCode::Space;
1247 else if( args[1] == "stats" )
1248 qCode = QueryCode::Stats;
1249 else if( args[1] == "xattr" )
1250 qCode = QueryCode::XAttr;
1251 else
1252 {
1253 log->Error( AppMsg, "Invalid query code." );
1255 }
1256
1257 if( !( qCode & QueryCode::Prepare ) && argc != 3 )
1258 {
1259 log->Error( AppMsg, "Wrong number of arguments." );
1261 }
1262
1263 std::string strArg = args[2];
1264 if( qCode & QueryCode::Prepare )
1265 {
1266 // strArg is supposed to contain already the request ID
1267
1268 for( size_t i = 3; i < args.size(); ++i )
1269 {
1270 std::string path = args[i];
1271 if( !BuildPath( path, env, path ).IsOK() )
1272 {
1273 log->Error( AppMsg, "Invalid path." );
1275 }
1276 // we use new line character as delimiter
1277 strArg += '\n';
1278 strArg += path;
1279 }
1280 }
1281 else
1282 {
1283 std::string strArg = args[2];
1284 if( qCode == QueryCode::ChecksumCancel ||
1285 qCode == QueryCode::Checksum ||
1286 qCode == QueryCode::XAttr )
1287 {
1288 if( !BuildPath( strArg, env, args[2] ).IsOK() )
1289 {
1290 log->Error( AppMsg, "Invalid path." );
1292 }
1293 }
1294 }
1295
1296 //----------------------------------------------------------------------------
1297 // Run the query
1298 //----------------------------------------------------------------------------
1299 Buffer arg( strArg.size() );
1300 arg.FromString( strArg );
1301 Buffer *response = 0;
1302 XRootDStatus st = fs->Query( qCode, arg, response );
1303
1304 if( !st.IsOK() )
1305 {
1306 log->Error( AppMsg, "Unable run query %s: %s",
1307 args[1].c_str(),
1308 st.ToStr().c_str() );
1309 return st;
1310 }
1311
1312 //----------------------------------------------------------------------------
1313 // Print the result
1314 //----------------------------------------------------------------------------
1315 std::cout << response->ToString() << std::endl;
1316 delete response;
1317 return XRootDStatus();
1318}
1319
1320//------------------------------------------------------------------------------
1321// Query the server
1322//------------------------------------------------------------------------------
1324 Env *env,
1325 const FSExecutor::CommandParams &args )
1326{
1327 //----------------------------------------------------------------------------
1328 // Check up the args
1329 //----------------------------------------------------------------------------
1330 Log *log = DefaultEnv::GetLog();
1331 uint32_t argc = args.size();
1332
1333 if( argc < 2 )
1334 {
1335 log->Error( AppMsg, "Wrong number of arguments." );
1337 }
1338
1340 std::vector<std::string> files;
1341 uint8_t priority = 0;
1342 std::string reqid;
1343
1344 for( uint32_t i = 1; i < args.size(); ++i )
1345 {
1346 if( args[i] == "-p" )
1347 {
1348 if( i < args.size()-1 )
1349 {
1350 char *result;
1351 int32_t param = ::strtol( args[i+1].c_str(), &result, 0 );
1352 if( *result != 0 || param > 3 || param < 0 )
1353 {
1354 log->Error( AppMsg, "Size priotiry needs to be an integer between 0 "
1355 "and 3" );
1357 }
1358 priority = (uint8_t)param;
1359 ++i;
1360 }
1361 else
1362 {
1363 log->Error( AppMsg, "Parameter '-p' requires an argument." );
1365 }
1366 }
1367 else if( args[i] == "-c" )
1368 flags |= PrepareFlags::Colocate;
1369 else if( args[i] == "-f" )
1370 flags |= PrepareFlags::Fresh;
1371 else if( args[i] == "-s" )
1372 flags |= PrepareFlags::Stage;
1373 else if( args[i] == "-w" )
1374 flags |= PrepareFlags::WriteMode;
1375 else if( args[i] == "-e" )
1376 flags |= PrepareFlags::Evict;
1377 else if( args[i] == "-a" )
1378 {
1379 flags |= PrepareFlags::Cancel;
1380 if( i < args.size()-1 )
1381 {
1382 // by convention the request ID appears as the the first token
1383 // in the list of files
1384 files.push_back( args[i+1] );
1385 ++i;
1386 }
1387 else
1388 {
1389 log->Error( AppMsg, "Parameter '-a' requires an argument." );
1391 }
1392 }
1393 else
1394 files.push_back( args[i] );
1395 }
1396
1397 if( files.empty() )
1398 {
1399 log->Error( AppMsg, "Filename missing." );
1401 }
1402
1403 //----------------------------------------------------------------------------
1404 // Run the command
1405 //----------------------------------------------------------------------------
1406 Buffer *response = 0;
1407 XRootDStatus st = fs->Prepare( files, flags, priority, response );
1408 if( !st.IsOK() )
1409 {
1410 log->Error( AppMsg, "Prepare request failed: %s", st.ToStr().c_str() );
1411 return st;
1412 }
1413
1414 if( ( flags & PrepareFlags::Stage ) && response )
1415 {
1416 std::cout << response->ToString() << '\n';
1417 }
1418
1419 delete response;
1420 return XRootDStatus();
1421}
1422
1423//------------------------------------------------------------------------------
1424// Copy progress handler
1425//------------------------------------------------------------------------------
1427{
1428 public:
1429 //--------------------------------------------------------------------------
1430 // Constructor
1431 //--------------------------------------------------------------------------
1432 ProgressDisplay(): pBytesProcessed(0), pBytesTotal(0), pPrevious(0)
1433 {}
1434
1435 //--------------------------------------------------------------------------
1436 // End job
1437 //--------------------------------------------------------------------------
1438 virtual void EndJob( uint16_t jobNum, const XrdCl::PropertyList *results )
1439 {
1440 JobProgress( jobNum, pBytesProcessed, pBytesTotal );
1441 std::cerr << std::endl;
1442 }
1443
1444 //--------------------------------------------------------------------------
1445 // Job progress
1446 //--------------------------------------------------------------------------
1447 virtual void JobProgress( uint16_t jobNum,
1448 uint64_t bytesProcessed,
1449 uint64_t bytesTotal )
1450 {
1451 pBytesProcessed = bytesProcessed;
1452 pBytesTotal = bytesTotal;
1453
1454 time_t now = time(0);
1455 if( (now - pPrevious < 1) && (bytesProcessed != bytesTotal) )
1456 return;
1457 pPrevious = now;
1458
1459 std::cerr << "\r";
1460 std::cerr << "Progress: ";
1461 std::cerr << XrdCl::Utils::BytesToString(bytesProcessed) << "B ";
1462
1463 if( bytesTotal )
1464 std::cerr << "(" << bytesProcessed*100/bytesTotal << "%)";
1465
1466 std::cerr << std::flush;
1467 }
1468
1469 private:
1470 uint64_t pBytesProcessed;
1471 uint64_t pBytesTotal;
1472 time_t pPrevious;
1473};
1474
1475//------------------------------------------------------------------------------
1476// Cat a file
1477//------------------------------------------------------------------------------
1479 Env *env,
1480 const FSExecutor::CommandParams &args )
1481{
1482 //----------------------------------------------------------------------------
1483 // Check up the args
1484 //----------------------------------------------------------------------------
1485 Log *log = DefaultEnv::GetLog();
1486 uint32_t argc = args.size();
1487
1488 if( argc < 2 )
1489 {
1490 log->Error( AppMsg, "Wrong number of arguments." );
1492 }
1493
1494 std::string server;
1495 env->GetString( "ServerURL", server );
1496 if( server.empty() )
1497 {
1498 log->Error( AppMsg, "Invalid address: \"%s\".", server.c_str() );
1500 }
1501
1502 std::vector<std::string> remotes;
1503 std::string local;
1504
1505 for( uint32_t i = 1; i < args.size(); ++i )
1506 {
1507 if( args[i] == "-o" )
1508 {
1509 if( i < args.size()-1 )
1510 {
1511 local = args[i+1];
1512 ++i;
1513 }
1514 else
1515 {
1516 log->Error( AppMsg, "Parameter '-o' requires an argument." );
1518 }
1519 }
1520 else
1521 remotes.emplace_back( args[i] );
1522 }
1523
1524 if( !local.empty() && remotes.size() > 1 )
1525 {
1526 log->Error( AppMsg, "If '-o' is used only can be used with only one remote file." );
1528 }
1529
1530 std::vector<URL> remoteUrls;
1531 remoteUrls.reserve( remotes.size() );
1532 for( auto &remote : remotes )
1533 {
1534 std::string remoteFile;
1535 if( !BuildPath( remoteFile, env, remote ).IsOK() )
1536 {
1537 log->Error( AppMsg, "Invalid path." );
1539 }
1540
1541 remoteUrls.emplace_back( server );
1542 remoteUrls.back().SetPath( remoteFile );
1543 }
1544
1545 //----------------------------------------------------------------------------
1546 // Fetch the data
1547 //----------------------------------------------------------------------------
1548 CopyProgressHandler *handler = 0; ProgressDisplay d;
1549 CopyProcess process;
1550 std::vector<PropertyList> props( remoteUrls.size() ), results( remoteUrls.size() );
1551
1552 for( size_t i = 0; i < remoteUrls.size(); ++i )
1553 {
1554 props[i].Set( "source", remoteUrls[i].GetURL() );
1555 if( !local.empty() )
1556 {
1557 props[i].Set( "target", std::string( "file://" ) + local );
1558 handler = &d;
1559 }
1560 else
1561 props[i].Set( "target", "stdio://-" );
1562
1563 props[i].Set( "dynamicSource", true );
1564
1565 XRootDStatus st = process.AddJob( props[i], &results[i] );
1566 if( !st.IsOK() )
1567 {
1568 log->Error( AppMsg, "Job adding failed: %s.", st.ToStr().c_str() );
1569 return st;
1570 }
1571 }
1572
1573 XRootDStatus st = process.Prepare();
1574 if( !st.IsOK() )
1575 {
1576 log->Error( AppMsg, "Copy preparation failed: %s.", st.ToStr().c_str() );
1577 return st;
1578 }
1579
1580 st = process.Run(handler);
1581 if( !st.IsOK() )
1582 {
1583 log->Error( AppMsg, "Cope process failed: %s.", st.ToStr().c_str() );
1584 return st;
1585 }
1586
1587 return XRootDStatus();
1588}
1589
1590//------------------------------------------------------------------------------
1591// Tail a file
1592//------------------------------------------------------------------------------
1594 Env *env,
1595 const FSExecutor::CommandParams &args )
1596{
1597 //----------------------------------------------------------------------------
1598 // Check up the args
1599 //----------------------------------------------------------------------------
1600 Log *log = DefaultEnv::GetLog();
1601 uint32_t argc = args.size();
1602
1603 if( argc < 2 || argc > 5 )
1604 {
1605 log->Error( AppMsg, "Wrong number of arguments." );
1607 }
1608
1609 std::string server;
1610 env->GetString( "ServerURL", server );
1611 if( server.empty() )
1612 {
1613 log->Error( AppMsg, "Invalid address: \"%s\".", server.c_str() );
1615 }
1616
1617 std::string remote;
1618 bool followMode = false;
1619 uint32_t offset = 512;
1620
1621 for( uint32_t i = 1; i < args.size(); ++i )
1622 {
1623 if( args[i] == "-f" )
1624 followMode = true;
1625 else if( args[i] == "-c" )
1626 {
1627 if( i < args.size()-1 )
1628 {
1629 char *result;
1630 offset = ::strtol( args[i+1].c_str(), &result, 0 );
1631 if( *result != 0 )
1632 {
1633 log->Error( AppMsg, "Offset from the end needs to be a number: %s",
1634 args[i+1].c_str() );
1636 }
1637 ++i;
1638 }
1639 else
1640 {
1641 log->Error( AppMsg, "Parameter '-n' requires an argument." );
1643 }
1644 }
1645 else
1646 remote = args[i];
1647 }
1648
1649 std::string remoteFile;
1650 if( !BuildPath( remoteFile, env, remote ).IsOK() )
1651 {
1652 log->Error( AppMsg, "Invalid path." );
1654 }
1655
1656 URL remoteUrl( server );
1657 remoteUrl.SetPath( remoteFile );
1658
1659 //----------------------------------------------------------------------------
1660 // Fetch the data
1661 //----------------------------------------------------------------------------
1662 File file;
1663 XRootDStatus st = file.Open( remoteUrl.GetURL(), OpenFlags::Read );
1664 if( !st.IsOK() )
1665 {
1666 log->Error( AppMsg, "Unable to open file %s: %s",
1667 remoteUrl.GetObfuscatedURL().c_str(), st.ToStr().c_str() );
1668 return st;
1669 }
1670
1671 StatInfo *info = 0;
1672 uint64_t size = 0;
1673 st = file.Stat( false, info );
1674 if (st.IsOK()) size = info->GetSize();
1675
1676 if( size < offset )
1677 offset = 0;
1678 else
1679 offset = size - offset;
1680
1681 uint32_t chunkSize = 1*1024*1024;
1682 char *buffer = new char[chunkSize];
1683 uint32_t bytesRead = 0;
1684 while(1)
1685 {
1686 st = file.Read( offset, chunkSize, buffer, bytesRead );
1687 if( !st.IsOK() )
1688 {
1689 log->Error( AppMsg, "Unable to read from %s: %s",
1690 remoteUrl.GetObfuscatedURL().c_str(), st.ToStr().c_str() );
1691 delete [] buffer;
1692 return st;
1693 }
1694
1695 offset += bytesRead;
1696 int ret = write( 1, buffer, bytesRead );
1697 if( ret == -1 )
1698 {
1699 log->Error( AppMsg, "Unable to write to stdout: %s",
1700 XrdSysE2T(errno) );
1701 delete [] buffer;
1702 return st;
1703 }
1704
1705 if( bytesRead < chunkSize )
1706 {
1707 if( !followMode )
1708 break;
1709 sleep(1);
1710 }
1711 }
1712 delete [] buffer;
1713
1714 XRootDStatus stC = file.Close();
1715
1716 return XRootDStatus();
1717}
1718
1719//------------------------------------------------------------------------------
1720// Print statistics concerning given space
1721//------------------------------------------------------------------------------
1723 Env *env,
1724 const FSExecutor::CommandParams &args )
1725{
1726 using namespace XrdCl;
1727
1728 //----------------------------------------------------------------------------
1729 // Check up the args
1730 //----------------------------------------------------------------------------
1731 Log *log = DefaultEnv::GetLog();
1732 uint32_t argc = args.size();
1733
1734 if( argc != 2 )
1735 {
1736 log->Error( AppMsg, "Wrong number of arguments." );
1738 }
1739
1741
1742 XRootDStatus st = FileSystemUtils::GetSpaceInfo( i, fs, args[1] );
1743 if( !st.IsOK() )
1744 return st;
1745
1746 if( st.code == suPartial )
1747 {
1748 std::cerr << "[!] Some of the requests failed. The result may be ";
1749 std::cerr << "incomplete." << std::endl;
1750 }
1751
1752 std::cout << "Path: " << args[1] << std::endl;
1753 std::cout << "Total: " << i->GetTotal() << std::endl;
1754 std::cout << "Free: " << i->GetFree() << std::endl;
1755 std::cout << "Used: " << i->GetUsed() << std::endl;
1756 std::cout << "Largest free chunk: " << i->GetLargestFreeChunk() << std::endl;
1757
1758 delete i;
1759 return XRootDStatus();
1760}
1761
1762//------------------------------------------------------------------------------
1763// Carry out xattr operation
1764//------------------------------------------------------------------------------
1766 Env *env,
1767 const FSExecutor::CommandParams &args )
1768{
1769 //----------------------------------------------------------------------------
1770 // Check up the args
1771 //----------------------------------------------------------------------------
1772 Log *log = DefaultEnv::GetLog();
1773 uint32_t argc = args.size();
1774
1775 if( argc < 3 )
1776 {
1777 log->Error( AppMsg, "Wrong number of arguments." );
1779 }
1780
1781 kXR_char code = 0;
1782 if( args[2] == "set")
1783 code = kXR_fattrSet;
1784 else if( args[2] == "get" )
1785 code = kXR_fattrGet;
1786 else if( args[2] == "del" )
1787 code = kXR_fattrDel;
1788 else if( args[2] == "list" )
1789 code = kXR_fattrList;
1790 else
1791 {
1792 log->Error( AppMsg, "Invalid xattr code." );
1794 }
1795
1796 std::string path;
1797 if( !BuildPath( path, env, args[1] ).IsOK() )
1798 {
1799 log->Error( AppMsg, "Invalid path." );
1801 }
1802
1803 //----------------------------------------------------------------------------
1804 // Issue the xattr operation
1805 //----------------------------------------------------------------------------
1806 XRootDStatus status;
1807 switch( code )
1808 {
1809 case kXR_fattrSet:
1810 {
1811 if( argc != 4 )
1812 {
1813 log->Error( AppMsg, "Wrong number of arguments." );
1815 }
1816
1817 std::string key_value = args[3];
1818 size_t pos = key_value.find( '=' );
1819 std::string key = key_value.substr( 0, pos );
1820 std::string value = key_value.substr( pos + 1 );
1821 std::vector<xattr_t> attrs;
1822 attrs.push_back( std::make_tuple( key, value ) );
1823
1824 std::vector<XAttrStatus> result;
1825 XRootDStatus status = fs->SetXAttr( path, attrs, result );
1826 XAttrStatus xst = status.IsOK() ? result.front() : XAttrStatus( key, status );
1827
1828 if( !xst.status.IsOK() )
1829 status = xst.status;
1830
1831 if( !status.IsOK() )
1832 log->Error( AppMsg, "Unable to xattr set %s %s: %s",
1833 key.c_str(), value.c_str(),
1834 status.ToStr().c_str() );
1835 return status;
1836 }
1837
1838 case kXR_fattrGet:
1839 {
1840 if( argc != 4 )
1841 {
1842 log->Error( AppMsg, "Wrong number of arguments." );
1844 }
1845
1846 std::string key = args[3];
1847 std::vector<std::string> attrs;
1848 attrs.push_back( key );
1849
1850 std::vector<XAttr> result;
1851 XRootDStatus status = fs->GetXAttr( path, attrs, result );
1852 XAttr xattr = status.IsOK() ? result.front() : XAttr( key, status );
1853
1854 if( !xattr.status.IsOK() )
1855 status = xattr.status;
1856
1857 if( !status.IsOK() )
1858 log->Error( AppMsg, "Unable to xattr get %s : %s",
1859 key.c_str(),
1860 status.ToStr().c_str() );
1861 else
1862 {
1863 std::cout << "# file: " << path << '\n';
1864 std::cout << xattr.name << "=\"" << xattr.value << "\"\n";
1865 }
1866
1867 return status;
1868 }
1869
1870 case kXR_fattrDel:
1871 {
1872 if( argc != 4 )
1873 {
1874 log->Error( AppMsg, "Wrong number of arguments." );
1876 }
1877
1878 std::string key = args[3];
1879 std::vector<std::string> attrs;
1880 attrs.push_back( key );
1881
1882 std::vector<XAttrStatus> result ;
1883 XRootDStatus status = fs->DelXAttr( path, attrs, result );
1884 XAttrStatus xst = status.IsOK() ? result.front() : XAttrStatus( key, status );
1885
1886 if( !xst.status.IsOK() )
1887 status = xst.status;
1888
1889 if( !status.IsOK() )
1890 log->Error( AppMsg, "Unable to xattr del %s : %s",
1891 key.c_str(),
1892 status.ToStr().c_str() );
1893 return status;
1894 }
1895
1896 case kXR_fattrList:
1897 {
1898 if( argc != 3 )
1899 {
1900 log->Error( AppMsg, "Wrong number of arguments." );
1902 }
1903
1904 std::vector<XAttr> result;
1905 XRootDStatus status = fs->ListXAttr( path, result );
1906
1907 if( !status.IsOK() )
1908 log->Error( AppMsg, "Unable to xattr list : %s",
1909 status.ToStr().c_str() );
1910 else
1911 {
1912 std::cout << "# file: " << path << '\n';
1913 auto itr = result.begin();
1914 for( ; itr != result.end(); ++itr )
1915 std::cout << itr->name << "=\"" << itr->value << "\"\n";
1916 }
1917
1918 return status;
1919 }
1920
1921 default:
1923 }
1924}
1925
1926//------------------------------------------------------------------------------
1927// Print help
1928//------------------------------------------------------------------------------
1931{
1932 printf( "Usage:\n" );
1933 printf( " xrdfs [--no-cwd] host[:port] - interactive mode\n" );
1934 printf( " xrdfs host[:port] command args - batch mode\n\n" );
1935
1936 printf( "Available options:\n\n" );
1937
1938 printf( " --no-cwd no CWD is being preset\n\n" );
1939
1940 printf( "Available commands:\n\n" );
1941
1942 printf( " exit\n" );
1943 printf( " Exits from the program.\n\n" );
1944
1945 printf( " help\n" );
1946 printf( " This help screen.\n\n" );
1947
1948 printf( " cache {evict | fevict} <path>\n" );
1949 printf( " Evict a file from a cache if not in use; while fevict\n" );
1950 printf( " forcibly evicts the file causing any current uses of the\n" );
1951 printf( " file to get read failures on a subsequent read\n\n" );
1952
1953 printf( " cd <path>\n" );
1954 printf( " Change the current working directory\n\n" );
1955
1956 printf( " chmod <path> <user><group><other>\n" );
1957 printf( " Modify permissions. Permission string example:\n" );
1958 printf( " rwxr-x--x\n\n" );
1959
1960 printf( " ls [-l] [-u] [-R] [-D] [-Z] [-C] [dirname]\n" );
1961 printf( " Get directory listing.\n" );
1962 printf( " -l stat every entry and print long listing\n" );
1963 printf( " -u print paths as URLs\n" );
1964 printf( " -R list subdirectories recursively\n" );
1965 printf( " -D show duplicate entries" );
1966 printf( " -Z if a ZIP archive list its content\n" );
1967 printf( " -C checksum every entry\n\n" );
1968
1969 printf( " locate [-n] [-r] [-d] [-m] [-i] [-p] <path>\n" );
1970 printf( " Get the locations of the path.\n" );
1971 printf( " -r refresh, don't use cached locations\n" );
1972 printf( " -n make the server return the response immediately even\n" );
1973 printf( " though it may be incomplete\n" );
1974 printf( " -d do a recursive (deep) locate\n" );
1975 printf( " -m|-h prefer host names to IP addresses\n" );
1976 printf( " -i ignore network dependencies\n" );
1977 printf( " -p be passive: ignore tried/triedrc cgi opaque info\n\n" );
1978
1979 printf( " mkdir [-p] [-m<user><group><other>] <dirname>\n" );
1980 printf( " Creates a directory/tree of directories.\n\n" );
1981
1982 printf( " mv <path1> <path2>\n" );
1983 printf( " Move path1 to path2 locally on the same server.\n\n" );
1984
1985 printf( " stat [-q query] <path>\n" );
1986 printf( " Get info about the file or directory.\n" );
1987 printf( " -q query optional flag query parameter that makes\n" );
1988 printf( " xrdfs return error code to the shell if the\n" );
1989 printf( " requested flag combination is not present;\n" );
1990 printf( " flags may be combined together using '|' or '&'\n" );
1991 printf( " Available flags:\n" );
1992 printf( " XBitSet, IsDir, Other, Offline, POSCPending,\n" );
1993 printf( " IsReadable, IsWritable\n\n" );
1994
1995 printf( " statvfs <path>\n" );
1996 printf( " Get info about a virtual file system.\n\n" );
1997
1998 printf( " query <code> <parameters>\n" );
1999 printf( " Obtain server information. Query codes:\n\n" );
2000
2001 printf( " config <what> Server configuration; <what> is\n" );
2002 printf( " one of the following:\n" );
2003 printf( " bind_max - the maximum number of parallel streams\n" );
2004 printf( " chksum - the supported checksum\n" );
2005 printf( " cms - the status of the cmsd\n" );
2006 printf( " pio_max - maximum number of parallel I/O requests\n" );
2007 printf( " readv_ior_max - maximum size of a readv element\n" );
2008 printf( " readv_iov_max - maximum number of readv entries\n" );
2009 printf( " role - the role in a cluster\n" );
2010 printf( " sitename - the site name\n" );
2011 printf( " tpc - support for third party copies\n" );
2012 printf( " version - the version of the server\n" );
2013 printf( " wan_port - the port to use for wan copies\n" );
2014 printf( " wan_window - the wan_port window size\n" );
2015 printf( " window - the tcp window size\n" );
2016 printf( " checksumcancel <path> File checksum cancellation\n" );
2017 printf( " checksum <path> File checksum\n" );
2018 printf( " opaque <arg> Implementation dependent\n" );
2019 printf( " opaquefile <arg> Implementation dependent\n" );
2020 printf( " space <space> Logical space stats\n" );
2021 printf( " stats <what> Server stats; <what> is a list\n" );
2022 printf( " of letters indicating information\n");
2023 printf( " to be returned:\n" );
2024 printf( " a - all statistics\n" );
2025 printf( " p - protocol statistics\n" );
2026 printf( " b - buffer usage statistics\n" );
2027 printf( " s - scheduling statistics\n" );
2028 printf( " d - device polling statistics\n" );
2029 printf( " u - usage statistics\n" );
2030 printf( " i - server identification\n" );
2031 printf( " z - synchronized statistics\n" );
2032 printf( " l - connection statistics\n" );
2033 printf( " xattr <path> Extended attributes\n" );
2034 printf( " prepare <reqid> [filenames] Prepare request status\n\n" );
2035
2036 printf( " rm <filename>\n" );
2037 printf( " Remove a file.\n\n" );
2038
2039 printf( " rmdir <dirname>\n" );
2040 printf( " Remove a directory.\n\n" );
2041
2042 printf( " truncate <filename> <length>\n" );
2043 printf( " Truncate a file.\n\n" );
2044
2045 printf( " prepare [-c] [-f] [-s] [-w] [-e] [-p priority] [-a requestid] filenames\n" );
2046 printf( " Prepare one or more files for access.\n" );
2047 printf( " -c co-locate staged files if possible\n" );
2048 printf( " -f refresh file access time even if the location is known\n" );
2049 printf( " -s stage the files to disk if they are not online\n" );
2050 printf( " -w the files will be accessed for modification\n" );
2051 printf( " -p priority of the request, 0 (lowest) - 3 (highest)\n" );
2052 printf( " -a abort stage request\n" );
2053 printf( " -e evict the file from disk cache\n\n" );
2054
2055 printf( " cat [-o local file] files\n" );
2056 printf( " Print contents of one or more files to stdout.\n" );
2057 printf( " -o print to the specified local file\n\n" );
2058
2059 printf( " tail [-c bytes] [-f] file\n" );
2060 printf( " Output last part of files to stdout.\n" );
2061 printf( " -c num_bytes out last num_bytes\n" );
2062 printf( " -f output appended data as file grows\n\n" );
2063
2064 printf( " spaceinfo path\n" );
2065 printf( " Get space statistics for given path.\n\n" );
2066
2067 printf( " xattr <path> <code> <params> \n" );
2068 printf( " Operation on extended attributes. Codes:\n\n" );
2069 printf( " set <attr> Set extended attribute; <attr> is\n" );
2070 printf( " string of form name=value\n" );
2071 printf( " get <name> Get extended attribute\n" );
2072 printf( " del <name> Delete extended attribute\n" );
2073 printf( " list List extended attributes\n\n" );
2074
2075 return XRootDStatus();
2076}
2077
2078//------------------------------------------------------------------------------
2079// Create the executor object
2080//------------------------------------------------------------------------------
2082{
2083 Env *env = new Env();
2084 env->PutString( "CWD", "/" );
2085 FSExecutor *executor = new FSExecutor( url, env );
2086 executor->AddCommand( "cache", DoCache );
2087 executor->AddCommand( "cd", DoCD );
2088 executor->AddCommand( "chmod", DoChMod );
2089 executor->AddCommand( "ls", DoLS );
2090 executor->AddCommand( "help", PrintHelp );
2091 executor->AddCommand( "stat", DoStat );
2092 executor->AddCommand( "statvfs", DoStatVFS );
2093 executor->AddCommand( "locate", DoLocate );
2094 executor->AddCommand( "mv", DoMv );
2095 executor->AddCommand( "mkdir", DoMkDir );
2096 executor->AddCommand( "rm", DoRm );
2097 executor->AddCommand( "rmdir", DoRmDir );
2098 executor->AddCommand( "query", DoQuery );
2099 executor->AddCommand( "truncate", DoTruncate );
2100 executor->AddCommand( "prepare", DoPrepare );
2101 executor->AddCommand( "cat", DoCat );
2102 executor->AddCommand( "tail", DoTail );
2103 executor->AddCommand( "spaceinfo", DoSpaceInfo );
2104 executor->AddCommand( "xattr", DoXAttr );
2105 return executor;
2106}
2107
2108//------------------------------------------------------------------------------
2109// Execute command
2110//------------------------------------------------------------------------------
2111int ExecuteCommand( FSExecutor *ex, int argc, char **argv )
2112{
2113 // std::vector<std::string> args (argv, argv + argc);
2114 std::vector<std::string> args;
2115 args.reserve(argc);
2116 for (int i = 0; i < argc; ++i)
2117 {
2118 args.push_back(argv[i]);
2119 }
2120 XRootDStatus st = ex->Execute( args );
2121 if( !st.IsOK() )
2122 std::cerr << st.ToStr() << std::endl;
2123 return st.GetShellCode();
2124}
2125
2126//------------------------------------------------------------------------------
2127// Define some functions required to function when build without readline
2128//------------------------------------------------------------------------------
2129#ifndef HAVE_READLINE
2130char *readline(const char *prompt)
2131{
2132 std::cout << prompt << std::flush;
2133 std::string input;
2134 std::getline( std::cin, input );
2135
2136 if( !std::cin.good() )
2137 return 0;
2138
2139 char *linebuf = (char *)malloc( input.size()+1 );
2140 strncpy( linebuf, input.c_str(), input.size()+1 );
2141
2142 return linebuf;
2143}
2144
2145void add_history( const char * )
2146{
2147}
2148
2149void rl_bind_key( char, uint16_t )
2150{
2151}
2152
2153uint16_t rl_insert = 0;
2154
2155int read_history( const char * )
2156{
2157 return 0;
2158}
2159
2160int write_history( const char * )
2161{
2162 return 0;
2163}
2164#endif
2165
2166//------------------------------------------------------------------------------
2167// Build the command prompt
2168//------------------------------------------------------------------------------
2169std::string BuildPrompt( Env *env, const URL &url )
2170{
2171 std::ostringstream prompt;
2172 std::string cwd = "/";
2173 env->GetString( "CWD", cwd );
2174 prompt << "[" << url.GetHostId() << "] " << cwd << " > ";
2175 return prompt.str();
2176}
2177
2178//------------------------------------------------------------------------
2184//------------------------------------------------------------------------
2185bool getArguments (std::vector<std::string> & result, const std::string &input)
2186{
2187 // the delimiter (space in the case of command line)
2188 static const char delimiter = ' ';
2189 // two types of quotes: single and double quotes
2190 const char singleQuote = '\'', doubleQuote = '\"';
2191 // if the current character of the command has been
2192 // quoted 'currentQuote' holds the type of quote,
2193 // otherwise it holds the null character
2194 char currentQuote = '\0';
2195
2196 std::string tmp;
2197 for (std::string::const_iterator it = input.begin (); it != input.end (); ++it)
2198 {
2199 // if we encountered a quote character ...
2200 if (*it == singleQuote || *it == doubleQuote)
2201 {
2202 // if we are not within quoted text ...
2203 if (!currentQuote)
2204 {
2205 currentQuote = *it; // set the type of quote
2206 continue; // and continue, the quote character itself is not a part of the parameter
2207 }
2208 // otherwise if it is the closing quote character ...
2209 else if (currentQuote == *it)
2210 {
2211 currentQuote = '\0'; // reset the current quote type
2212 continue; // and continue, the quote character itself is not a part of the parameter
2213 }
2214 }
2215 // if we are within quoted text or the character is not a delimiter ...
2216 if (currentQuote || *it != delimiter)
2217 {
2218 // concatenate it
2219 tmp += *it;
2220 }
2221 else
2222 {
2223 // otherwise add a parameter and erase the tmp string
2224 if (!tmp.empty ())
2225 {
2226 result.push_back(tmp);
2227 tmp.erase ();
2228 }
2229 }
2230 }
2231 // if the there are some remainders of the command add them
2232 if (!tmp.empty())
2233 {
2234 result.push_back(tmp);
2235 }
2236 // return true if the quotation has been closed
2237 return currentQuote == '\0';
2238}
2239
2240//------------------------------------------------------------------------------
2241// Execute interactive
2242//------------------------------------------------------------------------------
2243int ExecuteInteractive( const URL &url, bool noCwd = false )
2244{
2245 //----------------------------------------------------------------------------
2246 // Set up the environment
2247 //----------------------------------------------------------------------------
2248 std::string historyFile = getenv( "HOME" );
2249 historyFile += "/.xrdquery.history";
2250 rl_bind_key( '\t', rl_insert );
2251 read_history( historyFile.c_str() );
2252 FSExecutor *ex = CreateExecutor( url );
2253
2254 if( noCwd )
2255 ex->GetEnv()->PutInt( "NoCWD", 1 );
2256
2257 //----------------------------------------------------------------------------
2258 // Execute the commands
2259 //----------------------------------------------------------------------------
2260 std::string cmdline;
2261 while(1)
2262 {
2263 char *linebuf = 0;
2264 // print new prompt only if the previous line was complete
2265 // (a line is considered not to be complete if a quote has
2266 // been opened but it has not been closed)
2267 linebuf = readline( cmdline.empty() ? BuildPrompt( ex->GetEnv(), url ).c_str() : "> " );
2268 if( !linebuf || !strncmp( linebuf, "exit", 4 ) || !strncmp( linebuf, "quit", 4 ) )
2269 {
2270 std::cout << "Goodbye." << std::endl << std::endl;
2271 break;
2272 }
2273 if( !*linebuf)
2274 {
2275 free( linebuf );
2276 continue;
2277 }
2278 std::vector<std::string> args;
2279 cmdline += linebuf;
2280 free( linebuf );
2281 if (getArguments( args, cmdline ))
2282 {
2283 XRootDStatus st = ex->Execute( args );
2284 add_history( cmdline.c_str() );
2285 cmdline.erase();
2286 if( !st.IsOK() )
2287 std::cerr << st.ToStr() << std::endl;
2288 }
2289 }
2290
2291 //----------------------------------------------------------------------------
2292 // Cleanup
2293 //----------------------------------------------------------------------------
2294 delete ex;
2295 write_history( historyFile.c_str() );
2296 return 0;
2297}
2298
2299//------------------------------------------------------------------------------
2300// Execute command
2301//------------------------------------------------------------------------------
2302int ExecuteCommand( const URL &url, int argc, char **argv )
2303{
2304 //----------------------------------------------------------------------------
2305 // Build the command to be executed
2306 //----------------------------------------------------------------------------
2307 std::string commandline;
2308 for( int i = 0; i < argc; ++i )
2309 {
2310 commandline += argv[i];
2311 commandline += " ";
2312 }
2313
2314 FSExecutor *ex = CreateExecutor( url );
2315 ex->GetEnv()->PutInt( "NoCWD", 1 );
2316 int st = ExecuteCommand( ex, argc, argv );
2317 delete ex;
2318 return st;
2319}
2320
2321//------------------------------------------------------------------------------
2322// Start the show
2323//------------------------------------------------------------------------------
2324int main( int argc, char **argv )
2325{
2326 //----------------------------------------------------------------------------
2327 // Check the commandline parameters
2328 //----------------------------------------------------------------------------
2330 if( argc == 1 )
2331 {
2332 PrintHelp( 0, 0, params );
2333 return 1;
2334 }
2335
2336 if( !strcmp( argv[1], "--help" ) ||
2337 !strcmp( argv[1], "-h" ) )
2338 {
2339 PrintHelp( 0, 0, params );
2340 return 0;
2341 }
2342
2343 bool noCwd = false;
2344 int urlIndex = 1;
2345 if( !strcmp( argv[1], "--no-cwd") )
2346 {
2347 ++urlIndex;
2348 noCwd = true;
2349 }
2350
2351 URL url( argv[urlIndex] );
2352 if( !url.IsValid() )
2353 {
2354 PrintHelp( 0, 0, params );
2355 return 1;
2356 }
2357
2358 if( argc == urlIndex + 1 )
2359 return ExecuteInteractive( url, noCwd );
2360 int shift = urlIndex + 1;
2361 return ExecuteCommand( url, argc-shift, argv+shift );
2362}
@ kXR_fattrDel
Definition XProtocol.hh:270
@ kXR_fattrSet
Definition XProtocol.hh:273
@ kXR_fattrList
Definition XProtocol.hh:272
@ kXR_fattrGet
Definition XProtocol.hh:271
unsigned char kXR_char
Definition XPtypes.hh:65
uint32_t nbDigits(uint64_t nb)
Definition XrdClFS.cc:278
XRootDStatus DoQuery(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:1216
XRootDStatus DoLocate(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:822
int write_history(const char *)
Definition XrdClFS.cc:2160
XRootDStatus DoMkDir(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:497
void add_history(const char *)
Definition XrdClFS.cc:2145
XRootDStatus DoRmDir(FileSystem *query, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:560
XRootDStatus DoRm(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:653
XRootDStatus DoTail(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:1593
int ExecuteInteractive(const URL &url, bool noCwd=false)
Definition XrdClFS.cc:2243
int main(int argc, char **argv)
Definition XrdClFS.cc:2324
void rl_bind_key(char, uint16_t)
Definition XrdClFS.cc:2149
XRootDStatus DoStat(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:1018
XRootDStatus ProcessStatQuery(StatInfo &info, const std::string &query)
Definition XrdClFS.cc:953
XRootDStatus DoCat(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:1478
std::string BuildPrompt(Env *env, const URL &url)
Definition XrdClFS.cc:2169
XRootDStatus DoMv(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:601
XRootDStatus DoPrepare(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:1323
int ExecuteCommand(FSExecutor *ex, int argc, char **argv)
Definition XrdClFS.cc:2111
XRootDStatus DoChMod(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:773
void PrintDirListStatInfo(StatInfo *info, bool hascks=false, uint32_t ownerwidth=0, uint32_t groupwidth=0, uint32_t sizewidth=0)
Definition XrdClFS.cc:285
FSExecutor * CreateExecutor(const URL &url)
Definition XrdClFS.cc:2081
XRootDStatus DoLS(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:336
bool getArguments(std::vector< std::string > &result, const std::string &input)
Definition XrdClFS.cc:2185
XRootDStatus DoCD(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:227
XRootDStatus DoXAttr(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:1765
char * readline(const char *prompt)
Definition XrdClFS.cc:2130
XRootDStatus DoStatVFS(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:1154
XRootDStatus DoCache(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:165
XRootDStatus DoSpaceInfo(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:1722
XRootDStatus BuildPath(std::string &newPath, Env *env, const std::string &path)
Definition XrdClFS.cc:56
int read_history(const char *)
Definition XrdClFS.cc:2155
XRootDStatus ConvertMode(Access::Mode &mode, const std::string &modeStr)
Definition XrdClFS.cc:120
uint16_t rl_insert
Definition XrdClFS.cc:2153
XRootDStatus DoTruncate(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
Definition XrdClFS.cc:724
XRootDStatus PrintHelp(FileSystem *, Env *, const FSExecutor::CommandParams &)
Definition XrdClFS.cc:1929
static bool is_subdirectory(const std::string &dir, const std::string &subdir)
#define write(a, b, c)
Definition XrdPosix.hh:115
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
virtual void EndJob(uint16_t jobNum, const XrdCl::PropertyList *results)
Definition XrdClFS.cc:1438
virtual void JobProgress(uint16_t jobNum, uint64_t bytesProcessed, uint64_t bytesTotal)
Job progress.
Definition XrdClCopy.cc:221
Binary blob representation.
void FromString(const std::string str)
Fill the buffer from a string.
std::string ToString() const
Convert the buffer to a string.
Copy the data from one point to another.
XRootDStatus Run(CopyProgressHandler *handler)
Run the copy jobs.
XRootDStatus AddJob(const PropertyList &properties, PropertyList *results)
Interface for copy progress notification.
static Log * GetLog()
Get default log.
static Env * GetEnv()
Get default client environment.
const std::string & GetParentName() const
Get parent directory name.
DirList::iterator Iterator
Directory listing iterator.
Iterator End()
Get the end iterator.
Iterator Begin()
Get the begin iterator.
bool PutInt(const std::string &key, int value)
Definition XrdClEnv.cc:110
bool PutString(const std::string &key, const std::string &value)
Definition XrdClEnv.cc:52
bool GetString(const std::string &key, std::string &value)
Definition XrdClEnv.cc:31
bool GetInt(const std::string &key, int &value)
Definition XrdClEnv.cc:89
Execute queries given as a commandline.
std::vector< std::string > CommandParams
Definition of command argument list.
XRootDStatus Execute(const CommandParams &args)
bool AddCommand(const std::string &name, Command command)
Env * GetEnv()
Get the environment.
Container for space information.
uint64_t GetUsed() const
Amount of used space in MB.
uint64_t GetLargestFreeChunk() const
Largest single chunk of free space.
uint64_t GetTotal() const
Amount of total space in MB.
uint64_t GetFree() const
Amount of free space in MB.
static XRootDStatus GetSpaceInfo(SpaceInfo *&result, FileSystem *fs, const std::string &path)
Recursively get space information for given path.
Send file/filesystem queries to an XRootD cluster.
XRootDStatus SetXAttr(const std::string &path, const std::vector< xattr_t > &attrs, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus RmDir(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus DirList(const std::string &path, DirListFlags::Flags flags, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Mv(const std::string &source, const std::string &dest, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Query(QueryCode::Code queryCode, const Buffer &arg, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Locate(const std::string &path, OpenFlags::Flags flags, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Stat(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Prepare(const std::vector< std::string > &fileList, PrepareFlags::Flags flags, uint8_t priority, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus ChMod(const std::string &path, Access::Mode mode, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus DelXAttr(const std::string &path, const std::vector< std::string > &attrs, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus ListXAttr(const std::string &path, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus DeepLocate(const std::string &path, OpenFlags::Flags flags, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus SendCache(const std::string &info, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus GetXAttr(const std::string &path, const std::vector< std::string > &attrs, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus Truncate(const std::string &path, uint64_t size, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
bool GetProperty(const std::string &name, std::string &value) const
XRootDStatus MkDir(const std::string &path, MkDirFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus StatVFS(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
A file.
Definition XrdClFile.hh:46
XRootDStatus Read(uint64_t offset, uint32_t size, void *buffer, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
Definition XrdClFile.cc:206
XRootDStatus Close(ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
Definition XrdClFile.cc:151
XRootDStatus Open(const std::string &url, OpenFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
Definition XrdClFile.cc:99
XRootDStatus Stat(bool force, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
Definition XrdClFile.cc:177
Path location info.
Iterator Begin()
Get the location begin iterator.
@ Read
read access is allowed
@ ReadWrite
write access is allowed
@ ServerPending
server node where the file is pending to be online
@ ManagerOnline
manager node where the file is online
@ ServerOnline
server node where the file is online
@ ManagerPending
manager node where the file is pending to be online
LocationList::iterator Iterator
Iterator over locations.
Iterator End()
Get the location end iterator.
Handle diagnostics.
Definition XrdClLog.hh:101
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition XrdClLog.cc:231
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
Definition XrdClLog.cc:282
Pipeline exception, wrapps an XRootDStatus.
const XRootDStatus & GetError() const
A key-value pair map storing both keys and values as strings.
uint64_t GetFreeRW() const
Get size of the largest contiguous area of free r/w space (in MB)
uint64_t GetNodesStaging() const
Get number of nodes that can provide staging space.
uint8_t GetUtilizationStaging() const
Get percentage of the partition utilization represented by FreeStaging.
uint64_t GetFreeStaging() const
Get size of the largest contiguous area of free staging space (in MB)
uint8_t GetUtilizationRW() const
Get percentage of the partition utilization represented by FreeRW.
uint64_t GetNodesRW() const
Get number of nodes that can provide read/write space.
Object stat info.
std::string GetChangeTimeAsString() const
Get change time.
std::string GetModTimeAsString() const
Get modification time.
bool HasChecksum() const
Has checksum.
bool TestFlags(uint32_t flags) const
Test flags.
uint64_t GetSize() const
Get size (in bytes)
const std::string GetModeAsOctString() const
Get mode.
const std::string & GetOwner() const
Get owner.
@ IsReadable
Read access is allowed.
@ IsDir
This is a directory.
@ Other
Neither a file nor a directory.
@ BackUpExists
Back up copy exists.
@ XBitSet
Executable/searchable bit set.
@ Offline
File is not online (ie. on disk)
@ IsWritable
Write access is allowed.
uint32_t GetFlags() const
Get flags.
bool ExtendedFormat() const
Has extended stat information.
const std::string & GetModeAsString() const
Get mode.
const std::string & GetId() const
Get id.
const std::string & GetGroup() const
Get group.
std::string GetAccessTimeAsString() const
Get change time.
const std::string & GetChecksum() const
Get checksum.
URL representation.
Definition XrdClURL.hh:31
std::string GetHostId() const
Get the host part of the URL (user:password@host:port)
Definition XrdClURL.hh:99
std::string GetURL() const
Get the URL.
Definition XrdClURL.hh:86
std::string GetObfuscatedURL() const
Get the URL with authz information obfuscated.
Definition XrdClURL.cc:498
void SetPath(const std::string &path)
Set the path.
Definition XrdClURL.hh:225
bool IsValid() const
Is the url valid.
Definition XrdClURL.cc:452
static void splitString(Container &result, const std::string &input, const std::string &delimiter)
Split a string.
Definition XrdClUtils.hh:56
static std::string BytesToString(uint64_t bytes)
Convert bytes to a human readable string.
std::string ToStr() const
Convert to string.
const uint16_t suPartial
const uint16_t errInvalidAddr
RmImpl< false > Rm
const uint16_t stError
An error occurred that could potentially be retried.
const uint64_t AppMsg
const uint16_t errResponseNegative
Query response was negative.
StatImpl< false > Stat(Ctx< File > file, Arg< bool > force, uint16_t timeout=0)
XRootDStatus WaitFor(Pipeline pipeline, uint16_t timeout=0)
const uint16_t errInvalidArgs
std::future< XRootDStatus > Async(Pipeline pipeline, uint16_t timeout=0)
ParallelOperation< false > Parallel(Container &&container)
Factory function for creating parallel operation from a vector.
@ OX
world executable/browsable
@ OW
world writeable
@ UR
owner readable
@ GR
group readable
@ UW
owner writable
@ GX
group executable/browsable
@ GW
group writable
@ UX
owner executable/browsable
@ OR
world readable
@ Stat
Stat each entry.
@ Merge
Merge duplicates.
@ Zip
List content of ZIP files.
@ Recursive
Do a recursive listing.
@ Cksm
Get checksum for every entry.
@ None
Nothing special.
@ MakePath
create the entire directory tree if it doesn't exist
Flags
Open flags, may be or'd when appropriate.
@ Read
Open only for reading.
@ Cancel
cancel staging request
@ Colocate
co-locate staged files, if possible
Code
XRootD query request codes.
@ OpaqueFile
Implementation dependent.
@ XAttr
Query file extended attributes.
@ Opaque
Implementation dependent.
@ Config
Query server configuration.
@ Stats
Query server stats.
@ ChecksumCancel
Query file checksum cancellation.
@ Checksum
Query file checksum.
@ Space
Query logical space stats.
@ Prepare
Query prepare status.
uint16_t code
Error type, or additional hints on what to do.
bool IsOK() const
We're fine.
int GetShellCode() const
Get the status code that may be returned to the shell.
Extended attribute operation status.
Extended attributes with status.