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