"Fossies" - the Fresh Open Source Software Archive

Member "ntfs-3g_ntfsprogs-2017.3.23/libntfs-3g/xattrs.c" (23 Mar 2017, 19448 Bytes) of package /linux/misc/ntfs-3g_ntfsprogs-2017.3.23.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "xattrs.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3g_ntfsprogs-2016.2.22_vs_3g_ntfsprogs-2017.3.23.

    1 /**
    2  * xattrs.c : common functions to deal with system extended attributes
    3  *
    4  * Copyright (c) 2010-2014 Jean-Pierre Andre
    5  *
    6  * This program/include file is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU General Public License as published
    8  * by the Free Software Foundation; either version 2 of the License, or
    9  * (at your option) any later version.
   10  *
   11  * This program/include file is distributed in the hope that it will be
   12  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
   13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License
   17  * along with this program (in the main directory of the NTFS-3G
   18  * distribution in the file COPYING); if not, write to the Free Software
   19  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   20  */
   21 
   22 #ifdef HAVE_CONFIG_H
   23 #include "config.h"
   24 #endif
   25 
   26 #ifdef HAVE_STDIO_H
   27 #include <stdio.h>
   28 #endif
   29 #ifdef HAVE_STDLIB_H
   30 #include <stdlib.h>
   31 #endif
   32 #ifdef HAVE_STRING_H
   33 #include <string.h>
   34 #endif
   35 #ifdef HAVE_FCNTL_H
   36 #include <fcntl.h>
   37 #endif
   38 #ifdef HAVE_UNISTD_H
   39 #include <unistd.h>
   40 #endif
   41 #ifdef HAVE_ERRNO_H
   42 #include <errno.h>
   43 #endif
   44 
   45 #include "types.h"
   46 #include "param.h"
   47 #include "layout.h"
   48 #include "attrib.h"
   49 #include "index.h"
   50 #include "dir.h"
   51 #include "security.h"
   52 #include "acls.h"
   53 #include "efs.h"
   54 #include "reparse.h"
   55 #include "object_id.h"
   56 #include "ea.h"
   57 #include "misc.h"
   58 #include "logging.h"
   59 #include "xattrs.h"
   60 
   61 #if POSIXACLS
   62 #if __BYTE_ORDER == __BIG_ENDIAN
   63 
   64 /*
   65  *             Posix ACL structures
   66  */
   67         
   68 struct LE_POSIX_ACE {
   69     le16 tag;
   70     le16 perms;
   71     le32 id;    
   72 } __attribute__((__packed__));
   73 
   74 struct LE_POSIX_ACL {
   75     u8 version;
   76     u8 flags;
   77     le16 filler; 
   78     struct LE_POSIX_ACE ace[0];
   79 } __attribute__((__packed__));
   80         
   81 #endif
   82 #endif
   83 
   84 static const char nf_ns_xattr_ntfs_acl[] = "system.ntfs_acl";
   85 static const char nf_ns_xattr_attrib[] = "system.ntfs_attrib";
   86 static const char nf_ns_xattr_attrib_be[] = "system.ntfs_attrib_be";
   87 static const char nf_ns_xattr_efsinfo[] = "system.ntfs_efsinfo";
   88 static const char nf_ns_xattr_reparse[] = "system.ntfs_reparse_data";
   89 static const char nf_ns_xattr_object_id[] = "system.ntfs_object_id";
   90 static const char nf_ns_xattr_dos_name[] = "system.ntfs_dos_name";
   91 static const char nf_ns_xattr_times[] = "system.ntfs_times";
   92 static const char nf_ns_xattr_times_be[] = "system.ntfs_times_be";
   93 static const char nf_ns_xattr_crtime[] = "system.ntfs_crtime";
   94 static const char nf_ns_xattr_crtime_be[] = "system.ntfs_crtime_be";
   95 static const char nf_ns_xattr_ea[] = "system.ntfs_ea";
   96 static const char nf_ns_xattr_posix_access[] = "system.posix_acl_access";
   97 static const char nf_ns_xattr_posix_default[] = "system.posix_acl_default";
   98 
   99 static const char nf_ns_alt_xattr_efsinfo[] = "user.ntfs.efsinfo";
  100 
  101 struct XATTRNAME {
  102     enum SYSTEMXATTRS xattr;
  103     const char *name;
  104 } ;
  105 
  106 static struct XATTRNAME nf_ns_xattr_names[] = {
  107     { XATTR_NTFS_ACL, nf_ns_xattr_ntfs_acl },
  108     { XATTR_NTFS_ATTRIB, nf_ns_xattr_attrib },
  109     { XATTR_NTFS_ATTRIB_BE, nf_ns_xattr_attrib_be },
  110     { XATTR_NTFS_EFSINFO, nf_ns_xattr_efsinfo },
  111     { XATTR_NTFS_REPARSE_DATA, nf_ns_xattr_reparse },
  112     { XATTR_NTFS_OBJECT_ID, nf_ns_xattr_object_id },
  113     { XATTR_NTFS_DOS_NAME, nf_ns_xattr_dos_name },
  114     { XATTR_NTFS_TIMES, nf_ns_xattr_times },
  115     { XATTR_NTFS_TIMES_BE, nf_ns_xattr_times_be },
  116     { XATTR_NTFS_CRTIME, nf_ns_xattr_crtime },
  117     { XATTR_NTFS_CRTIME_BE, nf_ns_xattr_crtime_be },
  118     { XATTR_NTFS_EA, nf_ns_xattr_ea },
  119     { XATTR_POSIX_ACC, nf_ns_xattr_posix_access },
  120     { XATTR_POSIX_DEF, nf_ns_xattr_posix_default },
  121     { XATTR_UNMAPPED, (char*)NULL } /* terminator */
  122 };
  123 
  124 /*
  125  *      Make an integer big-endian
  126  *
  127  *  Swap bytes on a small-endian computer and does nothing on a
  128  *  big-endian computer.
  129  */
  130 
  131 static void fix_big_endian(char *p, int size)
  132 {
  133 #if __BYTE_ORDER == __LITTLE_ENDIAN
  134     int i,j;
  135     int c;
  136 
  137     i = 0;
  138     j = size - 1;
  139     while (i < j) {
  140         c = p[i];
  141         p[i++] = p[j];
  142         p[j--] = c;
  143     }
  144 #endif
  145 }
  146 
  147 #if POSIXACLS
  148 #if __BYTE_ORDER == __BIG_ENDIAN
  149 
  150 /*
  151  *      Make a Posix ACL CPU endian
  152  */
  153 
  154 static int le_acl_to_cpu(const struct LE_POSIX_ACL *le_acl, size_t size,
  155                 struct POSIX_ACL *acl)
  156 {
  157     int i;
  158     int cnt;
  159 
  160     acl->version = le_acl->version;
  161     acl->flags = le_acl->flags;
  162     acl->filler = 0;
  163     cnt = (size - sizeof(struct LE_POSIX_ACL)) / sizeof(struct LE_POSIX_ACE);
  164     for (i=0; i<cnt; i++) {
  165         acl->ace[i].tag = le16_to_cpu(le_acl->ace[i].tag);
  166         acl->ace[i].perms = le16_to_cpu(le_acl->ace[i].perms);
  167         acl->ace[i].id = le32_to_cpu(le_acl->ace[i].id);
  168     }
  169     return (0);
  170 }
  171 
  172 /*
  173  *      Make a Posix ACL little endian
  174  */
  175 
  176 int cpu_to_le_acl(const struct POSIX_ACL *acl, size_t size,
  177             struct LE_POSIX_ACL *le_acl)
  178 {
  179     int i;
  180     int cnt;
  181 
  182     le_acl->version = acl->version;
  183     le_acl->flags = acl->flags;
  184     le_acl->filler = const_cpu_to_le16(0);
  185     cnt = (size - sizeof(struct POSIX_ACL)) / sizeof(struct POSIX_ACE);
  186     for (i=0; i<cnt; i++) {
  187         le_acl->ace[i].tag = cpu_to_le16(acl->ace[i].tag);
  188         le_acl->ace[i].perms = cpu_to_le16(acl->ace[i].perms);
  189         le_acl->ace[i].id = cpu_to_le32(acl->ace[i].id);
  190     }
  191     return (0);
  192 }
  193 
  194 #endif
  195 #endif
  196 
  197 /*
  198  *      Determine whether an extended attribute is mapped to
  199  *  internal data (original name in system namespace, or renamed)
  200  */
  201 
  202 enum SYSTEMXATTRS ntfs_xattr_system_type(const char *name,
  203             ntfs_volume *vol)
  204 {
  205     struct XATTRNAME *p;
  206     enum SYSTEMXATTRS ret;
  207 #ifdef XATTR_MAPPINGS
  208     const struct XATTRMAPPING *q;
  209 #endif /* XATTR_MAPPINGS */
  210 
  211     p = nf_ns_xattr_names;
  212     while (p->name && strcmp(p->name,name))
  213         p++;
  214     ret = p->xattr;
  215 #ifdef XATTR_MAPPINGS
  216     if (!p->name && vol && vol->xattr_mapping) {
  217         q = vol->xattr_mapping;
  218         while (q && strcmp(q->name,name))
  219             q = q->next;
  220         if (q)
  221             ret = q->xattr;
  222     }
  223 #else /* XATTR_MAPPINGS */
  224     if (!p->name
  225         && vol
  226         && vol->efs_raw
  227         && !strcmp(nf_ns_alt_xattr_efsinfo,name))
  228         ret = XATTR_NTFS_EFSINFO;
  229 #endif /* XATTR_MAPPINGS */
  230     return (ret);
  231 }
  232 
  233 #ifdef XATTR_MAPPINGS
  234 
  235 /*
  236  *      Basic read from a user mapping file on another volume
  237  */
  238 
  239 static int basicread(void *fileid, char *buf, size_t size, off_t offs __attribute__((unused)))
  240 {
  241     return (read(*(int*)fileid, buf, size));
  242 }
  243 
  244 
  245 /*
  246  *      Read from a user mapping file on current NTFS partition
  247  */
  248 
  249 static int localread(void *fileid, char *buf, size_t size, off_t offs)
  250 {
  251     return (ntfs_attr_data_read((ntfs_inode*)fileid,
  252             AT_UNNAMED, 0, buf, size, offs));
  253 }
  254 
  255 /*
  256  *      Get a single mapping item from buffer
  257  *
  258  *  Always reads a full line, truncating long lines
  259  *  Refills buffer when exhausted
  260  *  Returns pointer to item, or NULL when there is no more
  261  *  Note : errors are logged, but not returned
  262 // TODO partially share with acls.c
  263  */
  264 
  265 static struct XATTRMAPPING *getmappingitem(FILEREADER reader, void *fileid,
  266         off_t *poffs, char *buf, int *psrc, s64 *psize)
  267 {
  268     int src;
  269     int dst;
  270     char *pe;
  271     char *ps;
  272     char *pu;
  273     enum SYSTEMXATTRS xattr;
  274     int gotend;
  275     char maptext[LINESZ];
  276     struct XATTRMAPPING *item;
  277 
  278     src = *psrc;
  279     dst = 0;
  280     do {
  281         gotend = 0;
  282         while ((src < *psize)
  283                && (buf[src] != '\n')) {
  284                 /* ignore spaces */
  285             if ((dst < LINESZ)
  286                 && (buf[src] != '\r')
  287                 && (buf[src] != '\t')
  288                 && (buf[src] != ' '))
  289                 maptext[dst++] = buf[src];
  290             src++;
  291         }
  292         if (src >= *psize) {
  293             *poffs += *psize;
  294             *psize = reader(fileid, buf, (size_t)BUFSZ, *poffs);
  295             src = 0;
  296         } else {
  297             gotend = 1;
  298             src++;
  299             maptext[dst] = '\0';
  300             dst = 0;
  301         }
  302     } while (*psize && ((maptext[0] == '#') || !gotend));
  303     item = (struct XATTRMAPPING*)NULL;
  304     if (gotend) {
  305             /* decompose into system name and user name */
  306         ps = maptext;
  307         pu = strchr(maptext,':');
  308         if (pu) {
  309             *pu++ = 0;
  310             pe = strchr(pu,':');
  311             if (pe)
  312                 *pe = 0;
  313                 /* check name validity */
  314             if ((strlen(pu) < 6) || strncmp(pu,"user.",5))
  315                 pu = (char*)NULL;
  316             xattr = ntfs_xattr_system_type(ps,
  317                     (ntfs_volume*)NULL);
  318             if (xattr == XATTR_UNMAPPED)
  319                 pu = (char*)NULL;
  320         }
  321         if (pu) {
  322             item = (struct XATTRMAPPING*)ntfs_malloc(
  323                 sizeof(struct XATTRMAPPING)
  324                 + strlen(pu));
  325             if (item) {
  326                 item->xattr = xattr;
  327                 strcpy(item->name,pu);
  328                 item->next = (struct XATTRMAPPING*)NULL;
  329             }
  330         } else {
  331             ntfs_log_early_error("Bad xattr mapping item, aborting\n");
  332         }
  333     }
  334     *psrc = src;
  335     return (item);
  336 }
  337 
  338 /*
  339  *      Read xattr mapping file and split into their attribute.
  340  *  Parameters are kept in a chained list.
  341  *  Returns the head of list, if any
  342  *  Errors are logged, but not returned
  343  *
  344  *  If an absolute path is provided, the mapping file is assumed
  345  *  to be located in another mounted file system, and plain read()
  346  *  are used to get its contents.
  347  *  If a relative path is provided, the mapping file is assumed
  348  *  to be located on the current file system, and internal IO
  349  *  have to be used since we are still mounting and we have not
  350  *  entered the fuse loop yet.
  351  */
  352 
  353 static struct XATTRMAPPING *ntfs_read_xattr_mapping(FILEREADER reader,
  354                 void *fileid)
  355 {
  356     char buf[BUFSZ];
  357     struct XATTRMAPPING *item;
  358     struct XATTRMAPPING *current;
  359     struct XATTRMAPPING *firstitem;
  360     struct XATTRMAPPING *lastitem;
  361     BOOL duplicated;
  362     int src;
  363     off_t offs;
  364     s64 size;
  365 
  366     firstitem = (struct XATTRMAPPING*)NULL;
  367     lastitem = (struct XATTRMAPPING*)NULL;
  368     offs = 0;
  369     size = reader(fileid, buf, (size_t)BUFSZ, (off_t)0);
  370     if (size > 0) {
  371         src = 0;
  372         do {
  373             item = getmappingitem(reader, fileid, &offs,
  374                 buf, &src, &size);
  375             if (item) {
  376                 /* check no double mapping */
  377                 duplicated = FALSE;
  378                 for (current=firstitem; current; current=current->next)
  379                     if ((current->xattr == item->xattr)
  380                         || !strcmp(current->name,item->name))
  381                         duplicated = TRUE;
  382                 if (duplicated) {
  383                     free(item);
  384                     ntfs_log_early_error("Conflicting xattr mapping ignored\n");
  385                 } else {
  386                     item->next = (struct XATTRMAPPING*)NULL;
  387                     if (lastitem)
  388                         lastitem->next = item;
  389                     else
  390                         firstitem = item;
  391                     lastitem = item;
  392                 }
  393             }
  394         } while (item);
  395     }
  396     return (firstitem);
  397 }
  398 
  399 /*
  400  *      Build the extended attribute mappings to user namespace
  401  *
  402  *  Note : no error is returned. If we refused mounting when there
  403  *  is an error it would be too difficult to fix the offending file
  404  */
  405 
  406 struct XATTRMAPPING *ntfs_xattr_build_mapping(ntfs_volume *vol,
  407             const char *xattrmap_path)
  408 {
  409     struct XATTRMAPPING *firstmapping;
  410     struct XATTRMAPPING *mapping;
  411     BOOL user_efs;
  412     BOOL notfound;
  413     ntfs_inode *ni;
  414     int fd;
  415 
  416     firstmapping = (struct XATTRMAPPING*)NULL;
  417     notfound = FALSE;
  418     if (!xattrmap_path)
  419         xattrmap_path = XATTRMAPPINGFILE;
  420     if (xattrmap_path[0] == '/') {
  421         fd = open(xattrmap_path,O_RDONLY);
  422         if (fd > 0) {
  423             firstmapping = ntfs_read_xattr_mapping(basicread, (void*)&fd);
  424             close(fd);
  425         } else
  426             notfound = TRUE;
  427     } else {
  428         ni = ntfs_pathname_to_inode(vol, NULL, xattrmap_path);
  429         if (ni) {
  430             firstmapping = ntfs_read_xattr_mapping(localread, ni);
  431             ntfs_inode_close(ni);
  432         } else
  433             notfound = TRUE;
  434     }
  435     if (notfound && strcmp(xattrmap_path, XATTRMAPPINGFILE)) {
  436         ntfs_log_early_error("Could not open \"%s\"\n",xattrmap_path);
  437     }
  438     if (vol->efs_raw) {
  439         user_efs = TRUE;
  440         for (mapping=firstmapping; mapping; mapping=mapping->next)
  441             if (mapping->xattr == XATTR_NTFS_EFSINFO)
  442                 user_efs = FALSE;
  443     } else
  444         user_efs = FALSE;
  445     if (user_efs) {
  446         mapping = (struct XATTRMAPPING*)ntfs_malloc(
  447                 sizeof(struct XATTRMAPPING)
  448                 + strlen(nf_ns_alt_xattr_efsinfo));
  449         if (mapping) {
  450             mapping->next = firstmapping;
  451             mapping->xattr = XATTR_NTFS_EFSINFO;
  452             strcpy(mapping->name,nf_ns_alt_xattr_efsinfo);
  453             firstmapping = mapping;
  454         }
  455     }
  456     return (firstmapping);
  457 }
  458 
  459 void ntfs_xattr_free_mapping(struct XATTRMAPPING *mapping)
  460 {
  461     struct XATTRMAPPING *p, *q;
  462 
  463     p = mapping;
  464     while (p) {
  465         q = p->next;
  466         free(p);
  467         p = q;
  468     }
  469 }
  470 
  471 #endif /* XATTR_MAPPINGS */
  472 
  473 int ntfs_xattr_system_getxattr(struct SECURITY_CONTEXT *scx,
  474             enum SYSTEMXATTRS attr,
  475             ntfs_inode *ni, ntfs_inode *dir_ni,
  476             char *value, size_t size)
  477 {
  478     int res;
  479     int i;
  480 #if POSIXACLS
  481 #if __BYTE_ORDER == __BIG_ENDIAN
  482     struct POSIX_ACL *acl;
  483 #endif
  484 #endif
  485 
  486                 /*
  487                  * the returned value is the needed
  488                  * size. If it is too small, no copy
  489                  * is done, and the caller has to
  490                  * issue a new call with correct size.
  491                  */
  492     switch (attr) {
  493     case XATTR_NTFS_ACL :
  494         res = ntfs_get_ntfs_acl(scx, ni, value, size);
  495         break;
  496 #if POSIXACLS
  497 #if __BYTE_ORDER == __BIG_ENDIAN
  498     case XATTR_POSIX_ACC :
  499         acl = (struct POSIX_ACL*)ntfs_malloc(size);
  500         if (acl) {
  501             res = ntfs_get_posix_acl(scx, ni,
  502                 nf_ns_xattr_posix_access, (char*)acl, size);
  503             if (res > 0) {
  504                 if (cpu_to_le_acl(acl,res,
  505                         (struct LE_POSIX_ACL*)value))
  506                     res = -errno;
  507             }
  508             free(acl);
  509         } else
  510             res = -errno;
  511         break;
  512     case XATTR_POSIX_DEF :
  513         acl = (struct POSIX_ACL*)ntfs_malloc(size);
  514         if (acl) {
  515             res = ntfs_get_posix_acl(scx, ni,
  516                 nf_ns_xattr_posix_default, (char*)acl, size);
  517             if (res > 0) {
  518                 if (cpu_to_le_acl(acl,res,
  519                         (struct LE_POSIX_ACL*)value))
  520                     res = -errno;
  521             }
  522             free(acl);
  523         } else
  524             res = -errno;
  525         break;
  526 #else
  527     case XATTR_POSIX_ACC :
  528         res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_access,
  529                 value, size);
  530         break;
  531     case XATTR_POSIX_DEF :
  532         res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_default,
  533                 value, size);
  534         break;
  535 #endif
  536 #endif
  537     case XATTR_NTFS_ATTRIB :
  538         res = ntfs_get_ntfs_attrib(ni, value, size);
  539         break;
  540     case XATTR_NTFS_ATTRIB_BE :
  541         res = ntfs_get_ntfs_attrib(ni, value, size);
  542         if ((res == 4) && value) {
  543             if (size >= 4)
  544                 fix_big_endian(value,4);
  545             else
  546                 res = -EINVAL;
  547         }
  548         break;
  549     case XATTR_NTFS_EFSINFO :
  550         if (ni->vol->efs_raw)
  551             res = ntfs_get_efs_info(ni, value, size);
  552         else
  553             res = -EPERM;
  554         break;
  555     case XATTR_NTFS_REPARSE_DATA :
  556         res = ntfs_get_ntfs_reparse_data(ni, value, size);
  557         break;
  558     case XATTR_NTFS_OBJECT_ID :
  559         res = ntfs_get_ntfs_object_id(ni, value, size);
  560         break;
  561     case XATTR_NTFS_DOS_NAME:
  562         if (dir_ni)
  563             res = ntfs_get_ntfs_dos_name(ni, dir_ni, value, size);
  564         else
  565             res = -errno;
  566         break;
  567     case XATTR_NTFS_TIMES:
  568         res = ntfs_inode_get_times(ni, value, size);
  569         break;
  570     case XATTR_NTFS_TIMES_BE:
  571         res = ntfs_inode_get_times(ni, value, size);
  572         if ((res > 0) && value) {
  573             for (i=0; (i+1)*sizeof(u64)<=(unsigned int)res; i++)
  574                 fix_big_endian(&value[i*sizeof(u64)],
  575                         sizeof(u64));
  576         }
  577         break;
  578     case XATTR_NTFS_CRTIME:
  579         res = ntfs_inode_get_times(ni, value,
  580                 (size >= sizeof(u64) ? sizeof(u64) : size));
  581         break;
  582     case XATTR_NTFS_CRTIME_BE:
  583         res = ntfs_inode_get_times(ni, value,
  584                 (size >= sizeof(u64) ? sizeof(u64) : size));
  585         if ((res >= (int)sizeof(u64)) && value)
  586             fix_big_endian(value,sizeof(u64));
  587         break;
  588     case XATTR_NTFS_EA :
  589         res = ntfs_get_ntfs_ea(ni, value, size);
  590         break;
  591     default :
  592         errno = EOPNOTSUPP;
  593         res = -errno;
  594         break;
  595     }
  596     return (res);
  597 }
  598 
  599 int ntfs_xattr_system_setxattr(struct SECURITY_CONTEXT *scx,
  600             enum SYSTEMXATTRS attr,
  601             ntfs_inode *ni, ntfs_inode *dir_ni,
  602             const char *value, size_t size, int flags)
  603 {
  604     int res;
  605     int i;
  606     char buf[4*sizeof(u64)];
  607 #if POSIXACLS
  608 #if __BYTE_ORDER == __BIG_ENDIAN
  609     struct POSIX_ACL *acl;
  610 #endif
  611 #endif
  612 
  613     switch (attr) {
  614     case XATTR_NTFS_ACL :
  615         res = ntfs_set_ntfs_acl(scx, ni, value, size, flags);
  616         break;
  617 #if POSIXACLS
  618 #if __BYTE_ORDER == __BIG_ENDIAN
  619     case XATTR_POSIX_ACC :
  620         acl = (struct POSIX_ACL*)ntfs_malloc(size);
  621         if (acl) {
  622             if (!le_acl_to_cpu((const struct LE_POSIX_ACL*)value,
  623                     size, acl)) {
  624                 res = ntfs_set_posix_acl(scx ,ni ,
  625                     nf_ns_xattr_posix_access,
  626                     (char*)acl, size, flags);
  627             } else
  628                 res = -errno;
  629             free(acl);
  630         } else
  631             res = -errno;
  632         break;
  633     case XATTR_POSIX_DEF :
  634         acl = (struct POSIX_ACL*)ntfs_malloc(size);
  635         if (acl) {
  636             if (!le_acl_to_cpu((const struct LE_POSIX_ACL*)value,
  637                     size, acl)) {
  638                 res = ntfs_set_posix_acl(scx ,ni ,
  639                     nf_ns_xattr_posix_default,
  640                     (char*)acl, size, flags);
  641             } else
  642                 res = -errno;
  643             free(acl);
  644         } else
  645             res = -errno;
  646         break;
  647 #else
  648     case XATTR_POSIX_ACC :
  649         res = ntfs_set_posix_acl(scx ,ni , nf_ns_xattr_posix_access,
  650                     value, size, flags);
  651         break;
  652     case XATTR_POSIX_DEF :
  653         res = ntfs_set_posix_acl(scx, ni, nf_ns_xattr_posix_default,
  654                     value, size, flags);
  655         break;
  656 #endif
  657 #endif
  658     case XATTR_NTFS_ATTRIB :
  659         res = ntfs_set_ntfs_attrib(ni, value, size, flags);
  660         break;
  661     case XATTR_NTFS_ATTRIB_BE :
  662         if (value && (size >= 4)) {
  663             memcpy(buf,value,4);
  664             fix_big_endian(buf,4);
  665             res = ntfs_set_ntfs_attrib(ni, buf, 4, flags);
  666         } else
  667             res = ntfs_set_ntfs_attrib(ni, value, size, flags);
  668         break;
  669     case XATTR_NTFS_EFSINFO :
  670         if (ni->vol->efs_raw)
  671             res = ntfs_set_efs_info(ni, value, size, flags);
  672         else
  673             res = -EPERM;
  674         break;
  675     case XATTR_NTFS_REPARSE_DATA :
  676         res = ntfs_set_ntfs_reparse_data(ni, value, size, flags);
  677         break;
  678     case XATTR_NTFS_OBJECT_ID :
  679         res = ntfs_set_ntfs_object_id(ni, value, size, flags);
  680         break;
  681     case XATTR_NTFS_DOS_NAME:
  682         if (dir_ni)
  683         /* warning : this closes both inodes */
  684             res = ntfs_set_ntfs_dos_name(ni, dir_ni, value,
  685                         size, flags);
  686         else
  687             res = -errno;
  688         break;
  689     case XATTR_NTFS_TIMES:
  690         res = ntfs_inode_set_times(ni, value, size, flags);
  691         break;
  692     case XATTR_NTFS_TIMES_BE:
  693         if (value && (size > 0) && (size <= 4*sizeof(u64))) {
  694             memcpy(buf,value,size);
  695             for (i=0; (i+1)*sizeof(u64)<=size; i++)
  696                 fix_big_endian(&buf[i*sizeof(u64)],
  697                         sizeof(u64));
  698             res = ntfs_inode_set_times(ni, buf, size, flags);
  699         } else
  700             res = ntfs_inode_set_times(ni, value, size, flags);
  701         break;
  702     case XATTR_NTFS_CRTIME:
  703         res = ntfs_inode_set_times(ni, value,
  704             (size >= sizeof(u64) ? sizeof(u64) : size), flags);
  705         break;
  706     case XATTR_NTFS_CRTIME_BE:
  707         if (value && (size >= sizeof(u64))) {
  708             memcpy(buf,value,sizeof(u64));
  709             fix_big_endian(buf,sizeof(u64));
  710             res = ntfs_inode_set_times(ni, buf, sizeof(u64), flags);
  711         } else
  712             res = ntfs_inode_set_times(ni, value, size, flags);
  713         break;
  714     case XATTR_NTFS_EA :
  715         res = ntfs_set_ntfs_ea(ni, value, size, flags);
  716         break;
  717     default :
  718         errno = EOPNOTSUPP;
  719         res = -errno;
  720         break;
  721     }
  722     return (res);
  723 }
  724 
  725 int ntfs_xattr_system_removexattr(struct SECURITY_CONTEXT *scx,
  726             enum SYSTEMXATTRS attr,
  727             ntfs_inode *ni, ntfs_inode *dir_ni)
  728 {
  729     int res;
  730 
  731     res = 0;
  732     switch (attr) {
  733         /*
  734          * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
  735          * is never allowed
  736          */
  737     case XATTR_NTFS_ACL :
  738     case XATTR_NTFS_ATTRIB :
  739     case XATTR_NTFS_ATTRIB_BE :
  740     case XATTR_NTFS_EFSINFO :
  741     case XATTR_NTFS_TIMES :
  742     case XATTR_NTFS_TIMES_BE :
  743     case XATTR_NTFS_CRTIME :
  744     case XATTR_NTFS_CRTIME_BE :
  745         res = -EPERM;
  746         break;
  747 #if POSIXACLS
  748     case XATTR_POSIX_ACC :
  749     case XATTR_POSIX_DEF :
  750         if (ni) {
  751             if (!ntfs_allowed_as_owner(scx, ni)
  752                || ntfs_remove_posix_acl(scx, ni,
  753                     (attr == XATTR_POSIX_ACC ?
  754                     nf_ns_xattr_posix_access :
  755                     nf_ns_xattr_posix_default)))
  756                 res = -errno;
  757         } else
  758             res = -errno;
  759         break;
  760 #endif
  761     case XATTR_NTFS_REPARSE_DATA :
  762         if (ni) {
  763             if (!ntfs_allowed_as_owner(scx, ni)
  764                 || ntfs_remove_ntfs_reparse_data(ni))
  765                 res = -errno;
  766         } else
  767             res = -errno;
  768         break;
  769     case XATTR_NTFS_OBJECT_ID :
  770         if (ni) {
  771             if (!ntfs_allowed_as_owner(scx, ni)
  772                 || ntfs_remove_ntfs_object_id(ni))
  773                 res = -errno;
  774         } else
  775             res = -errno;
  776         break;
  777     case XATTR_NTFS_DOS_NAME:
  778         if (ni && dir_ni) {
  779             if (ntfs_remove_ntfs_dos_name(ni,dir_ni))
  780                 res = -errno;
  781             /* ni and dir_ni have been closed */
  782         } else
  783             res = -errno;
  784         break;
  785     case XATTR_NTFS_EA :
  786         res = ntfs_remove_ntfs_ea(ni);
  787         break;
  788     default :
  789         errno = EOPNOTSUPP;
  790         res = -errno;
  791         break;
  792     }
  793     return (res);
  794 }