Skip to content

Commit cf9e00e

Browse files
authored
Merge pull request #14 from beclab/dev
fix: rename and cut/paste of smb bugfix
2 parents 06d0b27 + 8f1c5f8 commit cf9e00e

File tree

4 files changed

+269
-51
lines changed

4 files changed

+269
-51
lines changed

pkg/common/patch.go

+185-27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package common
22

33
import (
4+
"bytes"
45
"context"
56
"files/pkg/errors"
67
"files/pkg/files"
@@ -10,9 +11,11 @@ import (
1011
"github.com/spf13/afero"
1112
"k8s.io/klog/v2"
1213
"os"
14+
"os/exec"
1315
"path"
1416
"path/filepath"
1517
"strings"
18+
"time"
1619
)
1720

1821
func CheckParent(src, dst string) error {
@@ -51,7 +54,147 @@ func AddVersionSuffix(source string, fs afero.Fs, isDir bool) string {
5154
return source
5255
}
5356

54-
func MoveDir(ctx context.Context, fs afero.Fs, source, dest string, fileCache fileutils.FileCache) error {
57+
func pathExistsInLsOutput(path string, isDir bool) (bool, error) {
58+
dir := filepath.Dir(path)
59+
base := filepath.Base(path)
60+
61+
cmd := exec.Command("ls", "-l", dir)
62+
var out bytes.Buffer
63+
var stderr bytes.Buffer
64+
cmd.Stdout = &out
65+
cmd.Stderr = &stderr
66+
67+
err := cmd.Run()
68+
if err != nil {
69+
klog.Errorf("ls -l %s failed: %v, stderr: %s", path, err, stderr.String())
70+
}
71+
72+
lsOutput := out.String()
73+
74+
lines := strings.Split(lsOutput, "\n")
75+
for _, line := range lines {
76+
if line == "" {
77+
continue
78+
}
79+
80+
fileType := line[:1]
81+
82+
parts := strings.Fields(line)
83+
if len(parts) < 9 {
84+
continue
85+
}
86+
fileName := parts[len(parts)-1]
87+
88+
if fileName == base {
89+
if fileType == "d" && isDir {
90+
return true, nil
91+
} else if fileType == "-" && !isDir {
92+
return true, nil
93+
}
94+
}
95+
}
96+
return false, nil
97+
}
98+
99+
func Rmrf(path string) error {
100+
for {
101+
cmd := exec.Command("rm", "-rf", path)
102+
103+
//cmdStr := fmt.Sprintf("%s %s", cmd.Path, strings.Join(cmd.Args[1:], " "))
104+
//klog.Infoln("~~~Debug log: Executing command:", cmdStr)
105+
106+
var stdout, stderr bytes.Buffer
107+
cmd.Stdout = &stdout
108+
cmd.Stderr = &stderr
109+
110+
err := cmd.Run()
111+
if err != nil {
112+
klog.Infoln("Error executing rm -rf:", err)
113+
}
114+
//klog.Infoln("Command stdout:", stdout.String())
115+
//klog.Infoln("Command stderr:", stderr.String())
116+
117+
exists, err := pathExistsInLsOutput(path, true)
118+
if !exists && err == nil {
119+
klog.Infoln("Path successfully removed:", path)
120+
return nil
121+
} else if err != nil {
122+
klog.Infoln("Error checking path existence:", err)
123+
} else {
124+
klog.Infoln("Path still exists, retrying...")
125+
}
126+
time.Sleep(500 * time.Millisecond)
127+
}
128+
}
129+
130+
func safeRemoveAll(fs afero.Fs, source string) error {
131+
// TODO: not used for the time being
132+
realPath := filepath.Join(RootPrefix, source)
133+
for {
134+
klog.Infof("~~~Debug log: Attempting to delete folder %s", realPath)
135+
136+
err := fs.RemoveAll(source)
137+
if err != nil {
138+
klog.Errorf("Error attempting to delete folder %s: %v", realPath, err)
139+
} else {
140+
exists, err := pathExistsInLsOutput(filepath.Join(RootPrefix, source), true)
141+
if !exists && err == nil {
142+
klog.Infof("Successfully deleted folder %s", realPath)
143+
return nil
144+
} else if err != nil {
145+
klog.Errorf("Error checking folder existence after deletion attempt for %s: %v", realPath, err)
146+
} else {
147+
klog.Warningf("Folder %s still exists after deletion attempt, retrying...", realPath)
148+
}
149+
}
150+
151+
time.Sleep(500 * time.Millisecond)
152+
}
153+
}
154+
155+
func MoveDir(ctx context.Context, fs afero.Fs, source, dest, srcExternalType, dstExternalType string, fileCache fileutils.FileCache, delete bool) error {
156+
var err error
157+
if delete {
158+
// first recursively delete all thumbs
159+
err = filepath.Walk(RootPrefix+source, func(path string, info os.FileInfo, err error) error {
160+
if err != nil {
161+
return err
162+
}
163+
164+
if !info.IsDir() {
165+
file, err := files.NewFileInfo(files.FileOptions{
166+
Fs: files.DefaultFs,
167+
Path: path,
168+
Modify: true,
169+
Expand: false,
170+
ReadHeader: false,
171+
})
172+
if err != nil {
173+
return err
174+
}
175+
176+
// delete thumbnails
177+
err = preview.DelThumbs(ctx, fileCache, file)
178+
if err != nil {
179+
return err
180+
}
181+
}
182+
return nil
183+
})
184+
if err != nil {
185+
klog.Infoln("Error walking the directory:", err)
186+
} else {
187+
klog.Infoln("Directory traversal completed.")
188+
}
189+
}
190+
191+
// no matter what situation, try to rename all first
192+
if fs.Rename(source, dest) == nil {
193+
return nil
194+
}
195+
196+
// if rename all failed, recursively do things below, without delthumbs any more
197+
55198
// Get properties of source.
56199
srcinfo, err := fs.Stat(source)
57200
if err != nil {
@@ -78,13 +221,13 @@ func MoveDir(ctx context.Context, fs afero.Fs, source, dest string, fileCache fi
78221

79222
if obj.IsDir() {
80223
// Create sub-directories, recursively.
81-
err = MoveDir(ctx, fs, fsource, fdest, fileCache)
224+
err = MoveDir(ctx, fs, fsource, fdest, srcExternalType, dstExternalType, fileCache, false)
82225
if err != nil {
83226
errs = append(errs, err)
84227
}
85228
} else {
86229
// Perform the file copy.
87-
err = MoveFile(ctx, fs, fsource, fdest, fileCache)
230+
err = MoveFile(ctx, fs, fsource, fdest, fileCache, false)
88231
if err != nil {
89232
errs = append(errs, err)
90233
}
@@ -97,46 +240,61 @@ func MoveDir(ctx context.Context, fs afero.Fs, source, dest string, fileCache fi
97240
}
98241

99242
if errString != "" {
100-
err = fs.Remove(dest)
243+
klog.Infof("Rollbacking: Dest ExternalType is %s", dstExternalType)
244+
if dstExternalType == "smb" {
245+
err = Rmrf(RootPrefix + dest)
246+
} else {
247+
err = fs.RemoveAll(dest)
248+
}
101249
if err != nil {
102250
errString += err.Error() + "\n"
103251
}
104252
return fmt.Errorf(errString)
105253
}
106254

107-
err = fs.Remove(source)
108-
if err != nil {
109-
return err
255+
// finally delete all for folder is OK
256+
if delete {
257+
klog.Infof("Moving is going to Delete folder %s with ExternalType %s", RootPrefix+source, srcExternalType)
258+
if srcExternalType == "smb" {
259+
err = Rmrf(RootPrefix + source)
260+
} else {
261+
err = fs.RemoveAll(source)
262+
}
263+
if err != nil {
264+
return err
265+
}
110266
}
111267

112268
return nil
113269
}
114270

115-
func MoveFile(ctx context.Context, fs afero.Fs, src, dst string, fileCache fileutils.FileCache) error {
271+
func MoveFile(ctx context.Context, fs afero.Fs, src, dst string, fileCache fileutils.FileCache, delete bool) error {
116272
src = path.Clean("/" + src)
117273
dst = path.Clean("/" + dst)
118274

119-
file, err := files.NewFileInfo(files.FileOptions{
120-
Fs: files.DefaultFs,
121-
Path: src,
122-
Modify: true,
123-
Expand: false,
124-
ReadHeader: false,
125-
})
126-
if err != nil {
127-
return err
128-
}
275+
if delete {
276+
file, err := files.NewFileInfo(files.FileOptions{
277+
Fs: files.DefaultFs,
278+
Path: src,
279+
Modify: true,
280+
Expand: false,
281+
ReadHeader: false,
282+
})
283+
if err != nil {
284+
return err
285+
}
129286

130-
// delete thumbnails
131-
err = preview.DelThumbs(ctx, fileCache, file)
132-
if err != nil {
133-
return err
287+
// delete thumbnails
288+
err = preview.DelThumbs(ctx, fileCache, file)
289+
if err != nil {
290+
return err
291+
}
134292
}
135293

136294
return fileutils.MoveFile(fs, src, dst)
137295
}
138296

139-
func Move(ctx context.Context, fs afero.Fs, src, dst string, fileCache fileutils.FileCache) error {
297+
func Move(ctx context.Context, fs afero.Fs, src, dst, srcExternalType, dstExternalType string, fileCache fileutils.FileCache) error {
140298
if src = path.Clean("/" + src); src == "" {
141299
return os.ErrNotExist
142300
}
@@ -160,18 +318,18 @@ func Move(ctx context.Context, fs afero.Fs, src, dst string, fileCache fileutils
160318
}
161319

162320
if info.IsDir() {
163-
return MoveDir(ctx, fs, src, dst, fileCache)
321+
return MoveDir(ctx, fs, src, dst, srcExternalType, dstExternalType, fileCache, true)
164322
}
165323

166-
return MoveFile(ctx, fs, src, dst, fileCache)
324+
return MoveFile(ctx, fs, src, dst, fileCache, true)
167325
}
168326

169-
func PatchAction(ctx context.Context, action, src, dst string, fileCache fileutils.FileCache) error {
327+
func PatchAction(ctx context.Context, action, src, dst, srcExternalType, dstExternalType string, fileCache fileutils.FileCache) error {
170328
switch action {
171329
case "copy":
172330
return fileutils.Copy(files.DefaultFs, src, dst)
173331
case "rename":
174-
return Move(ctx, files.DefaultFs, src, dst, fileCache)
332+
return Move(ctx, files.DefaultFs, src, dst, srcExternalType, dstExternalType, fileCache)
175333
default:
176334
return fmt.Errorf("unsupported action %s: %w", action, errors.ErrInvalidRequestParams)
177335
}

pkg/drives/base.go

+29-18
Original file line numberDiff line numberDiff line change
@@ -127,23 +127,9 @@ func IsCloudDrives(dstType string) bool {
127127
}
128128
}
129129

130-
type BaseResourceService struct{}
131-
132-
func (rs *BaseResourceService) GetHandler(w http.ResponseWriter, r *http.Request, d *common.Data) (int, error) {
133-
xBflUser := r.Header.Get("X-Bfl-User")
134-
klog.Infoln("X-Bfl-User: ", xBflUser)
135-
136-
streamStr := r.URL.Query().Get("stream")
137-
stream := 0
138-
var err error = nil
139-
if streamStr != "" {
140-
stream, err = strconv.Atoi(streamStr)
141-
if err != nil {
142-
return http.StatusBadRequest, err
143-
}
144-
}
145-
130+
func GetMountedData(r *http.Request) []files.DiskInfo {
146131
var mountedData []files.DiskInfo = nil
132+
var err error = nil
147133
if files.TerminusdHost != "" {
148134
// for 1.12: path-incluster URL exists, won't err in normal condition
149135
// for 1.11: path-incluster URL may not exist, if err, use usb-incluster and hdd-incluster for system functional
@@ -194,6 +180,26 @@ func (rs *BaseResourceService) GetHandler(w http.ResponseWriter, r *http.Request
194180
}
195181
klog.Infoln("Mounted Data:", mountedData)
196182
}
183+
return mountedData
184+
}
185+
186+
type BaseResourceService struct{}
187+
188+
func (rs *BaseResourceService) GetHandler(w http.ResponseWriter, r *http.Request, d *common.Data) (int, error) {
189+
xBflUser := r.Header.Get("X-Bfl-User")
190+
klog.Infoln("X-Bfl-User: ", xBflUser)
191+
192+
streamStr := r.URL.Query().Get("stream")
193+
stream := 0
194+
var err error = nil
195+
if streamStr != "" {
196+
stream, err = strconv.Atoi(streamStr)
197+
if err != nil {
198+
return http.StatusBadRequest, err
199+
}
200+
}
201+
202+
mountedData := GetMountedData(r)
197203

198204
var file *files.FileInfo
199205
if mountedData != nil {
@@ -250,7 +256,8 @@ func (rs *BaseResourceService) GetHandler(w http.ResponseWriter, r *http.Request
250256

251257
if file.IsDir {
252258
if files.CheckPath(file.Path, files.ExternalPrefix, "/") {
253-
file.ExternalType = files.GetExternalType(file.Path, mountedData)
259+
//if strings.HasPrefix(file.Path, files.ExternalPrefix) {
260+
files.GetExternalExtraInfos(file, mountedData, 1)
254261
}
255262
file.Listing.Sorting = files.DefaultSorting
256263
file.Listing.ApplySort()
@@ -412,8 +419,12 @@ func (rs *BaseResourceService) PatchHandler(fileCache fileutils.FileCache) handl
412419
dst = common.AddVersionSuffix(dst, files.DefaultFs, strings.HasSuffix(src, "/"))
413420
}
414421

422+
mountedData := GetMountedData(r)
423+
srcExternalType := files.GetExternalType(src, mountedData)
424+
dstExternalType := files.GetExternalType(dst, mountedData)
425+
415426
klog.Infoln("Before patch action:", src, dst, action, rename)
416-
err = common.PatchAction(r.Context(), action, src, dst, fileCache)
427+
err = common.PatchAction(r.Context(), action, src, dst, srcExternalType, dstExternalType, fileCache)
417428

418429
return common.ErrToStatus(err), err
419430
}

pkg/drives/drive.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ type DriveResourceService struct {
2525
}
2626

2727
func (rs *DriveResourceService) PasteSame(action, src, dst string, rename bool, fileCache fileutils.FileCache, w http.ResponseWriter, r *http.Request) error {
28-
return common.PatchAction(r.Context(), action, src, dst, fileCache)
28+
mountedData := GetMountedData(r)
29+
srcExternalType := files.GetExternalType(src, mountedData)
30+
dstExternalType := files.GetExternalType(dst, mountedData)
31+
return common.PatchAction(r.Context(), action, src, dst, srcExternalType, dstExternalType, fileCache)
2932
}
3033

3134
func (rs *DriveResourceService) PasteDirFrom(fs afero.Fs, srcType, src, dstType, dst string, d *common.Data,

0 commit comments

Comments
 (0)