@ -1265,16 +1265,28 @@ func (s *posix) StatFile(volume, path string) (file FileInfo, err error) {
} , nil
}
// deleteFile deletes a file path if its empty. If it's successfully deleted,
// it will recursively move up the tree, deleting empty parent directories
// until it finds one with files in it. Returns nil for a non-empty directory.
func deleteFile ( basePath , deletePath string ) error {
if basePath == deletePath {
// deleteFile deletes a file or a directory if its empty unless recursive
// is set to true. If the target is successfully deleted, it will recursively
// move up the tree, deleting empty parent directories until it finds one
// with files in it. Returns nil for a non-empty directory even when
// recursive is set to false.
func deleteFile ( basePath , deletePath string , recursive bool ) error {
if basePath == "" || deletePath == "" {
return nil
}
basePath = filepath . Clean ( basePath )
deletePath = filepath . Clean ( deletePath )
if ! strings . HasPrefix ( deletePath , basePath ) || deletePath == basePath {
return nil
}
// Attempt to remove path.
if err := os . Remove ( ( deletePath ) ) ; err != nil {
var err error
if recursive {
err = os . RemoveAll ( deletePath )
} else {
err = os . Remove ( deletePath )
}
if err != nil {
switch {
case isSysErrNotEmpty ( err ) :
// Ignore errors if the directory is not empty. The server relies on
@ -1297,12 +1309,58 @@ func deleteFile(basePath, deletePath string) error {
deletePath = strings . TrimSuffix ( deletePath , SlashSeparator )
deletePath = slashpath . Dir ( deletePath )
// Delete parent directory. Errors for parent directories shouldn't trickle down.
deleteFile ( basePath , deletePath )
// Delete parent directory obviously not recursively. Errors for
// parent directories shouldn't trickle down.
deleteFile ( basePath , deletePath , false )
return nil
}
// DeletePrefixes forcibly deletes all the contents of a set of specified paths.
// Parent directories are automatically removed if they become empty. err can
// bil nil while errs can contain some errors for corresponding objects. No error
// is set if a specified prefix path does not exist.
func ( s * posix ) DeletePrefixes ( volume string , paths [ ] string ) ( errs [ ] error , err error ) {
atomic . AddInt32 ( & s . activeIOCount , 1 )
defer func ( ) {
atomic . AddInt32 ( & s . activeIOCount , - 1 )
} ( )
volumeDir , err := s . getVolDir ( volume )
if err != nil {
return nil , err
}
// Stat a volume entry.
_ , err = os . Stat ( volumeDir )
if err != nil {
if os . IsNotExist ( err ) {
return nil , errVolumeNotFound
} else if os . IsPermission ( err ) {
return nil , errVolumeAccessDenied
} else if isSysErrIO ( err ) {
return nil , errFaultyDisk
}
return nil , err
}
errs = make ( [ ] error , len ( paths ) )
// Following code is needed so that we retain SlashSeparator
// suffix if any in path argument.
for idx , path := range paths {
filePath := pathJoin ( volumeDir , path )
errs [ idx ] = checkPathLength ( filePath )
if errs [ idx ] != nil {
continue
}
// Delete file or a directory recursively, delete parent
// directory as well if its empty.
errs [ idx ] = deleteFile ( volumeDir , filePath , true )
}
return
}
// DeleteFile - delete a file at path.
func ( s * posix ) DeleteFile ( volume , path string ) ( err error ) {
atomic . AddInt32 ( & s . activeIOCount , 1 )
@ -1316,7 +1374,7 @@ func (s *posix) DeleteFile(volume, path string) (err error) {
}
// Stat a volume entry.
_ , err = os . Stat ( ( volumeDir ) )
_ , err = os . Stat ( volumeDir )
if err != nil {
if os . IsNotExist ( err ) {
return errVolumeNotFound
@ -1331,12 +1389,12 @@ func (s *posix) DeleteFile(volume, path string) (err error) {
// Following code is needed so that we retain SlashSeparator suffix if any in
// path argument.
filePath := pathJoin ( volumeDir , path )
if err = checkPathLength ( ( filePath ) ) ; err != nil {
if err = checkPathLength ( filePath ) ; err != nil {
return err
}
// Delete file and delete parent directory as well if its empty.
return deleteFile ( volumeDir , filePath )
return deleteFile ( volumeDir , filePath , false )
}
func ( s * posix ) DeleteFileBulk ( volume string , paths [ ] string ) ( errs [ ] error , err error ) {
@ -1373,7 +1431,7 @@ func (s *posix) DeleteFileBulk(volume string, paths []string) (errs []error, err
continue
}
// Delete file and delete parent directory as well if its empty.
errs [ idx ] = deleteFile ( volumeDir , filePath )
errs [ idx ] = deleteFile ( volumeDir , filePath , false )
}
return
}
@ -1460,7 +1518,7 @@ func (s *posix) RenameFile(srcVolume, srcPath, dstVolume, dstPath string) (err e
// Remove parent dir of the source file if empty
if parentDir := slashpath . Dir ( srcFilePath ) ; isDirEmpty ( parentDir ) {
deleteFile ( srcVolumeDir , parentDir )
deleteFile ( srcVolumeDir , parentDir , false )
}
return nil