1 /*
2    Unix SMB/CIFS implementation.
3 
4    POSIX NTVFS backend - xattr support using filesystem xattrs
5 
6    Copyright (C) Andrew Tridgell 2004
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 
23 #include "includes.h"
24 #include "vfs_posix.h"
25 #include "lib/util/wrap_xattr.h"
26 
27 /*
28   pull a xattr as a blob, from either a file or a file descriptor
29 */
pull_xattr_blob_system(struct pvfs_state * pvfs,TALLOC_CTX * mem_ctx,const char * attr_name,const char * fname,int fd,size_t estimated_size,DATA_BLOB * blob)30 NTSTATUS pull_xattr_blob_system(struct pvfs_state *pvfs,
31 				TALLOC_CTX *mem_ctx,
32 				const char *attr_name,
33 				const char *fname,
34 				int fd,
35 				size_t estimated_size,
36 				DATA_BLOB *blob)
37 {
38 	int ret;
39 
40 	*blob = data_blob_talloc(mem_ctx, NULL, estimated_size+16);
41 	if (blob->data == NULL) {
42 		return NT_STATUS_NO_MEMORY;
43 	}
44 
45 again:
46 	if (fd != -1) {
47 		ret = wrap_fgetxattr(fd, attr_name, blob->data, estimated_size);
48 	} else {
49 		ret = wrap_getxattr(fname, attr_name, blob->data, estimated_size);
50 	}
51 	if (ret == -1 && errno == ERANGE) {
52 		estimated_size *= 2;
53 		blob->data = talloc_realloc(mem_ctx, blob->data,
54 					    uint8_t, estimated_size);
55 		if (blob->data == NULL) {
56 			return NT_STATUS_NO_MEMORY;
57 		}
58 		blob->length = estimated_size;
59 		goto again;
60 	}
61 	if (ret == -1 && errno == EPERM) {
62 		struct stat statbuf;
63 
64 		if (fd != -1) {
65 			ret = fstat(fd, &statbuf);
66 		} else {
67 			ret = stat(fname, &statbuf);
68 		}
69 		if (ret == 0) {
70 			/* check if this is a directory and the sticky bit is set */
71 			if (S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & S_ISVTX)) {
72 				/* pretend we could not find the xattr */
73 
74 				data_blob_free(blob);
75 				return NT_STATUS_NOT_FOUND;
76 
77 			} else {
78 				/* if not this was probably a legittimate error
79 				 * reset ret and errno to the correct values */
80 				errno = EPERM;
81 				ret = -1;
82 			}
83 		}
84 	}
85 
86 	if (ret == -1) {
87 		data_blob_free(blob);
88 		return pvfs_map_errno(pvfs, errno);
89 	}
90 
91 	blob->length = ret;
92 
93 	return NT_STATUS_OK;
94 }
95 
96 /*
97   push a xattr as a blob, from either a file or a file descriptor
98 */
push_xattr_blob_system(struct pvfs_state * pvfs,const char * attr_name,const char * fname,int fd,const DATA_BLOB * blob)99 NTSTATUS push_xattr_blob_system(struct pvfs_state *pvfs,
100 				const char *attr_name,
101 				const char *fname,
102 				int fd,
103 				const DATA_BLOB *blob)
104 {
105 	int ret;
106 
107 	if (fd != -1) {
108 		ret = wrap_fsetxattr(fd, attr_name, blob->data, blob->length, 0);
109 	} else {
110 		ret = wrap_setxattr(fname, attr_name, blob->data, blob->length, 0);
111 	}
112 	if (ret == -1) {
113 		return pvfs_map_errno(pvfs, errno);
114 	}
115 
116 	return NT_STATUS_OK;
117 }
118 
119 
120 /*
121   delete a xattr
122 */
delete_xattr_system(struct pvfs_state * pvfs,const char * attr_name,const char * fname,int fd)123 NTSTATUS delete_xattr_system(struct pvfs_state *pvfs, const char *attr_name,
124 			     const char *fname, int fd)
125 {
126 	int ret;
127 
128 	if (fd != -1) {
129 		ret = wrap_fremovexattr(fd, attr_name);
130 	} else {
131 		ret = wrap_removexattr(fname, attr_name);
132 	}
133 	if (ret == -1) {
134 		return pvfs_map_errno(pvfs, errno);
135 	}
136 
137 	return NT_STATUS_OK;
138 }
139 
140 /*
141   unlink a file - cleanup any xattrs
142 */
unlink_xattr_system(struct pvfs_state * pvfs,const char * fname)143 NTSTATUS unlink_xattr_system(struct pvfs_state *pvfs, const char *fname)
144 {
145 	/* nothing needs to be done for filesystem based xattrs */
146 	return NT_STATUS_OK;
147 }
148