3 Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org>
4 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 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; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern int sync_open, sync_dirs;
34 static int find_handle(struct child_struct *child, int handle)
37 for (i=0;i<MAX_FILES;i++) {
38 if (ftable[i].handle == handle) return i;
40 printf("(%d) ERROR: handle %d was not found\n",
46 /* Find the directory holding a file, and flush it to disk. We do
47 this in -S mode after a directory-modifying mode, to simulate the
48 way knfsd tries to flush directories. MKDIR and similar operations
49 are meant to be synchronous on NFSv2. */
50 static void sync_parent(char *fname)
56 if (strchr(fname, '/')) {
57 copy_name = strdup(fname);
58 slash = strrchr(copy_name, '/');
61 copy_name = strdup(".");
64 dir_fd = open(copy_name, O_RDONLY);
66 printf("open directory \"%s\" for sync failed: %s\n",
70 if (fdatasync(dir_fd) == -1) {
71 printf("datasync directory \"%s\" failed: %s\n",
75 if (close(dir_fd) == -1) {
76 printf("close directory failed: %s\n",
83 static void xattr_fd_read_hook(int fd)
85 #if HAVE_XATTR_SUPPORT
86 extern int xattr_enable;
89 memset(buf, 0, sizeof(buf));
90 fgetxattr(fd, "user.DosAttrib", buf, sizeof(buf));
97 static void xattr_fname_read_hook(const char *fname)
99 #if HAVE_XATTR_SUPPORT
100 extern int xattr_enable;
103 getxattr(fname, "user.DosAttrib", buf, sizeof(buf));
110 static void xattr_fd_write_hook(int fd)
112 #if HAVE_XATTR_SUPPORT
113 extern int xattr_enable;
117 memset(buf, 0, sizeof(buf));
118 fgetxattr(fd, "user.DosAttrib", buf, sizeof(buf));
119 gettimeofday(&tv, NULL);
120 memcpy(buf, &tv, sizeof(tv));
121 if (fsetxattr(fd, "user.DosAttrib", buf, sizeof(buf), 0) != 0) {
122 printf("fsetxattr failed - %s\n", strerror(errno));
131 static int expected_status(const char *status)
133 if (strcmp(status, "NT_STATUS_OK") == 0) return 0;
138 simulate pvfs_resolve_name()
140 static void resolve_name(const char *name)
148 if (stat(name, &st) == 0) {
149 xattr_fname_read_hook(name);
153 dname = strdup(name);
154 p = strrchr(dname, '/');
159 dir = opendir(dname);
164 while ((d = readdir(dir))) {
165 if (strcasecmp(fname, d->d_name) == 0) break;
171 static void failed(struct child_struct *child)
174 printf("ERROR: child %d failed\n", child->id);
178 void nb_setup(struct child_struct *child)
183 void nb_unlink(struct child_struct *child, char *fname, int attr, const char *status)
189 if (unlink(fname) != expected_status(status)) {
190 printf("(%d) unlink %s failed (%s) - expected %s\n",
191 child->line, fname, strerror(errno), status);
194 if (sync_dirs) sync_parent(fname);
197 void nb_mkdir(struct child_struct *child, char *dname, const char *status)
205 void nb_rmdir(struct child_struct *child, char *fname, const char *status)
209 if (rmdir(fname) != expected_status(status)) {
210 printf("(%d) rmdir %s failed (%s) - expected %s\n",
211 child->line, fname, strerror(errno), status);
214 if (sync_dirs) sync_parent(fname);
217 void nb_createx(struct child_struct *child, const char *fname,
218 uint32_t create_options, uint32_t create_disposition, int fnum,
227 if (sync_open) flags |= O_SYNC;
229 if (create_disposition == FILE_CREATE) {
233 if (create_disposition == FILE_OVERWRITE ||
234 create_disposition == FILE_OVERWRITE_IF) {
235 flags |= O_CREAT | O_TRUNC;
238 if (create_options & FILE_DIRECTORY_FILE) {
239 /* not strictly correct, but close enough */
243 if (create_options & FILE_DIRECTORY_FILE) flags = O_RDONLY|O_DIRECTORY;
245 fd = open(fname, flags, 0600);
247 if (strcmp(status, "NT_STATUS_OK") == 0) {
248 printf("(%d) open %s failed for handle %d (%s)\n",
249 child->line, fname, fnum, strerror(errno));
253 if (strcmp(status, "NT_STATUS_OK") != 0) {
254 printf("(%d) open %s succeeded for handle %d\n",
255 child->line, fname, fnum);
260 for (i=0;i<MAX_FILES;i++) {
261 if (ftable[i].handle == 0) break;
263 if (i == MAX_FILES) {
264 printf("file table full for %s\n", fname);
267 ftable[i].name = strdup(fname);
268 ftable[i].handle = fnum;
273 if (!S_ISDIR(st.st_mode)) {
274 xattr_fd_write_hook(fd);
278 void nb_writex(struct child_struct *child, int handle, int offset,
279 int size, int ret_size, const char *status)
281 int i = find_handle(child, handle);
286 buf = calloc(size, 1);
288 if (pwrite(ftable[i].fd, buf, size, offset) != ret_size) {
289 printf("write failed on handle %d\n", handle);
295 child->bytes += size;
298 void nb_readx(struct child_struct *child, int handle, int offset,
299 int size, int ret_size, const char *status)
301 int i = find_handle(child, handle);
308 if (pread(ftable[i].fd, buf, size, offset) != ret_size) {
309 printf("read failed on handle %d\n", handle);
314 child->bytes += size;
317 void nb_close(struct child_struct *child, int handle, const char *status)
319 int i = find_handle(child, handle);
322 ftable[i].handle = 0;
323 if (ftable[i].name) free(ftable[i].name);
324 ftable[i].name = NULL;
327 void nb_rename(struct child_struct *child, char *old, char *new, const char *status)
332 if (rename(old, new) != expected_status(status)) {
333 printf("rename %s %s failed (%s) - expected %s\n",
334 old, new, strerror(errno), status);
337 if (sync_dirs) sync_parent(new);
340 void nb_flush(struct child_struct *child, int handle, const char *status)
343 find_handle(child, handle);
347 void nb_qpathinfo(struct child_struct *child, const char *fname, int level,
356 void nb_qfileinfo(struct child_struct *child, int handle, int level, const char *status)
359 int i = find_handle(child, handle);
363 fstat(ftable[i].fd, &st);
364 xattr_fd_read_hook(ftable[i].fd);
367 void nb_qfsinfo(struct child_struct *child, int level, const char *status)
374 statfs(child->directory, &st);
377 void nb_findfirst(struct child_struct *child, char *fname, int level, int maxcnt,
378 int count, const char *status)
391 if (strpbrk(fname, "<>*?\"") == NULL) {
395 p = strrchr(fname, '/');
398 dir = opendir(fname);
400 while (maxcnt && (d = readdir(dir))) maxcnt--;
404 void nb_cleanup(struct child_struct *child)
408 asprintf(&dname, "%s/clients/client%d", child->directory, child->id);
409 nb_deltree(child, dname);
412 asprintf(&dname, "%s%s", child->directory, "/clients");
417 void nb_deltree(struct child_struct *child, char *dname)
421 asprintf(&path, "/bin/rm -rf %s", dname);
426 void nb_sfileinfo(struct child_struct *child, int handle, int level, const char *status)
428 int i = find_handle(child, handle);
435 xattr_fd_read_hook(ftable[i].fd);
437 fstat(ftable[i].fd, &st);
439 tm.actime = st.st_atime - 10;
440 tm.modtime = st.st_mtime - 12;
442 utime(ftable[i].name, &tm);
444 if (!S_ISDIR(st.st_mode)) {
445 xattr_fd_write_hook(ftable[i].fd);
449 void nb_lockx(struct child_struct *child, int handle, uint32_t offset, int size,
452 int i = find_handle(child, handle);
458 lock.l_type = F_WRLCK;
459 lock.l_whence = SEEK_SET;
460 lock.l_start = offset;
464 fcntl(ftable[i].fd, F_SETLKW, &lock);
467 void nb_unlockx(struct child_struct *child,
468 int handle, uint32_t offset, int size, const char *status)
470 int i = find_handle(child, handle);
476 lock.l_type = F_UNLCK;
477 lock.l_whence = SEEK_SET;
478 lock.l_start = offset;
482 fcntl(ftable[i].fd, F_SETLKW, &lock);
485 void nb_sleep(struct child_struct *child, int usec, const char *status)