fix: EXIF解析越界与转正丢文件、.psb归类、日志接管panic恢复
This commit is contained in:
@@ -280,8 +280,8 @@ type imageProbeResult struct {
|
||||
// 只读数据库(查指纹),这是安全的。
|
||||
func (o *Organizer) probeImage(f scanner.File) imageProbeResult {
|
||||
r := imageProbeResult{}
|
||||
// PSD 不体检,直接标记"原样收走"
|
||||
if strings.EqualFold(f.Ext, ".psd") {
|
||||
// PSD/PSB 设计稿不体检,直接标记"原样收走"
|
||||
if strings.EqualFold(f.Ext, ".psd") || strings.EqualFold(f.Ext, ".psb") {
|
||||
r.psd = true
|
||||
return r
|
||||
}
|
||||
|
||||
+14
-6
@@ -71,13 +71,21 @@ func RotateImage(ffmpegPath, filePath string) error {
|
||||
}
|
||||
}
|
||||
|
||||
// 用转正后的文件替换原文件
|
||||
if err := os.Remove(filePath); err != nil {
|
||||
// 用转正后的文件替换原文件:先把原文件改名成备份,再让转正结果顶上,最后删备份。
|
||||
// 这样即使中途失败,原文件也还在(只是改了名),不会弄丢。
|
||||
backup := filePath + ".rotate.bak"
|
||||
if err := os.Rename(filePath, backup); err != nil {
|
||||
_ = os.Remove(tmp)
|
||||
return fmt.Errorf("备份原文件失败: %v", err)
|
||||
}
|
||||
if err := os.Rename(tmp, filePath); err != nil {
|
||||
// 转正结果放不回去:把备份挪回来尽量恢复原状
|
||||
_ = os.Rename(backup, filePath)
|
||||
_ = os.Remove(tmp)
|
||||
return fmt.Errorf("替换原文件失败: %v", err)
|
||||
}
|
||||
if err := os.Rename(tmp, filePath); err != nil {
|
||||
return fmt.Errorf("替换原文件失败: %v", err)
|
||||
if err := os.Remove(backup); err != nil {
|
||||
fmt.Printf("=== 删除原文件备份失败(可手动清理 %s): %v\n", backup, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -120,7 +128,7 @@ func readExifAPP1(filePath string) ([]byte, error) {
|
||||
if segLen < 2 {
|
||||
break
|
||||
}
|
||||
if marker == 0xE1 && segLen >= 8 && string(buf[pos+4:pos+8]) == "Exif" {
|
||||
if marker == 0xE1 && segLen >= 8 && pos+8 <= len(buf) && string(buf[pos+4:pos+8]) == "Exif" {
|
||||
end := pos + 2 + segLen
|
||||
if end > len(buf) {
|
||||
end = len(buf)
|
||||
@@ -254,7 +262,7 @@ func stripExifAPP1(rest []byte) []byte {
|
||||
out = append(out, rest[pos:]...)
|
||||
return out
|
||||
}
|
||||
isExif := marker == 0xE1 && segLen >= 8 && string(rest[pos+4:pos+8]) == "Exif"
|
||||
isExif := marker == 0xE1 && segLen >= 8 && pos+8 <= len(rest) && string(rest[pos+4:pos+8]) == "Exif"
|
||||
if !isExif {
|
||||
out = append(out, rest[pos:pos+2+segLen]...)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -327,6 +328,18 @@ func (s *ScanService) run(rootDir, destDir string) {
|
||||
}
|
||||
}()
|
||||
|
||||
// 收尾必须恢复 stdout 并关闭管道,否则整个进程后续输出都会丢进这根无人读的管道里。
|
||||
// 用 defer 保证即使 runScan 中途 panic 也不会留下这种状态;panic 还会被接住,
|
||||
// 转成"出错"状态推给前端,而不是让整个程序崩溃。
|
||||
defer func() {
|
||||
os.Stdout = oldStdout
|
||||
_ = w.Close()
|
||||
<-done // 等读日志的 goroutine 把剩下的日志读完
|
||||
if rcv := recover(); rcv != nil {
|
||||
s.finish(ScanError, fmt.Sprintf("扫描整理内部错误: %v\n%s", rcv, debug.Stack()))
|
||||
}
|
||||
}()
|
||||
|
||||
// 真正开始干活。期间程序里所有 fmt.Println/Printf 都会进上面的管道
|
||||
scanErr := s.runScan(rootDir, destDir)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user