From e60fb6b4cc8f3f89d9f802cf98889b981557a5dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Wed, 16 Feb 2022 15:48:53 +0000 Subject: [PATCH] fix restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- pkg/storage/utils/decomposedfs/tree/tree.go | 49 ++++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/pkg/storage/utils/decomposedfs/tree/tree.go b/pkg/storage/utils/decomposedfs/tree/tree.go index c8723e5d04e..005e62c96cf 100644 --- a/pkg/storage/utils/decomposedfs/tree/tree.go +++ b/pkg/storage/utils/decomposedfs/tree/tree.go @@ -817,26 +817,40 @@ func (t *Tree) createNode(n *node.Node, owner *userpb.UserId) (err error) { return n.WriteAllNodeMetadata(owner) } +// readTrashLink returns nodeID and timestamp +func readTrashLink(path string) (string, string, error) { + link, err := os.Readlink(path) + if err != nil { + return "", "", err + } + // ../../../../../nodes/e5/6c/75/a8/-d235-4cbb-8b4e-48b6fd0f2094.T.2022-02-16T14:38:11.769917408Z + // TODO use filepath.Separator to support windows + link = strings.ReplaceAll(link, "/", "") + // ..........nodese56c75a8-d235-4cbb-8b4e-48b6fd0f2094.T.2022-02-16T14:38:11.769917408Z + if link[0:15] != "..........nodes" || link[51:54] != ".T." { + return "", "", errtypes.InternalError("malformed trash link") + } + return link[15:51], link[54:], nil +} + // TODO refactor the returned params into Node properties? would make all the path transformations go away... func (t *Tree) readRecycleItem(ctx context.Context, spaceID, key, path string) (recycleNode *node.Node, trashItem string, deletedNodePath string, origin string, err error) { if key == "" { return nil, "", "", "", errtypes.InternalError("key is empty") } - trashItem = filepath.Join(t.lookup.InternalRoot(), "trash", spaceID, key, path) + trashItem = filepath.Join(t.lookup.InternalRoot(), "spaces", Pathify(spaceID, 1, 2), "trash", Pathify(key, 4, 2), path) - var link string - link, err = os.Readlink(trashItem) + nodeID, timeSuffix, err := readTrashLink(trashItem) if err != nil { appctx.GetLogger(ctx).Error().Err(err).Str("trashItem", trashItem).Msg("error reading trash link") return } - var attrStr string - trashNodeID := filepath.Base(link) - deletedNodePath = t.lookup.InternalPath(spaceID, trashNodeID) + deletedNodePath = t.lookup.InternalPath(spaceID, nodeID) + node.TrashIDDelimiter + timeSuffix owner := &userpb.UserId{} + var attrStr string // lookup ownerId in extended attributes if attrStr, err = xattrs.Get(deletedNodePath, xattrs.OwnerIDAttr); err == nil { owner.OpaqueId = attrStr @@ -856,7 +870,7 @@ func (t *Tree) readRecycleItem(ctx context.Context, spaceID, key, path string) ( return } - recycleNode = node.New(spaceID, trashNodeID, "", "", 0, "", owner, t.lookup) + recycleNode = node.New(spaceID, nodeID, "", "", 0, "", owner, t.lookup) // lookup blobID in extended attributes if attrStr, err = xattrs.Get(deletedNodePath, xattrs.BlobIDAttr); err == nil { recycleNode.BlobID = attrStr @@ -879,16 +893,8 @@ func (t *Tree) readRecycleItem(ctx context.Context, spaceID, key, path string) ( } // look up space root from the trashed node - err = recycleNode.FindStorageSpaceRoot() - - if path == "" || path == "/" { - parts := strings.SplitN(filepath.Base(link), node.TrashIDDelimiter, 2) - if len(parts) != 2 { - appctx.GetLogger(ctx).Error().Err(err).Str("trashItem", trashItem).Interface("parts", parts).Msg("malformed trash link") - return - } - // update the node id, drop the `.T.{timestamp}` suffix - recycleNode.ID = parts[0] + if err = recycleNode.FindStorageSpaceRoot(); err != nil { + return } // get origin node, is relative to space root @@ -896,20 +902,19 @@ func (t *Tree) readRecycleItem(ctx context.Context, spaceID, key, path string) ( deletedNodeRootPath := deletedNodePath if path != "" && path != "/" { - trashItemRoot := filepath.Join(t.lookup.InternalRoot(), "trash", spaceID, key) - var rootLink string - rootLink, err = os.Readlink(trashItemRoot) + trashItemRoot := filepath.Join(t.lookup.InternalRoot(), "spaces", Pathify(spaceID, 1, 2), "trash", Pathify(key, 4, 2)) + nodeID, _, err = readTrashLink(trashItemRoot) if err != nil { appctx.GetLogger(ctx).Error().Err(err).Str("trashItem", trashItem).Msg("error reading trash link") return } - deletedNodeRootPath = t.lookup.InternalPath(spaceID, filepath.Base(rootLink)) + deletedNodeRootPath = t.lookup.InternalPath(spaceID, nodeID) } // lookup origin path in extended attributes if attrStr, err = xattrs.Get(deletedNodeRootPath, xattrs.TrashOriginAttr); err == nil { origin = filepath.Join(attrStr, path) } else { - log.Error().Err(err).Str("trashItem", trashItem).Str("link", link).Str("deletedNodePath", deletedNodePath).Msg("could not read origin path, restoring to /") + log.Error().Err(err).Str("trashItem", trashItem).Str("deletedNodePath", deletedNodePath).Msg("could not read origin path, restoring to /") } return