diff --git a/code/rest/matter_dao.go b/code/rest/matter_dao.go index 6a0aaea..32865c6 100644 --- a/code/rest/matter_dao.go +++ b/code/rest/matter_dao.go @@ -412,23 +412,35 @@ func (this *MatterDao) SizeByPuuidAndUserUuid(matterUuid string, userUuid string } //delete a file from db and disk. -func (this *MatterDao) Delete(matter *Matter) { +func (this *MatterDao) Delete(matter *Matter, symbolLinkDir bool, symbolLevel int) { // recursive if dir if matter.Dir { + stat, _ := os.Lstat(matter.AbsolutePath()) + if stat.Mode()&os.ModeSymlink > 0 { + symbolLinkDir = true + } + if symbolLinkDir { + symbolLevel++ + } matters := this.FindByPuuidAndUserUuid(matter.Uuid, matter.UserUuid, nil) for _, f := range matters { - this.Delete(f) + this.Delete(f, symbolLinkDir, symbolLevel) } //delete from db. db := core.CONTEXT.GetDB().Delete(&matter) this.PanicError(db.Error) - //delete dir from disk. - util.DeleteEmptyDir(matter.AbsolutePath()) - + if symbolLinkDir { + if symbolLevel == 0 { + os.Remove(matter.AbsolutePath()) + } + } else { + //delete dir from disk. + util.DeleteEmptyDir(matter.AbsolutePath()) + } } else { //delete from db. @@ -442,11 +454,12 @@ func (this *MatterDao) Delete(matter *Matter) { this.bridgeDao.DeleteByMatterUuid(matter.Uuid) //delete from disk. - err := os.Remove(matter.AbsolutePath()) - if err != nil { - this.logger.Error("occur error when deleting file. %v", err) + if !symbolLinkDir { + err := os.Remove(matter.AbsolutePath()) + if err != nil { + this.logger.Error("occur error when deleting file. %v", err) + } } - } } diff --git a/code/rest/matter_service.go b/code/rest/matter_service.go index 8908dfd..c1e88bc 100644 --- a/code/rest/matter_service.go +++ b/code/rest/matter_service.go @@ -250,7 +250,7 @@ func (this *MatterService) Delete(request *http.Request, matter *Matter, user *U panic(result.BadRequest("matter cannot be nil")) } - this.matterDao.Delete(matter) + this.matterDao.Delete(matter, false, -1) //re compute the size of Route. this.ComputeRouteSize(matter.Puuid, user) @@ -987,7 +987,7 @@ func (this *MatterService) mirror(request *http.Request, srcPath string, destDir this.logger.Info("mirror srcPath = %s destPath = %s", srcPath, destDirMatter.Path) - if fileStat.IsDir() { + if fileStat.IsDir() || (fileStat.Mode()&os.ModeSymlink > 0) { //判断当前文件夹下,文件是否已经存在了。 srcDirMatter := this.matterDao.FindByUserUuidAndPuuidAndDirAndName(user.Uuid, destDirMatter.Uuid, TRUE, fileStat.Name()) @@ -1231,7 +1231,7 @@ func (this *MatterService) ScanPhysics(request *http.Request, user *User) { } func (this *MatterService) scanPhysicsFolder(request *http.Request, dirInfo os.FileInfo, dirMatter *Matter, user *User) { - if !dirInfo.IsDir() { + if !dirInfo.IsDir() && !(dirInfo.Mode()&os.ModeSymlink > 0) { return } @@ -1277,7 +1277,7 @@ func (this *MatterService) scanPhysicsFolder(request *http.Request, dirInfo os.F } else { - if fileInfo.IsDir() { + if fileInfo.IsDir() || (fileInfo.Mode()&os.ModeSymlink > 0) { //create folder. matter = this.createDirectory(request, dirMatter, name, user) diff --git a/code/tool/util/util_zip.go b/code/tool/util/util_zip.go index 54199f8..ab13541 100644 --- a/code/tool/util/util_zip.go +++ b/code/tool/util/util_zip.go @@ -53,7 +53,7 @@ func Zip(srcPath string, destPath string) error { fileHeader.Name = strings.TrimPrefix(path, baseDirPath) // directory need / - if fileInfo.IsDir() { + if fileInfo.IsDir() || (fileInfo.Mode()&os.ModeSymlink > 0) { fileHeader.Name += "/" } diff --git a/code/tool/webdav/file.go b/code/tool/webdav/file.go index 1b9dbc3..51cdeaa 100644 --- a/code/tool/webdav/file.go +++ b/code/tool/webdav/file.go @@ -203,7 +203,7 @@ func (fs *memFS) walk(op, fullname string, f func(dir *memFSNode, frag string, f Err: os.ErrNotExist, } } - if !child.mode.IsDir() { + if !child.mode.IsDir() && !(child.mode&os.ModeSymlink > 0) { return &os.PathError{ Op: op, Path: original, @@ -468,7 +468,7 @@ func (f *memFileInfo) Name() string { return f.name } func (f *memFileInfo) Size() int64 { return f.size } func (f *memFileInfo) Mode() os.FileMode { return f.mode } func (f *memFileInfo) ModTime() time.Time { return f.modTime } -func (f *memFileInfo) IsDir() bool { return f.mode.IsDir() } +func (f *memFileInfo) IsDir() bool { return f.mode.IsDir() || (f.mode&os.ModeSymlink > 0) } func (f *memFileInfo) Sys() interface{} { return nil } // A memFile is a File implementation for a memFSNode. It is a per-file (not @@ -495,7 +495,7 @@ func (f *memFile) Close() error { func (f *memFile) Read(p []byte) (int, error) { f.n.mu.Lock() defer f.n.mu.Unlock() - if f.n.mode.IsDir() { + if f.n.mode.IsDir() || (f.n.mode&os.ModeSymlink > 0) { return 0, os.ErrInvalid } if f.pos >= len(f.n.data) { @@ -509,7 +509,7 @@ func (f *memFile) Read(p []byte) (int, error) { func (f *memFile) Readdir(count int) ([]os.FileInfo, error) { f.n.mu.Lock() defer f.n.mu.Unlock() - if !f.n.mode.IsDir() { + if !f.n.mode.IsDir() && !(f.n.mode&os.ModeSymlink > 0) { return nil, os.ErrInvalid } old := f.pos @@ -564,7 +564,7 @@ func (f *memFile) Write(p []byte) (int, error) { f.n.mu.Lock() defer f.n.mu.Unlock() - if f.n.mode.IsDir() { + if f.n.mode.IsDir() || (f.n.mode&os.ModeSymlink > 0) { return 0, os.ErrInvalid } if f.pos < len(f.n.data) { @@ -693,7 +693,7 @@ func copyFiles(ctx context.Context, fs FileSystem, src, dst string, overwrite bo } } - if srcStat.IsDir() { + if srcStat.IsDir() || (srcStat.Mode()&os.ModeSymlink > 0) { if err := fs.Mkdir(ctx, dst, srcPerm); err != nil { return http.StatusForbidden, err } @@ -752,12 +752,12 @@ func walkFS(ctx context.Context, fs FileSystem, depth int, name string, info os. // This implementation is based on Walk's code in the standard path/filepath package. err := walkFn(name, info, nil) if err != nil { - if info.IsDir() && err == filepath.SkipDir { + if (info.IsDir() || (info.Mode()&os.ModeSymlink > 0)) && err == filepath.SkipDir { return nil } return err } - if !info.IsDir() || depth == 0 { + if (!info.IsDir() && !(info.Mode()&os.ModeSymlink > 0)) || depth == 0 { return nil } if depth == 1 { @@ -785,7 +785,7 @@ func walkFS(ctx context.Context, fs FileSystem, depth int, name string, info os. } else { err = walkFS(ctx, fs, depth, filename, fileInfo, walkFn) if err != nil { - if !fileInfo.IsDir() || err != filepath.SkipDir { + if (!fileInfo.IsDir() && !(fileInfo.Mode()&os.ModeSymlink > 0)) || err != filepath.SkipDir { return err } } diff --git a/code/tool/webdav/file_test.go b/code/tool/webdav/file_test.go index cba2025..5de8155 100644 --- a/code/tool/webdav/file_test.go +++ b/code/tool/webdav/file_test.go @@ -240,7 +240,7 @@ func find(ctx context.Context, ss []string, fs FileSystem, name string) ([]strin return nil, err } ss = append(ss, name) - if stat.IsDir() { + if stat.IsDir() || (stat.Mode()&os.ModeSymlink > 0) { f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0) if err != nil { return nil, err @@ -480,7 +480,7 @@ func testFS(t *testing.T, fs FileSystem) { var stat os.FileInfo fileName := parts[0] if stat, opErr = fs.Stat(ctx, fileName); opErr == nil { - if stat.IsDir() { + if stat.IsDir() || (stat.Mode()&os.ModeSymlink > 0) { got = "dir" } else { got = strconv.Itoa(int(stat.Size())) @@ -538,7 +538,7 @@ func TestMemFSRoot(t *testing.T) { if err != nil { t.Fatalf("i=%d: Stat: %v", i, err) } - if !stat.IsDir() { + if !stat.IsDir() && !(stat.Mode()&os.ModeSymlink > 0) { t.Fatalf("i=%d: Stat.IsDir is false, want true", i) } diff --git a/code/tool/webdav/prop.go b/code/tool/webdav/prop.go index 8a88360..9d51a73 100644 --- a/code/tool/webdav/prop.go +++ b/code/tool/webdav/prop.go @@ -176,7 +176,7 @@ func Props(ctx context.Context, fs FileSystem, ls LockSystem, name string, pname if err != nil { return nil, err } - isDir := fi.IsDir() + isDir := fi.IsDir() || (fi.Mode()&os.ModeSymlink > 0) var deadProps map[xml.Name]Property if dph, ok := f.(DeadPropsHolder); ok { diff --git a/code/tool/webdav/webdav.go b/code/tool/webdav/webdav.go index b335a38..5dd211d 100644 --- a/code/tool/webdav/webdav.go +++ b/code/tool/webdav/webdav.go @@ -177,7 +177,7 @@ func (h *Handler) handleOptions(w http.ResponseWriter, r *http.Request) (status ctx := r.Context() allow := "OPTIONS, LOCK, PUT, MKCOL" if fi, err := h.FileSystem.Stat(ctx, reqPath); err == nil { - if fi.IsDir() { + if fi.IsDir() || (fi.Mode()&os.ModeSymlink > 0) { allow = "OPTIONS, LOCK, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND" } else { allow = "OPTIONS, LOCK, GET, HEAD, POST, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND, PUT" @@ -207,7 +207,7 @@ func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (sta if err != nil { return http.StatusNotFound, err } - if fi.IsDir() { + if fi.IsDir() || (fi.Mode()&os.ModeSymlink > 0) { return http.StatusMethodNotAllowed, nil } etag, err := findETag(ctx, h.FileSystem, h.LockSystem, reqPath, fi) @@ -557,7 +557,7 @@ func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request) (status return err } href := path.Join(h.Prefix, reqPath) - if href != "/" && info.IsDir() { + if href != "/" && (info.IsDir() || (info.Mode()&os.ModeSymlink > 0)) { href += "/" } return mw.write(MakePropstatResponse(href, pstats))