Пример #1
0
//XXX:carefull, the dentry type is not supported by all fs
static void dir_parse(i parent_fd)
{
  ++depth;
  u8 dirents[DIRENTS_BUF_SZ];
  while(1){
    l r=getdents64(parent_fd,dirents,DIRENTS_BUF_SZ);
    if(ISERR(r)){
      PERR("ERROR(%ld):getdents error\n",r);
      exit(-1);
    }
    if(!r) break;
    l j=0;
    while(j<r){
      struct dirent64 *d=(struct dirent64*)(dirents+j);

      dout(d);

      if(d->type==DT_DIR&&!is_current(d->name)&&!is_parent(d->name)){
        i dir_fd;
        do
          dir_fd=(i)openat(parent_fd,d->name,RDONLY|NONBLOCK);
        while(dir_fd==-EINTR);
        if(ISERR(dir_fd))
          PERR("ERROR(%d):unable to open subdir:%s\n",dir_fd,d->name);
        else{
          dir_parse(dir_fd);
          l r1;
          do r1=close(dir_fd); while(r1==-EINTR);
        }
      }
      j+=d->rec_len;
    }
  }
  depth--;
}
Пример #2
0
struct dirent64* readdir64(DIR *d) {
  if (!d->num || (d->cur += ((struct dirent64*)(d->buf+d->cur))->d_reclen)>=d->num) {
    int res=getdents64(d->fd,(struct dirent64*)d->buf, sizeof (d->buf)-1);
    if (res<=0) return 0;
    d->num=res; d->cur=0;
  }
  return (struct dirent64*)(d->buf+d->cur);
}
Пример #3
0
int main(int ac, char **av)
{
	int lc;
	char *msg;
	int rval, fd;
	struct linux_dirent64 dir64;
	struct linux_dirent dir;

	if ((msg = parse_opts(ac, av, options, &help)) != NULL)
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);

	setup();

	for (lc = 0; TEST_LOOPING(lc); lc++) {
		tst_count = 0;

		if ((fd = open("test", O_CREAT | O_RDWR, 0777)) == -1)
			tst_brkm(TBROK | TERRNO, cleanup,
				 "open of file failed");

		if (longsyscall)
			rval = getdents64(fd, &dir64, sizeof(dir64));
		else
			rval = getdents(fd, &dir, sizeof(dir));

		/*
		 * Calling with a non directory file descriptor should give
		 * an ENOTDIR error.
		 */
		if (rval < 0) {
			TEST_ERROR_LOG(errno);

			switch (errno) {
			case ENOTDIR:
				tst_resm(TPASS,
					 "getdents failed as expected with ENOTDIR");
			break;
			case ENOSYS:
				tst_resm(TCONF, "syscall not implemented");
			break;
			break;
			default:
				tst_resm(TFAIL | TERRNO,
					 "getdents failed unexpectedly");
			break;
			}
		} else {
			tst_resm(TFAIL, "getdents call succeeded unexpectedly");
		}

		if (close(fd) == -1)
			tst_brkm(TBROK, cleanup, "fd close failed");
	}

	cleanup();
	tst_exit();
}
Пример #4
0
struct dirent64* readdir64(DIR *d) {
  struct linux_dirent64 *ld = d->num ? (struct linux_dirent64*)(d->buf+d->cur) : NULL;
  if (!d->num || (d->cur += ld->d_reclen)>=d->num) {
    int res=getdents64(d->fd,(struct linux_dirent64*)d->buf, __DIRSTREAM_BUF_SIZE-1);
    if (res<=0) return 0;
    d->num=res; d->cur=0; d->is_64=1;
  }
  /* \todo: ensure that dirent64 and linux_dirent64 are compatible */
  return (struct dirent64*)(d->buf+d->cur);
}
Пример #5
0
struct dirent64 *readdir64(DIR *dir){
	register struct dirent64 *this;
	this=((struct dirent64 *) (dir->buf + dir->bufpos));
	if (dir->bufsize == 0 || (dir->bufpos += this->d_reclen) >= dir->bufsize) {
		dir->bufsize = getdents64(dir->fd,(struct dirent64 *)dir->buf,PURE_DIRBUF_SIZE-1);
		if (dir->bufsize <= 0)
			return NULL;
		else
			dir->bufpos=0;
	}
	this=((struct dirent64 *) (dir->buf + dir->bufpos));
	return this;
}
Пример #6
0
static void test_ebadf(void)
{
	int fd = -5;
	struct linux_dirent64 dirp64;
	struct linux_dirent dirp;

	if (longsyscall)
		getdents64(fd, &dirp64, sizeof(dirp64));
	else
		getdents(fd, &dirp, sizeof(dirp));

	print_test_result(errno, EBADF);
}
Пример #7
0
/*
 * Support function:
 * Close all open file descriptors greater than or equal to lowfd.
 * This is executed in the child of vfork(), so we must not call
 * opendir() / readdir() because that would alter the parent's
 * address space.  We use the low-level getdents64() system call.
 * Return non-zero on error.
 */
static int
spawn_closefrom(int lowfd, void *buf)
{
	int procfd;
	int fd;
	int buflen;
	dirent64_t *dp;
	dirent64_t *dpend;

	if (lowfd <  0)
		lowfd = 0;

	/*
	 * Close lowfd right away as a hedge against failing
	 * to open the /proc file descriptor directory due
	 * all file descriptors being currently used up.
	 */
	(void) __close(lowfd++);

	if ((procfd = __open64("/proc/self/fd", O_RDONLY, 0)) < 0) {
		/*
		 * We could not open the /proc file descriptor directory.
		 * Just fail and be done with it.
		 */
		return (-1);
	}

	for (;;) {
		/*
		 * Collect a bunch of open file descriptors and close them.
		 * Repeat until the directory is exhausted.
		 */
		dp = (dirent64_t *)buf;
		if ((buflen = getdents64(procfd, dp, DIRBUF)) <= 0) {
			(void) __close(procfd);
			break;
		}
		dpend = (dirent64_t *)((uintptr_t)buf + buflen);
		do {
			/* skip '.', '..' and procfd */
			if (dp->d_name[0] != '.' &&
			    (fd = atoi(dp->d_name)) != procfd &&
			    fd >= lowfd)
				(void) __close(fd);
			dp = (dirent64_t *)((uintptr_t)dp + dp->d_reclen);
		} while (dp < dpend);
	}

	return (0);
}
Пример #8
0
static void test_enotdir(void)
{
	int fd;
	struct linux_dirent64 dir64;
	struct linux_dirent dir;

	fd = SAFE_OPEN(cleanup, "test", O_CREAT | O_RDWR);

	if (longsyscall)
		getdents64(fd, &dir64, sizeof(dir64));
	else
		getdents(fd, &dir, sizeof(dir));

	print_test_result(errno, ENOTDIR);

	SAFE_CLOSE(cleanup, fd);
}
Пример #9
0
static void test_einval(void)
{
	int fd;
	char buf[1];

	fd = SAFE_OPEN(cleanup, ".", O_RDONLY);

	/* Pass one byte long buffer. The result should be EINVAL */
	if (longsyscall)
		getdents64(fd, (void *)buf, sizeof(buf));
	else
		getdents(fd, (void *)buf, sizeof(buf));

	print_test_result(errno, EINVAL);

	SAFE_CLOSE(cleanup, fd);
}
Пример #10
0
struct dirent64* readdir64(DIR *d) {
#ifdef __NR_getdents64
  static int trygetdents64=1;
#endif
  static struct dirent64 d64;
#ifdef __NR_getdents64
again:
  if (!trygetdents64) {
#endif
    struct linux_dirent *ld = d->num ? (struct linux_dirent*)(d->buf+d->cur) : NULL;
    if (!d->num || (d->cur += ld->d_reclen)>=d->num) {
      int res=getdents(d->fd,(struct linux_dirent*)d->buf, __DIRSTREAM_BUF_SIZE-1);
      if (res<=0) return 0;
      d->num=res; d->cur=0;d->is_64=0;
      ld=(struct linux_dirent*)(d->buf+d->cur);
    }
    d64.d_ino=ld->d_ino;
    d64.d_off=ld->d_off;
    d64.d_reclen=ld->d_reclen;
    strcpy(d64.d_name,ld->d_name);
    d64.d_type=0;	/* is this correct? */
    return &d64;
#ifdef __NR_getdents64
  }
  {
  struct linux_dirent64 *ld = d->num ? (struct linux_dirent64*)(d->buf+d->cur) : NULL;
  if (!d->num || (d->cur += ld->d_reclen)>=d->num) {
    int res=getdents64(d->fd,(struct linux_dirent64*)d->buf,__DIRSTREAM_BUF_SIZE);
    if (res<=0) {
      if (errno==ENOSYS) {
	trygetdents64=0;
	goto again;
      }
      return 0;
    }
    d->num=res; d->cur=0; d->is_64=1;
  }
  }
  /* \todo: ensure that dirent64 and linux_dirent64 are compatible */
  return (struct dirent64*)(d->buf+d->cur);
#endif
}
Пример #11
0
struct dirent64* readdir64(DIR *d) {
#ifdef __NR_getdents64
  static int trygetdents64=1;
#endif
  struct dirent* o;
  static struct dirent64 d64;
#ifdef __NR_getdents64
again:
  if (!trygetdents64) {
#endif
    if (!d->num || (d->cur += ((struct dirent*)(d->buf+d->cur))->d_reclen)>=d->num) {
      int res=getdents(d->fd,(struct dirent*)d->buf, sizeof (d->buf)-1);
      if (res<=0) return 0;
      d->num=res; d->cur=0;
    }
    o=(struct dirent*)(d->buf+d->cur);
    d64.d_ino=o->d_ino;
    d64.d_off=o->d_off;
    d64.d_reclen=o->d_reclen;
    strcpy(d64.d_name,o->d_name);
    d64.d_type=0;	/* is this correct? */
    return &d64;
#ifdef __NR_getdents64
  }
  if (!d->num || (d->cur += ((struct dirent64*)(d->buf+d->cur))->d_reclen)>=d->num) {
    int res=getdents64(d->fd,(struct dirent64*)d->buf,sizeof (d->buf));
    if (res<=0) {
      if (errno==ENOSYS) {
	trygetdents64=0;
	goto again;
      }
      return 0;
    }
    d->num=res; d->cur=0;
  }
  return (struct dirent64*)(d->buf+d->cur);
#endif
}
Пример #12
0
static void test_enoent(void)
{
	int fd;
	struct linux_dirent64 dir64;
	struct linux_dirent dir;

	SAFE_MKDIR(cleanup, TEST_DIR, DIR_MODE);

	fd = SAFE_OPEN(cleanup, TEST_DIR, O_DIRECTORY);
	if (rmdir(TEST_DIR) == -1) {
		tst_brkm(TBROK | TERRNO, cleanup,
			 "rmdir(%s) failed", TEST_DIR);
	}

	if (longsyscall)
		getdents64(fd, &dir64, sizeof(dir64));
	else
		getdents(fd, &dir, sizeof(dir));

	print_test_result(errno, ENOENT);

	SAFE_CLOSE(cleanup, fd);
}
Пример #13
0
static struct direct64 *
internal_readdir(DIR *dirp)
{
	struct dirent64	*dp;	/* -> directory data */
	int saveloc = 0;

	if (dirp->dd_size != 0) {
		dp = (struct dirent64 *)&dirp->dd_buf[dirp->dd_loc];
		saveloc = dirp->dd_loc;   /* save for possible EOF */
		dirp->dd_loc += dp->d_reclen;
	}
	if (dirp->dd_loc >= dirp->dd_size)
		dirp->dd_loc = dirp->dd_size = 0;

	if (dirp->dd_size == 0 && 	/* refill buffer */
	    (dirp->dd_size = getdents64(dirp->dd_fd,
	    (struct dirent64 *)dirp->dd_buf, DIRBUF)) <= 0) {
		if (dirp->dd_size == 0)	/* This means EOF */
			dirp->dd_loc = saveloc;  /* EOF so save for telldir */
		return (NULL);	/* error or EOF */
	}

	dp = (struct dirent64 *)&dirp->dd_buf[dirp->dd_loc];

	/* Copy dirent into direct */
	dc64.d_ino = dp->d_ino;
	dc64.d_reclen = dp->d_reclen;
	dc64.d_namlen = (ushort_t)strlen(dp->d_name);
	if (dc64.d_namlen > MAXNAMLEN) {
		errno = ENAMETOOLONG;
		return (NULL);
	}
	(void) strcpy(dc64.d_name, dp->d_name);

	return (&dc64);
}
Пример #14
0
static int ftfs_recursive_delete(char * pathname)
{
    int fd, num, cnt;
    void * buf;
    struct dirent64 * dirp;
    char *full_name = kzalloc(PATH_MAX, GFP_KERNEL);

    if (!full_name)
	  return -ENOMEM;

    ftfs_log(__func__, "pathname = %s",pathname);
    fd = open(pathname, O_RDONLY, 0);
    if (fd < 0) {
	    ftfs_log(__func__, "open failed for recursive deletion %d",fd);
	    kfree(full_name);
	    return fd;
    }
    buf = kzalloc(BUF_SIZE, GFP_KERNEL);
    if (!buf) {
	    kfree(full_name);
	    close(fd);
	    return -ENOMEM;
    }
    dirp = buf;
    while (1) {
        num = getdents64(fd, (struct linux_dirent64 *)dirp, BUF_SIZE);
        if (num < 0) {
		kfree(buf);
		kfree(full_name);
		close(fd);
		ftfs_log(__func__, "getdents64 failed for recursive deletion %d",ftfs_get_errno());
		return 0-ftfs_get_errno(); //this looks weird but to keep consistent with getdents64 interface...
	} if (num == 0) {
		goto out;
	}
	cnt = num;
	while (cnt > 0) {
		struct stat st;
		int ret;
		char *name = dirp->d_name;
		if (strcmp(name,".") == 0)
			goto dot;
                if (strcmp(name, "..") == 0)
			goto dot;

		strcpy(full_name, pathname);
		strcat(full_name, "/");
		strcat(full_name, dirp->d_name);
		ret = ftfs_sys_newlstat(full_name, &st);

		WARN_ON_ONCE(ret);
		if (ret < 0) {
			ftfs_log(__func__, "newlstat failed for recursive deletion %d",ret);
			kfree(buf);
			kfree(full_name);
			close(fd);
			return ret;
		}

		if(S_ISDIR(st.st_mode)) {
			ftfs_recursive_delete(full_name);
		}
		else {
			#ifdef __TOKU_MISC_DEBUG
			ftfs_log(__func__, "going to delete file%s", full_name);
			#endif
			unlink(full_name);
		}
dot:

		cnt -= dirp->d_reclen;
		dirp = (void *) dirp + dirp->d_reclen;
	}

	dirp = buf;
	memset(dirp,0, BUF_SIZE);

    }

out:
    close(fd);
    kfree(buf);
    kfree(full_name);
   #ifdef __TOKU_MISC_DEBUG
    ftfs_log(__func__, "going to delete dir:%s", pathname);
   #endif
    rmdir(pathname);
    return 0;
}