REST API: add an option to create missing dirs

This commit is contained in:
Nicola Murino
2021-12-19 12:14:53 +01:00
parent cc73bb811b
commit ced73ed04e
13 changed files with 290 additions and 24 deletions

View File

@@ -245,6 +245,35 @@ func (c *BaseConnection) ListDir(virtualPath string) ([]os.FileInfo, error) {
return c.User.AddVirtualDirs(files, virtualPath), nil
}
// CheckParentDirs tries to create the specified directory and any missing parent dirs
func (c *BaseConnection) CheckParentDirs(virtualPath string) error {
fs, err := c.User.GetFilesystemForPath(virtualPath, "")
if err != nil {
return err
}
if fs.HasVirtualFolders() {
return nil
}
if _, err := c.DoStat(virtualPath, 0); !c.IsNotExistError(err) {
return err
}
dirs := util.GetDirsForVirtualPath(virtualPath)
for idx := len(dirs) - 1; idx >= 0; idx-- {
fs, err = c.User.GetFilesystemForPath(dirs[idx], "")
if err != nil {
return err
}
if fs.HasVirtualFolders() {
continue
}
if err = c.createDirIfMissing(dirs[idx]); err != nil {
return fmt.Errorf("unable to check/create missing parent dir %#v for virtual path %#v: %w",
dirs[idx], virtualPath, err)
}
}
return nil
}
// CreateDir creates a new directory at the specified fsPath
func (c *BaseConnection) CreateDir(virtualPath string) error {
if !c.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(virtualPath)) {
@@ -507,7 +536,7 @@ func (c *BaseConnection) DoStat(virtualPath string, mode int) (os.FileInfo, erro
info, err = fs.Stat(c.getRealFsPath(fsPath))
}
if err != nil {
c.Log(logger.LevelDebug, "stat error for path %#v: %+v", virtualPath, err)
c.Log(logger.LevelError, "stat error for path %#v: %+v", virtualPath, err)
return info, c.GetFsError(fs, err)
}
if vfs.IsCryptOsFs(fs) {
@@ -516,6 +545,14 @@ func (c *BaseConnection) DoStat(virtualPath string, mode int) (os.FileInfo, erro
return info, nil
}
func (c *BaseConnection) createDirIfMissing(name string) error {
_, err := c.DoStat(name, 0)
if c.IsNotExistError(err) {
return c.CreateDir(name)
}
return err
}
func (c *BaseConnection) ignoreSetStat(fs vfs.Fs) bool {
if Config.SetstatMode == 1 {
return true
@@ -1089,6 +1126,18 @@ func (c *BaseConnection) updateQuotaAfterRename(fs vfs.Fs, virtualSourcePath, vi
return nil
}
// IsNotExistError returns true if the specified fs error is not exist for the connection protocol
func (c *BaseConnection) IsNotExistError(err error) bool {
switch c.protocol {
case ProtocolSFTP:
return errors.Is(err, sftp.ErrSSHFxNoSuchFile)
case ProtocolWebDAV, ProtocolFTP, ProtocolHTTP, ProtocolHTTPShare, ProtocolDataRetention:
return errors.Is(err, os.ErrNotExist)
default:
return errors.Is(err, ErrNotExist)
}
}
// GetPermissionDeniedError returns an appropriate permission denied error for the connection protocol
func (c *BaseConnection) GetPermissionDeniedError() error {
switch c.protocol {