Permanent fallback to copy on hardlink error

This commit is contained in:
2025-01-07 03:39:05 +03:00
parent df4f2ebd99
commit 62daa023f5
3 changed files with 28 additions and 6 deletions

View File

@@ -30,7 +30,8 @@ sudo cp ${GOPATH}/bin/photocatalog /usr/local/bin/photocatalog
The tool supports the following organization modes:
- **copy** — Copies files to the target directory. If the filesystem supports it, uses Copy-on-Write (COW) for efficiency (via FICLONE ioctl call).
- **hardlink** — Creates hardlinks to the source files, saving disk space. Ideal if the source and target are on the same partition, though file permissions remain linked to the original.
- **hardlink** — Creates hardlinks to the source files, saving disk space. Ideal (and usable only) if the source and target are on the same partition,
though file permissions remain linked to the original. Fallback to copy on fail.
- **move** — Moves files from the source to the target directory.
- **symlink** — Creates symbolic links at the target pointing to the source files.

View File

@@ -1,20 +1,36 @@
package modes
import (
"fmt"
"log"
"os"
"sync/atomic"
)
var hardLinkNotSupported = atomic.Bool{}
type HardLink struct {
}
func (h HardLink) PlaceIt(sourcePath, targetPath string, mode os.FileMode) error {
if hardLinkNotSupported.Load() {
if copyErr := (Copy{}).PlaceIt(sourcePath, targetPath, mode); copyErr != nil {
return copyErr
}
}
if err := os.Link(sourcePath, targetPath); err != nil {
if os.IsExist(err) {
return nil
}
return fmt.Errorf("create hard link: %w", err)
log.Println("Create hardlink failed:", err.Error())
hardLinkNotSupported.Store(true)
if copyErr := (Copy{}).PlaceIt(sourcePath, targetPath, mode); copyErr != nil {
return copyErr
}
return nil
}
return nil

View File

@@ -11,6 +11,7 @@ import (
"strconv"
"strings"
"sync"
"syscall"
"github.com/fsnotify/fsnotify"
@@ -130,6 +131,8 @@ func (o *Organizer) Watch(ctx context.Context, wg *sync.WaitGroup) error {
if err := watcher.Close(); err != nil {
o.logErr(fmt.Errorf("close watcher: %w", err))
}
syscall.Sync()
}()
go func() {
@@ -155,9 +158,11 @@ func (o *Organizer) Watch(ctx context.Context, wg *sync.WaitGroup) error {
continue
}
if err := o.processFile(event.Name); err != nil {
o.logErr(fmt.Errorf("process file %s: %w", event.Name, err))
}
go func() {
if err := o.processFile(event.Name); err != nil {
o.logErr(fmt.Errorf("process file %s: %w", event.Name, err))
}
}()
}
case <-ctx.Done():