Example #1
0
File: nfs.c Project: UIKit0/unfs3
MKNOD3res *nfsproc3_mknod_3_svc(MKNOD3args * argp, struct svc_req * rqstp)
{
    static MKNOD3res result;
    char *path;
    pre_op_attr pre;
    post_op_attr post;
    char obj[NFS_MAXPATHLEN];
    int res;
    mode_t new_mode = 0;
    dev_t dev = 0;

    PREP(path, argp->where.dir);
    pre = get_pre_cached();
    result.status =
	join3(cat_name(path, argp->where.name, obj),
	      mknod_args(argp->what, obj, &new_mode, &dev), exports_rw());

    cluster_create(obj, rqstp, &result.status);

    if (result.status == NFS3_OK) {
	if (argp->what.type == NF3CHR || argp->what.type == NF3BLK)
	    res = backend_mknod(obj, new_mode, dev);	/* device */
	else if (argp->what.type == NF3FIFO)
	    res = backend_mkfifo(obj, new_mode);	/* FIFO */
	else
	    res = backend_mksocket(obj, new_mode);	/* socket */

	if (res == -1) {
	    result.status = mknod_err();
	} else {
	    result.MKNOD3res_u.resok.obj =
		fh_extend_type(argp->where.dir, obj,
			       type_to_mode(argp->what.type));
	    result.MKNOD3res_u.resok.obj_attributes = get_post_cached(rqstp);
	}
    }

    post = get_post_attr(path, argp->where.dir, rqstp);

    /* overlaps with resfail */
    result.MKNOD3res_u.resok.dir_wcc.before = pre;
    result.MKNOD3res_u.resok.dir_wcc.after = post;

    return &result;
}
Example #2
0
static void
process_dir (char *pathname, char *name, int pathlen, const struct stat *statp, char *parent)
{
  int subdirs_left;		/* Number of unexamined subdirs in PATHNAME. */
  bool subdirs_unreliable;	/* if true, cannot use dir link count as subdir limif (if false, it may STILL be unreliable) */
  struct stat stat_buf;
  size_t dircount = 0u;
  DIR *dirp;

  if (statp->st_nlink < 2)
    {
      subdirs_unreliable = true;
      subdirs_left = 0;
    }
  else
    {
      subdirs_unreliable = false; /* not necessarily right */
      subdirs_left = statp->st_nlink - 2; /* Account for name and ".". */
    }

  errno = 0;
  dirp = opendir_safer (name);

  if (dirp == NULL)
    {
      assert (errno != 0);
      error (0, errno, "%s", safely_quote_err_filename (0, pathname));
      state.exit_status = 1;
    }
  else
    {
      char *cur_path;		/* Full path of each file to process. */
      char *cur_name;		/* Base name of each file to process. */
      unsigned cur_path_size;	/* Bytes allocated for `cur_path'. */
      register unsigned file_len; /* Length of each path to process. */
      register unsigned pathname_len; /* PATHLEN plus trailing '/'. */
      bool did_stat = false;

      if (pathname[pathlen - 1] == '/')
	pathname_len = pathlen + 1; /* For '\0'; already have '/'. */
      else
	pathname_len = pathlen + 2; /* For '/' and '\0'. */
      cur_path_size = 0;
      cur_path = NULL;

      /* We're about to leave the directory.  If there are any
       * -execdir argument lists which have been built but have not
       * yet been processed, do them now because they must be done in
       * the same directory.
       */
      complete_pending_execdirs ();

      if (strcmp (name, "."))
	{
	  enum SafeChdirStatus status = safely_chdir (name, TraversingDown, &stat_buf, SymlinkHandleDefault, &did_stat);
	  switch (status)
	    {
	    case SafeChdirOK:
	      /* If there had been a change but wd_sanity_check()
	       * accepted it, we need to accept that on the
	       * way back up as well, so modify our record
	       * of what we think we should see later.
	       * If there was no change, the assignments are a no-op.
	       *
	       * However, before performing the assignment, we need to
	       * check that we have the stat information.   If O_NOFOLLOW
	       * is available, safely_chdir() will not have needed to use
	       * stat(), and so stat_buf will just contain random data.
	       */
	      if (!did_stat)
		{
		  /* If there is a link we need to follow it.  Hence
		   * the direct call to stat() not through (options.xstat)
		   */
		  set_stat_placeholders (&stat_buf);
		  if (0 != stat (".", &stat_buf))
		    break;	/* skip the assignment. */
		}
	      dir_ids[dir_curr].dev = stat_buf.st_dev;
	      dir_ids[dir_curr].ino = stat_buf.st_ino;

	      break;

	    case SafeChdirFailWouldBeUnableToReturn:
	      error (0, errno, ".");
	      state.exit_status = 1;
	      break;

	    case SafeChdirFailNonexistent:
	    case SafeChdirFailDestUnreadable:
	    case SafeChdirFailStat:
	    case SafeChdirFailNotDir:
	    case SafeChdirFailChdirFailed:
	      error (0, errno, "%s",
		     safely_quote_err_filename (0, pathname));
	      state.exit_status = 1;
	      return;

	    case SafeChdirFailSymlink:
	      error (0, 0,
		     _("warning: not following the symbolic link %s"),
		     safely_quote_err_filename (0, pathname));
	      state.exit_status = 1;
	      return;
	    }
	}

      while (1)
	{
	  const char *namep;
	  mode_t mode = 0;
	  const struct dirent *dp;

	  /* We reset errno here to distinguish between end-of-directory and an error */
	  errno = 0;
	  dp = readdir (dirp);
	  if (NULL == dp)
	    {
	      if (errno)
		{
		  /* an error occurred, but we are not yet at the end
		     of the directory stream. */
		  error (0, errno, "%s", safely_quote_err_filename (0, pathname));
		  continue;
		}
	      else
		{
		  break;	/* End of the directory stream. */
		}
	    }
	  else
	    {
	      namep = dp->d_name;
	      /* Skip "", ".", and "..".  "" is returned by at least one buggy
		 implementation: Solaris 2.4 readdir on NFS file systems.  */
	      if (!namep[0] ||
                  (namep[0] == '.' && (namep[1] == 0 ||
                                       (namep[1] == '.' && namep[2] == 0))))
		continue;
	    }

#if defined HAVE_STRUCT_DIRENT_D_TYPE
	  if (dp->d_type != DT_UNKNOWN)
	    mode = type_to_mode (dp->d_type);
#endif

	  /* Append this directory entry's name to the path being searched. */
	  file_len = pathname_len + strlen (namep);
	  if (file_len > cur_path_size)
	    {
	      while (file_len > cur_path_size)
		cur_path_size += 1024;
	      free (cur_path);
	      cur_path = xmalloc (cur_path_size);
	      strcpy (cur_path, pathname);
	      cur_path[pathname_len - 2] = '/';
	    }
	  cur_name = cur_path + pathname_len - 1;
	  strcpy (cur_name, namep);

	  state.curdepth++;
	  if (!options.no_leaf_check && !subdirs_unreliable)
	    {
	      if (mode && S_ISDIR(mode) && (subdirs_left == 0))
		{
		  /* This is a subdirectory, but the number of directories we
		   * have found now exceeds the number we would expect given
		   * the hard link count on the parent.   This is likely to be
		   * a bug in the file system driver (e.g. Linux's
		   * /proc file system) or may just be a fact that the OS
		   * doesn't really handle hard links with Unix semantics.
		   * In the latter case, -noleaf should be used routinely.
		   */
		  error (0, 0, _("WARNING: Hard link count is wrong for %s (saw only st_nlink=%" PRIuMAX  " but we already saw %" PRIuMAX " subdirectories): this may be a bug in your file system driver.  Automatically turning on find's -noleaf option.  Earlier results may have failed to include directories that should have been searched."),
			 safely_quote_err_filename(0, pathname),
			 (uintmax_t) statp->st_nlink,
			 (uintmax_t) dircount);
		  state.exit_status = 1; /* We know the result is wrong, now */
		  options.no_leaf_check = true;	/* Don't make same
						   mistake again */
		  subdirs_unreliable = 1;
		  subdirs_left = 1; /* band-aid for this iteration. */
		}

	      /* Normal case optimization.  On normal Unix
		 file systems, a directory that has no subdirectories
		 has two links: its name, and ".".  Any additional
		 links are to the ".." entries of its subdirectories.
		 Once we have processed as many subdirectories as
		 there are additional links, we know that the rest of
		 the entries are non-directories -- in other words,
		 leaf files. */
	      {
		int count;
		count = process_path (cur_path, cur_name,
				      subdirs_left == 0, pathname,
				      mode, D_INO(dp));
		subdirs_left -= count;
		dircount += count;
	      }
	    }
	  else
	    {
	      /* There might be weird (e.g., CD-ROM or MS-DOS) file systems
		 mounted, which don't have Unix-like directory link counts. */
	      process_path (cur_path, cur_name, false, pathname, mode,
			    D_INO(dp));
	    }

	  state.curdepth--;
	}


      /* We're about to leave the directory.  If there are any
       * -execdir argument lists which have been built but have not
       * yet been processed, do them now because they must be done in
       * the same directory.
       */
      complete_pending_execdirs ();

      if (strcmp (name, "."))
	{
	  enum SafeChdirStatus status;

	  /* We could go back and do the next command-line arg
	     instead, maybe using longjmp.  */
	  char const *dir;
	  bool deref = following_links () ? true : false;

	  if ( (state.curdepth>0) && !deref)
	    dir = "..";
	  else
	    {
	      chdir_back ();
	      dir = parent;
	    }

	  did_stat = false;
	  status = safely_chdir (dir, TraversingUp, &stat_buf, SymlinkHandleDefault, &did_stat);
	  switch (status)
	    {
	    case SafeChdirOK:
	      break;

	    case SafeChdirFailWouldBeUnableToReturn:
	      error (EXIT_FAILURE, errno, ".");
	      return;

	    case SafeChdirFailNonexistent:
	    case SafeChdirFailDestUnreadable:
	    case SafeChdirFailStat:
	    case SafeChdirFailSymlink:
	    case SafeChdirFailNotDir:
	    case SafeChdirFailChdirFailed:
	      error (EXIT_FAILURE, errno,
		     "%s", safely_quote_err_filename (0, pathname));
	      return;
	    }
	}

      free (cur_path);
      CLOSEDIR (dirp);
    }

  if (subdirs_unreliable)
    {
      /* Make sure we hasn't used the variable subdirs_left if we knew
       * we shouldn't do so.
       */
      assert (0 == subdirs_left || options.no_leaf_check);
    }
}
Example #3
0
static char *
old_savedirinfo (const char *dir, struct savedir_extrainfo **extra)
{
  DIR *dirp;
  struct dirent *dp;
  char *name_space;
  size_t namebuf_allocated = 0u, namebuf_used = 0u;
#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
  size_t extra_allocated = 0u, extra_used = 0u;
  struct savedir_extrainfo *info = NULL;
#endif
  int save_errno;

  if (extra)
    *extra = NULL;
  
  dirp = opendir (dir);
  if (dirp == NULL)
    return NULL;

  errno = 0;
  name_space = NULL;
  while ((dp = readdir (dirp)) != NULL)
    {
      /* Skip "", ".", and "..".  "" is returned by at least one buggy
         implementation: Solaris 2.4 readdir on NFS file systems.  */
      char const *entry = dp->d_name;
      if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
	{
	  /* Remember the name. */
	  size_t entry_size = strlen (entry) + 1;
	  name_space = extendbuf(name_space, namebuf_used+entry_size, &namebuf_allocated);
	  memcpy (name_space + namebuf_used, entry, entry_size);
	  namebuf_used += entry_size;


#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
	  /* Remember the type. */
	  if (extra)
	    {
	      info = extendbuf(info,
			       (extra_used+1) * sizeof(struct savedir_dirinfo),
			       &extra_allocated);
	      info[extra_used].type_info = type_to_mode(dp->d_type);
	      ++extra_used;
	    }
#endif
	}
    }
  
  name_space = extendbuf(name_space, namebuf_used+1, &namebuf_allocated);
  name_space[namebuf_used] = '\0';
  
  save_errno = errno;
  if (CLOSEDIR (dirp) != 0)
    save_errno = errno;
  if (save_errno != 0)
    {
      free (name_space);
      errno = save_errno;
      return NULL;
    }
  
#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
  if (extra && info)
    *extra = info;
#endif
  
  return name_space;
}
Example #4
0
struct savedir_dirinfo *
xsavedir(const char *dir, int flags)
{
  DIR *dirp;
  struct dirent *dp;
  struct savedir_dirinfo *result = NULL;
  struct new_savedir_direntry_internal *internal;
  
  size_t namebuf_allocated = 0u, namebuf_used = 0u;
  size_t entrybuf_allocated = 0u;
  int save_errno;

  dirp = opendir (dir);
  if (dirp == NULL)
    return NULL;

  errno = 0;
  result = xmalloc(sizeof(*result));
  result->buffer = NULL;
  result->size = 0u;
  result->entries = NULL;
  internal = NULL;
  
  while ((dp = readdir (dirp)) != NULL)
    {
      /* Skip "", ".", and "..".  "" is returned by at least one buggy
         implementation: Solaris 2.4 readdir on NFS file systems.  */
      char const *entry = dp->d_name;
      if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
	{
	  /* Remember the name. */
	  size_t entry_size = strlen (entry) + 1;
	  result->buffer = extendbuf(result->buffer, namebuf_used+entry_size, &namebuf_allocated);
	  memcpy ((result->buffer) + namebuf_used, entry, entry_size);
	  
	  /* Remember the other stuff. */
	  internal = extendbuf(internal, (1+result->size)*sizeof(*internal), &entrybuf_allocated);
	  internal[result->size].flags = 0;
	  
#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
	  internal[result->size].type_info = type_to_mode(dp->d_type);
	  if (dp->d_type != DT_UNKNOWN)
	    internal[result->size].flags |= SavedirHaveFileType;
#else
	  internal[result->size].type_info = 0;
#endif
	  internal[result->size].buffer_offset = namebuf_used;

	  /* Prepare for the next iteration */
	  ++(result->size);
	  namebuf_used += entry_size;
	}
    }
  
  result->buffer = extendbuf(result->buffer, namebuf_used+1, &namebuf_allocated);
  result->buffer[namebuf_used] = '\0';

  /* convert the result to its externally-usable form. */
  result->entries = convertentries(result, internal);
  free(internal);
  internal = NULL;


  if (flags & SavedirSort)
    {
      qsort(result->entries,
	    result->size, sizeof(*result->entries),
	    savedir_cmp);
    }
  

  save_errno = errno;
  if (CLOSEDIR (dirp) != 0)
    save_errno = errno;
  if (save_errno != 0)
    {
      free (result->buffer);
      free (result);
      errno = save_errno;
      return NULL;
    }

  return result;
}