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 defined(HAVE_FDATASYNC)
71 if (fdatasync(dir_fd) == -1) {
73 if (fsync(dir_fd) == -1) {
75 printf("datasync directory \"%s\" failed: %s\n",
79 if (close(dir_fd) == -1) {
80 printf("close directory failed: %s\n",
87 static void xattr_fd_read_hook(int fd)
93 memset(buf, 0, sizeof(buf));
94 sys_fgetxattr(fd, "user.DosAttrib", buf, sizeof(buf));
101 static void xattr_fname_read_hook(const char *fname)
104 extern int ea_enable;
107 sys_getxattr(fname, "user.DosAttrib", buf, sizeof(buf));
114 static void xattr_fd_write_hook(int fd)
117 extern int ea_enable;
121 sys_fgetxattr(fd, "user.DosAttrib", buf, sizeof(buf));
122 memset(buf, 0, sizeof(buf));
123 /* give some probability of sharing */
124 if (random() % 10 < 2) {
125 *(time_t *)buf = time(NULL);
127 gettimeofday(&tv, NULL);
128 memcpy(buf, &tv, sizeof(tv));
130 if (sys_fsetxattr(fd, "user.DosAttrib", buf, sizeof(buf), 0) != 0) {
131 printf("fsetxattr failed - %s\n", strerror(errno));
140 static int expected_status(const char *status)
142 if (strcmp(status, "NT_STATUS_OK") == 0) return 0;
147 simulate pvfs_resolve_name()
149 static void resolve_name(const char *name)
157 if (stat(name, &st) == 0) {
158 xattr_fname_read_hook(name);
162 dname = strdup(name);
163 p = strrchr(dname, '/');
168 dir = opendir(dname);
173 while ((d = readdir(dir))) {
174 if (strcasecmp(fname, d->d_name) == 0) break;
180 static void failed(struct child_struct *child)
183 printf("ERROR: child %d failed\n", child->id);
187 void nb_setup(struct child_struct *child)
192 void nb_unlink(struct child_struct *child, char *fname, int attr, const char *status)
198 if (unlink(fname) != expected_status(status)) {
199 printf("(%d) unlink %s failed (%s) - expected %s\n",
200 child->line, fname, strerror(errno), status);
203 if (sync_dirs) sync_parent(fname);
206 void nb_mkdir(struct child_struct *child, char *dname, const char *status)
214 void nb_rmdir(struct child_struct *child, char *fname, const char *status)
218 if (rmdir(fname) != expected_status(status)) {
219 printf("(%d) rmdir %s failed (%s) - expected %s\n",
220 child->line, fname, strerror(errno), status);
223 if (sync_dirs) sync_parent(fname);
226 void nb_createx(struct child_struct *child, const char *fname,
227 uint32_t create_options, uint32_t create_disposition, int fnum,
236 if (sync_open) flags |= O_SYNC;
238 if (create_disposition == FILE_CREATE) {
242 if (create_disposition == FILE_OVERWRITE ||
243 create_disposition == FILE_OVERWRITE_IF) {
244 flags |= O_CREAT | O_TRUNC;
247 if (create_options & FILE_DIRECTORY_FILE) {
248 /* not strictly correct, but close enough */
252 if (create_options & FILE_DIRECTORY_FILE) flags = O_RDONLY|O_DIRECTORY;
254 fd = open(fname, flags, 0600);
256 if (strcmp(status, "NT_STATUS_OK") == 0) {
257 printf("(%d) open %s failed for handle %d (%s)\n",
258 child->line, fname, fnum, strerror(errno));
262 if (strcmp(status, "NT_STATUS_OK") != 0) {
263 printf("(%d) open %s succeeded for handle %d\n",
264 child->line, fname, fnum);
269 for (i=0;i<MAX_FILES;i++) {
270 if (ftable[i].handle == 0) break;
272 if (i == MAX_FILES) {
273 printf("file table full for %s\n", fname);
276 ftable[i].name = strdup(fname);
277 ftable[i].handle = fnum;
282 if (!S_ISDIR(st.st_mode)) {
283 xattr_fd_write_hook(fd);
287 void nb_writex(struct child_struct *child, int handle, int offset,
288 int size, int ret_size, const char *status)
290 int i = find_handle(child, handle);
295 buf = calloc(size, 1);
297 if (pwrite(ftable[i].fd, buf, size, offset) != ret_size) {
298 printf("write failed on handle %d (%s)\n", handle, strerror(errno));
304 child->bytes += size;
307 void nb_readx(struct child_struct *child, int handle, int offset,
308 int size, int ret_size, const char *status)
310 int i = find_handle(child, handle);
317 if (pread(ftable[i].fd, buf, size, offset) != ret_size) {
318 printf("read failed on handle %d (%s)\n", handle, strerror(errno));
323 child->bytes += size;
326 void nb_close(struct child_struct *child, int handle, const char *status)
328 int i = find_handle(child, handle);
331 ftable[i].handle = 0;
332 if (ftable[i].name) free(ftable[i].name);
333 ftable[i].name = NULL;
336 void nb_rename(struct child_struct *child, char *old, char *new, const char *status)
341 if (rename(old, new) != expected_status(status)) {
342 printf("rename %s %s failed (%s) - expected %s\n",
343 old, new, strerror(errno), status);
346 if (sync_dirs) sync_parent(new);
349 void nb_flush(struct child_struct *child, int handle, const char *status)
352 find_handle(child, handle);
356 void nb_qpathinfo(struct child_struct *child, const char *fname, int level,
365 void nb_qfileinfo(struct child_struct *child, int handle, int level, const char *status)
368 int i = find_handle(child, handle);
372 fstat(ftable[i].fd, &st);
373 xattr_fd_read_hook(ftable[i].fd);
376 void nb_qfsinfo(struct child_struct *child, int level, const char *status)
383 statvfs(child->directory, &st);
386 void nb_findfirst(struct child_struct *child, char *fname, int level, int maxcnt,
387 int count, const char *status)
400 if (strpbrk(fname, "<>*?\"") == NULL) {
404 p = strrchr(fname, '/');
407 dir = opendir(fname);
409 while (maxcnt && (d = readdir(dir))) maxcnt--;
413 void nb_cleanup(struct child_struct *child)
417 asprintf(&dname, "%s/clients/client%d", child->directory, child->id);
418 nb_deltree(child, dname);
421 asprintf(&dname, "%s%s", child->directory, "/clients");
426 void nb_deltree(struct child_struct *child, char *dname)
430 asprintf(&path, "/bin/rm -rf %s", dname);
435 void nb_sfileinfo(struct child_struct *child, int handle, int level, const char *status)
437 int i = find_handle(child, handle);
444 xattr_fd_read_hook(ftable[i].fd);
446 fstat(ftable[i].fd, &st);
448 tm.actime = st.st_atime - 10;
449 tm.modtime = st.st_mtime - 12;
451 utime(ftable[i].name, &tm);
453 if (!S_ISDIR(st.st_mode)) {
454 xattr_fd_write_hook(ftable[i].fd);
458 void nb_lockx(struct child_struct *child, int handle, uint32_t offset, int size,
461 int i = find_handle(child, handle);
467 lock.l_type = F_WRLCK;
468 lock.l_whence = SEEK_SET;
469 lock.l_start = offset;
473 fcntl(ftable[i].fd, F_SETLKW, &lock);
476 void nb_unlockx(struct child_struct *child,
477 int handle, uint32_t offset, int size, const char *status)
479 int i = find_handle(child, handle);
485 lock.l_type = F_UNLCK;
486 lock.l_whence = SEEK_SET;
487 lock.l_start = offset;
491 fcntl(ftable[i].fd, F_SETLKW, &lock);
494 void nb_sleep(struct child_struct *child, int usec, const char *status)