# Copyright (C) 2017-2020 OpenIO SAS, as part of OpenIO SDS
# Copyright (C) 2021-2023 OVH SAS
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library.

from __future__ import absolute_import
import errno
import os

from oio.common.constants import (
    CHUNK_XATTR_KEYS,
    CHUNK_XATTR_CONTENT_FULLPATH_PREFIX,
    OIO_VERSION,
)
from oio.common.easy_value import debinarize


def read_user_xattr(fd):
    """Read all extended attributes starting with "user." """
    if hasattr(fd, "fileno"):
        fd = fd.fileno()
    meta = {}
    try:
        meta = debinarize(
            {
                k[5:]: os.getxattr(fd, k)
                for k in os.listxattr(fd)
                if k.startswith("user.")
            }
        )
    except IOError as err:
        for code in ("ENOTSUP", "EOPNOTSUPP", "ENOENT"):
            if hasattr(errno, code) and err.errno == getattr(errno, code):
                raise err

    return meta


def set_fullpath_xattr(fd, new_fullpaths, remove_old_xattr=False, xattr_to_remove=None):
    """
    Insert new fullpath extended attributes, remove deprecated ones.

    :param new_fullpaths: dictionary of "fullpath" extended attributes
        that should be set on file. The key is the chunk ID (required
        to generate the attribute key), the value is the "fullpath".
    :param remove_old_xattr: remove legacy attributes from file
    :type remove_old_xattr: `bool`
    :param xattr_to_remove: list of extra extended attributes
        that should be removed from file
    """
    if hasattr(fd, "fileno"):
        fd = fd.fileno()
    for chunk_id, new_fullpath in new_fullpaths.items():
        os.setxattr(
            fd,
            "user." + CHUNK_XATTR_CONTENT_FULLPATH_PREFIX + chunk_id.upper(),
            new_fullpath.encode("utf-8"),
        )

    if xattr_to_remove:
        for key in xattr_to_remove:
            try:
                os.removexattr(fd, "user." + key)
            except IOError:
                pass

    if remove_old_xattr:
        for key in [
            "chunk_id",
            "container_id",
            "content_path",
            "content_version",
            "content_id",
        ]:
            try:
                os.removexattr(fd, "user." + CHUNK_XATTR_KEYS[key])
            except IOError:
                pass

        os.setxattr(
            fd, "user." + CHUNK_XATTR_KEYS["oio_version"], OIO_VERSION.encode("utf-8")
        )

ab19b4fca7861fef93ea2fbc417772d56f9bd43e
<mask token>

<mask token>


def set_fullpath_xattr(fd, new_fullpaths, remove_old_xattr=False,
    xattr_to_remove=None):
    """
    Insert new fullpath extended attributes, remove deprecated ones.

    :param new_fullpaths: dictionary of "fullpath" extended attributes
        that should be set on file. The key is the chunk ID (required
        to generate the attribute key), the value is the "fullpath".
    :param remove_old_xattr: remove legacy attributes from file
    :type remove_old_xattr: `bool`
    :param xattr_to_remove: list of extra extended attributes
        that should be removed from file
    """
    if hasattr(fd, 'fileno'):
        fd = fd.fileno()
    for chunk_id, new_fullpath in new_fullpaths.items():
        os.setxattr(fd, 'user.' + CHUNK_XATTR_CONTENT_FULLPATH_PREFIX +
            chunk_id.upper(), new_fullpath.encode('utf-8'))
    if xattr_to_remove:
        for key in xattr_to_remove:
            try:
                os.removexattr(fd, 'user.' + key)
            except IOError:
                pass
    if remove_old_xattr:
        for key in ['chunk_id', 'container_id', 'content_path',
            'content_version', 'content_id']:
            try:
                os.removexattr(fd, 'user.' + CHUNK_XATTR_KEYS[key])
            except IOError:
                pass
        os.setxattr(fd, 'user.' + CHUNK_XATTR_KEYS['oio_version'],
            OIO_VERSION.encode('utf-8'))

<mask token>


def read_user_xattr(fd):
    """Read all extended attributes starting with "user." """
    if hasattr(fd, 'fileno'):
        fd = fd.fileno()
    meta = {}
    try:
        meta = debinarize({k[5:]: os.getxattr(fd, k) for k in os.listxattr(
            fd) if k.startswith('user.')})
    except IOError as err:
        for code in ('ENOTSUP', 'EOPNOTSUPP', 'ENOENT'):
            if hasattr(errno, code) and err.errno == getattr(errno, code):
                raise err
    return meta


def set_fullpath_xattr(fd, new_fullpaths, remove_old_xattr=False,
    xattr_to_remove=None):
    """
    Insert new fullpath extended attributes, remove deprecated ones.

    :param new_fullpaths: dictionary of "fullpath" extended attributes
        that should be set on file. The key is the chunk ID (required
        to generate the attribute key), the value is the "fullpath".
    :param remove_old_xattr: remove legacy attributes from file
    :type remove_old_xattr: `bool`
    :param xattr_to_remove: list of extra extended attributes
        that should be removed from file
    """
    if hasattr(fd, 'fileno'):
        fd = fd.fileno()
    for chunk_id, new_fullpath in new_fullpaths.items():
        os.setxattr(fd, 'user.' + CHUNK_XATTR_CONTENT_FULLPATH_PREFIX +
            chunk_id.upper(), new_fullpath.encode('utf-8'))
    if xattr_to_remove:
        for key in xattr_to_remove:
            try:
                os.removexattr(fd, 'user.' + key)
            except IOError:
                pass
    if remove_old_xattr:
        for key in ['chunk_id', 'container_id', 'content_path',
            'content_version', 'content_id']:
            try:
                os.removexattr(fd, 'user.' + CHUNK_XATTR_KEYS[key])
            except IOError:
                pass
        os.setxattr(fd, 'user.' + CHUNK_XATTR_KEYS['oio_version'],
            OIO_VERSION.encode('utf-8'))

from __future__ import absolute_import
import errno
import os
from oio.common.constants import CHUNK_XATTR_KEYS, CHUNK_XATTR_CONTENT_FULLPATH_PREFIX, OIO_VERSION
from oio.common.easy_value import debinarize


def read_user_xattr(fd):
    """Read all extended attributes starting with "user." """
    if hasattr(fd, 'fileno'):
        fd = fd.fileno()
    meta = {}
    try:
        meta = debinarize({k[5:]: os.getxattr(fd, k) for k in os.listxattr(
            fd) if k.startswith('user.')})
    except IOError as err:
        for code in ('ENOTSUP', 'EOPNOTSUPP', 'ENOENT'):
            if hasattr(errno, code) and err.errno == getattr(errno, code):
                raise err
    return meta


def set_fullpath_xattr(fd, new_fullpaths, remove_old_xattr=False,
    xattr_to_remove=None):
    """
    Insert new fullpath extended attributes, remove deprecated ones.

    :param new_fullpaths: dictionary of "fullpath" extended attributes
        that should be set on file. The key is the chunk ID (required
        to generate the attribute key), the value is the "fullpath".
    :param remove_old_xattr: remove legacy attributes from file
    :type remove_old_xattr: `bool`
    :param xattr_to_remove: list of extra extended attributes
        that should be removed from file
    """
    if hasattr(fd, 'fileno'):
        fd = fd.fileno()
    for chunk_id, new_fullpath in new_fullpaths.items():
        os.setxattr(fd, 'user.' + CHUNK_XATTR_CONTENT_FULLPATH_PREFIX +
            chunk_id.upper(), new_fullpath.encode('utf-8'))
    if xattr_to_remove:
        for key in xattr_to_remove:
            try:
                os.removexattr(fd, 'user.' + key)
            except IOError:
                pass
    if remove_old_xattr:
        for key in ['chunk_id', 'container_id', 'content_path',
            'content_version', 'content_id']:
            try:
                os.removexattr(fd, 'user.' + CHUNK_XATTR_KEYS[key])
            except IOError:
                pass
        os.setxattr(fd, 'user.' + CHUNK_XATTR_KEYS['oio_version'],
            OIO_VERSION.encode('utf-8'))

# Copyright (C) 2017-2020 OpenIO SAS, as part of OpenIO SDS
# Copyright (C) 2021-2023 OVH SAS
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library.

from __future__ import absolute_import
import errno
import os

from oio.common.constants import (
    CHUNK_XATTR_KEYS,
    CHUNK_XATTR_CONTENT_FULLPATH_PREFIX,
    OIO_VERSION,
)
from oio.common.easy_value import debinarize


def read_user_xattr(fd):
    """Read all extended attributes starting with "user." """
    if hasattr(fd, "fileno"):
        fd = fd.fileno()
    meta = {}
    try:
        meta = debinarize(
            {
                k[5:]: os.getxattr(fd, k)
                for k in os.listxattr(fd)
                if k.startswith("user.")
            }
        )
    except IOError as err:
        for code in ("ENOTSUP", "EOPNOTSUPP", "ENOENT"):
            if hasattr(errno, code) and err.errno == getattr(errno, code):
                raise err

    return meta


def set_fullpath_xattr(fd, new_fullpaths, remove_old_xattr=False, xattr_to_remove=None):
    """
    Insert new fullpath extended attributes, remove deprecated ones.

    :param new_fullpaths: dictionary of "fullpath" extended attributes
        that should be set on file. The key is the chunk ID (required
        to generate the attribute key), the value is the "fullpath".
    :param remove_old_xattr: remove legacy attributes from file
    :type remove_old_xattr: `bool`
    :param xattr_to_remove: list of extra extended attributes
        that should be removed from file
    """
    if hasattr(fd, "fileno"):
        fd = fd.fileno()
    for chunk_id, new_fullpath in new_fullpaths.items():
        os.setxattr(
            fd,
            "user." + CHUNK_XATTR_CONTENT_FULLPATH_PREFIX + chunk_id.upper(),
            new_fullpath.encode("utf-8"),
        )

    if xattr_to_remove:
        for key in xattr_to_remove:
            try:
                os.removexattr(fd, "user." + key)
            except IOError:
                pass

    if remove_old_xattr:
        for key in [
            "chunk_id",
            "container_id",
            "content_path",
            "content_version",
            "content_id",
        ]:
            try:
                os.removexattr(fd, "user." + CHUNK_XATTR_KEYS[key])
            except IOError:
                pass

        os.setxattr(
            fd, "user." + CHUNK_XATTR_KEYS["oio_version"], OIO_VERSION.encode("utf-8")
        )
