xattr_mem2file.c

/*
 *  Copyright (C) 2006  James Antill
 *
 *  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 2 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; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  email: james@and.org
 */
/* these functions are higher level abstractions for setting the list of
 * xattrs to a file/fd */

#include "xattr_mem2file.h"
#include "xattr_sc.h"
#include <string.h>
#include <errno.h>

static int xattr__ret_EPERM(int ret)
{
  if (ret == -1)
    errno = EPERM;

  return (ret);
}

int xattr_mem2file_app(Xattrs *xattrs, const char *fname, unsigned int flags)
{
  size_t scan = 0;
  int ret = 0;
  
  while (scan < xattrs->num)
  {
    char  *key = xattrs->ents[scan].key;
    void  *val = xattrs->ents[scan].val;
    size_t vsz = xattrs->ents[scan].vsz;
    int tmp = -1;

    if (flags & XATTR_FLAG_SC_SETXATTRS_FOLLOW)
      tmp =  setxattr(fname, key, val, vsz, 0);
    else
      tmp = lsetxattr(fname, key, val, vsz, 0);
    
    if ((tmp == -1) && (errno == EPERM))
      ret = -1;
    else if (tmp == -1)
      return (-1);
      
    ++scan;
  }

  return (xattr__ret_EPERM(ret));
}

int xattr_mem2file_sub(Xattrs *xattrs, const char *fname, unsigned int flags)
{
  char   *list_mem = NULL;
  ssize_t list_sz  = 0;
  int ret = 0;
  const char *attr = NULL;
  
  if (!(list_mem = xattr_sc_listxattrs(fname, -1, flags, &list_sz)))
    return (-1);

  attr = list_mem;
  while (list_sz > 0)
  {
    size_t len = strlen(attr);

    if (!xattr_srch_key(xattrs, attr))
    {
      int tmp = -1;
      
      if (flags & XATTR_FLAG_SC_SETXATTRS_FOLLOW)
        tmp =  removexattr(fname, attr);
      else
        tmp = lremovexattr(fname, attr);
      
      if ((tmp == -1) && (errno == EPERM))
        ret = -1;
      else if (tmp == -1)
      {
        XATTR_SC_RET_FREE(list_mem);
        return (-1);
      }
    }
    
    attr    += len + 1;
    list_sz -= len + 1;
  }

  XATTR_SC_RET_FREE(list_mem);
  
  return (xattr__ret_EPERM(ret));
}

int xattr_mem2file_set(Xattrs *xattrs, const char *fname, unsigned int flags)
{
  int ret = -1;

  ret = xattr_mem2file_app(xattrs, fname, flags);
  if (ret == -1)
    return (-1);

  return (xattr_mem2file_sub(xattrs, fname, flags));
}

int xattr_mem2fd_app(Xattrs *xattrs, int fd)
{
  size_t scan = 0;
  int ret = 0;
  
  while (scan < xattrs->num)
  {
    char  *key = xattrs->ents[scan].key;
    void  *val = xattrs->ents[scan].val;
    size_t vsz = xattrs->ents[scan].vsz;
    int tmp = -1;
    
    tmp = fsetxattr(fd, key, val, vsz, 0);
    if ((tmp == -1) && (errno == EPERM))
      ret = -1;
    else if (tmp == -1)
      return (-1);
      
    ++scan;
  }
  
  return (xattr__ret_EPERM(ret));
}

int xattr_mem2fd_sub(Xattrs *xattrs, int fd)
{
  char   *list_mem = NULL;
  ssize_t list_sz  = 0;
  int ret = 0;
  const char *attr = NULL;
  

  if (!(list_mem = xattr_sc_listxattrs(NULL, fd, 0, &list_sz)))
    return (-1);

  attr = list_mem;
  while (list_sz > 0)
  {
    size_t len = strlen(attr);

    if (!xattr_srch_key(xattrs, attr))
    {
      int tmp = -1;
      
      tmp = fremovexattr(fd, attr);

      if ((tmp == -1) && (errno == EPERM))
        ret = -1;
      else if (errno == EOPNOTSUPP)
      {
        XATTR_SC_RET_FREE(list_mem);
        return (-1);
      }
    }
    
    attr    += len + 1;
    list_sz -= len + 1;
  }

  XATTR_SC_RET_FREE(list_mem);
  
  return (xattr__ret_EPERM(ret));
}

int xattr_mem2fd_set(Xattrs *xattrs, int fd)
{
  int ret = -1;

  ret = xattr_mem2fd_app(xattrs, fd);
  if (ret == -1)
    return (-1);

  return (xattr_mem2fd_sub(xattrs, fd));
}