// =-=-=-=-=-=-=- // local function to call readdir via resource plugin int _rsFileReaddir( rsComm_t* _comm, fileReaddirInp_t* _file_readdir_inp, rodsDirent_t** _rods_dirent ) { // =-=-=-=-=-=-=- // create a collection_object, and extract dir ptr from the file desc table irods::collection_object_ptr coll_obj( new irods::collection_object( FileDesc[ _file_readdir_inp->fileInx].fileName, FileDesc[ _file_readdir_inp->fileInx].rescHier, 0, 0 ) ); coll_obj->directory_pointer( reinterpret_cast< DIR* >( FileDesc[ _file_readdir_inp->fileInx].driverDep ) ); // =-=-=-=-=-=-=- // make call to readdir via resource plugin and handle errors, if necessary irods::error readdir_err = fileReaddir( _comm, coll_obj, _rods_dirent ); if ( !readdir_err.ok() ) { std::stringstream msg; msg << "fileReaddir failed for ["; msg << FileDesc[ _file_readdir_inp->fileInx].fileName; msg << "]"; irods::error err = PASSMSG( msg.str(), readdir_err ); irods::log( err ); return readdir_err.code(); } else { // =-=-=-=-=-=-=- // case for handle end of file if ( -1 == readdir_err.code() ) { return readdir_err.code(); } } // =-=-=-=-=-=-=- // error code holds 'status' of api call return readdir_err.code(); } // _rsFileReaddir
// =-=-=-=-=-=-=- // int chkEmptyDir( rsComm_t* rsComm, const std::string& cacheDir, const std::string& hier ) { int status = 0; char childPath[MAX_NAME_LEN]; struct stat myFileStat; struct rodsDirent* myFileDirent = 0; // =-=-=-=-=-=-=- // call opendir via resource plugin irods::collection_object_ptr cacheDir_obj( new irods::collection_object( cacheDir, hier, 0, 0 ) ); irods::error opendir_err = fileOpendir( rsComm, cacheDir_obj ); // =-=-=-=-=-=-=- // don't log an error as this is part // of the functionality of this code if ( !opendir_err.ok() ) { return 0; } // =-=-=-=-=-=-=- // make call to readdir via resource plugin irods::error readdir_err = fileReaddir( rsComm, cacheDir_obj, &myFileDirent ); while ( readdir_err.ok() && 0 == readdir_err.code() ) { // =-=-=-=-=-=-=- // handle relative paths if ( strcmp( myFileDirent->d_name, "." ) == 0 || strcmp( myFileDirent->d_name, ".." ) == 0 ) { readdir_err = fileReaddir( rsComm, cacheDir_obj, &myFileDirent ); continue; } // =-=-=-=-=-=-=- // get status of path snprintf( childPath, MAX_NAME_LEN, "%s/%s", cacheDir.c_str(), myFileDirent->d_name ); irods::collection_object_ptr tmp_coll_obj( new irods::collection_object( childPath, hier, 0, 0 ) ); irods::error stat_err = fileStat( rsComm, tmp_coll_obj, &myFileStat ); // =-=-=-=-=-=-=- // handle hard error if ( stat_err.code() < 0 ) { rodsLog( LOG_ERROR, "chkEmptyDir: fileStat error for %s, status = %d", childPath, stat_err.code() ); break; } // =-=-=-=-=-=-=- // path exists if ( myFileStat.st_mode & S_IFREG ) { status = SYS_DIR_IN_VAULT_NOT_EMPTY; rodsLog( LOG_ERROR, "chkEmptyDir: file %s exists", childPath, status ); break; } // =-=-=-=-=-=-=- // recurse for another directory if ( myFileStat.st_mode & S_IFDIR ) { status = chkEmptyDir( rsComm, childPath, hier ); if ( status == SYS_DIR_IN_VAULT_NOT_EMPTY ) { rodsLog( LOG_ERROR, "chkEmptyDir: dir %s is not empty", childPath ); break; } } // =-=-=-=-=-=-=- // continue with child path readdir_err = fileReaddir( rsComm, cacheDir_obj, &myFileDirent ); } // while // =-=-=-=-=-=-=- // make call to closedir via resource plugin, log error if necessary irods::error closedir_err = fileClosedir( rsComm, cacheDir_obj ); if ( !closedir_err.ok() ) { std::stringstream msg; msg << "fileClosedir failed for ["; msg << cacheDir; msg << "]"; irods::error log_err = PASSMSG( msg.str(), closedir_err ); irods::log( log_err ); } if ( status != SYS_DIR_IN_VAULT_NOT_EMPTY ) { irods::collection_object_ptr coll_obj( new irods::collection_object( cacheDir, hier, 0, 0 ) ); irods::error rmdir_err = fileRmdir( rsComm, coll_obj ); if ( !rmdir_err.ok() ) { std::stringstream msg; msg << "fileRmdir failed for ["; msg << cacheDir; msg << "]"; irods::error err = PASSMSG( msg.str(), rmdir_err ); irods::log( err ); } status = 0; } return status; } // chkEmptyDir
int chkEmptyDir (int fileType, rsComm_t *rsComm, char *cacheDir) { void *dirPtr = NULL; #if defined(solaris_platform) char fileDirent[sizeof (struct dirent) + MAX_NAME_LEN]; struct dirent *myFileDirent = (struct dirent *) fileDirent; #else struct dirent fileDirent; struct dirent *myFileDirent = &fileDirent; #endif int status; char childPath[MAX_NAME_LEN]; struct stat myFileStat; status = fileOpendir ((fileDriverType_t)fileType, rsComm, cacheDir, &dirPtr); if (status < 0) { return (0); } while ((status = fileReaddir ((fileDriverType_t)fileType, rsComm, dirPtr, myFileDirent)) >= 0) { if (strcmp (myFileDirent->d_name, ".") == 0 || strcmp (myFileDirent->d_name, "..") == 0) { continue; } snprintf (childPath, MAX_NAME_LEN, "%s/%s", cacheDir, myFileDirent->d_name); status = fileStat ((fileDriverType_t)fileType, rsComm, childPath, &myFileStat); if (status < 0) { rodsLog (LOG_ERROR, "chkEmptyDir: fileStat error for %s, status = %d", childPath, status); break; } if (myFileStat.st_mode & S_IFREG) { rodsLog (LOG_ERROR, "chkEmptyDir: file %s exists", childPath, status); status = SYS_DIR_IN_VAULT_NOT_EMPTY; break; } if (myFileStat.st_mode & S_IFDIR) { status = chkEmptyDir ((fileDriverType_t)fileType, rsComm, childPath); if (status == SYS_DIR_IN_VAULT_NOT_EMPTY) { rodsLog (LOG_ERROR, "chkEmptyDir: dir %s is not empty", childPath); break; } } } fileClosedir ((fileDriverType_t)fileType, rsComm, dirPtr); if (status != SYS_DIR_IN_VAULT_NOT_EMPTY) { fileRmdir ((fileDriverType_t)fileType, rsComm, cacheDir); status = 0; } return status; }
// =-=-=-=-=-=-=- // local function which handles removing directories via the resource plugin int _rsFileRmdir( rsComm_t* _comm, fileRmdirInp_t* _rmdir_inp ) { irods::collection_object_ptr coll_obj( new irods::collection_object( _rmdir_inp->dirName, _rmdir_inp->rescHier, 0, 0 ) ); if ( ( _rmdir_inp->flags & RMDIR_RECUR ) != 0 ) { // FIXME :: revisit this after moving to First class Objects // recursive. This is a very dangerous operation. curently // it is only used to remove cache directory of structured // files struct rodsDirent* myFileDirent = 0; // if it is not a cache dir, return an error as we only do this // for cache dirs at the moment. if ( strstr( _rmdir_inp->dirName, CACHE_DIR_STR ) == NULL ) { rodsLog( LOG_ERROR, "_rsFileRmdir: recursive rm of non cachedir path %s", _rmdir_inp->dirName ); return SYS_INVALID_FILE_PATH; } // call opendir via resource plugin irods::error opendir_err = fileOpendir( _comm, coll_obj ); // log an error, if any if ( !opendir_err.ok() ) { std::stringstream msg; msg << "fileOpendir failed for ["; msg << _rmdir_inp->dirName; msg << "]"; irods::error err = PASSMSG( msg.str(), opendir_err ); irods::log( err ); return opendir_err.code(); } // read the directory via resource plugin and either handle files or recurse into another directory irods::error readdir_err = fileReaddir( _comm, coll_obj, &myFileDirent ); while ( readdir_err.ok() && 0 == readdir_err.code() ) { struct stat statbuf; char myPath[MAX_NAME_LEN]; // handle relative paths if ( strcmp( myFileDirent->d_name, "." ) == 0 || strcmp( myFileDirent->d_name, ".." ) == 0 ) { readdir_err = fileReaddir( _comm, coll_obj, &myFileDirent ); continue; } // cache path name snprintf( myPath, MAX_NAME_LEN, "%s/%s", &_rmdir_inp->dirName[0], &myFileDirent->d_name[0] ); // =-=-=-=-=-=-=- // call stat via resource plugin, handle errors irods::collection_object_ptr myPath_obj( new irods::collection_object( myPath, _rmdir_inp->rescHier, 0, 0 ) ); irods::error stat_err = fileStat( _comm, myPath_obj, &statbuf ); if ( !stat_err.ok() ) { std::stringstream msg; msg << "fileStat failed for ["; msg << myPath; msg << "]"; irods::error log_err = PASSMSG( msg.str(), stat_err ); irods::log( log_err ); // call closedir via resource plugin, handle errors irods::error closedir_err = fileClosedir( _comm, myPath_obj ); if ( !closedir_err.ok() ) { std::stringstream msg; msg << "fileClosedir for ["; msg << myPath; msg << "]"; irods::error log_err = PASSMSG( msg.str(), closedir_err ); irods::log( log_err ); } return stat_err.code(); } // if !stat_err.ok() // filter based on stat results: file, dir, or error int status = 0; if ( ( statbuf.st_mode & S_IFREG ) != 0 ) { // handle case where file is found irods::error unlink_err = fileUnlink( _comm, myPath_obj ); status = unlink_err.code(); if ( !unlink_err.ok() ) { irods::error log_err = PASSMSG( "error during unlink.", unlink_err ); irods::log( log_err ); } } else if ( ( statbuf.st_mode & S_IFDIR ) != 0 ) { // handle case where directory is found fileRmdirInp_t myRmdirInp; memset( &myRmdirInp, 0, sizeof( myRmdirInp ) ); myRmdirInp.flags = _rmdir_inp->flags; rstrcpy( myRmdirInp.dirName, myPath, MAX_NAME_LEN ); rstrcpy( myRmdirInp.rescHier, _rmdir_inp->rescHier, MAX_NAME_LEN ); // RECURSE - call _rsFileRmdir on this new found directory status = _rsFileRmdir( _comm, &myRmdirInp ); } else { status = SYS_INVALID_FILE_PATH; rodsLog( LOG_NOTICE, "_rsFileRmdir: for %s, status = %d", myPath, status ); } // handle error condition on the above three cases if ( status < 0 ) { rodsLog( LOG_NOTICE, "_rsFileRmdir: rm of %s failed, status = %d", myPath, status ); // call closedir via resource plugin, handle errors irods::error closedir_err = fileClosedir( _comm, myPath_obj ); if ( !closedir_err.ok() ) { std::stringstream msg; msg << "fileClosedir failed for ["; msg << myPath; msg << "]"; irods::error log_err = PASSMSG( msg.str(), closedir_err ); irods::log( log_err ); } return status; } // if status < 0 // =-=-=-=-=-=-=- // continue readdir via resource plugin readdir_err = fileReaddir( _comm, coll_obj, &myFileDirent ); } // while // =-=-=-=-=-=-=- // call closedir via resource plugin, handle errors irods::error closedir_err = fileClosedir( _comm, coll_obj ); if ( !closedir_err.ok() ) { std::stringstream msg; msg << "fileClosedir failed for ["; msg << _rmdir_inp->dirName; msg << "]"; irods::error log_err = PASSMSG( msg.str(), closedir_err ); irods::log( log_err ); } } // if RMDIR_RECUR ( recursive delete ) // =-=-=-=-=-=-=- // make the call to rmdir via the resource plugin irods::error rmdir_err = fileRmdir( _comm, coll_obj ); if ( !rmdir_err.ok() ) { std::stringstream msg; msg << "fileRmdir failed for ["; msg << _rmdir_inp->dirName; msg << "]"; irods::error err = PASSMSG( msg.str(), rmdir_err ); irods::log( err ); } return rmdir_err.code(); } // _rsFileRmdir