@ -128,28 +128,8 @@ func checkDiskFree(diskPath string, minFreeDisk int64) (err error) {
return nil
return nil
}
}
func removeDuplicateVols ( volsInfo [ ] VolInfo ) [ ] VolInfo {
// List all the volumes from diskPath.
// Use map to record duplicates as we find them.
func listVols ( dirPath string ) ( [ ] VolInfo , error ) {
result := [ ] VolInfo { }
m := make ( map [ string ] VolInfo )
for _ , v := range volsInfo {
if _ , found := m [ v . Name ] ; ! found {
m [ v . Name ] = v
}
}
result = make ( [ ] VolInfo , 0 , len ( m ) )
for _ , v := range m {
result = append ( result , v )
}
// Return the new slice.
return result
}
// gets all the unique directories from diskPath.
func getAllUniqueVols ( dirPath string ) ( [ ] VolInfo , error ) {
if err := checkPathLength ( dirPath ) ; err != nil {
if err := checkPathLength ( dirPath ) ; err != nil {
return nil , err
return nil , err
}
}
@ -179,14 +159,14 @@ func getAllUniqueVols(dirPath string) ([]VolInfo, error) {
Created : fi . ModTime ( ) ,
Created : fi . ModTime ( ) ,
} )
} )
}
}
return removeDuplicateVols ( volsInfo ) , nil
return volsInfo , nil
}
}
// getVolume Dir - will convert incoming volume names to
// getVolDir - will convert incoming volume names to
// corresponding valid volume names on the backend in a platform
// corresponding valid volume names on the backend in a platform
// compatible way for all operating systems. If volume is not found
// compatible way for all operating systems. If volume is not found
// an error is generated.
// an error is generated.
func ( s fsStorage ) getVolume Dir ( volume string ) ( string , error ) {
func ( s fsStorage ) getVolDir ( volume string ) ( string , error ) {
if ! isValidVolname ( volume ) {
if ! isValidVolname ( volume ) {
return "" , errInvalidArgument
return "" , errInvalidArgument
}
}
@ -194,30 +174,7 @@ func (s fsStorage) getVolumeDir(volume string) (string, error) {
return "" , err
return "" , err
}
}
volumeDir := pathJoin ( s . diskPath , volume )
volumeDir := pathJoin ( s . diskPath , volume )
_ , err := os . Stat ( volumeDir )
return volumeDir , nil
if err == nil {
return volumeDir , nil
}
if os . IsNotExist ( err ) {
var volsInfo [ ] VolInfo
volsInfo , err = getAllUniqueVols ( s . diskPath )
if err != nil {
// For any errors, treat it as disk not found.
return volumeDir , err
}
for _ , vol := range volsInfo {
// Verify if lowercase version of the volume is equal to
// the incoming volume, then use the proper name.
if strings . ToLower ( vol . Name ) == volume {
volumeDir = pathJoin ( s . diskPath , vol . Name )
return volumeDir , nil
}
}
return volumeDir , errVolumeNotFound
} else if os . IsPermission ( err ) {
return volumeDir , errVolumeAccessDenied
}
return volumeDir , err
}
}
// Make a volume entry.
// Make a volume entry.
@ -227,20 +184,17 @@ func (s fsStorage) MakeVol(volume string) (err error) {
return err
return err
}
}
volumeDir , err := s . getVolumeDir ( volume )
volumeDir , err := s . getVolDir ( volume )
if err == nil {
if err != nil {
// Volume already exists, return error.
return err
return errVolumeExists
}
}
// Make a volume entry.
// If volume not found create it.
err = os . Mkdir ( volumeDir , 0700 )
if err == errVolumeNotFound {
if err != nil && os . IsExist ( err ) {
// Make a volume entry.
return errVolumeExists
return os . Mkdir ( volumeDir , 0700 )
}
}
// Success
// For all other errors return here.
return nil
return err
}
}
// ListVols - list volumes.
// ListVols - list volumes.
@ -251,7 +205,7 @@ func (s fsStorage) ListVols() (volsInfo []VolInfo, err error) {
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
volsInfo , err = getAllUnique Vols( s . diskPath )
volsInfo , err = list Vols( s . diskPath )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
@ -275,7 +229,7 @@ func (s fsStorage) ListVols() (volsInfo []VolInfo, err error) {
// StatVol - get volume info.
// StatVol - get volume info.
func ( s fsStorage ) StatVol ( volume string ) ( volInfo VolInfo , err error ) {
func ( s fsStorage ) StatVol ( volume string ) ( volInfo VolInfo , err error ) {
// Verify if volume is valid and it exists.
// Verify if volume is valid and it exists.
volumeDir , err := s . getVolume Dir ( volume )
volumeDir , err := s . getVolDir ( volume )
if err != nil {
if err != nil {
return VolInfo { } , err
return VolInfo { } , err
}
}
@ -309,7 +263,7 @@ func (s fsStorage) StatVol(volume string) (volInfo VolInfo, err error) {
// DeleteVol - delete a volume.
// DeleteVol - delete a volume.
func ( s fsStorage ) DeleteVol ( volume string ) error {
func ( s fsStorage ) DeleteVol ( volume string ) error {
// Verify if volume is valid and it exists.
// Verify if volume is valid and it exists.
volumeDir , err := s . getVolume Dir ( volume )
volumeDir , err := s . getVolDir ( volume )
if err != nil {
if err != nil {
return err
return err
}
}
@ -321,8 +275,7 @@ func (s fsStorage) DeleteVol(volume string) error {
// On windows the string is slightly different, handle it here.
// On windows the string is slightly different, handle it here.
return errVolumeNotEmpty
return errVolumeNotEmpty
} else if strings . Contains ( err . Error ( ) , "directory not empty" ) {
} else if strings . Contains ( err . Error ( ) , "directory not empty" ) {
// Hopefully for all other
// Hopefully for all other operating systems, this is
// operating systems, this is
// assumed to be consistent.
// assumed to be consistent.
return errVolumeNotEmpty
return errVolumeNotEmpty
}
}
@ -335,7 +288,7 @@ func (s fsStorage) DeleteVol(volume string) error {
// If an entry is a directory it will be returned with a trailing "/".
// If an entry is a directory it will be returned with a trailing "/".
func ( s fsStorage ) ListDir ( volume , dirPath string ) ( [ ] string , error ) {
func ( s fsStorage ) ListDir ( volume , dirPath string ) ( [ ] string , error ) {
// Verify if volume is valid and it exists.
// Verify if volume is valid and it exists.
volumeDir , err := s . getVolume Dir ( volume )
volumeDir , err := s . getVolDir ( volume )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
@ -352,8 +305,16 @@ func (s fsStorage) ListDir(volume, dirPath string) ([]string, error) {
// ReadFile - read a file at a given offset.
// ReadFile - read a file at a given offset.
func ( s fsStorage ) ReadFile ( volume string , path string , offset int64 ) ( readCloser io . ReadCloser , err error ) {
func ( s fsStorage ) ReadFile ( volume string , path string , offset int64 ) ( readCloser io . ReadCloser , err error ) {
volumeDir , err := s . getVolumeDir ( volume )
volumeDir , err := s . getVolDir ( volume )
if err != nil {
return nil , err
}
// Stat a volume entry.
_ , err = os . Stat ( volumeDir )
if err != nil {
if err != nil {
if os . IsNotExist ( err ) {
return nil , errVolumeNotFound
}
return nil , err
return nil , err
}
}
@ -388,10 +349,18 @@ func (s fsStorage) ReadFile(volume string, path string, offset int64) (readClose
// CreateFile - create a file at path.
// CreateFile - create a file at path.
func ( s fsStorage ) CreateFile ( volume , path string ) ( writeCloser io . WriteCloser , err error ) {
func ( s fsStorage ) CreateFile ( volume , path string ) ( writeCloser io . WriteCloser , err error ) {
volumeDir , err := s . getVolume Dir ( volume )
volumeDir , err := s . getVolDir ( volume )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
// Stat a volume entry.
_ , err = os . Stat ( volumeDir )
if err != nil {
if os . IsNotExist ( err ) {
return nil , errVolumeNotFound
}
return nil , err
}
if err = checkDiskFree ( s . diskPath , s . minFreeDisk ) ; err != nil {
if err = checkDiskFree ( s . diskPath , s . minFreeDisk ) ; err != nil {
return nil , err
return nil , err
}
}
@ -419,8 +388,16 @@ func (s fsStorage) CreateFile(volume, path string) (writeCloser io.WriteCloser,
// StatFile - get file info.
// StatFile - get file info.
func ( s fsStorage ) StatFile ( volume , path string ) ( file FileInfo , err error ) {
func ( s fsStorage ) StatFile ( volume , path string ) ( file FileInfo , err error ) {
volumeDir , err := s . getVolumeDir ( volume )
volumeDir , err := s . getVolDir ( volume )
if err != nil {
return FileInfo { } , err
}
// Stat a volume entry.
_ , err = os . Stat ( volumeDir )
if err != nil {
if err != nil {
if os . IsNotExist ( err ) {
return FileInfo { } , errVolumeNotFound
}
return FileInfo { } , err
return FileInfo { } , err
}
}
@ -489,8 +466,16 @@ func deleteFile(basePath, deletePath string) error {
// DeleteFile - delete a file at path.
// DeleteFile - delete a file at path.
func ( s fsStorage ) DeleteFile ( volume , path string ) error {
func ( s fsStorage ) DeleteFile ( volume , path string ) error {
volumeDir , err := s . getVolumeDir ( volume )
volumeDir , err := s . getVolDir ( volume )
if err != nil {
return err
}
// Stat a volume entry.
_ , err = os . Stat ( volumeDir )
if err != nil {
if err != nil {
if os . IsNotExist ( err ) {
return errVolumeNotFound
}
return err
return err
}
}
@ -507,14 +492,29 @@ func (s fsStorage) DeleteFile(volume, path string) error {
// RenameFile - rename file.
// RenameFile - rename file.
func ( s fsStorage ) RenameFile ( srcVolume , srcPath , dstVolume , dstPath string ) error {
func ( s fsStorage ) RenameFile ( srcVolume , srcPath , dstVolume , dstPath string ) error {
srcVolumeDir , err := s . getVolumeDir ( srcVolume )
srcVolumeDir , err := s . getVolDir ( srcVolume )
if err != nil {
return err
}
dstVolumeDir , err := s . getVolDir ( dstVolume )
if err != nil {
if err != nil {
return err
return err
}
}
dstVolumeDir , err := s . getVolumeDir ( dstVolume )
// Stat a volume entry.
_ , err = os . Stat ( srcVolumeDir )
if err != nil {
if err != nil {
if os . IsNotExist ( err ) {
return errVolumeNotFound
}
return err
return err
}
}
_ , err = os . Stat ( dstVolumeDir )
if err != nil {
if os . IsNotExist ( err ) {
return errVolumeNotFound
}
}
srcIsDir := strings . HasSuffix ( srcPath , slashSeparator )
srcIsDir := strings . HasSuffix ( srcPath , slashSeparator )
dstIsDir := strings . HasSuffix ( dstPath , slashSeparator )
dstIsDir := strings . HasSuffix ( dstPath , slashSeparator )
// Either src and dst have to be directories or files, else return error.
// Either src and dst have to be directories or files, else return error.