4 Copyright (C) 1999-2007 by Andrew Tridgell <tridge@samba.org>
5 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
31 static int find_handle(struct child_struct *child, int handle)
33 struct ftable *ftable = child->private;
35 for (i=0;i<MAX_FILES;i++) {
36 if (ftable[i].handle == handle) return i;
38 printf("(%d) ERROR: handle %d was not found\n",
44 /* Find the directory holding a file, and flush it to disk. We do
45 this in -S mode after a directory-modifying mode, to simulate the
46 way knfsd tries to flush directories. MKDIR and similar operations
47 are meant to be synchronous on NFSv2. */
48 static void sync_parent(const char *fname)
54 if (strchr(fname, '/')) {
55 copy_name = strdup(fname);
56 slash = strrchr(copy_name, '/');
59 copy_name = strdup(".");
62 dir_fd = open(copy_name, O_RDONLY);
64 printf("open directory \"%s\" for sync failed: %s\n",
68 #if defined(HAVE_FDATASYNC)
69 if (fdatasync(dir_fd) == -1) {
71 if (fsync(dir_fd) == -1) {
73 printf("datasync directory \"%s\" failed: %s\n",
77 if (close(dir_fd) == -1) {
78 printf("close directory failed: %s\n",
85 static void xattr_fd_read_hook(int fd)
89 if (options.ea_enable) {
90 memset(buf, 0, sizeof(buf));
91 sys_fgetxattr(fd, "user.DosAttrib", buf, sizeof(buf));
98 static void xattr_fname_read_hook(const char *fname)
101 if (options.ea_enable) {
103 sys_getxattr(fname, "user.DosAttrib", buf, sizeof(buf));
110 static void xattr_fd_write_hook(int fd)
113 if (options.ea_enable) {
116 sys_fgetxattr(fd, "user.DosAttrib", buf, sizeof(buf));
117 memset(buf, 0, sizeof(buf));
118 /* give some probability of sharing */
119 if (random() % 10 < 2) {
120 *(time_t *)buf = time(NULL);
122 gettimeofday(&tv, NULL);
123 memcpy(buf, &tv, sizeof(tv));
125 if (sys_fsetxattr(fd, "user.DosAttrib", buf, sizeof(buf), 0) != 0) {
126 printf("fsetxattr failed - %s\n", strerror(errno));
135 static int expected_status(const char *status)
137 if (strcmp(status, "NT_STATUS_OK") == 0) {
140 if (strncmp(status, "0x", 2) == 0 &&
141 strtoul(status, NULL, 16) == 0) {
148 simulate pvfs_resolve_name()
150 static void resolve_name(const char *name)
158 if (name == NULL) return;
160 if (stat(name, &st) == 0) {
161 xattr_fname_read_hook(name);
165 dname = strdup(name);
166 p = strrchr(dname, '/');
171 dir = opendir(dname);
176 while ((d = readdir(dir))) {
177 if (strcasecmp(fname, d->d_name) == 0) break;
183 static void failed(struct child_struct *child)
186 printf("ERROR: child %d failed\n", child->id);
190 void nb_setup(struct child_struct *child)
192 struct ftable *ftable;
193 ftable = calloc(MAX_FILES, sizeof(struct ftable));
194 child->private = ftable;
195 child->rate.last_time = timeval_current();
196 child->rate.last_bytes = 0;
199 void nb_unlink(struct child_struct *child, const char *fname, int attr, const char *status)
205 if (unlink(fname) != expected_status(status)) {
206 printf("(%d) unlink %s failed (%s) - expected %s\n",
207 child->line, fname, strerror(errno), status);
210 if (options.sync_dirs) sync_parent(fname);
213 void nb_mkdir(struct child_struct *child, const char *dname, const char *status)
221 void nb_rmdir(struct child_struct *child, const char *fname, const char *status)
225 if (rmdir(fname) != expected_status(status)) {
226 printf("(%d) rmdir %s failed (%s) - expected %s\n",
227 child->line, fname, strerror(errno), status);
230 if (options.sync_dirs) sync_parent(fname);
233 void nb_createx(struct child_struct *child, const char *fname,
234 uint32_t create_options, uint32_t create_disposition, int fnum,
240 struct ftable *ftable = (struct ftable *)child->private;
244 if (options.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);
305 struct ftable *ftable = (struct ftable *)child->private;
309 buf = calloc(size, 1);
311 if (size == 1 && fstat(ftable[i].fd, &st) == 0) {
312 if (st.st_size > offset) {
314 pread(ftable[i].fd, &c, 1, offset);
315 if (c == ((unsigned char *)buf)[0]) {
317 child->bytes += size;
320 } else if (((unsigned char *)buf)[0] == 0) {
321 ftruncate(ftable[i].fd, offset+1);
323 child->bytes += size;
328 if (pwrite(ftable[i].fd, buf, size, offset) != ret_size) {
329 printf("write failed on handle %d (%s)\n", handle, strerror(errno));
333 if (options.do_fsync) fsync(ftable[i].fd);
337 child->bytes += size;
338 child->bytes_since_fsync += size;
341 void nb_readx(struct child_struct *child, int handle, int offset,
342 int size, int ret_size, const char *status)
344 int i = find_handle(child, handle);
346 struct ftable *ftable = (struct ftable *)child->private;
352 if (pread(ftable[i].fd, buf, size, offset) != ret_size) {
353 printf("read failed on handle %d (%s)\n", handle, strerror(errno));
358 child->bytes += size;
361 void nb_close(struct child_struct *child, int handle, const char *status)
363 struct ftable *ftable = (struct ftable *)child->private;
364 int i = find_handle(child, handle);
367 ftable[i].handle = 0;
368 if (ftable[i].name) free(ftable[i].name);
369 ftable[i].name = NULL;
372 void nb_rename(struct child_struct *child, const char *old, const char *new, const char *status)
377 if (rename(old, new) != expected_status(status)) {
378 printf("rename %s %s failed (%s) - expected %s\n",
379 old, new, strerror(errno), status);
382 if (options.sync_dirs) sync_parent(new);
385 void nb_flush(struct child_struct *child, int handle, const char *status)
387 struct ftable *ftable = (struct ftable *)child->private;
388 int i = find_handle(child, handle);
393 void nb_qpathinfo(struct child_struct *child, const char *fname, int level,
402 void nb_qfileinfo(struct child_struct *child, int handle, int level, const char *status)
404 struct ftable *ftable = (struct ftable *)child->private;
406 int i = find_handle(child, handle);
410 fstat(ftable[i].fd, &st);
411 xattr_fd_read_hook(ftable[i].fd);
414 void nb_qfsinfo(struct child_struct *child, int level, const char *status)
421 statvfs(child->directory, &st);
424 void nb_findfirst(struct child_struct *child, const char *fname, int level, int maxcnt,
425 int count, const char *status)
438 if (strpbrk(fname, "<>*?\"") == NULL) {
442 p = strrchr(fname, '/');
445 dir = opendir(fname);
447 while (maxcnt && (d = readdir(dir))) maxcnt--;
451 void nb_cleanup(struct child_struct *child)
455 asprintf(&dname, "%s/clients/client%d", child->directory, child->id);
456 nb_deltree(child, dname);
459 asprintf(&dname, "%s%s", child->directory, "/clients");
464 void nb_deltree(struct child_struct *child, const char *dname)
468 asprintf(&path, "/bin/rm -rf %s", dname);
473 void nb_sfileinfo(struct child_struct *child, int handle, int level, const char *status)
475 struct ftable *ftable = (struct ftable *)child->private;
476 int i = find_handle(child, handle);
483 xattr_fd_read_hook(ftable[i].fd);
485 fstat(ftable[i].fd, &st);
487 tm.actime = st.st_atime - 10;
488 tm.modtime = st.st_mtime - 12;
490 utime(ftable[i].name, &tm);
492 if (!S_ISDIR(st.st_mode)) {
493 xattr_fd_write_hook(ftable[i].fd);
497 void nb_lockx(struct child_struct *child, int handle, uint32_t offset, int size,
500 struct ftable *ftable = (struct ftable *)child->private;
501 int i = find_handle(child, handle);
507 lock.l_type = F_WRLCK;
508 lock.l_whence = SEEK_SET;
509 lock.l_start = offset;
513 fcntl(ftable[i].fd, F_SETLKW, &lock);
516 void nb_unlockx(struct child_struct *child,
517 int handle, uint32_t offset, int size, const char *status)
519 struct ftable *ftable = (struct ftable *)child->private;
520 int i = find_handle(child, handle);
526 lock.l_type = F_UNLCK;
527 lock.l_whence = SEEK_SET;
528 lock.l_start = offset;
532 fcntl(ftable[i].fd, F_SETLKW, &lock);
535 void nb_sleep(struct child_struct *child, int usec, const char *status)