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 /* 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 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 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 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