1987da915Sopenharmony_ci/**
2987da915Sopenharmony_ci * xattrs.c : common functions to deal with system extended attributes
3987da915Sopenharmony_ci *
4987da915Sopenharmony_ci * Copyright (c) 2010-2014 Jean-Pierre Andre
5987da915Sopenharmony_ci *
6987da915Sopenharmony_ci * This program/include file is free software; you can redistribute it and/or
7987da915Sopenharmony_ci * modify it under the terms of the GNU General Public License as published
8987da915Sopenharmony_ci * by the Free Software Foundation; either version 2 of the License, or
9987da915Sopenharmony_ci * (at your option) any later version.
10987da915Sopenharmony_ci *
11987da915Sopenharmony_ci * This program/include file is distributed in the hope that it will be
12987da915Sopenharmony_ci * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13987da915Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14987da915Sopenharmony_ci * GNU General Public License for more details.
15987da915Sopenharmony_ci *
16987da915Sopenharmony_ci * You should have received a copy of the GNU General Public License
17987da915Sopenharmony_ci * along with this program (in the main directory of the NTFS-3G
18987da915Sopenharmony_ci * distribution in the file COPYING); if not, write to the Free Software
19987da915Sopenharmony_ci * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20987da915Sopenharmony_ci */
21987da915Sopenharmony_ci
22987da915Sopenharmony_ci#ifdef HAVE_CONFIG_H
23987da915Sopenharmony_ci#include "config.h"
24987da915Sopenharmony_ci#endif
25987da915Sopenharmony_ci
26987da915Sopenharmony_ci#ifdef HAVE_STDIO_H
27987da915Sopenharmony_ci#include <stdio.h>
28987da915Sopenharmony_ci#endif
29987da915Sopenharmony_ci#ifdef HAVE_STDLIB_H
30987da915Sopenharmony_ci#include <stdlib.h>
31987da915Sopenharmony_ci#endif
32987da915Sopenharmony_ci#ifdef HAVE_STRING_H
33987da915Sopenharmony_ci#include <string.h>
34987da915Sopenharmony_ci#endif
35987da915Sopenharmony_ci#ifdef HAVE_FCNTL_H
36987da915Sopenharmony_ci#include <fcntl.h>
37987da915Sopenharmony_ci#endif
38987da915Sopenharmony_ci#ifdef HAVE_UNISTD_H
39987da915Sopenharmony_ci#include <unistd.h>
40987da915Sopenharmony_ci#endif
41987da915Sopenharmony_ci#ifdef HAVE_ERRNO_H
42987da915Sopenharmony_ci#include <errno.h>
43987da915Sopenharmony_ci#endif
44987da915Sopenharmony_ci
45987da915Sopenharmony_ci#include "types.h"
46987da915Sopenharmony_ci#include "param.h"
47987da915Sopenharmony_ci#include "layout.h"
48987da915Sopenharmony_ci#include "attrib.h"
49987da915Sopenharmony_ci#include "index.h"
50987da915Sopenharmony_ci#include "dir.h"
51987da915Sopenharmony_ci#include "security.h"
52987da915Sopenharmony_ci#include "acls.h"
53987da915Sopenharmony_ci#include "efs.h"
54987da915Sopenharmony_ci#include "reparse.h"
55987da915Sopenharmony_ci#include "object_id.h"
56987da915Sopenharmony_ci#include "ea.h"
57987da915Sopenharmony_ci#include "misc.h"
58987da915Sopenharmony_ci#include "logging.h"
59987da915Sopenharmony_ci#include "xattrs.h"
60987da915Sopenharmony_ci
61987da915Sopenharmony_ci#if POSIXACLS
62987da915Sopenharmony_ci#if __BYTE_ORDER == __BIG_ENDIAN
63987da915Sopenharmony_ci
64987da915Sopenharmony_ci/*
65987da915Sopenharmony_ci *		       Posix ACL structures
66987da915Sopenharmony_ci */
67987da915Sopenharmony_ci
68987da915Sopenharmony_cistruct LE_POSIX_ACE {
69987da915Sopenharmony_ci	le16 tag;
70987da915Sopenharmony_ci	le16 perms;
71987da915Sopenharmony_ci	le32 id;
72987da915Sopenharmony_ci} __attribute__((__packed__));
73987da915Sopenharmony_ci
74987da915Sopenharmony_cistruct LE_POSIX_ACL {
75987da915Sopenharmony_ci	u8 version;
76987da915Sopenharmony_ci	u8 flags;
77987da915Sopenharmony_ci	le16 filler;
78987da915Sopenharmony_ci	struct LE_POSIX_ACE ace[0];
79987da915Sopenharmony_ci} __attribute__((__packed__));
80987da915Sopenharmony_ci
81987da915Sopenharmony_ci#endif
82987da915Sopenharmony_ci#endif
83987da915Sopenharmony_ci
84987da915Sopenharmony_cistatic const char nf_ns_xattr_ntfs_acl[] = "system.ntfs_acl";
85987da915Sopenharmony_cistatic const char nf_ns_xattr_attrib[] = "system.ntfs_attrib";
86987da915Sopenharmony_cistatic const char nf_ns_xattr_attrib_be[] = "system.ntfs_attrib_be";
87987da915Sopenharmony_cistatic const char nf_ns_xattr_efsinfo[] = "system.ntfs_efsinfo";
88987da915Sopenharmony_cistatic const char nf_ns_xattr_reparse[] = "system.ntfs_reparse_data";
89987da915Sopenharmony_cistatic const char nf_ns_xattr_object_id[] = "system.ntfs_object_id";
90987da915Sopenharmony_cistatic const char nf_ns_xattr_dos_name[] = "system.ntfs_dos_name";
91987da915Sopenharmony_cistatic const char nf_ns_xattr_times[] = "system.ntfs_times";
92987da915Sopenharmony_cistatic const char nf_ns_xattr_times_be[] = "system.ntfs_times_be";
93987da915Sopenharmony_cistatic const char nf_ns_xattr_crtime[] = "system.ntfs_crtime";
94987da915Sopenharmony_cistatic const char nf_ns_xattr_crtime_be[] = "system.ntfs_crtime_be";
95987da915Sopenharmony_cistatic const char nf_ns_xattr_ea[] = "system.ntfs_ea";
96987da915Sopenharmony_cistatic const char nf_ns_xattr_posix_access[] = "system.posix_acl_access";
97987da915Sopenharmony_cistatic const char nf_ns_xattr_posix_default[] = "system.posix_acl_default";
98987da915Sopenharmony_ci
99987da915Sopenharmony_cistatic const char nf_ns_alt_xattr_efsinfo[] = "user.ntfs.efsinfo";
100987da915Sopenharmony_ci
101987da915Sopenharmony_cistruct XATTRNAME {
102987da915Sopenharmony_ci	enum SYSTEMXATTRS xattr;
103987da915Sopenharmony_ci	const char *name;
104987da915Sopenharmony_ci} ;
105987da915Sopenharmony_ci
106987da915Sopenharmony_cistatic struct XATTRNAME nf_ns_xattr_names[] = {
107987da915Sopenharmony_ci	{ XATTR_NTFS_ACL, nf_ns_xattr_ntfs_acl },
108987da915Sopenharmony_ci	{ XATTR_NTFS_ATTRIB, nf_ns_xattr_attrib },
109987da915Sopenharmony_ci	{ XATTR_NTFS_ATTRIB_BE, nf_ns_xattr_attrib_be },
110987da915Sopenharmony_ci	{ XATTR_NTFS_EFSINFO, nf_ns_xattr_efsinfo },
111987da915Sopenharmony_ci	{ XATTR_NTFS_REPARSE_DATA, nf_ns_xattr_reparse },
112987da915Sopenharmony_ci	{ XATTR_NTFS_OBJECT_ID, nf_ns_xattr_object_id },
113987da915Sopenharmony_ci	{ XATTR_NTFS_DOS_NAME, nf_ns_xattr_dos_name },
114987da915Sopenharmony_ci	{ XATTR_NTFS_TIMES, nf_ns_xattr_times },
115987da915Sopenharmony_ci	{ XATTR_NTFS_TIMES_BE, nf_ns_xattr_times_be },
116987da915Sopenharmony_ci	{ XATTR_NTFS_CRTIME, nf_ns_xattr_crtime },
117987da915Sopenharmony_ci	{ XATTR_NTFS_CRTIME_BE, nf_ns_xattr_crtime_be },
118987da915Sopenharmony_ci	{ XATTR_NTFS_EA, nf_ns_xattr_ea },
119987da915Sopenharmony_ci	{ XATTR_POSIX_ACC, nf_ns_xattr_posix_access },
120987da915Sopenharmony_ci	{ XATTR_POSIX_DEF, nf_ns_xattr_posix_default },
121987da915Sopenharmony_ci	{ XATTR_UNMAPPED, (char*)NULL } /* terminator */
122987da915Sopenharmony_ci};
123987da915Sopenharmony_ci
124987da915Sopenharmony_ci/*
125987da915Sopenharmony_ci *		Make an integer big-endian
126987da915Sopenharmony_ci *
127987da915Sopenharmony_ci *	Swap bytes on a small-endian computer and does nothing on a
128987da915Sopenharmony_ci *	big-endian computer.
129987da915Sopenharmony_ci */
130987da915Sopenharmony_ci
131987da915Sopenharmony_cistatic void fix_big_endian(char *p, int size)
132987da915Sopenharmony_ci{
133987da915Sopenharmony_ci#if __BYTE_ORDER == __LITTLE_ENDIAN
134987da915Sopenharmony_ci	int i,j;
135987da915Sopenharmony_ci	int c;
136987da915Sopenharmony_ci
137987da915Sopenharmony_ci	i = 0;
138987da915Sopenharmony_ci	j = size - 1;
139987da915Sopenharmony_ci	while (i < j) {
140987da915Sopenharmony_ci		c = p[i];
141987da915Sopenharmony_ci		p[i++] = p[j];
142987da915Sopenharmony_ci		p[j--] = c;
143987da915Sopenharmony_ci	}
144987da915Sopenharmony_ci#endif
145987da915Sopenharmony_ci}
146987da915Sopenharmony_ci
147987da915Sopenharmony_ci#if POSIXACLS
148987da915Sopenharmony_ci#if __BYTE_ORDER == __BIG_ENDIAN
149987da915Sopenharmony_ci
150987da915Sopenharmony_ci/*
151987da915Sopenharmony_ci *		Make a Posix ACL CPU endian
152987da915Sopenharmony_ci */
153987da915Sopenharmony_ci
154987da915Sopenharmony_cistatic int le_acl_to_cpu(const struct LE_POSIX_ACL *le_acl, size_t size,
155987da915Sopenharmony_ci				struct POSIX_ACL *acl)
156987da915Sopenharmony_ci{
157987da915Sopenharmony_ci	int i;
158987da915Sopenharmony_ci	int cnt;
159987da915Sopenharmony_ci
160987da915Sopenharmony_ci	acl->version = le_acl->version;
161987da915Sopenharmony_ci	acl->flags = le_acl->flags;
162987da915Sopenharmony_ci	acl->filler = 0;
163987da915Sopenharmony_ci	cnt = (size - sizeof(struct LE_POSIX_ACL)) / sizeof(struct LE_POSIX_ACE);
164987da915Sopenharmony_ci	for (i=0; i<cnt; i++) {
165987da915Sopenharmony_ci		acl->ace[i].tag = le16_to_cpu(le_acl->ace[i].tag);
166987da915Sopenharmony_ci		acl->ace[i].perms = le16_to_cpu(le_acl->ace[i].perms);
167987da915Sopenharmony_ci		acl->ace[i].id = le32_to_cpu(le_acl->ace[i].id);
168987da915Sopenharmony_ci	}
169987da915Sopenharmony_ci	return (0);
170987da915Sopenharmony_ci}
171987da915Sopenharmony_ci
172987da915Sopenharmony_ci/*
173987da915Sopenharmony_ci *		Make a Posix ACL little endian
174987da915Sopenharmony_ci */
175987da915Sopenharmony_ci
176987da915Sopenharmony_ciint cpu_to_le_acl(const struct POSIX_ACL *acl, size_t size,
177987da915Sopenharmony_ci			struct LE_POSIX_ACL *le_acl)
178987da915Sopenharmony_ci{
179987da915Sopenharmony_ci	int i;
180987da915Sopenharmony_ci	int cnt;
181987da915Sopenharmony_ci
182987da915Sopenharmony_ci	le_acl->version = acl->version;
183987da915Sopenharmony_ci	le_acl->flags = acl->flags;
184987da915Sopenharmony_ci	le_acl->filler = const_cpu_to_le16(0);
185987da915Sopenharmony_ci	cnt = (size - sizeof(struct POSIX_ACL)) / sizeof(struct POSIX_ACE);
186987da915Sopenharmony_ci	for (i=0; i<cnt; i++) {
187987da915Sopenharmony_ci		le_acl->ace[i].tag = cpu_to_le16(acl->ace[i].tag);
188987da915Sopenharmony_ci		le_acl->ace[i].perms = cpu_to_le16(acl->ace[i].perms);
189987da915Sopenharmony_ci		le_acl->ace[i].id = cpu_to_le32(acl->ace[i].id);
190987da915Sopenharmony_ci	}
191987da915Sopenharmony_ci	return (0);
192987da915Sopenharmony_ci}
193987da915Sopenharmony_ci
194987da915Sopenharmony_ci#endif
195987da915Sopenharmony_ci#endif
196987da915Sopenharmony_ci
197987da915Sopenharmony_ci/*
198987da915Sopenharmony_ci *		Determine whether an extended attribute is mapped to
199987da915Sopenharmony_ci *	internal data (original name in system namespace, or renamed)
200987da915Sopenharmony_ci */
201987da915Sopenharmony_ci
202987da915Sopenharmony_cienum SYSTEMXATTRS ntfs_xattr_system_type(const char *name,
203987da915Sopenharmony_ci			ntfs_volume *vol)
204987da915Sopenharmony_ci{
205987da915Sopenharmony_ci	struct XATTRNAME *p;
206987da915Sopenharmony_ci	enum SYSTEMXATTRS ret;
207987da915Sopenharmony_ci#ifdef XATTR_MAPPINGS
208987da915Sopenharmony_ci	const struct XATTRMAPPING *q;
209987da915Sopenharmony_ci#endif /* XATTR_MAPPINGS */
210987da915Sopenharmony_ci
211987da915Sopenharmony_ci	p = nf_ns_xattr_names;
212987da915Sopenharmony_ci	while (p->name && strcmp(p->name,name))
213987da915Sopenharmony_ci		p++;
214987da915Sopenharmony_ci	ret = p->xattr;
215987da915Sopenharmony_ci#ifdef XATTR_MAPPINGS
216987da915Sopenharmony_ci	if (!p->name && vol && vol->xattr_mapping) {
217987da915Sopenharmony_ci		q = vol->xattr_mapping;
218987da915Sopenharmony_ci		while (q && strcmp(q->name,name))
219987da915Sopenharmony_ci			q = q->next;
220987da915Sopenharmony_ci		if (q)
221987da915Sopenharmony_ci			ret = q->xattr;
222987da915Sopenharmony_ci	}
223987da915Sopenharmony_ci#else /* XATTR_MAPPINGS */
224987da915Sopenharmony_ci	if (!p->name
225987da915Sopenharmony_ci	    && vol
226987da915Sopenharmony_ci	    && vol->efs_raw
227987da915Sopenharmony_ci	    && !strcmp(nf_ns_alt_xattr_efsinfo,name))
228987da915Sopenharmony_ci		ret = XATTR_NTFS_EFSINFO;
229987da915Sopenharmony_ci#endif /* XATTR_MAPPINGS */
230987da915Sopenharmony_ci	return (ret);
231987da915Sopenharmony_ci}
232987da915Sopenharmony_ci
233987da915Sopenharmony_ci#ifdef XATTR_MAPPINGS
234987da915Sopenharmony_ci
235987da915Sopenharmony_ci/*
236987da915Sopenharmony_ci *		Basic read from a user mapping file on another volume
237987da915Sopenharmony_ci */
238987da915Sopenharmony_ci
239987da915Sopenharmony_cistatic int basicread(void *fileid, char *buf, size_t size, off_t offs __attribute__((unused)))
240987da915Sopenharmony_ci{
241987da915Sopenharmony_ci	return (read(*(int*)fileid, buf, size));
242987da915Sopenharmony_ci}
243987da915Sopenharmony_ci
244987da915Sopenharmony_ci
245987da915Sopenharmony_ci/*
246987da915Sopenharmony_ci *		Read from a user mapping file on current NTFS partition
247987da915Sopenharmony_ci */
248987da915Sopenharmony_ci
249987da915Sopenharmony_cistatic int localread(void *fileid, char *buf, size_t size, off_t offs)
250987da915Sopenharmony_ci{
251987da915Sopenharmony_ci	return (ntfs_attr_data_read((ntfs_inode*)fileid,
252987da915Sopenharmony_ci			AT_UNNAMED, 0, buf, size, offs));
253987da915Sopenharmony_ci}
254987da915Sopenharmony_ci
255987da915Sopenharmony_ci/*
256987da915Sopenharmony_ci *		Get a single mapping item from buffer
257987da915Sopenharmony_ci *
258987da915Sopenharmony_ci *	Always reads a full line, truncating long lines
259987da915Sopenharmony_ci *	Refills buffer when exhausted
260987da915Sopenharmony_ci *	Returns pointer to item, or NULL when there is no more
261987da915Sopenharmony_ci *	Note : errors are logged, but not returned
262987da915Sopenharmony_ci// TODO partially share with acls.c
263987da915Sopenharmony_ci */
264987da915Sopenharmony_ci
265987da915Sopenharmony_cistatic struct XATTRMAPPING *getmappingitem(FILEREADER reader, void *fileid,
266987da915Sopenharmony_ci		off_t *poffs, char *buf, int *psrc, s64 *psize)
267987da915Sopenharmony_ci{
268987da915Sopenharmony_ci	int src;
269987da915Sopenharmony_ci	int dst;
270987da915Sopenharmony_ci	char *pe;
271987da915Sopenharmony_ci	char *ps;
272987da915Sopenharmony_ci	char *pu;
273987da915Sopenharmony_ci	enum SYSTEMXATTRS xattr;
274987da915Sopenharmony_ci	int gotend;
275987da915Sopenharmony_ci	char maptext[LINESZ];
276987da915Sopenharmony_ci	struct XATTRMAPPING *item;
277987da915Sopenharmony_ci
278987da915Sopenharmony_ci	src = *psrc;
279987da915Sopenharmony_ci	dst = 0;
280987da915Sopenharmony_ci	do {
281987da915Sopenharmony_ci		gotend = 0;
282987da915Sopenharmony_ci		while ((src < *psize)
283987da915Sopenharmony_ci		       && (buf[src] != '\n')) {
284987da915Sopenharmony_ci				/* ignore spaces */
285987da915Sopenharmony_ci			if ((dst < LINESZ)
286987da915Sopenharmony_ci			    && (buf[src] != '\r')
287987da915Sopenharmony_ci			    && (buf[src] != '\t')
288987da915Sopenharmony_ci			    && (buf[src] != ' '))
289987da915Sopenharmony_ci				maptext[dst++] = buf[src];
290987da915Sopenharmony_ci			src++;
291987da915Sopenharmony_ci		}
292987da915Sopenharmony_ci		if (src >= *psize) {
293987da915Sopenharmony_ci			*poffs += *psize;
294987da915Sopenharmony_ci			*psize = reader(fileid, buf, (size_t)BUFSZ, *poffs);
295987da915Sopenharmony_ci			src = 0;
296987da915Sopenharmony_ci		} else {
297987da915Sopenharmony_ci			gotend = 1;
298987da915Sopenharmony_ci			src++;
299987da915Sopenharmony_ci			maptext[dst] = '\0';
300987da915Sopenharmony_ci			dst = 0;
301987da915Sopenharmony_ci		}
302987da915Sopenharmony_ci	} while (*psize && ((maptext[0] == '#') || !gotend));
303987da915Sopenharmony_ci	item = (struct XATTRMAPPING*)NULL;
304987da915Sopenharmony_ci	if (gotend) {
305987da915Sopenharmony_ci			/* decompose into system name and user name */
306987da915Sopenharmony_ci		ps = maptext;
307987da915Sopenharmony_ci		pu = strchr(maptext,':');
308987da915Sopenharmony_ci		if (pu) {
309987da915Sopenharmony_ci			*pu++ = 0;
310987da915Sopenharmony_ci			pe = strchr(pu,':');
311987da915Sopenharmony_ci			if (pe)
312987da915Sopenharmony_ci				*pe = 0;
313987da915Sopenharmony_ci				/* check name validity */
314987da915Sopenharmony_ci			if ((strlen(pu) < 6) || strncmp(pu,"user.",5))
315987da915Sopenharmony_ci				pu = (char*)NULL;
316987da915Sopenharmony_ci			xattr = ntfs_xattr_system_type(ps,
317987da915Sopenharmony_ci					(ntfs_volume*)NULL);
318987da915Sopenharmony_ci			if (xattr == XATTR_UNMAPPED)
319987da915Sopenharmony_ci				pu = (char*)NULL;
320987da915Sopenharmony_ci		}
321987da915Sopenharmony_ci		if (pu) {
322987da915Sopenharmony_ci			item = (struct XATTRMAPPING*)ntfs_malloc(
323987da915Sopenharmony_ci				sizeof(struct XATTRMAPPING)
324987da915Sopenharmony_ci				+ strlen(pu));
325987da915Sopenharmony_ci			if (item) {
326987da915Sopenharmony_ci				item->xattr = xattr;
327987da915Sopenharmony_ci				strcpy(item->name,pu);
328987da915Sopenharmony_ci				item->next = (struct XATTRMAPPING*)NULL;
329987da915Sopenharmony_ci			}
330987da915Sopenharmony_ci		} else {
331987da915Sopenharmony_ci			ntfs_log_early_error("Bad xattr mapping item, aborting\n");
332987da915Sopenharmony_ci		}
333987da915Sopenharmony_ci	}
334987da915Sopenharmony_ci	*psrc = src;
335987da915Sopenharmony_ci	return (item);
336987da915Sopenharmony_ci}
337987da915Sopenharmony_ci
338987da915Sopenharmony_ci/*
339987da915Sopenharmony_ci *		Read xattr mapping file and split into their attribute.
340987da915Sopenharmony_ci *	Parameters are kept in a chained list.
341987da915Sopenharmony_ci *	Returns the head of list, if any
342987da915Sopenharmony_ci *	Errors are logged, but not returned
343987da915Sopenharmony_ci *
344987da915Sopenharmony_ci *	If an absolute path is provided, the mapping file is assumed
345987da915Sopenharmony_ci *	to be located in another mounted file system, and plain read()
346987da915Sopenharmony_ci *	are used to get its contents.
347987da915Sopenharmony_ci *	If a relative path is provided, the mapping file is assumed
348987da915Sopenharmony_ci *	to be located on the current file system, and internal IO
349987da915Sopenharmony_ci *	have to be used since we are still mounting and we have not
350987da915Sopenharmony_ci *	entered the fuse loop yet.
351987da915Sopenharmony_ci */
352987da915Sopenharmony_ci
353987da915Sopenharmony_cistatic struct XATTRMAPPING *ntfs_read_xattr_mapping(FILEREADER reader,
354987da915Sopenharmony_ci				void *fileid)
355987da915Sopenharmony_ci{
356987da915Sopenharmony_ci	char buf[BUFSZ];
357987da915Sopenharmony_ci	struct XATTRMAPPING *item;
358987da915Sopenharmony_ci	struct XATTRMAPPING *current;
359987da915Sopenharmony_ci	struct XATTRMAPPING *firstitem;
360987da915Sopenharmony_ci	struct XATTRMAPPING *lastitem;
361987da915Sopenharmony_ci	BOOL duplicated;
362987da915Sopenharmony_ci	int src;
363987da915Sopenharmony_ci	off_t offs;
364987da915Sopenharmony_ci	s64 size;
365987da915Sopenharmony_ci
366987da915Sopenharmony_ci	firstitem = (struct XATTRMAPPING*)NULL;
367987da915Sopenharmony_ci	lastitem = (struct XATTRMAPPING*)NULL;
368987da915Sopenharmony_ci	offs = 0;
369987da915Sopenharmony_ci	size = reader(fileid, buf, (size_t)BUFSZ, (off_t)0);
370987da915Sopenharmony_ci	if (size > 0) {
371987da915Sopenharmony_ci		src = 0;
372987da915Sopenharmony_ci		do {
373987da915Sopenharmony_ci			item = getmappingitem(reader, fileid, &offs,
374987da915Sopenharmony_ci				buf, &src, &size);
375987da915Sopenharmony_ci			if (item) {
376987da915Sopenharmony_ci				/* check no double mapping */
377987da915Sopenharmony_ci				duplicated = FALSE;
378987da915Sopenharmony_ci				for (current=firstitem; current; current=current->next)
379987da915Sopenharmony_ci					if ((current->xattr == item->xattr)
380987da915Sopenharmony_ci					    || !strcmp(current->name,item->name))
381987da915Sopenharmony_ci						duplicated = TRUE;
382987da915Sopenharmony_ci				if (duplicated) {
383987da915Sopenharmony_ci					free(item);
384987da915Sopenharmony_ci					ntfs_log_early_error("Conflicting xattr mapping ignored\n");
385987da915Sopenharmony_ci				} else {
386987da915Sopenharmony_ci					item->next = (struct XATTRMAPPING*)NULL;
387987da915Sopenharmony_ci					if (lastitem)
388987da915Sopenharmony_ci						lastitem->next = item;
389987da915Sopenharmony_ci					else
390987da915Sopenharmony_ci						firstitem = item;
391987da915Sopenharmony_ci					lastitem = item;
392987da915Sopenharmony_ci				}
393987da915Sopenharmony_ci			}
394987da915Sopenharmony_ci		} while (item);
395987da915Sopenharmony_ci	}
396987da915Sopenharmony_ci	return (firstitem);
397987da915Sopenharmony_ci}
398987da915Sopenharmony_ci
399987da915Sopenharmony_ci/*
400987da915Sopenharmony_ci *		Build the extended attribute mappings to user namespace
401987da915Sopenharmony_ci *
402987da915Sopenharmony_ci *	Note : no error is returned. If we refused mounting when there
403987da915Sopenharmony_ci *	is an error it would be too difficult to fix the offending file
404987da915Sopenharmony_ci */
405987da915Sopenharmony_ci
406987da915Sopenharmony_cistruct XATTRMAPPING *ntfs_xattr_build_mapping(ntfs_volume *vol,
407987da915Sopenharmony_ci			const char *xattrmap_path)
408987da915Sopenharmony_ci{
409987da915Sopenharmony_ci	struct XATTRMAPPING *firstmapping;
410987da915Sopenharmony_ci	struct XATTRMAPPING *mapping;
411987da915Sopenharmony_ci	BOOL user_efs;
412987da915Sopenharmony_ci	BOOL notfound;
413987da915Sopenharmony_ci	ntfs_inode *ni;
414987da915Sopenharmony_ci	int fd;
415987da915Sopenharmony_ci
416987da915Sopenharmony_ci	firstmapping = (struct XATTRMAPPING*)NULL;
417987da915Sopenharmony_ci	notfound = FALSE;
418987da915Sopenharmony_ci	if (!xattrmap_path)
419987da915Sopenharmony_ci		xattrmap_path = XATTRMAPPINGFILE;
420987da915Sopenharmony_ci	if (xattrmap_path[0] == '/') {
421987da915Sopenharmony_ci		fd = open(xattrmap_path,O_RDONLY);
422987da915Sopenharmony_ci		if (fd > 0) {
423987da915Sopenharmony_ci			firstmapping = ntfs_read_xattr_mapping(basicread, (void*)&fd);
424987da915Sopenharmony_ci			close(fd);
425987da915Sopenharmony_ci		} else
426987da915Sopenharmony_ci			notfound = TRUE;
427987da915Sopenharmony_ci	} else {
428987da915Sopenharmony_ci		ni = ntfs_pathname_to_inode(vol, NULL, xattrmap_path);
429987da915Sopenharmony_ci		if (ni) {
430987da915Sopenharmony_ci			firstmapping = ntfs_read_xattr_mapping(localread, ni);
431987da915Sopenharmony_ci			ntfs_inode_close(ni);
432987da915Sopenharmony_ci		} else
433987da915Sopenharmony_ci			notfound = TRUE;
434987da915Sopenharmony_ci	}
435987da915Sopenharmony_ci	if (notfound && strcmp(xattrmap_path, XATTRMAPPINGFILE)) {
436987da915Sopenharmony_ci		ntfs_log_early_error("Could not open \"%s\"\n",xattrmap_path);
437987da915Sopenharmony_ci	}
438987da915Sopenharmony_ci	if (vol->efs_raw) {
439987da915Sopenharmony_ci		user_efs = TRUE;
440987da915Sopenharmony_ci		for (mapping=firstmapping; mapping; mapping=mapping->next)
441987da915Sopenharmony_ci			if (mapping->xattr == XATTR_NTFS_EFSINFO)
442987da915Sopenharmony_ci				user_efs = FALSE;
443987da915Sopenharmony_ci	} else
444987da915Sopenharmony_ci		user_efs = FALSE;
445987da915Sopenharmony_ci	if (user_efs) {
446987da915Sopenharmony_ci		mapping = (struct XATTRMAPPING*)ntfs_malloc(
447987da915Sopenharmony_ci				sizeof(struct XATTRMAPPING)
448987da915Sopenharmony_ci				+ strlen(nf_ns_alt_xattr_efsinfo));
449987da915Sopenharmony_ci		if (mapping) {
450987da915Sopenharmony_ci			mapping->next = firstmapping;
451987da915Sopenharmony_ci			mapping->xattr = XATTR_NTFS_EFSINFO;
452987da915Sopenharmony_ci			strcpy(mapping->name,nf_ns_alt_xattr_efsinfo);
453987da915Sopenharmony_ci			firstmapping = mapping;
454987da915Sopenharmony_ci		}
455987da915Sopenharmony_ci	}
456987da915Sopenharmony_ci	return (firstmapping);
457987da915Sopenharmony_ci}
458987da915Sopenharmony_ci
459987da915Sopenharmony_civoid ntfs_xattr_free_mapping(struct XATTRMAPPING *mapping)
460987da915Sopenharmony_ci{
461987da915Sopenharmony_ci	struct XATTRMAPPING *p, *q;
462987da915Sopenharmony_ci
463987da915Sopenharmony_ci	p = mapping;
464987da915Sopenharmony_ci	while (p) {
465987da915Sopenharmony_ci		q = p->next;
466987da915Sopenharmony_ci		free(p);
467987da915Sopenharmony_ci		p = q;
468987da915Sopenharmony_ci	}
469987da915Sopenharmony_ci}
470987da915Sopenharmony_ci
471987da915Sopenharmony_ci#endif /* XATTR_MAPPINGS */
472987da915Sopenharmony_ci
473987da915Sopenharmony_ci/*
474987da915Sopenharmony_ci *		Get an NTFS attribute into an extended attribute
475987da915Sopenharmony_ci *
476987da915Sopenharmony_ci *	Returns the non-negative size of attribute if successful,
477987da915Sopenharmony_ci *	        or negative, with errno set, when fails
478987da915Sopenharmony_ci *	Note : the size is returned even if no buffer is provided
479987da915Sopenharmony_ci *	for returning the attribute, or if it is zero-sized.
480987da915Sopenharmony_ci */
481987da915Sopenharmony_ci
482987da915Sopenharmony_ciint ntfs_xattr_system_getxattr(struct SECURITY_CONTEXT *scx,
483987da915Sopenharmony_ci			enum SYSTEMXATTRS attr,
484987da915Sopenharmony_ci			ntfs_inode *ni, ntfs_inode *dir_ni,
485987da915Sopenharmony_ci			char *value, size_t size)
486987da915Sopenharmony_ci{
487987da915Sopenharmony_ci	int res;
488987da915Sopenharmony_ci	int i;
489987da915Sopenharmony_ci#if POSIXACLS
490987da915Sopenharmony_ci#if __BYTE_ORDER == __BIG_ENDIAN
491987da915Sopenharmony_ci	struct POSIX_ACL *acl;
492987da915Sopenharmony_ci#endif
493987da915Sopenharmony_ci#endif
494987da915Sopenharmony_ci
495987da915Sopenharmony_ci	switch (attr) {
496987da915Sopenharmony_ci	case XATTR_NTFS_ACL :
497987da915Sopenharmony_ci		res = ntfs_get_ntfs_acl(scx, ni, value, size);
498987da915Sopenharmony_ci		break;
499987da915Sopenharmony_ci#if POSIXACLS
500987da915Sopenharmony_ci#if __BYTE_ORDER == __BIG_ENDIAN
501987da915Sopenharmony_ci	case XATTR_POSIX_ACC :
502987da915Sopenharmony_ci		acl = (struct POSIX_ACL*)ntfs_malloc(size);
503987da915Sopenharmony_ci		if (acl) {
504987da915Sopenharmony_ci			res = ntfs_get_posix_acl(scx, ni,
505987da915Sopenharmony_ci				nf_ns_xattr_posix_access, (char*)acl, size);
506987da915Sopenharmony_ci			if (res > 0) {
507987da915Sopenharmony_ci				if (cpu_to_le_acl(acl,res,
508987da915Sopenharmony_ci						(struct LE_POSIX_ACL*)value))
509987da915Sopenharmony_ci					res = -errno;
510987da915Sopenharmony_ci			}
511987da915Sopenharmony_ci			free(acl);
512987da915Sopenharmony_ci		} else
513987da915Sopenharmony_ci			res = -errno;
514987da915Sopenharmony_ci		break;
515987da915Sopenharmony_ci	case XATTR_POSIX_DEF :
516987da915Sopenharmony_ci		acl = (struct POSIX_ACL*)ntfs_malloc(size);
517987da915Sopenharmony_ci		if (acl) {
518987da915Sopenharmony_ci			res = ntfs_get_posix_acl(scx, ni,
519987da915Sopenharmony_ci				nf_ns_xattr_posix_default, (char*)acl, size);
520987da915Sopenharmony_ci			if (res > 0) {
521987da915Sopenharmony_ci				if (cpu_to_le_acl(acl,res,
522987da915Sopenharmony_ci						(struct LE_POSIX_ACL*)value))
523987da915Sopenharmony_ci					res = -errno;
524987da915Sopenharmony_ci			}
525987da915Sopenharmony_ci			free(acl);
526987da915Sopenharmony_ci		} else
527987da915Sopenharmony_ci			res = -errno;
528987da915Sopenharmony_ci		break;
529987da915Sopenharmony_ci#else
530987da915Sopenharmony_ci	case XATTR_POSIX_ACC :
531987da915Sopenharmony_ci		res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_access,
532987da915Sopenharmony_ci				value, size);
533987da915Sopenharmony_ci		break;
534987da915Sopenharmony_ci	case XATTR_POSIX_DEF :
535987da915Sopenharmony_ci		res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_default,
536987da915Sopenharmony_ci				value, size);
537987da915Sopenharmony_ci		break;
538987da915Sopenharmony_ci#endif
539987da915Sopenharmony_ci#endif
540987da915Sopenharmony_ci	case XATTR_NTFS_ATTRIB :
541987da915Sopenharmony_ci		res = ntfs_get_ntfs_attrib(ni, value, size);
542987da915Sopenharmony_ci		break;
543987da915Sopenharmony_ci	case XATTR_NTFS_ATTRIB_BE :
544987da915Sopenharmony_ci		res = ntfs_get_ntfs_attrib(ni, value, size);
545987da915Sopenharmony_ci		if ((res == 4) && value) {
546987da915Sopenharmony_ci			if (size >= 4)
547987da915Sopenharmony_ci				fix_big_endian(value,4);
548987da915Sopenharmony_ci			else
549987da915Sopenharmony_ci				res = -EINVAL;
550987da915Sopenharmony_ci		}
551987da915Sopenharmony_ci		break;
552987da915Sopenharmony_ci	case XATTR_NTFS_EFSINFO :
553987da915Sopenharmony_ci		if (ni->vol->efs_raw)
554987da915Sopenharmony_ci			res = ntfs_get_efs_info(ni, value, size);
555987da915Sopenharmony_ci		else
556987da915Sopenharmony_ci			res = -EPERM;
557987da915Sopenharmony_ci		break;
558987da915Sopenharmony_ci	case XATTR_NTFS_REPARSE_DATA :
559987da915Sopenharmony_ci		res = ntfs_get_ntfs_reparse_data(ni, value, size);
560987da915Sopenharmony_ci		break;
561987da915Sopenharmony_ci	case XATTR_NTFS_OBJECT_ID :
562987da915Sopenharmony_ci		res = ntfs_get_ntfs_object_id(ni, value, size);
563987da915Sopenharmony_ci		break;
564987da915Sopenharmony_ci	case XATTR_NTFS_DOS_NAME:
565987da915Sopenharmony_ci		if (dir_ni)
566987da915Sopenharmony_ci			res = ntfs_get_ntfs_dos_name(ni, dir_ni, value, size);
567987da915Sopenharmony_ci		else
568987da915Sopenharmony_ci			res = -errno;
569987da915Sopenharmony_ci		break;
570987da915Sopenharmony_ci	case XATTR_NTFS_TIMES:
571987da915Sopenharmony_ci		res = ntfs_inode_get_times(ni, value, size);
572987da915Sopenharmony_ci		break;
573987da915Sopenharmony_ci	case XATTR_NTFS_TIMES_BE:
574987da915Sopenharmony_ci		res = ntfs_inode_get_times(ni, value, size);
575987da915Sopenharmony_ci		if ((res > 0) && value) {
576987da915Sopenharmony_ci			for (i=0; (i+1)*sizeof(u64)<=(unsigned int)res; i++)
577987da915Sopenharmony_ci				fix_big_endian(&value[i*sizeof(u64)],
578987da915Sopenharmony_ci						sizeof(u64));
579987da915Sopenharmony_ci		}
580987da915Sopenharmony_ci		break;
581987da915Sopenharmony_ci	case XATTR_NTFS_CRTIME:
582987da915Sopenharmony_ci		res = ntfs_inode_get_times(ni, value,
583987da915Sopenharmony_ci				(size >= sizeof(u64) ? sizeof(u64) : size));
584987da915Sopenharmony_ci		break;
585987da915Sopenharmony_ci	case XATTR_NTFS_CRTIME_BE:
586987da915Sopenharmony_ci		res = ntfs_inode_get_times(ni, value,
587987da915Sopenharmony_ci				(size >= sizeof(u64) ? sizeof(u64) : size));
588987da915Sopenharmony_ci		if ((res >= (int)sizeof(u64)) && value)
589987da915Sopenharmony_ci			fix_big_endian(value,sizeof(u64));
590987da915Sopenharmony_ci		break;
591987da915Sopenharmony_ci	case XATTR_NTFS_EA :
592987da915Sopenharmony_ci		res = ntfs_get_ntfs_ea(ni, value, size);
593987da915Sopenharmony_ci		break;
594987da915Sopenharmony_ci	default :
595987da915Sopenharmony_ci		errno = EOPNOTSUPP;
596987da915Sopenharmony_ci		res = -errno;
597987da915Sopenharmony_ci		break;
598987da915Sopenharmony_ci	}
599987da915Sopenharmony_ci	return (res);
600987da915Sopenharmony_ci}
601987da915Sopenharmony_ci
602987da915Sopenharmony_ci/*
603987da915Sopenharmony_ci *		Set an NTFS attribute from an extended attribute
604987da915Sopenharmony_ci *
605987da915Sopenharmony_ci *	Returns 0 if successful,
606987da915Sopenharmony_ci *	        non-zero, with errno set, when fails
607987da915Sopenharmony_ci */
608987da915Sopenharmony_ci
609987da915Sopenharmony_ciint ntfs_xattr_system_setxattr(struct SECURITY_CONTEXT *scx,
610987da915Sopenharmony_ci			enum SYSTEMXATTRS attr,
611987da915Sopenharmony_ci			ntfs_inode *ni, ntfs_inode *dir_ni,
612987da915Sopenharmony_ci			const char *value, size_t size, int flags)
613987da915Sopenharmony_ci{
614987da915Sopenharmony_ci	int res;
615987da915Sopenharmony_ci	int i;
616987da915Sopenharmony_ci	char buf[4*sizeof(u64)];
617987da915Sopenharmony_ci#if POSIXACLS
618987da915Sopenharmony_ci#if __BYTE_ORDER == __BIG_ENDIAN
619987da915Sopenharmony_ci	struct POSIX_ACL *acl;
620987da915Sopenharmony_ci#endif
621987da915Sopenharmony_ci#endif
622987da915Sopenharmony_ci
623987da915Sopenharmony_ci	switch (attr) {
624987da915Sopenharmony_ci	case XATTR_NTFS_ACL :
625987da915Sopenharmony_ci		res = ntfs_set_ntfs_acl(scx, ni, value, size, flags);
626987da915Sopenharmony_ci		break;
627987da915Sopenharmony_ci#if POSIXACLS
628987da915Sopenharmony_ci#if __BYTE_ORDER == __BIG_ENDIAN
629987da915Sopenharmony_ci	case XATTR_POSIX_ACC :
630987da915Sopenharmony_ci		acl = (struct POSIX_ACL*)ntfs_malloc(size);
631987da915Sopenharmony_ci		if (acl) {
632987da915Sopenharmony_ci			if (!le_acl_to_cpu((const struct LE_POSIX_ACL*)value,
633987da915Sopenharmony_ci					size, acl)) {
634987da915Sopenharmony_ci				res = ntfs_set_posix_acl(scx ,ni ,
635987da915Sopenharmony_ci					nf_ns_xattr_posix_access,
636987da915Sopenharmony_ci					(char*)acl, size, flags);
637987da915Sopenharmony_ci			} else
638987da915Sopenharmony_ci				res = -errno;
639987da915Sopenharmony_ci			free(acl);
640987da915Sopenharmony_ci		} else
641987da915Sopenharmony_ci			res = -errno;
642987da915Sopenharmony_ci		break;
643987da915Sopenharmony_ci	case XATTR_POSIX_DEF :
644987da915Sopenharmony_ci		acl = (struct POSIX_ACL*)ntfs_malloc(size);
645987da915Sopenharmony_ci		if (acl) {
646987da915Sopenharmony_ci			if (!le_acl_to_cpu((const struct LE_POSIX_ACL*)value,
647987da915Sopenharmony_ci					size, acl)) {
648987da915Sopenharmony_ci				res = ntfs_set_posix_acl(scx ,ni ,
649987da915Sopenharmony_ci					nf_ns_xattr_posix_default,
650987da915Sopenharmony_ci					(char*)acl, size, flags);
651987da915Sopenharmony_ci			} else
652987da915Sopenharmony_ci				res = -errno;
653987da915Sopenharmony_ci			free(acl);
654987da915Sopenharmony_ci		} else
655987da915Sopenharmony_ci			res = -errno;
656987da915Sopenharmony_ci		break;
657987da915Sopenharmony_ci#else
658987da915Sopenharmony_ci	case XATTR_POSIX_ACC :
659987da915Sopenharmony_ci		res = ntfs_set_posix_acl(scx ,ni , nf_ns_xattr_posix_access,
660987da915Sopenharmony_ci					value, size, flags);
661987da915Sopenharmony_ci		break;
662987da915Sopenharmony_ci	case XATTR_POSIX_DEF :
663987da915Sopenharmony_ci		res = ntfs_set_posix_acl(scx, ni, nf_ns_xattr_posix_default,
664987da915Sopenharmony_ci					value, size, flags);
665987da915Sopenharmony_ci		break;
666987da915Sopenharmony_ci#endif
667987da915Sopenharmony_ci#endif
668987da915Sopenharmony_ci	case XATTR_NTFS_ATTRIB :
669987da915Sopenharmony_ci		res = ntfs_set_ntfs_attrib(ni, value, size, flags);
670987da915Sopenharmony_ci		break;
671987da915Sopenharmony_ci	case XATTR_NTFS_ATTRIB_BE :
672987da915Sopenharmony_ci		if (value && (size >= 4)) {
673987da915Sopenharmony_ci			memcpy(buf,value,4);
674987da915Sopenharmony_ci			fix_big_endian(buf,4);
675987da915Sopenharmony_ci			res = ntfs_set_ntfs_attrib(ni, buf, 4, flags);
676987da915Sopenharmony_ci		} else
677987da915Sopenharmony_ci			res = ntfs_set_ntfs_attrib(ni, value, size, flags);
678987da915Sopenharmony_ci		break;
679987da915Sopenharmony_ci	case XATTR_NTFS_EFSINFO :
680987da915Sopenharmony_ci		if (ni->vol->efs_raw)
681987da915Sopenharmony_ci			res = ntfs_set_efs_info(ni, value, size, flags);
682987da915Sopenharmony_ci		else {
683987da915Sopenharmony_ci			errno = EPERM;
684987da915Sopenharmony_ci			res = -EPERM;
685987da915Sopenharmony_ci		}
686987da915Sopenharmony_ci		break;
687987da915Sopenharmony_ci	case XATTR_NTFS_REPARSE_DATA :
688987da915Sopenharmony_ci		res = ntfs_set_ntfs_reparse_data(ni, value, size, flags);
689987da915Sopenharmony_ci		break;
690987da915Sopenharmony_ci	case XATTR_NTFS_OBJECT_ID :
691987da915Sopenharmony_ci		res = ntfs_set_ntfs_object_id(ni, value, size, flags);
692987da915Sopenharmony_ci		break;
693987da915Sopenharmony_ci	case XATTR_NTFS_DOS_NAME:
694987da915Sopenharmony_ci		if (dir_ni)
695987da915Sopenharmony_ci		/* warning : this closes both inodes */
696987da915Sopenharmony_ci			res = ntfs_set_ntfs_dos_name(ni, dir_ni, value,
697987da915Sopenharmony_ci						size, flags);
698987da915Sopenharmony_ci		else {
699987da915Sopenharmony_ci			errno = EINVAL;
700987da915Sopenharmony_ci			res = -errno;
701987da915Sopenharmony_ci		}
702987da915Sopenharmony_ci		break;
703987da915Sopenharmony_ci	case XATTR_NTFS_TIMES:
704987da915Sopenharmony_ci		res = ntfs_inode_set_times(ni, value, size, flags);
705987da915Sopenharmony_ci		break;
706987da915Sopenharmony_ci	case XATTR_NTFS_TIMES_BE:
707987da915Sopenharmony_ci		if (value && (size > 0) && (size <= 4*sizeof(u64))) {
708987da915Sopenharmony_ci			memcpy(buf,value,size);
709987da915Sopenharmony_ci			for (i=0; (i+1)*sizeof(u64)<=size; i++)
710987da915Sopenharmony_ci				fix_big_endian(&buf[i*sizeof(u64)],
711987da915Sopenharmony_ci						sizeof(u64));
712987da915Sopenharmony_ci			res = ntfs_inode_set_times(ni, buf, size, flags);
713987da915Sopenharmony_ci		} else
714987da915Sopenharmony_ci			res = ntfs_inode_set_times(ni, value, size, flags);
715987da915Sopenharmony_ci		break;
716987da915Sopenharmony_ci	case XATTR_NTFS_CRTIME:
717987da915Sopenharmony_ci		res = ntfs_inode_set_times(ni, value,
718987da915Sopenharmony_ci			(size >= sizeof(u64) ? sizeof(u64) : size), flags);
719987da915Sopenharmony_ci		break;
720987da915Sopenharmony_ci	case XATTR_NTFS_CRTIME_BE:
721987da915Sopenharmony_ci		if (value && (size >= sizeof(u64))) {
722987da915Sopenharmony_ci			memcpy(buf,value,sizeof(u64));
723987da915Sopenharmony_ci			fix_big_endian(buf,sizeof(u64));
724987da915Sopenharmony_ci			res = ntfs_inode_set_times(ni, buf, sizeof(u64), flags);
725987da915Sopenharmony_ci		} else
726987da915Sopenharmony_ci			res = ntfs_inode_set_times(ni, value, size, flags);
727987da915Sopenharmony_ci		break;
728987da915Sopenharmony_ci	case XATTR_NTFS_EA :
729987da915Sopenharmony_ci		res = ntfs_set_ntfs_ea(ni, value, size, flags);
730987da915Sopenharmony_ci		break;
731987da915Sopenharmony_ci	default :
732987da915Sopenharmony_ci		errno = EOPNOTSUPP;
733987da915Sopenharmony_ci		res = -errno;
734987da915Sopenharmony_ci		break;
735987da915Sopenharmony_ci	}
736987da915Sopenharmony_ci	return (res);
737987da915Sopenharmony_ci}
738987da915Sopenharmony_ci
739987da915Sopenharmony_ciint ntfs_xattr_system_removexattr(struct SECURITY_CONTEXT *scx,
740987da915Sopenharmony_ci			enum SYSTEMXATTRS attr,
741987da915Sopenharmony_ci			ntfs_inode *ni, ntfs_inode *dir_ni)
742987da915Sopenharmony_ci{
743987da915Sopenharmony_ci	int res;
744987da915Sopenharmony_ci
745987da915Sopenharmony_ci	res = 0;
746987da915Sopenharmony_ci	switch (attr) {
747987da915Sopenharmony_ci		/*
748987da915Sopenharmony_ci		 * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
749987da915Sopenharmony_ci		 * is never allowed
750987da915Sopenharmony_ci		 */
751987da915Sopenharmony_ci	case XATTR_NTFS_ACL :
752987da915Sopenharmony_ci	case XATTR_NTFS_ATTRIB :
753987da915Sopenharmony_ci	case XATTR_NTFS_ATTRIB_BE :
754987da915Sopenharmony_ci	case XATTR_NTFS_EFSINFO :
755987da915Sopenharmony_ci	case XATTR_NTFS_TIMES :
756987da915Sopenharmony_ci	case XATTR_NTFS_TIMES_BE :
757987da915Sopenharmony_ci	case XATTR_NTFS_CRTIME :
758987da915Sopenharmony_ci	case XATTR_NTFS_CRTIME_BE :
759987da915Sopenharmony_ci		res = -EPERM;
760987da915Sopenharmony_ci		break;
761987da915Sopenharmony_ci#if POSIXACLS
762987da915Sopenharmony_ci	case XATTR_POSIX_ACC :
763987da915Sopenharmony_ci	case XATTR_POSIX_DEF :
764987da915Sopenharmony_ci		if (ni) {
765987da915Sopenharmony_ci			if (!ntfs_allowed_as_owner(scx, ni)
766987da915Sopenharmony_ci			   || ntfs_remove_posix_acl(scx, ni,
767987da915Sopenharmony_ci					(attr == XATTR_POSIX_ACC ?
768987da915Sopenharmony_ci					nf_ns_xattr_posix_access :
769987da915Sopenharmony_ci					nf_ns_xattr_posix_default)))
770987da915Sopenharmony_ci				res = -errno;
771987da915Sopenharmony_ci		} else
772987da915Sopenharmony_ci			res = -errno;
773987da915Sopenharmony_ci		break;
774987da915Sopenharmony_ci#endif
775987da915Sopenharmony_ci	case XATTR_NTFS_REPARSE_DATA :
776987da915Sopenharmony_ci		if (ni) {
777987da915Sopenharmony_ci			if (!ntfs_allowed_as_owner(scx, ni)
778987da915Sopenharmony_ci			    || ntfs_remove_ntfs_reparse_data(ni))
779987da915Sopenharmony_ci				res = -errno;
780987da915Sopenharmony_ci		} else
781987da915Sopenharmony_ci			res = -errno;
782987da915Sopenharmony_ci		break;
783987da915Sopenharmony_ci	case XATTR_NTFS_OBJECT_ID :
784987da915Sopenharmony_ci		if (ni) {
785987da915Sopenharmony_ci			if (!ntfs_allowed_as_owner(scx, ni)
786987da915Sopenharmony_ci			    || ntfs_remove_ntfs_object_id(ni))
787987da915Sopenharmony_ci				res = -errno;
788987da915Sopenharmony_ci		} else
789987da915Sopenharmony_ci			res = -errno;
790987da915Sopenharmony_ci		break;
791987da915Sopenharmony_ci	case XATTR_NTFS_DOS_NAME:
792987da915Sopenharmony_ci		if (ni && dir_ni) {
793987da915Sopenharmony_ci			if (ntfs_remove_ntfs_dos_name(ni,dir_ni))
794987da915Sopenharmony_ci				res = -errno;
795987da915Sopenharmony_ci			/* ni and dir_ni have been closed */
796987da915Sopenharmony_ci		} else
797987da915Sopenharmony_ci			res = -errno;
798987da915Sopenharmony_ci		break;
799987da915Sopenharmony_ci	case XATTR_NTFS_EA :
800987da915Sopenharmony_ci		res = ntfs_remove_ntfs_ea(ni);
801987da915Sopenharmony_ci		break;
802987da915Sopenharmony_ci	default :
803987da915Sopenharmony_ci		errno = EOPNOTSUPP;
804987da915Sopenharmony_ci		res = -errno;
805987da915Sopenharmony_ci		break;
806987da915Sopenharmony_ci	}
807987da915Sopenharmony_ci	return (res);
808987da915Sopenharmony_ci}
809