2 * xattrs.c : common functions to deal with system extended attributes
4 * Copyright (c) 2010-2014 Jean-Pierre Andre
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.
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.
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
55 #include "object_id.h"
62 #if __BYTE_ORDER == __BIG_ENDIAN
65 * Posix ACL structures
72 } __attribute__((__packed__
));
78 struct LE_POSIX_ACE ace
[0];
79 } __attribute__((__packed__
));
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";
99 static const char nf_ns_alt_xattr_efsinfo
[] = "user.ntfs.efsinfo";
102 enum SYSTEMXATTRS xattr
;
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 */
125 * Make an integer big-endian
127 * Swap bytes on a small-endian computer and does nothing on a
128 * big-endian computer.
131 static void fix_big_endian(char *p
, int size
)
133 #if __BYTE_ORDER == __LITTLE_ENDIAN
148 #if __BYTE_ORDER == __BIG_ENDIAN
151 * Make a Posix ACL CPU endian
154 static int le_acl_to_cpu(const struct LE_POSIX_ACL
*le_acl
, size_t size
,
155 struct POSIX_ACL
*acl
)
160 acl
->version
= le_acl
->version
;
161 acl
->flags
= le_acl
->flags
;
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
);
173 * Make a Posix ACL little endian
176 int cpu_to_le_acl(const struct POSIX_ACL
*acl
, size_t size
,
177 struct LE_POSIX_ACL
*le_acl
)
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
);
198 * Determine whether an extended attribute is mapped to
199 * internal data (original name in system namespace, or renamed)
202 enum SYSTEMXATTRS
ntfs_xattr_system_type(const char *name
,
206 enum SYSTEMXATTRS ret
;
207 #ifdef XATTR_MAPPINGS
208 const struct XATTRMAPPING
*q
;
209 #endif /* XATTR_MAPPINGS */
211 p
= nf_ns_xattr_names
;
212 while (p
->name
&& strcmp(p
->name
,name
))
215 #ifdef XATTR_MAPPINGS
216 if (!p
->name
&& vol
&& vol
->xattr_mapping
) {
217 q
= vol
->xattr_mapping
;
218 while (q
&& strcmp(q
->name
,name
))
223 #else /* XATTR_MAPPINGS */
227 && !strcmp(nf_ns_alt_xattr_efsinfo
,name
))
228 ret
= XATTR_NTFS_EFSINFO
;
229 #endif /* XATTR_MAPPINGS */
233 #ifdef XATTR_MAPPINGS
236 * Basic read from a user mapping file on another volume
239 static int basicread(void *fileid
, char *buf
, size_t size
, off_t offs
__attribute__((unused
)))
241 return (read(*(int*)fileid
, buf
, size
));
246 * Read from a user mapping file on current NTFS partition
249 static int localread(void *fileid
, char *buf
, size_t size
, off_t offs
)
251 return (ntfs_attr_data_read((ntfs_inode
*)fileid
,
252 AT_UNNAMED
, 0, buf
, size
, offs
));
256 * Get a single mapping item from buffer
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
265 static struct XATTRMAPPING
*getmappingitem(FILEREADER reader
, void *fileid
,
266 off_t
*poffs
, char *buf
, int *psrc
, s64
*psize
)
273 enum SYSTEMXATTRS xattr
;
275 char maptext
[LINESZ
];
276 struct XATTRMAPPING
*item
;
282 while ((src
< *psize
)
283 && (buf
[src
] != '\n')) {
286 && (buf
[src
] != '\r')
287 && (buf
[src
] != '\t')
288 && (buf
[src
] != ' '))
289 maptext
[dst
++] = buf
[src
];
294 *psize
= reader(fileid
, buf
, (size_t)BUFSZ
, *poffs
);
302 } while (*psize
&& ((maptext
[0] == '#') || !gotend
));
303 item
= (struct XATTRMAPPING
*)NULL
;
305 /* decompose into system name and user name */
307 pu
= strchr(maptext
,':');
313 /* check name validity */
314 if ((strlen(pu
) < 6) || strncmp(pu
,"user.",5))
316 xattr
= ntfs_xattr_system_type(ps
,
318 if (xattr
== XATTR_UNMAPPED
)
322 item
= (struct XATTRMAPPING
*)ntfs_malloc(
323 sizeof(struct XATTRMAPPING
)
327 strcpy(item
->name
,pu
);
328 item
->next
= (struct XATTRMAPPING
*)NULL
;
331 ntfs_log_early_error("Bad xattr mapping item, aborting\n");
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
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.
353 static struct XATTRMAPPING
*ntfs_read_xattr_mapping(FILEREADER reader
,
357 struct XATTRMAPPING
*item
;
358 struct XATTRMAPPING
*current
;
359 struct XATTRMAPPING
*firstitem
;
360 struct XATTRMAPPING
*lastitem
;
366 firstitem
= (struct XATTRMAPPING
*)NULL
;
367 lastitem
= (struct XATTRMAPPING
*)NULL
;
369 size
= reader(fileid
, buf
, (size_t)BUFSZ
, (off_t
)0);
373 item
= getmappingitem(reader
, fileid
, &offs
,
376 /* check no double mapping */
378 for (current
=firstitem
; current
; current
=current
->next
)
379 if ((current
->xattr
== item
->xattr
)
380 || !strcmp(current
->name
,item
->name
))
384 ntfs_log_early_error("Conflicting xattr mapping ignored\n");
386 item
->next
= (struct XATTRMAPPING
*)NULL
;
388 lastitem
->next
= item
;
400 * Build the extended attribute mappings to user namespace
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
406 struct XATTRMAPPING
*ntfs_xattr_build_mapping(ntfs_volume
*vol
,
407 const char *xattrmap_path
)
409 struct XATTRMAPPING
*firstmapping
;
410 struct XATTRMAPPING
*mapping
;
416 firstmapping
= (struct XATTRMAPPING
*)NULL
;
419 xattrmap_path
= XATTRMAPPINGFILE
;
420 if (xattrmap_path
[0] == '/') {
421 fd
= open(xattrmap_path
,O_RDONLY
);
423 firstmapping
= ntfs_read_xattr_mapping(basicread
, (void*)&fd
);
428 ni
= ntfs_pathname_to_inode(vol
, NULL
, xattrmap_path
);
430 firstmapping
= ntfs_read_xattr_mapping(localread
, ni
);
431 ntfs_inode_close(ni
);
435 if (notfound
&& strcmp(xattrmap_path
, XATTRMAPPINGFILE
)) {
436 ntfs_log_early_error("Could not open \"%s\"\n",xattrmap_path
);
440 for (mapping
=firstmapping
; mapping
; mapping
=mapping
->next
)
441 if (mapping
->xattr
== XATTR_NTFS_EFSINFO
)
446 mapping
= (struct XATTRMAPPING
*)ntfs_malloc(
447 sizeof(struct XATTRMAPPING
)
448 + strlen(nf_ns_alt_xattr_efsinfo
));
450 mapping
->next
= firstmapping
;
451 mapping
->xattr
= XATTR_NTFS_EFSINFO
;
452 strcpy(mapping
->name
,nf_ns_alt_xattr_efsinfo
);
453 firstmapping
= mapping
;
456 return (firstmapping
);
459 void ntfs_xattr_free_mapping(struct XATTRMAPPING
*mapping
)
461 struct XATTRMAPPING
*p
, *q
;
471 #endif /* XATTR_MAPPINGS */
474 * Get an NTFS attribute into an extended attribute
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.
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
)
490 #if __BYTE_ORDER == __BIG_ENDIAN
491 struct POSIX_ACL
*acl
;
496 case XATTR_NTFS_ACL
:
497 res
= ntfs_get_ntfs_acl(scx
, ni
, value
, size
);
500 #if __BYTE_ORDER == __BIG_ENDIAN
501 case XATTR_POSIX_ACC
:
502 acl
= (struct POSIX_ACL
*)ntfs_malloc(size
);
504 res
= ntfs_get_posix_acl(scx
, ni
,
505 nf_ns_xattr_posix_access
, (char*)acl
, size
);
507 if (cpu_to_le_acl(acl
,res
,
508 (struct LE_POSIX_ACL
*)value
))
515 case XATTR_POSIX_DEF
:
516 acl
= (struct POSIX_ACL
*)ntfs_malloc(size
);
518 res
= ntfs_get_posix_acl(scx
, ni
,
519 nf_ns_xattr_posix_default
, (char*)acl
, size
);
521 if (cpu_to_le_acl(acl
,res
,
522 (struct LE_POSIX_ACL
*)value
))
530 case XATTR_POSIX_ACC
:
531 res
= ntfs_get_posix_acl(scx
, ni
, nf_ns_xattr_posix_access
,
534 case XATTR_POSIX_DEF
:
535 res
= ntfs_get_posix_acl(scx
, ni
, nf_ns_xattr_posix_default
,
540 case XATTR_NTFS_ATTRIB
:
541 res
= ntfs_get_ntfs_attrib(ni
, value
, size
);
543 case XATTR_NTFS_ATTRIB_BE
:
544 res
= ntfs_get_ntfs_attrib(ni
, value
, size
);
545 if ((res
== 4) && value
) {
547 fix_big_endian(value
,4);
552 case XATTR_NTFS_EFSINFO
:
553 if (ni
->vol
->efs_raw
)
554 res
= ntfs_get_efs_info(ni
, value
, size
);
558 case XATTR_NTFS_REPARSE_DATA
:
559 res
= ntfs_get_ntfs_reparse_data(ni
, value
, size
);
561 case XATTR_NTFS_OBJECT_ID
:
562 res
= ntfs_get_ntfs_object_id(ni
, value
, size
);
564 case XATTR_NTFS_DOS_NAME
:
566 res
= ntfs_get_ntfs_dos_name(ni
, dir_ni
, value
, size
);
570 case XATTR_NTFS_TIMES
:
571 res
= ntfs_inode_get_times(ni
, value
, size
);
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
)],
581 case XATTR_NTFS_CRTIME
:
582 res
= ntfs_inode_get_times(ni
, value
,
583 (size
>= sizeof(u64
) ? sizeof(u64
) : size
));
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
));
592 res
= ntfs_get_ntfs_ea(ni
, value
, size
);
603 * Set an NTFS attribute from an extended attribute
605 * Returns 0 if successful,
606 * non-zero, with errno set, when fails
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
)
616 char buf
[4*sizeof(u64
)];
618 #if __BYTE_ORDER == __BIG_ENDIAN
619 struct POSIX_ACL
*acl
;
624 case XATTR_NTFS_ACL
:
625 res
= ntfs_set_ntfs_acl(scx
, ni
, value
, size
, flags
);
628 #if __BYTE_ORDER == __BIG_ENDIAN
629 case XATTR_POSIX_ACC
:
630 acl
= (struct POSIX_ACL
*)ntfs_malloc(size
);
632 if (!le_acl_to_cpu((const struct LE_POSIX_ACL
*)value
,
634 res
= ntfs_set_posix_acl(scx
,ni
,
635 nf_ns_xattr_posix_access
,
636 (char*)acl
, size
, flags
);
643 case XATTR_POSIX_DEF
:
644 acl
= (struct POSIX_ACL
*)ntfs_malloc(size
);
646 if (!le_acl_to_cpu((const struct LE_POSIX_ACL
*)value
,
648 res
= ntfs_set_posix_acl(scx
,ni
,
649 nf_ns_xattr_posix_default
,
650 (char*)acl
, size
, flags
);
658 case XATTR_POSIX_ACC
:
659 res
= ntfs_set_posix_acl(scx
,ni
, nf_ns_xattr_posix_access
,
662 case XATTR_POSIX_DEF
:
663 res
= ntfs_set_posix_acl(scx
, ni
, nf_ns_xattr_posix_default
,
668 case XATTR_NTFS_ATTRIB
:
669 res
= ntfs_set_ntfs_attrib(ni
, value
, size
, flags
);
671 case XATTR_NTFS_ATTRIB_BE
:
672 if (value
&& (size
>= 4)) {
674 fix_big_endian(buf
,4);
675 res
= ntfs_set_ntfs_attrib(ni
, buf
, 4, flags
);
677 res
= ntfs_set_ntfs_attrib(ni
, value
, size
, flags
);
679 case XATTR_NTFS_EFSINFO
:
680 if (ni
->vol
->efs_raw
)
681 res
= ntfs_set_efs_info(ni
, value
, size
, flags
);
687 case XATTR_NTFS_REPARSE_DATA
:
688 res
= ntfs_set_ntfs_reparse_data(ni
, value
, size
, flags
);
690 case XATTR_NTFS_OBJECT_ID
:
691 res
= ntfs_set_ntfs_object_id(ni
, value
, size
, flags
);
693 case XATTR_NTFS_DOS_NAME
:
695 /* warning : this closes both inodes */
696 res
= ntfs_set_ntfs_dos_name(ni
, dir_ni
, value
,
703 case XATTR_NTFS_TIMES
:
704 res
= ntfs_inode_set_times(ni
, value
, size
, flags
);
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
)],
712 res
= ntfs_inode_set_times(ni
, buf
, size
, flags
);
714 res
= ntfs_inode_set_times(ni
, value
, size
, flags
);
716 case XATTR_NTFS_CRTIME
:
717 res
= ntfs_inode_set_times(ni
, value
,
718 (size
>= sizeof(u64
) ? sizeof(u64
) : size
), flags
);
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
);
726 res
= ntfs_inode_set_times(ni
, value
, size
, flags
);
729 res
= ntfs_set_ntfs_ea(ni
, value
, size
, flags
);
739 int ntfs_xattr_system_removexattr(struct SECURITY_CONTEXT
*scx
,
740 enum SYSTEMXATTRS attr
,
741 ntfs_inode
*ni
, ntfs_inode
*dir_ni
)
748 * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
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
:
762 case XATTR_POSIX_ACC
:
763 case XATTR_POSIX_DEF
:
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
)))
775 case XATTR_NTFS_REPARSE_DATA
:
777 if (!ntfs_allowed_as_owner(scx
, ni
)
778 || ntfs_remove_ntfs_reparse_data(ni
))
783 case XATTR_NTFS_OBJECT_ID
:
785 if (!ntfs_allowed_as_owner(scx
, ni
)
786 || ntfs_remove_ntfs_object_id(ni
))
791 case XATTR_NTFS_DOS_NAME
:
793 if (ntfs_remove_ntfs_dos_name(ni
,dir_ni
))
795 /* ni and dir_ni have been closed */
800 res
= ntfs_remove_ntfs_ea(ni
);