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