Skip to content

Commit

Permalink
core: remove "file name too long" limitation
Browse files Browse the repository at this point in the history
* part four, prev. commit: b89781d

Signed-off-by: Alex Aizman <[email protected]>
  • Loading branch information
alex-aizman committed Jan 9, 2025
1 parent 2bd9540 commit d221976
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
26 changes: 21 additions & 5 deletions core/lfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,28 @@ func (lom *LOM) RenameFinalize(wfqn string) error {
return &errBdir{cname: lom.Cname(), err: err}
}
err := lom.RenameToMain(wfqn)
if err == nil {
switch {
case err == nil:
return nil
}
if cos.IsErrMv(err) {
case cos.IsErrMv(err):
return err
case cos.IsErrFntl(err):
// - when finalizing LOM: fixup fntl in place
var (
short = lom.ShortenFntl()
saved = lom.PushFntl(short)
)
err = lom.RenameToMain(wfqn)
if err == nil {
lom.md.lid = lom.md.lid.setlmfl(lmflFntl)
lom.SetCustomKey(cmn.OrigFntl, saved[0])
} else {
debug.Assert(!cos.IsErrFntl(err))
lom.PopFntl(saved)
}
return err
default:
T.FSHC(err, lom.Mountpath(), wfqn)
return cmn.NewErrFailedTo(T, "finalize", lom.Cname(), err)
}
T.FSHC(err, lom.Mountpath(), wfqn)
return cmn.NewErrFailedTo(T, "finalize", lom.Cname(), err)
}
10 changes: 4 additions & 6 deletions core/lom.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ func (lom *LOM) FromFS() error {
switch {
case os.IsNotExist(err):
return err

case strings.Contains(err.Error(), "not a directory") && cos.IsPathErr(err):
// e.g. err "stat .../aaa/111: not a directory" when there's existing ".../aaa" object
return fmt.Errorf("%w (object in the path?)", err)
Expand Down Expand Up @@ -665,20 +666,17 @@ func (lom *LOM) Unlock(exclusive bool) {
// file name too long (0x24) ----------------------------
//

const (
prefixFntl = ".x"
)

func (lom *LOM) IsFntl() bool {
return lom.md.lid.haslmfl(lmflFntl)
}

func (lom *LOM) HasFntlPrefix() bool {
return strings.HasPrefix(lom.ObjName, prefixFntl)
return strings.HasPrefix(lom.ObjName, fs.PrefixFntl)
}

func (lom *LOM) ShortenFntl() []string {
noname := prefixFntl + cos.ChecksumB2S(cos.UnsafeB(lom.FQN), cos.ChecksumSHA256)
// (compare with fs/content Gen())
noname := fs.PrefixFntl + cos.ChecksumB2S(cos.UnsafeB(lom.FQN), cos.ChecksumSHA256)
nfqn := lom.mi.MakePathFQN(lom.Bucket(), fs.ObjectType, noname)

debug.Assert(len(nfqn) < 4096, "PATH_MAX /usr/include/limits.h", len(nfqn))
Expand Down
20 changes: 20 additions & 0 deletions fs/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ const (
ECMetaType = "mt"
)

// file name too long (0x24)
const (
PrefixFntl = ".x"

maxLenBasename = 255
maxLenPath = 4000 // ref: PATH_MAX = 4096 in /usr/include/limits.h
)

type (
ContentResolver interface {
// Generates unique base name for original one. This function may add
Expand Down Expand Up @@ -120,6 +128,18 @@ func (f *contentSpecMgr) Gen(parts PartsFQN, contentType, prefix string) (fqn st
spec = f.m[contentType]
objName = spec.GenUniqueFQN(parts.ObjectName(), prefix)
)

// [NOTE]
// override caller-provided `objName` to prevent "file name too long" errno 0x24
// - full pathname should be fine as (validated) bucket name <= 64
// - see related: core/lom and "fixup fntl"
if l := len(objName); l > maxLenBasename {
if l > maxLenPath || len(filepath.Base(objName)) > maxLenBasename {
nlog.Warningln("file name too long (0x24):", objName)
objName = PrefixFntl + cos.ChecksumB2S(cos.UnsafeB(objName), cos.ChecksumSHA256)
}
}

return parts.Mountpath().MakePathFQN(parts.Bucket(), contentType, objName)
}

Expand Down

0 comments on commit d221976

Please sign in to comment.