// Must run inside mutex. func (me *memNode) promote() { if me.backing == "" { me.backing = me.fs.getFilename() destfs := pathfs.NewLoopbackFileSystem("/") pathfs.CopyFile(me.fs.readonly, destfs, me.original, strings.TrimLeft(me.backing, "/"), nil) me.original = "" files := me.Inode().Files(0) for _, f := range files { mf := f.File.(*memNodeFile) inner := mf.File osFile, err := os.Open(me.backing) if err != nil { panic("error opening backing file") } mf.File = nodefs.NewLoopbackFile(osFile) inner.Flush() inner.Release() } } }
func (fs *unionFS) Promote(name string, srcResult branchResult, context *fuse.Context) (code fuse.Status) { writable := fs.fileSystems[0] sourceFs := fs.fileSystems[srcResult.branch] // Promote directories. fs.promoteDirsTo(name) if srcResult.attr.IsRegular() { code = pathfs.CopyFile(sourceFs, writable, name, name, context) if code.Ok() { code = writable.Chmod(name, srcResult.attr.Mode&07777|0200, context) } if code.Ok() { aTime := srcResult.attr.AccessTime() mTime := srcResult.attr.ModTime() code = writable.Utimens(name, &aTime, &mTime, context) } files := fs.nodeFs.AllFiles(name, 0) for _, fileWrapper := range files { if !code.Ok() { break } var uf *unionFsFile f := fileWrapper.File for f != nil { ok := false uf, ok = f.(*unionFsFile) if ok { break } f = f.InnerFile() } if uf == nil { panic("no unionFsFile found inside") } if uf.layer > 0 { uf.layer = 0 f := uf.File uf.File, code = fs.fileSystems[0].Open(name, fileWrapper.OpenFlags, context) f.Flush() f.Release() } } } else if srcResult.attr.IsSymlink() { link := "" link, code = sourceFs.Readlink(name, context) if !code.Ok() { log.Println("can't read link in source fs", name) } else { code = writable.Symlink(link, name, context) } } else if srcResult.attr.IsDir() { code = writable.Mkdir(name, srcResult.attr.Mode&07777|0200, context) } else { log.Println("Unknown file type:", srcResult.attr) return fuse.ENOSYS } if !code.Ok() { fs.branchCache.GetFresh(name) return code } else { r := fs.getBranch(name) r.branch = 0 fs.branchCache.Set(name, r) } return fuse.OK }