Whamcloud - gitweb
e2fsck: clean up xattr checking code, add test
[tools/e2fsprogs.git] / lib / ext2fs / tst_read_ea.c
1 /*
2  * tst_getsize.c --- this function tests the getsize function
3  *
4  * %Begin-Header%
5  * This file may be redistributed under the terms of the GNU Public
6  * License.
7  * %End-Header%
8  */
9
10 #ifndef _GNU_SOURCE
11 #define _GNU_SOURCE     /* for asprintf */
12 #endif
13 #include <stdio.h>
14 #include <string.h>
15 #if HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 #include <fcntl.h>
19 #include <time.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #ifdef HAVE_ATTR_XATTR_H
23 #include <attr/xattr.h>
24 #elif HAVE_SYS_XATTR_H
25 #include <sys/xattr.h>
26 #else
27 /* This is just a test program, let's try to work around the lack of header */
28 extern ssize_t fgetxattr (int __filedes, const char *__name,
29                                 void *__value, size_t __size);
30 extern int fsetxattr (int __filedes, const char *__name,
31                       const void *__value, size_t __size, int __flags);
32 #endif
33 #if HAVE_MNTENT_H
34 #include <mntent.h>
35 #include <assert.h>
36 #if HAVE_ERRNO_H
37 #include <errno.h>
38 #endif
39
40 #include "ext2_fs.h"
41 #include "ext2fs.h"
42
43 #define NR_XATTRS 256
44 char tmpvalue[NR_XATTRS + 1];
45
46 struct ea {
47         char *name;
48         char *value;
49 };
50
51 struct ea *ea_table;
52
53 static void init_ea_table(void)
54 {
55         int i;
56
57         ea_table = malloc(sizeof(struct ea) * NR_XATTRS);
58         if (ea_table == NULL) {
59                 perror("maloc failed");
60                 exit(1);
61         }
62         for (i = 0; i < NR_XATTRS; i ++) {
63                 ea_table[i].name = malloc(i + 2 + strlen("user."));
64                 if (ea_table[i].name == NULL) {
65                         perror("malloc failed");
66                         exit(1);
67                 }
68                 strcpy(ea_table[i].name, "user.");
69                 memset(ea_table[i].name + strlen("user."), 'X', i + 1);
70                 ea_table[i].name[i + 1 + strlen("user.")] = 0;
71
72                 ea_table[i].value = malloc(NR_XATTRS - i + 1);
73                 if (ea_table[i].value == NULL) {
74                         perror("malloc failed");
75                         exit(1);
76                 }
77                 memset(ea_table[i].value, 'Y', NR_XATTRS - i);
78                 ea_table[i].value[NR_XATTRS - i] = 0;
79         }
80 }
81
82 static int set_xattrs(int fd)
83 {
84         int i;
85
86         for (i = 0; i < NR_XATTRS; i ++) {
87                 if (fsetxattr(fd, ea_table[i].name, ea_table[i].value,
88                               NR_XATTRS - i + 1, XATTR_CREATE) == -1) {
89                         if (errno != ENOSPC) {
90                                 perror("fsetxattr failed");
91                                 exit(1);
92                         }
93                         break;
94                 }
95         }
96         printf("\t%d xattrs are set\n", i);
97         return i;
98 }
99
100 void get_xattrs1(int fd, int nr)
101 {
102         int i;
103         ssize_t size;
104
105         printf("\ttesting fgetxattr .. "); fflush(stdout);
106
107         for (i = 0; i < nr; i ++) {
108                 size = fgetxattr(fd, ea_table[i].name, tmpvalue,
109                                  NR_XATTRS - i + 1);
110                 if (size == -1) {
111                         perror("fgetxattr failed");
112                         exit(1);
113                 }
114                 if (memcmp(ea_table[i].value, tmpvalue, nr - i + 1)) {
115                         fprintf(stderr, "value mismatch");
116                         exit(1);
117                 }
118         }
119
120         printf("%d xattrs are checked, ok\n", i);
121 }
122
123 void get_xattrs2(const char *device, ext2_ino_t ino, int nr)
124 {
125         ext2_filsys fs;
126         int i;
127         struct ext2_inode *inode;
128         errcode_t err;
129         int size;
130
131         printf("\ttesting ext2fs_attr_get .. "); fflush(stdout);
132
133         err = ext2fs_open(device, 0, 0, 0, unix_io_manager, &fs);
134         assert(err == 0);
135
136         err = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
137         if (err) {
138                 com_err("get_xattrs2", err, "allocating memory");
139                 exit(1);
140         }
141
142         err = ext2fs_read_inode_full(fs, ino, inode,
143                                      EXT2_INODE_SIZE(fs->super));
144         if (err) {
145                 com_err("get_xattrs2", err, "reading inode");
146                 exit(1);
147         }
148         for (i = 0; i < nr; i ++) {
149                 err = ext2fs_attr_get(fs, inode, EXT2_ATTR_INDEX_USER,
150                                       ea_table[i].name + strlen("user."),
151                                       tmpvalue, sizeof(tmpvalue), &size);
152                 if (err) {
153                         com_err("get_xattrs2", err, "getting xattr");
154                         exit(1);
155                 }
156                 assert(size == (NR_XATTRS - i + 1));
157
158                 if (memcmp(ea_table[i].value, tmpvalue, size)) {
159                         fprintf(stderr, "value mismatch");
160                         exit(1);
161                 }
162         }
163         ext2fs_close(fs);
164
165         printf("%d xattrs are checked, ok\n", i);
166 }
167 #endif /* HAVE_MNTENT_H */
168
169 int main(int argc, const char *argv[])
170 {
171 #if HAVE_MNTENT_H
172         ext2_filsys fs;
173         FILE *f;
174         struct mntent *mnt;
175         char *name;
176         int fd;
177         errcode_t err;
178         struct stat st;
179         int nr;
180         int tested = 0;
181
182         initialize_ext2_error_table();
183
184         init_ea_table();
185
186         f = setmntent(MOUNTED, "r");
187         if (!f) {
188                 fprintf(stderr, "failed to setmntent\n");
189                 return 1;
190         }
191
192         while ((mnt = getmntent(f)) != NULL) {
193                 if (hasmntopt(mnt, "user_xattr") == NULL)
194                         continue;
195                 err = ext2fs_open(mnt->mnt_fsname, 0, 0, 0,
196                                   unix_io_manager, &fs);
197                 if (err) {
198                         com_err("tst_read_ea", err, "opening fs %s:%s",
199                                 mnt->mnt_fsname, mnt->mnt_type);
200                         continue;
201                 }
202                 ext2fs_close(fs);
203
204                 printf("type=%s, fsname=%s, mtpt=%s\n", mnt->mnt_type,
205                        mnt->mnt_fsname, mnt->mnt_dir);
206
207                 asprintf(&name, "%s/readeaXXXXXX", mnt->mnt_dir);
208                 fd = mkstemp(name);
209                 if (fd == -1) {
210                         fprintf(stderr, "tst_read_ea: mkstemp failed on %s: %s",
211                                 name, strerror(errno));
212                         continue;
213                 }
214                 if (fstat(fd, &st)) {
215                         fprintf(stderr, "tst_read_ea: fstat failed on %s: %s\n",
216                                 name, strerror(errno));
217                         exit(1);
218                 }
219                 nr = set_xattrs(fd);
220
221                 sync();
222                 get_xattrs1(fd, nr);
223                 close(fd);
224
225                 get_xattrs2(mnt->mnt_fsname, st.st_ino, nr);
226
227                 unlink(name);
228                 free(name);
229                 tested = 1;
230         }
231         endmntent(f);
232
233         if (!tested)
234                 fprintf(stderr,
235                         "\tno ext2 based filesystems mounted with user_xattr\n"
236                         "\thope it is ok\n");
237 #endif /* HAVE_MNTENT_H */
238         return 0;
239 }