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, do_fsync;
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) {
145 if (strncmp(status, "0x", 2) == 0 &&
146 strtoul(status, NULL, 16) == 0) {
153 simulate pvfs_resolve_name()
155 static void resolve_name(const char *name)
163 if (name == NULL) return;
165 if (stat(name, &st) == 0) {
166 xattr_fname_read_hook(name);
170 dname = strdup(name);
171 p = strrchr(dname, '/');
176 dir = opendir(dname);
181 while ((d = readdir(dir))) {
182 if (strcasecmp(fname, d->d_name) == 0) break;
188 static void failed(struct child_struct *child)
191 printf("ERROR: child %d failed\n", child->id);
195 void nb_setup(struct child_struct *child)
200 void nb_unlink(struct child_struct *child, char *fname, int attr, const char *status)
206 if (unlink(fname) != expected_status(status)) {
207 printf("(%d) unlink %s failed (%s) - expected %s\n",
208 child->line, fname, strerror(errno), status);
211 if (sync_dirs) sync_parent(fname);
214 void nb_mkdir(struct child_struct *child, char *dname, const char *status)
222 void nb_rmdir(struct child_struct *child, char *fname, const char *status)
226 if (rmdir(fname) != expected_status(status)) {
227 printf("(%d) rmdir %s failed (%s) - expected %s\n",
228 child->line, fname, strerror(errno), status);
231 if (sync_dirs) sync_parent(fname);
234 void nb_createx(struct child_struct *child, const char *fname,
235 uint32_t create_options, uint32_t create_disposition, int fnum,
244 if (sync_open) flags |= O_SYNC;
246 if (create_disposition == FILE_CREATE) {
250 if (create_disposition == FILE_OVERWRITE ||
251 create_disposition == FILE_OVERWRITE_IF) {
252 flags |= O_CREAT | O_TRUNC;
255 if (create_options & FILE_DIRECTORY_FILE) {
256 /* not strictly correct, but close enough */
260 if (create_options & FILE_DIRECTORY_FILE) flags = O_RDONLY|O_DIRECTORY;
262 fd = open(fname, flags, 0600);
263 if (fd == -1 && errno == EISDIR) {
264 flags = O_RDONLY|O_DIRECTORY;
265 fd = open(fname, flags, 0600);
268 if (expected_status(status) == 0) {
269 printf("(%d) open %s failed for handle %d (%s)\n",
270 child->line, fname, fnum, strerror(errno));
274 if (expected_status(status) != 0) {
275 printf("(%d) open %s succeeded for handle %d\n",
276 child->line, fname, fnum);
281 for (i=0;i<MAX_FILES;i++) {
282 if (ftable[i].handle == 0) break;
284 if (i == MAX_FILES) {
285 printf("file table full for %s\n", fname);
288 ftable[i].name = strdup(fname);
289 ftable[i].handle = fnum;
294 if (!S_ISDIR(st.st_mode)) {
295 xattr_fd_write_hook(fd);
299 void nb_writex(struct child_struct *child, int handle, int offset,
300 int size, int ret_size, const char *status)
302 int i = find_handle(child, handle);
308 buf = calloc(size, 1);
310 if (size == 1 && fstat(ftable[i].fd, &st) == 0) {
311 if (st.st_size > offset) {
313 pread(ftable[i].fd, &c, 1, offset);
314 if (c == ((unsigned char *)buf)[0]) {
316 child->bytes += size;
319 } else if (((unsigned char *)buf)[0] == 0) {
320 ftruncate(ftable[i].fd, offset+1);
322 child->bytes += size;
327 if (pwrite(ftable[i].fd, buf, size, offset) != ret_size) {
328 printf("write failed on handle %d (%s)\n", handle, strerror(errno));
332 if (do_fsync) fsync(ftable[i].fd);
336 child->bytes += size;
339 void nb_readx(struct child_struct *child, int handle, int offset,
340 int size, int ret_size, const char *status)
342 int i = find_handle(child, handle);
349 if (pread(ftable[i].fd, buf, size, offset) != ret_size) {
350 printf("read failed on handle %d (%s)\n", handle, strerror(errno));
355 child->bytes += size;
358 void nb_close(struct child_struct *child, int handle, const char *status)
360 int i = find_handle(child, handle);
363 ftable[i].handle = 0;
364 if (ftable[i].name) free(ftable[i].name);
365 ftable[i].name = NULL;
368 void nb_rename(struct child_struct *child, char *old, char *new, const char *status)
373 if (rename(old, new) != expected_status(status)) {
374 printf("rename %s %s failed (%s) - expected %s\n",
375 old, new, strerror(errno), status);
378 if (sync_dirs) sync_parent(new);
381 void nb_flush(struct child_struct *child, int handle, const char *status)
384 find_handle(child, handle);
388 void nb_qpathinfo(struct child_struct *child, const char *fname, int level,
397 void nb_qfileinfo(struct child_struct *child, int handle, int level, const char *status)
400 int i = find_handle(child, handle);
404 fstat(ftable[i].fd, &st);
405 xattr_fd_read_hook(ftable[i].fd);
408 void nb_qfsinfo(struct child_struct *child, int level, const char *status)
415 statvfs(child->directory, &st);
418 void nb_findfirst(struct child_struct *child, char *fname, int level, int maxcnt,
419 int count, const char *status)
432 if (strpbrk(fname, "<>*?\"") == NULL) {
436 p = strrchr(fname, '/');
439 dir = opendir(fname);
441 while (maxcnt && (d = readdir(dir))) maxcnt--;
445 void nb_cleanup(struct child_struct *child)
449 asprintf(&dname, "%s/clients/client%d", child->directory, child->id);
450 nb_deltree(child, dname);
453 asprintf(&dname, "%s%s", child->directory, "/clients");
458 void nb_deltree(struct child_struct *child, char *dname)
462 asprintf(&path, "/bin/rm -rf %s", dname);
467 void nb_sfileinfo(struct child_struct *child, int handle, int level, const char *status)
469 int i = find_handle(child, handle);
476 xattr_fd_read_hook(ftable[i].fd);
478 fstat(ftable[i].fd, &st);
480 tm.actime = st.st_atime - 10;
481 tm.modtime = st.st_mtime - 12;
483 utime(ftable[i].name, &tm);
485 if (!S_ISDIR(st.st_mode)) {
486 xattr_fd_write_hook(ftable[i].fd);
490 void nb_lockx(struct child_struct *child, int handle, uint32_t offset, int size,
493 int i = find_handle(child, handle);
499 lock.l_type = F_WRLCK;
500 lock.l_whence = SEEK_SET;
501 lock.l_start = offset;
505 fcntl(ftable[i].fd, F_SETLKW, &lock);
508 void nb_unlockx(struct child_struct *child,
509 int handle, uint32_t offset, int size, const char *status)
511 int i = find_handle(child, handle);
517 lock.l_type = F_UNLCK;
518 lock.l_whence = SEEK_SET;
519 lock.l_start = offset;
523 fcntl(ftable[i].fd, F_SETLKW, &lock);
526 void nb_sleep(struct child_struct *child, int usec, const char *status)