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
fix_big_endian(char * p,int size)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
le_acl_to_cpu(const struct LE_POSIX_ACL * le_acl,size_t size,struct POSIX_ACL * acl)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
cpu_to_le_acl(const struct POSIX_ACL * acl,size_t size,struct LE_POSIX_ACL * le_acl)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
ntfs_xattr_system_type(const char * name,ntfs_volume * vol)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
basicread(void * fileid,char * buf,size_t size,off_t offs)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
localread(void * fileid,char * buf,size_t size,off_t offs)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
getmappingitem(FILEREADER reader,void * fileid,off_t * poffs,char * buf,int * psrc,s64 * psize)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
ntfs_read_xattr_mapping(FILEREADER reader,void * fileid)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
ntfs_xattr_build_mapping(ntfs_volume * vol,const char * xattrmap_path)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
ntfs_xattr_free_mapping(struct XATTRMAPPING * mapping)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 /*
474 * Get an NTFS attribute into an extended attribute
475 *
476 * Returns the non-negative size of attribute if successful,
477 * or negative, with errno set, when fails
478 * Note : the size is returned even if no buffer is provided
479 * for returning the attribute, or if it is zero-sized.
480 */
481
ntfs_xattr_system_getxattr(struct SECURITY_CONTEXT * scx,enum SYSTEMXATTRS attr,ntfs_inode * ni,ntfs_inode * dir_ni,char * value,size_t size)482 int ntfs_xattr_system_getxattr(struct SECURITY_CONTEXT *scx,
483 enum SYSTEMXATTRS attr,
484 ntfs_inode *ni, ntfs_inode *dir_ni,
485 char *value, size_t size)
486 {
487 int res;
488 int i;
489 #if POSIXACLS
490 #if __BYTE_ORDER == __BIG_ENDIAN
491 struct POSIX_ACL *acl;
492 #endif
493 #endif
494
495 switch (attr) {
496 case XATTR_NTFS_ACL :
497 res = ntfs_get_ntfs_acl(scx, ni, value, size);
498 break;
499 #if POSIXACLS
500 #if __BYTE_ORDER == __BIG_ENDIAN
501 case XATTR_POSIX_ACC :
502 acl = (struct POSIX_ACL*)ntfs_malloc(size);
503 if (acl) {
504 res = ntfs_get_posix_acl(scx, ni,
505 nf_ns_xattr_posix_access, (char*)acl, size);
506 if (res > 0) {
507 if (cpu_to_le_acl(acl,res,
508 (struct LE_POSIX_ACL*)value))
509 res = -errno;
510 }
511 free(acl);
512 } else
513 res = -errno;
514 break;
515 case XATTR_POSIX_DEF :
516 acl = (struct POSIX_ACL*)ntfs_malloc(size);
517 if (acl) {
518 res = ntfs_get_posix_acl(scx, ni,
519 nf_ns_xattr_posix_default, (char*)acl, size);
520 if (res > 0) {
521 if (cpu_to_le_acl(acl,res,
522 (struct LE_POSIX_ACL*)value))
523 res = -errno;
524 }
525 free(acl);
526 } else
527 res = -errno;
528 break;
529 #else
530 case XATTR_POSIX_ACC :
531 res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_access,
532 value, size);
533 break;
534 case XATTR_POSIX_DEF :
535 res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_default,
536 value, size);
537 break;
538 #endif
539 #endif
540 case XATTR_NTFS_ATTRIB :
541 res = ntfs_get_ntfs_attrib(ni, value, size);
542 break;
543 case XATTR_NTFS_ATTRIB_BE :
544 res = ntfs_get_ntfs_attrib(ni, value, size);
545 if ((res == 4) && value) {
546 if (size >= 4)
547 fix_big_endian(value,4);
548 else
549 res = -EINVAL;
550 }
551 break;
552 case XATTR_NTFS_EFSINFO :
553 if (ni->vol->efs_raw)
554 res = ntfs_get_efs_info(ni, value, size);
555 else
556 res = -EPERM;
557 break;
558 case XATTR_NTFS_REPARSE_DATA :
559 res = ntfs_get_ntfs_reparse_data(ni, value, size);
560 break;
561 case XATTR_NTFS_OBJECT_ID :
562 res = ntfs_get_ntfs_object_id(ni, value, size);
563 break;
564 case XATTR_NTFS_DOS_NAME:
565 if (dir_ni)
566 res = ntfs_get_ntfs_dos_name(ni, dir_ni, value, size);
567 else
568 res = -errno;
569 break;
570 case XATTR_NTFS_TIMES:
571 res = ntfs_inode_get_times(ni, value, size);
572 break;
573 case XATTR_NTFS_TIMES_BE:
574 res = ntfs_inode_get_times(ni, value, size);
575 if ((res > 0) && value) {
576 for (i=0; (i+1)*sizeof(u64)<=(unsigned int)res; i++)
577 fix_big_endian(&value[i*sizeof(u64)],
578 sizeof(u64));
579 }
580 break;
581 case XATTR_NTFS_CRTIME:
582 res = ntfs_inode_get_times(ni, value,
583 (size >= sizeof(u64) ? sizeof(u64) : size));
584 break;
585 case XATTR_NTFS_CRTIME_BE:
586 res = ntfs_inode_get_times(ni, value,
587 (size >= sizeof(u64) ? sizeof(u64) : size));
588 if ((res >= (int)sizeof(u64)) && value)
589 fix_big_endian(value,sizeof(u64));
590 break;
591 case XATTR_NTFS_EA :
592 res = ntfs_get_ntfs_ea(ni, value, size);
593 break;
594 default :
595 errno = EOPNOTSUPP;
596 res = -errno;
597 break;
598 }
599 return (res);
600 }
601
602 /*
603 * Set an NTFS attribute from an extended attribute
604 *
605 * Returns 0 if successful,
606 * non-zero, with errno set, when fails
607 */
608
ntfs_xattr_system_setxattr(struct SECURITY_CONTEXT * scx,enum SYSTEMXATTRS attr,ntfs_inode * ni,ntfs_inode * dir_ni,const char * value,size_t size,int flags)609 int ntfs_xattr_system_setxattr(struct SECURITY_CONTEXT *scx,
610 enum SYSTEMXATTRS attr,
611 ntfs_inode *ni, ntfs_inode *dir_ni,
612 const char *value, size_t size, int flags)
613 {
614 int res;
615 int i;
616 char buf[4*sizeof(u64)];
617 #if POSIXACLS
618 #if __BYTE_ORDER == __BIG_ENDIAN
619 struct POSIX_ACL *acl;
620 #endif
621 #endif
622
623 switch (attr) {
624 case XATTR_NTFS_ACL :
625 res = ntfs_set_ntfs_acl(scx, ni, value, size, flags);
626 break;
627 #if POSIXACLS
628 #if __BYTE_ORDER == __BIG_ENDIAN
629 case XATTR_POSIX_ACC :
630 acl = (struct POSIX_ACL*)ntfs_malloc(size);
631 if (acl) {
632 if (!le_acl_to_cpu((const struct LE_POSIX_ACL*)value,
633 size, acl)) {
634 res = ntfs_set_posix_acl(scx ,ni ,
635 nf_ns_xattr_posix_access,
636 (char*)acl, size, flags);
637 } else
638 res = -errno;
639 free(acl);
640 } else
641 res = -errno;
642 break;
643 case XATTR_POSIX_DEF :
644 acl = (struct POSIX_ACL*)ntfs_malloc(size);
645 if (acl) {
646 if (!le_acl_to_cpu((const struct LE_POSIX_ACL*)value,
647 size, acl)) {
648 res = ntfs_set_posix_acl(scx ,ni ,
649 nf_ns_xattr_posix_default,
650 (char*)acl, size, flags);
651 } else
652 res = -errno;
653 free(acl);
654 } else
655 res = -errno;
656 break;
657 #else
658 case XATTR_POSIX_ACC :
659 res = ntfs_set_posix_acl(scx ,ni , nf_ns_xattr_posix_access,
660 value, size, flags);
661 break;
662 case XATTR_POSIX_DEF :
663 res = ntfs_set_posix_acl(scx, ni, nf_ns_xattr_posix_default,
664 value, size, flags);
665 break;
666 #endif
667 #endif
668 case XATTR_NTFS_ATTRIB :
669 res = ntfs_set_ntfs_attrib(ni, value, size, flags);
670 break;
671 case XATTR_NTFS_ATTRIB_BE :
672 if (value && (size >= 4)) {
673 memcpy(buf,value,4);
674 fix_big_endian(buf,4);
675 res = ntfs_set_ntfs_attrib(ni, buf, 4, flags);
676 } else
677 res = ntfs_set_ntfs_attrib(ni, value, size, flags);
678 break;
679 case XATTR_NTFS_EFSINFO :
680 if (ni->vol->efs_raw)
681 res = ntfs_set_efs_info(ni, value, size, flags);
682 else {
683 errno = EPERM;
684 res = -EPERM;
685 }
686 break;
687 case XATTR_NTFS_REPARSE_DATA :
688 res = ntfs_set_ntfs_reparse_data(ni, value, size, flags);
689 break;
690 case XATTR_NTFS_OBJECT_ID :
691 res = ntfs_set_ntfs_object_id(ni, value, size, flags);
692 break;
693 case XATTR_NTFS_DOS_NAME:
694 if (dir_ni)
695 /* warning : this closes both inodes */
696 res = ntfs_set_ntfs_dos_name(ni, dir_ni, value,
697 size, flags);
698 else {
699 errno = EINVAL;
700 res = -errno;
701 }
702 break;
703 case XATTR_NTFS_TIMES:
704 res = ntfs_inode_set_times(ni, value, size, flags);
705 break;
706 case XATTR_NTFS_TIMES_BE:
707 if (value && (size > 0) && (size <= 4*sizeof(u64))) {
708 memcpy(buf,value,size);
709 for (i=0; (i+1)*sizeof(u64)<=size; i++)
710 fix_big_endian(&buf[i*sizeof(u64)],
711 sizeof(u64));
712 res = ntfs_inode_set_times(ni, buf, size, flags);
713 } else
714 res = ntfs_inode_set_times(ni, value, size, flags);
715 break;
716 case XATTR_NTFS_CRTIME:
717 res = ntfs_inode_set_times(ni, value,
718 (size >= sizeof(u64) ? sizeof(u64) : size), flags);
719 break;
720 case XATTR_NTFS_CRTIME_BE:
721 if (value && (size >= sizeof(u64))) {
722 memcpy(buf,value,sizeof(u64));
723 fix_big_endian(buf,sizeof(u64));
724 res = ntfs_inode_set_times(ni, buf, sizeof(u64), flags);
725 } else
726 res = ntfs_inode_set_times(ni, value, size, flags);
727 break;
728 case XATTR_NTFS_EA :
729 res = ntfs_set_ntfs_ea(ni, value, size, flags);
730 break;
731 default :
732 errno = EOPNOTSUPP;
733 res = -errno;
734 break;
735 }
736 return (res);
737 }
738
ntfs_xattr_system_removexattr(struct SECURITY_CONTEXT * scx,enum SYSTEMXATTRS attr,ntfs_inode * ni,ntfs_inode * dir_ni)739 int ntfs_xattr_system_removexattr(struct SECURITY_CONTEXT *scx,
740 enum SYSTEMXATTRS attr,
741 ntfs_inode *ni, ntfs_inode *dir_ni)
742 {
743 int res;
744
745 res = 0;
746 switch (attr) {
747 /*
748 * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
749 * is never allowed
750 */
751 case XATTR_NTFS_ACL :
752 case XATTR_NTFS_ATTRIB :
753 case XATTR_NTFS_ATTRIB_BE :
754 case XATTR_NTFS_EFSINFO :
755 case XATTR_NTFS_TIMES :
756 case XATTR_NTFS_TIMES_BE :
757 case XATTR_NTFS_CRTIME :
758 case XATTR_NTFS_CRTIME_BE :
759 res = -EPERM;
760 break;
761 #if POSIXACLS
762 case XATTR_POSIX_ACC :
763 case XATTR_POSIX_DEF :
764 if (ni) {
765 if (!ntfs_allowed_as_owner(scx, ni)
766 || ntfs_remove_posix_acl(scx, ni,
767 (attr == XATTR_POSIX_ACC ?
768 nf_ns_xattr_posix_access :
769 nf_ns_xattr_posix_default)))
770 res = -errno;
771 } else
772 res = -errno;
773 break;
774 #endif
775 case XATTR_NTFS_REPARSE_DATA :
776 if (ni) {
777 if (!ntfs_allowed_as_owner(scx, ni)
778 || ntfs_remove_ntfs_reparse_data(ni))
779 res = -errno;
780 } else
781 res = -errno;
782 break;
783 case XATTR_NTFS_OBJECT_ID :
784 if (ni) {
785 if (!ntfs_allowed_as_owner(scx, ni)
786 || ntfs_remove_ntfs_object_id(ni))
787 res = -errno;
788 } else
789 res = -errno;
790 break;
791 case XATTR_NTFS_DOS_NAME:
792 if (ni && dir_ni) {
793 if (ntfs_remove_ntfs_dos_name(ni,dir_ni))
794 res = -errno;
795 /* ni and dir_ni have been closed */
796 } else
797 res = -errno;
798 break;
799 case XATTR_NTFS_EA :
800 res = ntfs_remove_ntfs_ea(ni);
801 break;
802 default :
803 errno = EOPNOTSUPP;
804 res = -errno;
805 break;
806 }
807 return (res);
808 }
809