Changeset 2283

Show
Ignore:
Timestamp:
13/09/2008 16:31:26 (18 months ago)
Author:
chris
Message:

Allow undelete command to work on files as well as directories.

Add delete command that works on files and directories.

Document both commands.

Location:
box/trunk/bin/bbackupquery
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • box/trunk/bin/bbackupquery/BackupQueries.cpp

    r2261 r2283  
    7272// 
    7373// -------------------------------------------------------------------------- 
    74 BackupQueries::BackupQueries(BackupProtocolClient &rConnection, const Configuration &rConfiguration) 
    75         : mrConnection(rConnection), 
     74BackupQueries::BackupQueries(BackupProtocolClient &rConnection, 
     75        const Configuration &rConfiguration, bool readWrite) 
     76        : mReadWrite(readWrite), 
     77          mrConnection(rConnection), 
    7678          mrConfiguration(rConfiguration), 
    7779          mQuitNow(false), 
     
    223225                { "usage", "" }, 
    224226                { "undelete", "" }, 
     227                { "delete", "" }, 
    225228                { NULL, NULL }  
    226229        }; 
    227         #define COMMAND_Quit            0 
    228         #define COMMAND_Exit            1 
    229         #define COMMAND_List            2 
    230         #define COMMAND_pwd                     3 
    231         #define COMMAND_cd                      4 
    232         #define COMMAND_lcd                     5 
    233         #define COMMAND_sh                      6 
    234         #define COMMAND_GetObject       7 
    235         #define COMMAND_Get                     8 
    236         #define COMMAND_Compare         9 
    237         #define COMMAND_Restore         10 
    238         #define COMMAND_Help            11 
    239         #define COMMAND_Usage           12 
    240         #define COMMAND_Undelete        13 
    241         static const char *alias[] = {"ls",                     0}; 
    242         static const int aliasIs[] = {COMMAND_List, 0}; 
     230 
     231        typedef enum 
     232        { 
     233                Command_Quit = 0, 
     234                Command_Exit, 
     235                Command_List, 
     236                Command_pwd, 
     237                Command_cd, 
     238                Command_lcd, 
     239                Command_sh, 
     240                Command_GetObject, 
     241                Command_Get, 
     242                Command_Compare, 
     243                Command_Restore, 
     244                Command_Help, 
     245                Command_Usage, 
     246                Command_Undelete, 
     247                Command_Delete, 
     248        } 
     249        CommandType; 
     250 
     251        static const char *alias[] = {"ls", 0}; 
     252        static const int aliasIs[] = {Command_List, 0}; 
    243253         
    244254        // Work out which command it is... 
     
    294304        } 
    295305 
    296         if(cmd != COMMAND_Quit && cmd != COMMAND_Exit) 
     306        if(cmd != Command_Quit && cmd != Command_Exit) 
    297307        { 
    298308                // If not a quit command, set the return code to zero 
     
    303313        switch(cmd) 
    304314        { 
    305         case COMMAND_Quit: 
    306         case COMMAND_Exit: 
     315        case Command_Quit: 
     316        case Command_Exit: 
    307317                mQuitNow = true; 
    308318                break; 
    309319                 
    310         case COMMAND_List: 
     320        case Command_List: 
    311321                CommandList(args, opts); 
    312322                break; 
    313323                 
    314         case COMMAND_pwd: 
     324        case Command_pwd: 
    315325                { 
    316326                        // Simple implementation, so do it here 
     
    320330                break; 
    321331 
    322         case COMMAND_cd: 
     332        case Command_cd: 
    323333                CommandChangeDir(args, opts); 
    324334                break; 
    325335                 
    326         case COMMAND_lcd: 
     336        case Command_lcd: 
    327337                CommandChangeLocalDir(args); 
    328338                break; 
    329339                 
    330         case COMMAND_sh: 
     340        case Command_sh: 
    331341                BOX_ERROR("The command to run must be specified as an argument."); 
    332342                break; 
    333343                 
    334         case COMMAND_GetObject: 
     344        case Command_GetObject: 
    335345                CommandGetObject(args, opts); 
    336346                break; 
    337347                 
    338         case COMMAND_Get: 
     348        case Command_Get: 
    339349                CommandGet(args, opts); 
    340350                break; 
    341351                 
    342         case COMMAND_Compare: 
     352        case Command_Compare: 
    343353                CommandCompare(args, opts); 
    344354                break; 
    345355                 
    346         case COMMAND_Restore: 
     356        case Command_Restore: 
    347357                CommandRestore(args, opts); 
    348358                break; 
    349359                 
    350         case COMMAND_Usage: 
     360        case Command_Usage: 
    351361                CommandUsage(); 
    352362                break; 
    353363                 
    354         case COMMAND_Help: 
     364        case Command_Help: 
    355365                CommandHelp(args); 
    356366                break; 
    357367 
    358         case COMMAND_Undelete: 
     368        case Command_Undelete: 
    359369                CommandUndelete(args, opts); 
    360370                break; 
    361371                 
     372        case Command_Delete: 
     373                CommandDelete(args, opts); 
     374                break; 
     375                 
    362376        default: 
     377                BOX_ERROR("Unknown command: " << Command); 
    363378                break; 
    364379        } 
     
    602617// 
    603618// Function 
    604 //              Name:    BackupQueries::FindDirectoryObjectID(const std::string &) 
    605 //              Purpose: Find the object ID of a directory on the store, or return 0 for not found. 
    606 //                               If pStack != 0, the object is set to the stack of directories. 
    607 //                               Will start from the current directory stack. 
     619//              Name:    BackupQueries::FindDirectoryObjectID(const 
     620//                       std::string &) 
     621//              Purpose: Find the object ID of a directory on the store, 
     622//                       or return 0 for not found. If pStack != 0, the 
     623//                       object is set to the stack of directories. 
     624//                       Will start from the current directory stack. 
    608625//              Created: 2003/10/10 
    609626// 
    610627// -------------------------------------------------------------------------- 
    611 int64_t BackupQueries::FindDirectoryObjectID(const std::string &rDirName, bool AllowOldVersion, 
    612                         bool AllowDeletedDirs, std::vector<std::pair<std::string, int64_t> > *pStack) 
     628int64_t BackupQueries::FindDirectoryObjectID(const std::string &rDirName, 
     629        bool AllowOldVersion, bool AllowDeletedDirs, 
     630        std::vector<std::pair<std::string, int64_t> > *pStack) 
    613631{ 
    614632        // Split up string into elements 
     
    936954 
    937955 
     956// -------------------------------------------------------------------------- 
     957// 
     958// Function 
     959//              Name:    BackupQueries::FindFileID(const std::string& 
     960//                       rNameOrIdString, const bool *options, 
     961//                       int64_t *pDirIdOut, std::string* pFileNameOut) 
     962//              Purpose: Locate a file on the store (either by name or by 
     963//                       object ID, depending on opts['i'], where name can 
     964//                       include a path) and return the file ID, placing the 
     965//                       directory ID in *pDirIdOut and the filename part 
     966//                       of the path (if not looking up by ID and not NULL) 
     967//                       in *pFileNameOut. 
     968//              Created: 2008-09-12 
     969// 
     970// -------------------------------------------------------------------------- 
     971int64_t BackupQueries::FindFileID(const std::string& rNameOrIdString, 
     972        const bool *opts, int64_t *pDirIdOut, std::string* pFileNameOut, 
     973        int16_t flagsInclude, int16_t flagsExclude, int16_t* pFlagsOut) 
     974{ 
     975        // Find object ID somehow 
     976        int64_t fileId; 
     977        int64_t dirId = GetCurrentDirectoryID(); 
     978        std::string fileName = rNameOrIdString; 
     979 
     980        if(!opts['i']) 
     981        { 
     982                // does this remote filename include a path? 
     983                std::string::size_type index = fileName.rfind('/'); 
     984                if(index != std::string::npos) 
     985                { 
     986                        std::string dirName(fileName.substr(0, index)); 
     987                        fileName = fileName.substr(index + 1); 
     988 
     989                        dirId = FindDirectoryObjectID(dirName); 
     990                        if(dirId == 0) 
     991                        { 
     992                                BOX_ERROR("Directory '" << dirName << 
     993                                        "' not found."); 
     994                                return 0; 
     995                        } 
     996                } 
     997 
     998                if(pFileNameOut) 
     999                { 
     1000                        *pFileNameOut = fileName; 
     1001                } 
     1002        } 
     1003 
     1004        BackupStoreFilenameClear fn(fileName); 
     1005 
     1006        // Need to look it up in the current directory 
     1007        mrConnection.QueryListDirectory( 
     1008                dirId, flagsInclude, flagsExclude, 
     1009                true /* do want attributes */); 
     1010 
     1011        // Retrieve the directory from the stream following 
     1012        BackupStoreDirectory dir; 
     1013        std::auto_ptr<IOStream> dirstream(mrConnection.ReceiveStream()); 
     1014        dir.ReadFromStream(*dirstream, mrConnection.GetTimeout()); 
     1015        BackupStoreDirectory::Entry *en; 
     1016 
     1017        if(opts['i']) 
     1018        { 
     1019                // Specified as ID.  
     1020                fileId = ::strtoll(rNameOrIdString.c_str(), 0, 16); 
     1021                if(fileId == std::numeric_limits<long long>::min() ||  
     1022                        fileId == std::numeric_limits<long long>::max() ||  
     1023                        fileId == 0) 
     1024                { 
     1025                        BOX_ERROR("Not a valid object ID (specified in hex)."); 
     1026                        return 0; 
     1027                } 
     1028                 
     1029                // Check that the item is actually in the directory 
     1030                en = dir.FindEntryByID(fileId); 
     1031                if(en == 0) 
     1032                { 
     1033                        BOX_ERROR("File ID " <<  
     1034                                BOX_FORMAT_OBJECTID(fileId) << 
     1035                                " not found in current directory on store.\n" 
     1036                                "(You can only access files by ID from the " 
     1037                                "current directory.)"); 
     1038                        return 0; 
     1039                } 
     1040        } 
     1041        else 
     1042        {                                
     1043                // Specified by name, find the object in the directory to get the ID 
     1044                BackupStoreDirectory::Iterator i(dir); 
     1045                en = i.FindMatchingClearName(fn); 
     1046                if(en == 0) 
     1047                { 
     1048                        BOX_ERROR("Filename '" << rNameOrIdString << "' " 
     1049                                "not found in current directory on store.\n" 
     1050                                "(Subdirectories in path not searched.)"); 
     1051                        return 0; 
     1052                } 
     1053                 
     1054                fileId = en->GetObjectID(); 
     1055        } 
     1056 
     1057        *pDirIdOut = dirId; 
     1058 
     1059        if(pFlagsOut) 
     1060        { 
     1061                *pFlagsOut = en->GetFlags(); 
     1062        } 
     1063 
     1064        return fileId; 
     1065} 
     1066 
    9381067 
    9391068// -------------------------------------------------------------------------- 
     
    9581087 
    9591088        // Find object ID somehow 
    960         int64_t fileId; 
    961         int64_t dirId = GetCurrentDirectoryID(); 
     1089        int64_t fileId, dirId; 
    9621090        std::string localName; 
    9631091 
    964         // BLOCK 
    965         { 
    9661092#ifdef WIN32 
    967                 for (std::vector<std::string>::iterator  
    968                         i = args.begin(); i != args.end(); i++) 
    969                 { 
    970                         std::string out; 
    971                         if(!ConvertConsoleToUtf8(i->c_str(), out)) 
    972                         { 
    973                                 BOX_ERROR("Failed to convert encoding."); 
    974                                 return; 
    975                         } 
    976                         *i = out; 
    977                 } 
    978 #endif 
    979  
    980                 std::string fileName(args[0]); 
    981  
    982                 if(!opts['i']) 
    983                 { 
    984                         // does this remote filename include a path? 
    985                         std::string::size_type index = fileName.rfind('/'); 
    986                         if(index != std::string::npos) 
    987                         { 
    988                                 std::string dirName(fileName.substr(0, index)); 
    989                                 fileName = fileName.substr(index + 1); 
    990  
    991                                 dirId = FindDirectoryObjectID(dirName); 
    992                                 if(dirId == 0) 
    993                                 { 
    994                                         BOX_ERROR("Directory '" << dirName << 
    995                                                 "' not found."); 
    996                                         return; 
    997                                 } 
    998                         } 
    999                 } 
    1000  
    1001                 BackupStoreFilenameClear fn(fileName); 
    1002  
    1003                 // Need to look it up in the current directory 
    1004                 mrConnection.QueryListDirectory( 
    1005                                 dirId, 
    1006                                 BackupProtocolClientListDirectory::Flags_File,  // just files 
    1007                                 (opts['i'])?(BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING):(BackupProtocolClientListDirectory::Flags_OldVersion | BackupProtocolClientListDirectory::Flags_Deleted), // only current versions 
    1008                                 false /* don't want attributes */); 
    1009  
    1010                 // Retrieve the directory from the stream following 
    1011                 BackupStoreDirectory dir; 
    1012                 std::auto_ptr<IOStream> dirstream(mrConnection.ReceiveStream()); 
    1013                 dir.ReadFromStream(*dirstream, mrConnection.GetTimeout()); 
    1014  
    1015                 if(opts['i']) 
    1016                 { 
    1017                         // Specified as ID.  
    1018                         fileId = ::strtoll(args[0].c_str(), 0, 16); 
    1019                         if(fileId == std::numeric_limits<long long>::min() ||  
    1020                                 fileId == std::numeric_limits<long long>::max() ||  
    1021                                 fileId == 0) 
    1022                         { 
    1023                                 BOX_ERROR("Not a valid object ID (specified in hex)."); 
    1024                                 return; 
    1025                         } 
    1026                          
    1027                         // Check that the item is actually in the directory 
    1028                         if(dir.FindEntryByID(fileId) == 0) 
    1029                         { 
    1030                                 BOX_ERROR("File ID " <<  
    1031                                         BOX_FORMAT_OBJECTID(fileId) << 
    1032                                         " not found in current " 
    1033                                         "directory on store.\n" 
    1034                                         "(You can only download files by ID " 
    1035                                         "from the current directory.)"); 
    1036                                 return; 
    1037                         } 
    1038                          
    1039                         // Must have a local name in the arguments (check at beginning of function ensures this) 
     1093        for (std::vector<std::string>::iterator  
     1094                i = args.begin(); i != args.end(); i++) 
     1095        { 
     1096                std::string out; 
     1097                if(!ConvertConsoleToUtf8(i->c_str(), out)) 
     1098                { 
     1099                        BOX_ERROR("Failed to convert encoding."); 
     1100                        return; 
     1101                } 
     1102                *i = out; 
     1103        } 
     1104#endif 
     1105 
     1106        int16_t flagsExclude; 
     1107 
     1108        if(opts['i']) 
     1109        { 
     1110                // can retrieve anything by ID 
     1111                flagsExclude = BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING; 
     1112        } 
     1113        else 
     1114        { 
     1115                // only current versions by name 
     1116                flagsExclude = 
     1117                        BackupProtocolClientListDirectory::Flags_OldVersion | 
     1118                        BackupProtocolClientListDirectory::Flags_Deleted; 
     1119        } 
     1120 
     1121 
     1122        fileId = FindFileID(args[0], opts, &dirId, &localName, 
     1123                BackupProtocolClientListDirectory::Flags_File, // just files 
     1124                flagsExclude, NULL /* don't care about flags found */); 
     1125 
     1126        if (fileId == 0) 
     1127        { 
     1128                // error already reported 
     1129                return; 
     1130        } 
     1131 
     1132        if(opts['i']) 
     1133        { 
     1134                // Specified as ID.  Must have a local name in the arguments 
     1135                // (check at beginning of function ensures this) 
     1136                localName = args[1]; 
     1137        } 
     1138        else 
     1139        {                                
     1140                // Specified by name. Local name already set by FindFileID, 
     1141                // but may be overridden by user supplying a second argument. 
     1142                if(args.size() == 2) 
     1143                { 
    10401144                        localName = args[1]; 
    1041                 } 
    1042                 else 
    1043                 {                                
    1044                         // Specified by name, find the object in the directory to get the ID 
    1045                         BackupStoreDirectory::Iterator i(dir); 
    1046                         BackupStoreDirectory::Entry *en = i.FindMatchingClearName(fn); 
    1047                          
    1048                         if(en == 0) 
    1049                         { 
    1050                                 BOX_ERROR("Filename '" << args[0] << "' " 
    1051                                         "not found in current " 
    1052                                         "directory on store.\n" 
    1053                                         "(Subdirectories in path not " 
    1054                                         "searched.)"); 
    1055                                 return; 
    1056                         } 
    1057                          
    1058                         fileId = en->GetObjectID(); 
    1059                          
    1060                         // Local name is the last argument, which is either  
    1061                         // the looked up filename, or a filename specified  
    1062                         // by the user. 
    1063                         localName = args[args.size() - 1]; 
    10641145                } 
    10651146        } 
     
    22112292void BackupQueries::CommandUndelete(const std::vector<std::string> &args, const bool *opts) 
    22122293{ 
     2294        if (!mReadWrite) 
     2295        { 
     2296                BOX_ERROR("This command requires a read-write connection. " 
     2297                        "Please reconnect with the -w option."); 
     2298                return; 
     2299        } 
     2300 
    22132301        // Check arguments 
    22142302        if(args.size() != 1) 
    22152303        { 
    2216                 BOX_ERROR("Incorrect usage. undelete <directory-name>"); 
     2304                BOX_ERROR("Incorrect usage. undelete <name> or undelete -i <object-id>"); 
    22172305                return; 
    22182306        } 
     
    22242312        const std::string& storeDirEncoded(args[0]); 
    22252313#endif 
    2226          
    2227         // Get directory ID 
    2228         int64_t dirID = FindDirectoryObjectID(storeDirEncoded,  
    2229                 false /* no old versions */, true /* find deleted dirs */); 
    2230          
    2231         // Allowable? 
    2232         if(dirID == 0) 
    2233         { 
    2234                 BOX_ERROR("Directory '" << args[0] << "' not found on server."); 
    2235                 return; 
    2236         } 
    2237         if(dirID == BackupProtocolClientListDirectory::RootDirectory) 
    2238         { 
    2239                 BOX_ERROR("Cannot undelete the root directory."); 
    2240                 return; 
    2241         } 
    2242  
    2243         // Undelete 
    2244         mrConnection.QueryUndeleteDirectory(dirID); 
    2245 } 
     2314 
     2315        // Find object ID somehow 
     2316        int64_t fileId, parentId; 
     2317        std::string fileName; 
     2318        int16_t flagsOut; 
     2319 
     2320        fileId = FindFileID(storeDirEncoded, opts, &parentId, &fileName, 
     2321                /* include files and directories */ 
     2322                BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, 
     2323                /* include old and deleted files */ 
     2324                BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, 
     2325                &flagsOut); 
     2326 
     2327        if (fileId == 0) 
     2328        { 
     2329                // error already reported 
     2330                return; 
     2331        } 
     2332 
     2333        // Undelete it on the store 
     2334        try 
     2335        { 
     2336                // Undelete object 
     2337                if(flagsOut & BackupProtocolClientListDirectory::Flags_File) 
     2338                { 
     2339                        mrConnection.QueryUndeleteFile(parentId, fileId); 
     2340                } 
     2341                else 
     2342                { 
     2343                        mrConnection.QueryUndeleteDirectory(fileId); 
     2344                } 
     2345        } 
     2346        catch (BoxException &e) 
     2347        { 
     2348                BOX_ERROR("Failed to undelete object: " <<  
     2349                        e.what()); 
     2350        } 
     2351        catch(std::exception &e) 
     2352        { 
     2353                BOX_ERROR("Failed to undelete object: " << 
     2354                        e.what()); 
     2355        } 
     2356        catch(...) 
     2357        { 
     2358                BOX_ERROR("Failed to undelete object: unknown error"); 
     2359        } 
     2360} 
     2361 
     2362// -------------------------------------------------------------------------- 
     2363// 
     2364// Function 
     2365//              Name:    BackupQueries::CommandDelete(const 
     2366//                       std::vector<std::string> &, const bool *) 
     2367//              Purpose: Deletes a file 
     2368//              Created: 23/11/03 
     2369// 
     2370// -------------------------------------------------------------------------- 
     2371void BackupQueries::CommandDelete(const std::vector<std::string> &args, 
     2372        const bool *opts) 
     2373{ 
     2374        if (!mReadWrite) 
     2375        { 
     2376                BOX_ERROR("This command requires a read-write connection. " 
     2377                        "Please reconnect with the -w option."); 
     2378                return; 
     2379        } 
     2380 
     2381        // Check arguments 
     2382        if(args.size() != 1) 
     2383        { 
     2384                BOX_ERROR("Incorrect usage. delete <name>"); 
     2385                return; 
     2386        } 
     2387 
     2388#ifdef WIN32 
     2389        std::string storeDirEncoded; 
     2390        if(!ConvertConsoleToUtf8(args[0].c_str(), storeDirEncoded)) return; 
     2391#else 
     2392        const std::string& storeDirEncoded(args[0]); 
     2393#endif 
     2394 
     2395        // Find object ID somehow 
     2396        int64_t fileId, parentId; 
     2397        std::string fileName; 
     2398        int16_t flagsOut; 
     2399 
     2400        fileId = FindFileID(storeDirEncoded, opts, &parentId, &fileName, 
     2401                /* include files and directories */ 
     2402                BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, 
     2403                /* exclude old and deleted files */ 
     2404                BackupProtocolClientListDirectory::Flags_OldVersion | 
     2405                BackupProtocolClientListDirectory::Flags_Deleted, 
     2406                &flagsOut); 
     2407 
     2408        if (fileId == 0) 
     2409        { 
     2410                // error already reported 
     2411                return; 
     2412        } 
     2413 
     2414        BackupStoreFilenameClear fn(fileName); 
     2415 
     2416        // Delete it on the store 
     2417        try 
     2418        { 
     2419                // Delete object 
     2420                if(flagsOut & BackupProtocolClientListDirectory::Flags_File) 
     2421                { 
     2422                        mrConnection.QueryDeleteFile(parentId, fn); 
     2423                } 
     2424                else 
     2425                { 
     2426                        mrConnection.QueryDeleteDirectory(fileId); 
     2427                } 
     2428        } 
     2429        catch (BoxException &e) 
     2430        { 
     2431                BOX_ERROR("Failed to delete object: " <<  
     2432                        e.what()); 
     2433        } 
     2434        catch(std::exception &e) 
     2435        { 
     2436                BOX_ERROR("Failed to delete object: " << 
     2437                        e.what()); 
     2438        } 
     2439        catch(...) 
     2440        { 
     2441                BOX_ERROR("Failed to delete object: unknown error"); 
     2442        } 
     2443} 
  • box/trunk/bin/bbackupquery/BackupQueries.h

    r2263 r2283  
    3131{ 
    3232public: 
    33         BackupQueries(BackupProtocolClient &rConnection, const Configuration &rConfiguration); 
     33        BackupQueries(BackupProtocolClient &rConnection, 
     34                const Configuration &rConfiguration, 
     35                bool readWrite); 
    3436        ~BackupQueries(); 
    3537private: 
     
    5557        void CommandRestore(const std::vector<std::string> &args, const bool *opts); 
    5658        void CommandUndelete(const std::vector<std::string> &args, const bool *opts); 
     59        void CommandDelete(const std::vector<std::string> &args, 
     60                const bool *opts); 
    5761        void CommandUsage(); 
    58         void CommandUsageDisplayEntry(const char *Name, int64_t Size, int64_t HardLimit, int32_t BlockSize); 
     62        void CommandUsageDisplayEntry(const char *Name, int64_t Size, 
     63                int64_t HardLimit, int32_t BlockSize); 
    5964        void CommandHelp(const std::vector<std::string> &args); 
    6065 
    6166        // Implementations 
    62         void List(int64_t DirID, const std::string &rListRoot, const bool *opts, bool FirstLevel); 
     67        void List(int64_t DirID, const std::string &rListRoot, const bool *opts, 
     68                bool FirstLevel); 
    6369         
    6470public: 
     
    106112 
    107113        // Utility functions 
    108         int64_t FindDirectoryObjectID(const std::string &rDirName, bool AllowOldVersion = false, 
    109                 bool AllowDeletedDirs = false, std::vector<std::pair<std::string, int64_t> > *pStack = 0); 
     114        int64_t FindDirectoryObjectID(const std::string &rDirName, 
     115                bool AllowOldVersion = false, bool AllowDeletedDirs = false, 
     116                std::vector<std::pair<std::string, int64_t> > *pStack = 0); 
     117        int64_t FindFileID(const std::string& rNameOrIdString, 
     118                const bool *opts, int64_t *pDirIdOut, 
     119                std::string* pFileNameOut, int16_t flagsInclude, 
     120                int16_t flagsExclude, int16_t* pFlagsOut); 
    110121        int64_t GetCurrentDirectoryID(); 
    111122        std::string GetCurrentDirectoryName(); 
     
    113124 
    114125private: 
     126        bool mReadWrite; 
    115127        BackupProtocolClient &mrConnection; 
    116128        const Configuration &mrConfiguration; 
  • box/trunk/bin/bbackupquery/bbackupquery.cpp

    r2184 r2283  
    309309         
    310310        // Set up a context for our work 
    311         BackupQueries context(connection, conf); 
     311        BackupQueries context(connection, conf, readWrite); 
    312312         
    313313        // Start running commands... first from the command line 
  • box/trunk/bin/bbackupquery/documentation.txt

    r2157 r2283  
    160160< 
    161161 
     162> undelete <directory-name> 
     163undelete -i <object-id> 
     164 
     165        Removes the deleted flag from the specified directory name (in the 
     166        current directory) or hex object ID. Be careful not to use this 
     167        command where a directory already exists with the same name which is 
     168        not marked as deleted. 
     169< 
     170 
     171> delete <file-name> 
     172 
     173        Sets the deleted flag on the specified file name (in the current 
     174        directory, or with a relative path). 
     175< 
     176 
    162177> quit 
    163178