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