Back to index

glibc  2.9
xattr.c
Go to the documentation of this file.
00001 /* Support for *xattr interfaces on GNU/Hurd.
00002    Copyright (C) 2006 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <hurd.h>
00021 #include <hurd/xattr.h>
00022 #include <string.h>
00023 #include <sys/mman.h>
00024 
00025 /* Right now we support only a fixed set of xattr names for Hurd features.
00026    There are no RPC interfaces for free-form xattr names and values.
00027 
00028    Name                     Value encoding
00029    ----                     ----- --------
00030    gnu.author        empty if st_author==st_uid
00031                      uid_t giving st_author value
00032    gnu.translator    empty if no passive translator
00033                      translator and arguments: "/hurd/foo\0arg1\0arg2\0"
00034 */
00035 
00036 error_t
00037 _hurd_xattr_get (io_t port, const char *name, void *value, size_t *size)
00038 {
00039   if (strncmp (name, "gnu.", 4))
00040     return EOPNOTSUPP;
00041   name += 4;
00042 
00043   if (!strcmp (name, "author"))
00044     {
00045       struct stat64 st;
00046       error_t err = __io_stat (port, &st);
00047       if (err)
00048        return err;
00049       if (st.st_author == st.st_uid)
00050        *size = 0;
00051       else if (value)
00052        {
00053          if (*size < sizeof st.st_author)
00054            return ERANGE;
00055          memcpy (value, &st.st_author, sizeof st.st_author);
00056        }
00057       *size = sizeof st.st_author;
00058       return 0;
00059     }
00060 
00061   if (!strcmp (name, "translator"))
00062     {
00063       char *buf = value;
00064       size_t bufsz = value ? *size : 0;
00065       error_t err = __file_get_translator (port, &buf, &bufsz);
00066       if (err)
00067        return err;
00068       if (value != NULL && *size < bufsz)
00069        {
00070          if (buf != value)
00071            munmap (buf, bufsz);
00072          return -ERANGE;
00073        }
00074       if (buf != value && bufsz > 0)
00075        {
00076          if (value != NULL)
00077            memcpy (value, buf, bufsz);
00078          munmap (buf, bufsz);
00079        }
00080       *size = bufsz;
00081       return 0;
00082     }
00083 
00084   return EOPNOTSUPP;
00085 }
00086 
00087 error_t
00088 _hurd_xattr_set (io_t port, const char *name, const void *value, size_t size,
00089                int flags)
00090 {
00091   if (strncmp (name, "gnu.", 4))
00092     return EOPNOTSUPP;
00093   name += 4;
00094 
00095   if (!strcmp (name, "author"))
00096     switch (size)
00097       {
00098       default:
00099        return EINVAL;
00100       case 0:               /* "Clear" author by setting to st_uid. */
00101        {
00102          struct stat64 st;
00103          error_t err = __io_stat (port, &st);
00104          if (err)
00105            return err;
00106          if (st.st_author == st.st_uid)
00107            {
00108              /* Nothing to do.  */
00109              if (flags & XATTR_REPLACE)
00110               return ENODATA;
00111              return 0;
00112            }
00113          if (flags & XATTR_CREATE)
00114            return EEXIST;
00115          return __file_chauthor (port, st.st_uid);
00116        }
00117       case sizeof (uid_t):  /* Set the author.  */
00118        {
00119          uid_t id;
00120          memcpy (&id, value, sizeof id);
00121          if (flags & (XATTR_CREATE|XATTR_REPLACE))
00122            {
00123              struct stat64 st;
00124              error_t err = __io_stat (port, &st);
00125              if (err)
00126               return err;
00127              if (st.st_author == st.st_uid)
00128               {
00129                 if (flags & XATTR_REPLACE)
00130                   return ENODATA;
00131               }
00132              else if (flags & XATTR_CREATE)
00133               return EEXIST;
00134              if (st.st_author == id)
00135               /* Nothing to do.  */
00136               return 0;
00137            }
00138          return __file_chauthor (port, id);
00139        }
00140       }
00141 
00142   if (!strcmp (name, "translator"))
00143     {
00144       if (flags & XATTR_REPLACE)
00145        {
00146          /* Must make sure it's already there.  */
00147          char *buf = NULL;
00148          size_t bufsz = 0;
00149          error_t err = __file_get_translator (port, &buf, &bufsz);
00150          if (err)
00151            return err;
00152          if (bufsz > 0)
00153            {
00154              munmap (buf, bufsz);
00155              return ENODATA;
00156            }
00157        }
00158       return __file_set_translator (port,
00159                                 FS_TRANS_SET | ((flags & XATTR_CREATE)
00160                                               ? FS_TRANS_EXCL : 0), 0, 0,
00161                                 value, size,
00162                                 MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND);
00163     }
00164 
00165   return EOPNOTSUPP;
00166 }
00167 
00168 error_t
00169 _hurd_xattr_remove (io_t port, const char *name)
00170 {
00171   return _hurd_xattr_set (port, name, NULL, 0, XATTR_REPLACE);
00172 }
00173 
00174 error_t
00175 _hurd_xattr_list (io_t port, void *buffer, size_t *size)
00176 {
00177   size_t total = 0;
00178   char *bufp = buffer;
00179   inline void add (const char *name, size_t len)
00180     {
00181       total += len;
00182       if (bufp != NULL && total <= *size)
00183        bufp = __mempcpy (bufp, name, len);
00184     }
00185 #define add(s) add (s, sizeof s)
00186 
00187   struct stat64 st;
00188   error_t err = __io_stat (port, &st);
00189   if (err)
00190     return err;
00191 
00192   if (st.st_author != st.st_uid)
00193     add ("gnu.author");
00194   if (st.st_mode & S_IPTRANS)
00195     add ("gnu.translator");
00196 
00197   if (buffer != NULL && total > *size)
00198     return ERANGE;
00199   *size = total;
00200   return 0;
00201 }