summaryrefslogtreecommitdiff
path: root/src/ntfs-3g_common.c (plain)
blob: ca805d6fab3914f9042bb451f7249c7f44146a75
1/**
2 * ntfs-3g_common.c - Common definitions for ntfs-3g and lowntfs-3g.
3 *
4 * Copyright (c) 2010-2012 Jean-Pierre Andre
5 * Copyright (c) 2010 Erik Larsson
6 *
7 * This program/include file is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program/include file is distributed in the hope that it will be
13 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program (in the main directory of the NTFS-3G
19 * distribution in the file COPYING); if not, write to the Free Software
20 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#ifdef HAVE_STDLIB_H
28#include <stdlib.h>
29#endif
30
31#ifdef HAVE_STRING_H
32#include <string.h>
33#endif
34
35#ifdef HAVE_LIMITS_H
36#include <limits.h>
37#endif
38
39#ifdef HAVE_ERRNO_H
40#include <errno.h>
41#endif
42
43#include <getopt.h>
44#include <fuse.h>
45
46#include "inode.h"
47#include "security.h"
48#include "xattrs.h"
49#include "ntfs-3g_common.h"
50#include "realpath.h"
51#include "misc.h"
52
53const char xattr_ntfs_3g[] = "ntfs-3g.";
54
55const char nf_ns_user_prefix[] = "user.";
56const int nf_ns_user_prefix_len = sizeof(nf_ns_user_prefix) - 1;
57const char nf_ns_system_prefix[] = "system.";
58const int nf_ns_system_prefix_len = sizeof(nf_ns_system_prefix) - 1;
59const char nf_ns_security_prefix[] = "security.";
60const int nf_ns_security_prefix_len = sizeof(nf_ns_security_prefix) - 1;
61const char nf_ns_trusted_prefix[] = "trusted.";
62const int nf_ns_trusted_prefix_len = sizeof(nf_ns_trusted_prefix) - 1;
63
64static const char nf_ns_alt_xattr_efsinfo[] = "user.ntfs.efsinfo";
65
66static const char def_opts[] = "allow_other,nonempty,";
67
68 /*
69 * Table of recognized options
70 * Their order may be significant
71 * The options invalid in some configuration should still
72 * be present, so that an error can be returned
73 */
74const struct DEFOPTION optionlist[] = {
75 { "ro", OPT_RO, FLGOPT_APPEND | FLGOPT_BOGUS },
76 { "noatime", OPT_NOATIME, FLGOPT_BOGUS },
77 { "atime", OPT_ATIME, FLGOPT_BOGUS },
78 { "relatime", OPT_RELATIME, FLGOPT_BOGUS },
79 { "delay_mtime", OPT_DMTIME, FLGOPT_DECIMAL | FLGOPT_OPTIONAL },
80 { "fake_rw", OPT_FAKE_RW, FLGOPT_BOGUS },
81 { "fsname", OPT_FSNAME, FLGOPT_NOSUPPORT },
82 { "no_def_opts", OPT_NO_DEF_OPTS, FLGOPT_BOGUS },
83 { "default_permissions", OPT_DEFAULT_PERMISSIONS, FLGOPT_BOGUS },
84 { "permissions", OPT_PERMISSIONS, FLGOPT_BOGUS },
85 { "acl", OPT_ACL, FLGOPT_BOGUS },
86 { "umask", OPT_UMASK, FLGOPT_OCTAL },
87 { "fmask", OPT_FMASK, FLGOPT_OCTAL },
88 { "dmask", OPT_DMASK, FLGOPT_OCTAL },
89 { "uid", OPT_UID, FLGOPT_DECIMAL },
90 { "gid", OPT_GID, FLGOPT_DECIMAL },
91 { "show_sys_files", OPT_SHOW_SYS_FILES, FLGOPT_BOGUS },
92 { "hide_hid_files", OPT_HIDE_HID_FILES, FLGOPT_BOGUS },
93 { "hide_dot_files", OPT_HIDE_DOT_FILES, FLGOPT_BOGUS },
94 { "ignore_case", OPT_IGNORE_CASE, FLGOPT_BOGUS },
95 { "windows_names", OPT_WINDOWS_NAMES, FLGOPT_BOGUS },
96 { "compression", OPT_COMPRESSION, FLGOPT_BOGUS },
97 { "nocompression", OPT_NOCOMPRESSION, FLGOPT_BOGUS },
98 { "silent", OPT_SILENT, FLGOPT_BOGUS },
99 { "recover", OPT_RECOVER, FLGOPT_BOGUS },
100 { "norecover", OPT_NORECOVER, FLGOPT_BOGUS },
101 { "remove_hiberfile", OPT_REMOVE_HIBERFILE, FLGOPT_BOGUS },
102 { "sync", OPT_SYNC, FLGOPT_BOGUS | FLGOPT_APPEND },
103 { "big_writes", OPT_BIG_WRITES, FLGOPT_BOGUS },
104 { "locale", OPT_LOCALE, FLGOPT_STRING },
105 { "nfconv", OPT_NFCONV, FLGOPT_BOGUS },
106 { "nonfconv", OPT_NONFCONV, FLGOPT_BOGUS },
107 { "streams_interface", OPT_STREAMS_INTERFACE, FLGOPT_STRING },
108 { "user_xattr", OPT_USER_XATTR, FLGOPT_BOGUS },
109 { "noauto", OPT_NOAUTO, FLGOPT_BOGUS },
110 { "debug", OPT_DEBUG, FLGOPT_BOGUS },
111 { "no_detach", OPT_NO_DETACH, FLGOPT_BOGUS },
112 { "remount", OPT_REMOUNT, FLGOPT_BOGUS },
113 { "blksize", OPT_BLKSIZE, FLGOPT_STRING },
114 { "inherit", OPT_INHERIT, FLGOPT_BOGUS },
115 { "addsecurids", OPT_ADDSECURIDS, FLGOPT_BOGUS },
116 { "staticgrps", OPT_STATICGRPS, FLGOPT_BOGUS },
117 { "usermapping", OPT_USERMAPPING, FLGOPT_STRING },
118 { "xattrmapping", OPT_XATTRMAPPING, FLGOPT_STRING },
119 { "efs_raw", OPT_EFS_RAW, FLGOPT_BOGUS },
120 { (const char*)NULL, 0, 0 } /* end marker */
121} ;
122
123#define STRAPPEND_MAX_INSIZE 8192
124#define strappend_is_large(x) ((x) > STRAPPEND_MAX_INSIZE)
125
126int ntfs_strappend(char **dest, const char *append)
127{
128 char *p;
129 size_t size_append, size_dest = 0;
130
131 if (!dest)
132 return -1;
133 if (!append)
134 return 0;
135
136 size_append = strlen(append);
137 if (*dest)
138 size_dest = strlen(*dest);
139
140 if (strappend_is_large(size_dest) || strappend_is_large(size_append)) {
141 errno = EOVERFLOW;
142 ntfs_log_perror("%s: Too large input buffer", EXEC_NAME);
143 return -1;
144 }
145
146 p = (char*)realloc(*dest, size_dest + size_append + 1);
147 if (!p) {
148 ntfs_log_perror("%s: Memory realloction failed", EXEC_NAME);
149 return -1;
150 }
151
152 *dest = p;
153 strcpy(*dest + size_dest, append);
154
155 return 0;
156}
157
158/*
159 * Insert an option before ",fsname="
160 * This is for keeping "fsname" as the last option, because on
161 * Solaris device names may contain commas.
162 */
163
164int ntfs_strinsert(char **dest, const char *append)
165{
166 char *p, *q;
167 size_t size_append, size_dest = 0;
168
169 if (!dest)
170 return -1;
171 if (!append)
172 return 0;
173
174 size_append = strlen(append);
175 if (*dest)
176 size_dest = strlen(*dest);
177
178 if (strappend_is_large(size_dest) || strappend_is_large(size_append)) {
179 errno = EOVERFLOW;
180 ntfs_log_perror("%s: Too large input buffer", EXEC_NAME);
181 return -1;
182 }
183
184 p = (char*)malloc(size_dest + size_append + 1);
185 if (!p) {
186 ntfs_log_perror("%s: Memory reallocation failed", EXEC_NAME);
187 return -1;
188 }
189 strcpy(p, *dest);
190 q = strstr(p, ",fsname=");
191 if (q) {
192 strcpy(q, append);
193 q = strstr(*dest, ",fsname=");
194 if (q)
195 strcat(p, q);
196 free(*dest);
197 *dest = p;
198 } else {
199 free(*dest);
200 *dest = p;
201 strcpy(*dest + size_dest, append);
202 }
203 return 0;
204}
205
206static int bogus_option_value(char *val, const char *s)
207{
208 if (val) {
209 ntfs_log_error("'%s' option shouldn't have value.\n", s);
210 return -1;
211 }
212 return 0;
213}
214
215static int missing_option_value(char *val, const char *s)
216{
217 if (!val) {
218 ntfs_log_error("'%s' option should have a value.\n", s);
219 return -1;
220 }
221 return 0;
222}
223
224char *parse_mount_options(ntfs_fuse_context_t *ctx,
225 const struct ntfs_options *popts, BOOL low_fuse)
226{
227 char *options, *s, *opt, *val, *ret = NULL;
228 const char *orig_opts = popts->options;
229 BOOL no_def_opts = FALSE;
230 int default_permissions = 0;
231 int permissions = 0;
232 int acl = 0;
233 int want_permissions = 0;
234 int intarg;
235 const struct DEFOPTION *poptl;
236
237 ctx->secure_flags = 0;
238#ifdef HAVE_SETXATTR /* extended attributes interface required */
239 ctx->efs_raw = FALSE;
240#endif /* HAVE_SETXATTR */
241 ctx->compression = DEFAULT_COMPRESSION;
242 options = strdup(orig_opts ? orig_opts : "");
243 if (!options) {
244 ntfs_log_perror("%s: strdup failed", EXEC_NAME);
245 return NULL;
246 }
247
248 s = options;
249 while (s && *s && (val = strsep(&s, ","))) {
250 opt = strsep(&val, "=");
251 poptl = optionlist;
252 while (poptl->name && strcmp(poptl->name,opt))
253 poptl++;
254 if (poptl->name) {
255 if ((poptl->flags & FLGOPT_BOGUS)
256 && bogus_option_value(val, opt))
257 goto err_exit;
258 if ((poptl->flags & FLGOPT_OCTAL)
259 && (!val
260 || !sscanf(val, "%o", &intarg))) {
261 ntfs_log_error("'%s' option needs an octal value\n",
262 opt);
263 goto err_exit;
264 }
265 if (poptl->flags & FLGOPT_DECIMAL) {
266 if ((poptl->flags & FLGOPT_OPTIONAL) && !val)
267 intarg = 0;
268 else
269 if (!val
270 || !sscanf(val, "%i", &intarg)) {
271 ntfs_log_error("'%s' option "
272 "needs a decimal value\n",
273 opt);
274 goto err_exit;
275 }
276 }
277 if ((poptl->flags & FLGOPT_STRING)
278 && missing_option_value(val, opt))
279 goto err_exit;
280
281 switch (poptl->type) {
282 case OPT_RO :
283 case OPT_FAKE_RW :
284 ctx->ro = TRUE;
285 break;
286 case OPT_NOATIME :
287 ctx->atime = ATIME_DISABLED;
288 break;
289 case OPT_ATIME :
290 ctx->atime = ATIME_ENABLED;
291 break;
292 case OPT_RELATIME :
293 ctx->atime = ATIME_RELATIVE;
294 break;
295 case OPT_DMTIME :
296 if (!intarg)
297 intarg = DEFAULT_DMTIME;
298 ctx->dmtime = intarg*10000000LL;
299 break;
300 case OPT_NO_DEF_OPTS :
301 no_def_opts = TRUE; /* Don't add default options. */
302 ctx->silent = FALSE; /* cancel default silent */
303 break;
304 case OPT_DEFAULT_PERMISSIONS :
305 default_permissions = 1;
306 break;
307 case OPT_PERMISSIONS :
308 permissions = 1;
309 break;
310#if POSIXACLS
311 case OPT_ACL :
312 acl = 1;
313 break;
314#endif
315 case OPT_UMASK :
316 ctx->dmask = ctx->fmask = intarg;
317 want_permissions = 1;
318 break;
319 case OPT_FMASK :
320 ctx->fmask = intarg;
321 want_permissions = 1;
322 break;
323 case OPT_DMASK :
324 ctx->dmask = intarg;
325 want_permissions = 1;
326 break;
327 case OPT_UID :
328 ctx->uid = intarg;
329 want_permissions = 1;
330 break;
331 case OPT_GID :
332 ctx->gid = intarg;
333 want_permissions = 1;
334 break;
335 case OPT_SHOW_SYS_FILES :
336 ctx->show_sys_files = TRUE;
337 break;
338 case OPT_HIDE_HID_FILES :
339 ctx->hide_hid_files = TRUE;
340 break;
341 case OPT_HIDE_DOT_FILES :
342 ctx->hide_dot_files = TRUE;
343 break;
344 case OPT_WINDOWS_NAMES :
345 ctx->windows_names = TRUE;
346 break;
347 case OPT_IGNORE_CASE :
348 if (low_fuse)
349 ctx->ignore_case = TRUE;
350 else {
351 ntfs_log_error("'%s' is an unsupported option.\n",
352 poptl->name);
353 goto err_exit;
354 }
355 break;
356 case OPT_COMPRESSION :
357 ctx->compression = TRUE;
358 break;
359 case OPT_NOCOMPRESSION :
360 ctx->compression = FALSE;
361 break;
362 case OPT_SILENT :
363 ctx->silent = TRUE;
364 break;
365 case OPT_RECOVER :
366 ctx->recover = TRUE;
367 break;
368 case OPT_NORECOVER :
369 ctx->recover = FALSE;
370 break;
371 case OPT_REMOVE_HIBERFILE :
372 ctx->hiberfile = TRUE;
373 break;
374 case OPT_SYNC :
375 ctx->sync = TRUE;
376 break;
377#ifdef FUSE_CAP_BIG_WRITES
378 case OPT_BIG_WRITES :
379 ctx->big_writes = TRUE;
380 break;
381#endif
382 case OPT_LOCALE :
383 ntfs_set_char_encoding(val);
384 break;
385#if defined(__APPLE__) || defined(__DARWIN__)
386#ifdef ENABLE_NFCONV
387 case OPT_NFCONV :
388 if (ntfs_macosx_normalize_filenames(1)) {
389 ntfs_log_error("ntfs_macosx_normalize_filenames(1) failed!\n");
390 goto err_exit;
391 }
392 break;
393 case OPT_NONFCONV :
394 if (ntfs_macosx_normalize_filenames(0)) {
395 ntfs_log_error("ntfs_macosx_normalize_filenames(0) failed!\n");
396 goto err_exit;
397 }
398 break;
399#endif /* ENABLE_NFCONV */
400#endif /* defined(__APPLE__) || defined(__DARWIN__) */
401 case OPT_STREAMS_INTERFACE :
402 if (!strcmp(val, "none"))
403 ctx->streams = NF_STREAMS_INTERFACE_NONE;
404 else if (!strcmp(val, "xattr"))
405 ctx->streams = NF_STREAMS_INTERFACE_XATTR;
406 else if (!strcmp(val, "openxattr"))
407 ctx->streams = NF_STREAMS_INTERFACE_OPENXATTR;
408 else if (!low_fuse && !strcmp(val, "windows"))
409 ctx->streams = NF_STREAMS_INTERFACE_WINDOWS;
410 else {
411 ntfs_log_error("Invalid named data streams "
412 "access interface.\n");
413 goto err_exit;
414 }
415 break;
416 case OPT_USER_XATTR :
417 ctx->streams = NF_STREAMS_INTERFACE_XATTR;
418 break;
419 case OPT_NOAUTO :
420 /* Don't pass noauto option to fuse. */
421 break;
422 case OPT_DEBUG :
423 ctx->debug = TRUE;
424 ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);
425 ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
426 break;
427 case OPT_NO_DETACH :
428 ctx->no_detach = TRUE;
429 break;
430 case OPT_REMOUNT :
431 ntfs_log_error("Remounting is not supported at present."
432 " You have to umount volume and then "
433 "mount it once again.\n");
434 goto err_exit;
435 case OPT_BLKSIZE :
436 ntfs_log_info("WARNING: blksize option is ignored "
437 "because ntfs-3g must calculate it.\n");
438 break;
439 case OPT_INHERIT :
440 /*
441 * do not overwrite inherited permissions
442 * in create()
443 */
444 ctx->inherit = TRUE;
445 break;
446 case OPT_ADDSECURIDS :
447 /*
448 * create security ids for files being read
449 * with an individual security attribute
450 */
451 ctx->secure_flags |= (1 << SECURITY_ADDSECURIDS);
452 break;
453 case OPT_STATICGRPS :
454 /*
455 * use static definition of groups
456 * for file access control
457 */
458 ctx->secure_flags |= (1 << SECURITY_STATICGRPS);
459 break;
460 case OPT_USERMAPPING :
461 ctx->usermap_path = strdup(val);
462 if (!ctx->usermap_path) {
463 ntfs_log_error("no more memory to store "
464 "'usermapping' option.\n");
465 goto err_exit;
466 }
467 break;
468#ifdef HAVE_SETXATTR /* extended attributes interface required */
469#ifdef XATTR_MAPPINGS
470 case OPT_XATTRMAPPING :
471 ctx->xattrmap_path = strdup(val);
472 if (!ctx->xattrmap_path) {
473 ntfs_log_error("no more memory to store "
474 "'xattrmapping' option.\n");
475 goto err_exit;
476 }
477 break;
478#endif /* XATTR_MAPPINGS */
479 case OPT_EFS_RAW :
480 ctx->efs_raw = TRUE;
481 break;
482#endif /* HAVE_SETXATTR */
483 case OPT_FSNAME : /* Filesystem name. */
484 /*
485 * We need this to be able to check whether filesystem
486 * mounted or not.
487 * (falling through to default)
488 */
489 default :
490 ntfs_log_error("'%s' is an unsupported option.\n",
491 poptl->name);
492 goto err_exit;
493 }
494 if ((poptl->flags & FLGOPT_APPEND)
495 && (ntfs_strappend(&ret, poptl->name)
496 || ntfs_strappend(&ret, ",")))
497 goto err_exit;
498 } else { /* Probably FUSE option. */
499 if (ntfs_strappend(&ret, opt))
500 goto err_exit;
501 if (val) {
502 if (ntfs_strappend(&ret, "="))
503 goto err_exit;
504 if (ntfs_strappend(&ret, val))
505 goto err_exit;
506 }
507 if (ntfs_strappend(&ret, ","))
508 goto err_exit;
509 }
510 }
511 if (!no_def_opts && ntfs_strappend(&ret, def_opts))
512 goto err_exit;
513 if ((default_permissions || (permissions && !acl))
514 && ntfs_strappend(&ret, "default_permissions,"))
515 goto err_exit;
516 /* The atime options exclude each other */
517 if (ctx->atime == ATIME_RELATIVE && ntfs_strappend(&ret, "relatime,"))
518 goto err_exit;
519 else if (ctx->atime == ATIME_ENABLED && ntfs_strappend(&ret, "atime,"))
520 goto err_exit;
521 else if (ctx->atime == ATIME_DISABLED && ntfs_strappend(&ret, "noatime,"))
522 goto err_exit;
523
524 if (ntfs_strappend(&ret, "fsname="))
525 goto err_exit;
526 if (ntfs_strappend(&ret, popts->device))
527 goto err_exit;
528 if (permissions && !acl)
529 ctx->secure_flags |= (1 << SECURITY_DEFAULT);
530 if (acl)
531 ctx->secure_flags |= (1 << SECURITY_ACL);
532 if (want_permissions)
533 ctx->secure_flags |= (1 << SECURITY_WANTED);
534 if (ctx->ro)
535 ctx->secure_flags &= ~(1 << SECURITY_ADDSECURIDS);
536exit:
537 free(options);
538 return ret;
539err_exit:
540 free(ret);
541 ret = NULL;
542 goto exit;
543}
544
545/**
546 * parse_options - Read and validate the programs command line
547 * Read the command line, verify the syntax and parse the options.
548 *
549 * Return: 0 success, -1 error.
550 */
551int ntfs_parse_options(struct ntfs_options *popts, void (*usage)(void),
552 int argc, char *argv[])
553{
554 int c;
555
556 static const char *sopt = "-o:hnvV";
557 static const struct option lopt[] = {
558 { "options", required_argument, NULL, 'o' },
559 { "help", no_argument, NULL, 'h' },
560 { "no-mtab", no_argument, NULL, 'n' },
561 { "verbose", no_argument, NULL, 'v' },
562 { "version", no_argument, NULL, 'V' },
563 { NULL, 0, NULL, 0 }
564 };
565
566 opterr = 0; /* We'll handle the errors, thank you. */
567
568 while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
569 switch (c) {
570 case 1: /* A non-option argument */
571 if (!popts->device) {
572 popts->device = ntfs_malloc(PATH_MAX + 1);
573 if (!popts->device)
574 return -1;
575
576 /* Canonicalize device name (mtab, etc) */
577 popts->arg_device = optarg;
578 if (!ntfs_realpath_canonicalize(optarg,
579 popts->device)) {
580 ntfs_log_perror("%s: Failed to access "
581 "volume '%s'", EXEC_NAME, optarg);
582 free(popts->device);
583 popts->device = NULL;
584 return -1;
585 }
586 } else if (!popts->mnt_point) {
587 popts->mnt_point = optarg;
588 } else {
589 ntfs_log_error("%s: You must specify exactly one "
590 "device and exactly one mount "
591 "point.\n", EXEC_NAME);
592 return -1;
593 }
594 break;
595 case 'o':
596 if (popts->options)
597 if (ntfs_strappend(&popts->options, ","))
598 return -1;
599 if (ntfs_strappend(&popts->options, optarg))
600 return -1;
601 break;
602 case 'h':
603 usage();
604 exit(9);
605 case 'n':
606 /*
607 * no effect - automount passes it, meaning 'no-mtab'
608 */
609 break;
610 case 'v':
611 /*
612 * We must handle the 'verbose' option even if
613 * we don't use it because mount(8) passes it.
614 */
615 break;
616 case 'V':
617 ntfs_log_info("%s %s %s %d\n", EXEC_NAME, VERSION,
618 FUSE_TYPE, fuse_version());
619 exit(0);
620 default:
621 ntfs_log_error("%s: Unknown option '%s'.\n", EXEC_NAME,
622 argv[optind - 1]);
623 return -1;
624 }
625 }
626
627 if (!popts->device) {
628 ntfs_log_error("%s: No device is specified.\n", EXEC_NAME);
629 return -1;
630 }
631 if (!popts->mnt_point) {
632 ntfs_log_error("%s: No mountpoint is specified.\n", EXEC_NAME);
633 return -1;
634 }
635
636 return 0;
637}
638
639#ifdef HAVE_SETXATTR
640
641int ntfs_fuse_listxattr_common(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
642 char *list, size_t size, BOOL prefixing)
643{
644 int ret = 0;
645 char *to = list;
646#ifdef XATTR_MAPPINGS
647 BOOL accepted;
648 const struct XATTRMAPPING *item;
649#endif /* XATTR_MAPPINGS */
650
651 /* first list the regular user attributes (ADS) */
652 while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE,
653 0, NULL, 0, actx)) {
654 char *tmp_name = NULL;
655 int tmp_name_len;
656
657 if (!actx->attr->name_length)
658 continue;
659 tmp_name_len = ntfs_ucstombs(
660 (ntfschar *)((u8*)actx->attr +
661 le16_to_cpu(actx->attr->name_offset)),
662 actx->attr->name_length, &tmp_name, 0);
663 if (tmp_name_len < 0) {
664 ret = -errno;
665 goto exit;
666 }
667 /*
668 * When using name spaces, do not return
669 * security, trusted or system attributes
670 * (filtered elsewhere anyway)
671 * otherwise insert "user." prefix
672 */
673 if (prefixing) {
674 if ((strlen(tmp_name) > sizeof(xattr_ntfs_3g))
675 && !strncmp(tmp_name,xattr_ntfs_3g,
676 sizeof(xattr_ntfs_3g)-1))
677 tmp_name_len = 0;
678 else
679 ret += tmp_name_len
680 + nf_ns_user_prefix_len + 1;
681 } else
682 ret += tmp_name_len + 1;
683 if (size && tmp_name_len) {
684 if ((size_t)ret <= size) {
685 if (prefixing) {
686 strcpy(to, nf_ns_user_prefix);
687 to += nf_ns_user_prefix_len;
688 }
689 strncpy(to, tmp_name, tmp_name_len);
690 to += tmp_name_len;
691 *to = 0;
692 to++;
693 } else {
694 free(tmp_name);
695 ret = -ERANGE;
696 goto exit;
697 }
698 }
699 free(tmp_name);
700 }
701#ifdef XATTR_MAPPINGS
702 /* now append the system attributes mapped to user space */
703 for (item=ni->vol->xattr_mapping; item; item=item->next) {
704 switch (item->xattr) {
705 case XATTR_NTFS_EFSINFO :
706 accepted = ni->vol->efs_raw
707 && (ni->flags & FILE_ATTR_ENCRYPTED);
708 break;
709 case XATTR_NTFS_REPARSE_DATA :
710 accepted = (ni->flags & FILE_ATTR_REPARSE_POINT)
711 != const_cpu_to_le32(0);
712 break;
713// TODO : we are supposed to only return xattrs which are set
714// this is more complex for OBJECT_ID and DOS_NAME
715 default : accepted = TRUE;
716 break;
717 }
718 if (accepted) {
719 ret += strlen(item->name) + 1;
720 if (size) {
721 if ((size_t)ret <= size) {
722 strcpy(to, item->name);
723 to += strlen(item->name);
724 *to++ = 0;
725 } else {
726 ret = -ERANGE;
727 goto exit;
728 }
729 }
730#else /* XATTR_MAPPINGS */
731 /* List efs info xattr for encrypted files */
732 if (ni->vol->efs_raw && (ni->flags & FILE_ATTR_ENCRYPTED)) {
733 ret += sizeof(nf_ns_alt_xattr_efsinfo);
734 if ((size_t)ret <= size) {
735 memcpy(to, nf_ns_alt_xattr_efsinfo,
736 sizeof(nf_ns_alt_xattr_efsinfo));
737 to += sizeof(nf_ns_alt_xattr_efsinfo);
738#endif /* XATTR_MAPPINGS */
739 }
740 }
741exit :
742 return (ret);
743}
744
745#endif /* HAVE_SETXATTR */
746