/*
 * Unsquash a squashfs filesystem.  This is a highly compressed read only
 * filesystem.
 *
 * Copyright (c) 2010, 2012
 * Phillip Lougher <phillip@squashfs.org.uk>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2,
 * or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * unsquashfs_xattr.c
 */

#include "unsquashfs.h"
#include "xattr.h"

#include <sys/xattr.h>

#ifdef XATTR_NOFOLLOW /* Apple's xattrs */
    #define lsetxattr(path_, name_, val_, sz_, flags_) \
        setxattr(path_, name_, val_, sz_, 0, flags_ | XATTR_NOFOLLOW)
#endif

#define NOSPACE_MAX 10

extern int root_process;
extern int user_xattrs;

void write_xattr(char *pathname, unsigned int xattr)
{
	unsigned int count;
	struct xattr_list *xattr_list;
	int i;
	static int nonsuper_error = FALSE;
	static int ignore_xattrs = FALSE;
	static int nospace_error = 0;

	if(ignore_xattrs || xattr == SQUASHFS_INVALID_XATTR ||
			sBlk.s.xattr_id_table_start == SQUASHFS_INVALID_BLK)
		return;

	xattr_list = get_xattr(xattr, &count, 1);
	if(xattr_list == NULL) {
		ERROR("Failed to read xattrs for file %s\n", pathname);
		return;
	}

	for(i = 0; i < count; i++) {
		int prefix = xattr_list[i].type & SQUASHFS_XATTR_PREFIX_MASK;

		if(user_xattrs && prefix != SQUASHFS_XATTR_USER)
			continue;

		if(root_process || prefix == SQUASHFS_XATTR_USER) {
			int res = lsetxattr(pathname, xattr_list[i].full_name,
				xattr_list[i].value, xattr_list[i].vsize, 0);

			if(res == -1) {
				if(errno == ENOTSUP) {
					/*
					 * If the destination filesystem cannot
					 * suppport xattrs, print error, and
					 * disable xattr output as this error is
					 * unlikely to go away, and printing
					 * screenfulls of the same error message
					 * is rather annoying
					 */
					ERROR("write_xattr: failed to write "
						"xattr %s for file %s because " 
						"extended attributes are not "
						"supported by the destination "
						"filesystem\n",
						xattr_list[i].full_name,
						pathname);
					ERROR("Ignoring xattrs in "
								"filesystem\n");
					ERROR("To avoid this error message, "
						"specify -no-xattrs\n");
					ignore_xattrs = TRUE;
				} else if((errno == ENOSPC || errno == EDQUOT)
						&& nospace_error < NOSPACE_MAX) {
					/*
					 * Many filesystems like ext2/3/4 have
					 * limits on the amount of xattr
					 * data that can be stored per file
					 * (typically one block or 4K), so
					 * we shouldn't disable xattr ouput,
					 * as the error may be restriced to one
					 * file only.  If we get a lot of these
					 * then suppress the error messsage
					 */
					ERROR("write_xattr: failed to write "
						"xattr %s for file %s because " 
						"no extended attribute space "
						"remaining (per file or "
						"filesystem limit)\n",
						xattr_list[i].full_name,
						pathname);
					if(++ nospace_error == NOSPACE_MAX)
						ERROR("%d of these errors "
							"printed, further error "
							"messages of this type "
							"are suppressed!\n",
							NOSPACE_MAX);
				} else
					ERROR("write_xattr: failed to write "
						"xattr %s for file %s because "
						"%s\n", xattr_list[i].full_name,
						pathname, strerror(errno));
			}
		} else if(nonsuper_error == FALSE) {
			/*
			 * if extract user xattrs only then
			 * error message is suppressed, if not
			 * print error, and then suppress further error
			 * messages to avoid possible screenfulls of the
			 * same error message!
			 */
			ERROR("write_xattr: could not write xattr %s "
					"for file %s because you're not "
					"superuser!\n",
					xattr_list[i].full_name, pathname);
			ERROR("write_xattr: to avoid this error message, either"
				" specify -user-xattrs, -no-xattrs, or run as "
				"superuser!\n");
			ERROR("Further error messages of this type are "
				"suppressed!\n");
			nonsuper_error = TRUE;
		}
	}

	free_xattr(xattr_list, count);
}
