Пример #1
0
/*Computes the size of the given directory*/
error_t node_get_size (node_t * dir, OFFSET_T * off)
{
  error_t err = 0;

  /*The final size */
  size_t size = 0;

  /*The number of directory entries */
  /*int count = 0; */

  /*The the node in the directory entries list from which we start counting */
  /*node_dirent_t * dirent_start = NULL; */

  /*The currently analyzed dirent */
  node_dirent_t *dirent_current = NULL;

  /*The pointer to the beginning of the list of dirents */
  node_dirent_t *dirent_list = NULL;

  /*The first entry we have to analyze */
  /*int first_entry = 2; */

  /*Takes into consideration the name of the current dirent */
  void bump_size (const char *name)
  {
    /*Increment the current size by the size of the current dirent */
    size += DIRENT_LEN (strlen (name));

    /*Count the current dirent */
    /*++count; */
  }				/*bump_size */
Пример #2
0
static error_t
_get_node_size (struct node *dir, OFFSET_T *off)
{
  size_t size = 0;
  error_t err;
  int count = 0;
  node_dirent_t *dirent_start, *dirent_current;
  node_dirent_t *dirent_list = NULL;
  int first_entry = 2;
  
  int bump_size (const char *name)
    {
      size_t new_size = size + DIRENT_LEN (strlen (name));
      
      size = new_size;
      count ++;
      return 1;
    }
Пример #3
0
/* Fetch a directory  */
error_t
netfs_get_dirents (struct iouser *cred, struct node *dir,
		 int first_entry, int max_entries, char **data,
		 mach_msg_type_number_t *data_len,
		 vm_size_t max_data_len, int *data_entries)
{
  error_t err = procfs_refresh_node (dir);
  struct procfs_dir_entry *dir_entry;

  if (! err)
    {
      if (dir->nn->dir) 
        {
          if (! procfs_dir_refresh (dir->nn->dir, dir == dir->nn->fs->root))
            {
              for (dir_entry = dir->nn->dir->ordered; first_entry > 0 &&
                  dir_entry; first_entry--,
                  dir_entry = dir_entry->ordered_next);
              if (! dir_entry )
                max_entries = 0;
                
              if (max_entries != 0)
                {  
                  size_t size = 0;
                  char *p;
                  int count = 0;

             
                  if (max_data_len == 0) 
                    size = DIRENTS_CHUNK_SIZE;
                  else if (max_data_len > DIRENTS_CHUNK_SIZE)
                    size = DIRENTS_CHUNK_SIZE;
                  else 
                    size = max_data_len;  
                
                  *data = mmap (0, size, PROT_READ|PROT_WRITE,
		            MAP_ANON, 0, 0);
		             
	          err = ((void *) *data == (void *) -1) ? errno : 0;
	       
	          if (! err)
	            {
	              p = *data;
	           
	              /* This gets all the actual entries present.  */

                      while ((max_entries == -1 || count < max_entries) && dir_entry)
                        {
                          struct dirent hdr;
                          size_t name_len = strlen (dir_entry->name);
                          size_t sz = DIRENT_LEN (name_len);
                          int entry_type = IFTODT (dir_entry->stat.st_mode);

                          if ((p - *data) + sz > size)
       		            {
		              if (max_data_len > 0)
		                break;
		              else   /* The Buffer Size must be increased. */
                                {
		                  vm_address_t extension = (vm_address_t)(*data + size);
		                  err = vm_allocate (mach_task_self (), &extension,
					 DIRENTS_CHUNK_SIZE, 0);
					 
		                  if (err)
			            break;
			           
		                  size += DIRENTS_CHUNK_SIZE;
		                }
		            }

	                  hdr.d_namlen = name_len;
                          hdr.d_fileno = dir_entry->stat.st_ino;
	                  hdr.d_reclen = sz;
	                  hdr.d_type = entry_type;

	                  memcpy (p, &hdr, DIRENT_NAME_OFFS);
	                  strcpy (p + DIRENT_NAME_OFFS, dir_entry->name);

	                  p += sz;

                          count++;
	                  dir_entry = dir_entry->ordered_next;
                        }
                        
                      if (err)
                        munmap (*data, size);
                      else
                        {
	                  vm_address_t alloc_end = (vm_address_t)(*data + size);
	                  vm_address_t real_end = round_page (p);
	                  if (alloc_end > real_end)
		            munmap ((caddr_t) real_end, alloc_end - real_end);
	                  *data_len = p - *data;
	                  *data_entries = count;
	                }  
	            }
                }
              else
                {
                  *data_len = 0;
                  *data_entries = 0;
                }
            }
        }
      else
        return ENOTDIR;          
    }      
    
  procfs_dir_entries_remove (dir->nn->dir);
  return err;
}		 
Пример #4
0
/*Reads the directory entries from `node`, which must be locked*/
error_t node_entries_get (node_t * node, node_dirent_t ** dirents)
{
  error_t err = 0;

  /*The list of dirents */
  struct dirent **dirent_list, **dirent;

  /*The head of the list of dirents */
  node_dirent_t *node_dirent_list = NULL;

  /*The size of the array of pointers to dirent */
  size_t dirent_data_size;

  /*The array of dirents */
  char *dirent_data;

  /*Obtain the directory entries for the given node */
  err = dir_entries_get
    (node->nn->port, &dirent_data, &dirent_data_size, &dirent_list);
  if (err)
    {
      return err;
    }

  /*The new entry in the list */
  node_dirent_t *node_dirent_new;

  /*The new dirent */
  struct dirent *dirent_new;

  /*LOG_MSG("node_entries_get: Getting entries for %p", node); */

  /*The name of the current dirent */
  char *name;

  /*The length of the current name */
  size_t name_len;

  /*The size of the current dirent */
  size_t size;

  /*Go through all elements of the list of pointers to dirent */
  for (dirent = dirent_list; *dirent; ++dirent)
    {
      /*obtain the name of the current dirent */
      name = &((*dirent)->d_name[0]);

      /*If the current dirent is either '.' or '..', skip it */
      if ((strcmp (name, ".") == 0) || (strcmp (name, "..") == 0))
	continue;

      /*obtain the length of the current name */
      name_len = strlen (name);

      /*obtain the length of the current dirent */
      size = DIRENT_LEN (name_len);

      /*create a new list element */
      node_dirent_new = malloc (sizeof (node_dirent_t));
      if (!node_dirent_new)
	{
	  err = ENOMEM;
	  break;
	}

      /*create a new dirent */
      dirent_new = malloc (size);
      if (!dirent_new)
	{
	  free (node_dirent_new);
	  err = ENOMEM;
	  break;
	}

      /*fill the dirent with information */
      dirent_new->d_ino = (*dirent)->d_ino;
      dirent_new->d_type = (*dirent)->d_type;
      dirent_new->d_reclen = size;
      strcpy ((char *) dirent_new + DIRENT_NAME_OFFS, name);

      /*add the dirent to the list */
      node_dirent_new->dirent = dirent_new;
      node_dirent_new->next = node_dirent_list;
      node_dirent_list = node_dirent_new;
    }

  /*If something went wrong in the loop */
  if (err)
    /*free the list of dirents */
    node_entries_free (node_dirent_list);
  else
    /*store the list of dirents in the second parameter */
    *dirents = node_dirent_list;

  /*Free the list of pointers to dirent */
  free (dirent_list);

  /*Free the results of listing the dirents */
  munmap (dirent_data, dirent_data_size);

  /*Return the result of operations */
  return err;
}				/*node_entries_get */
Пример #5
0
/* Fetch a directory, as for netfs_get_dirents.  */
static error_t
get_dirents (struct ftpfs_dir *dir,
	     int first_entry, int max_entries, char **data,
	     mach_msg_type_number_t *data_len,
	     vm_size_t max_data_len, int *data_entries)
{
  struct ftpfs_dir_entry *e;
  error_t err = 0;

  if (! dir)
    return ENOTDIR;

  e = dir->ordered;

  /* Find the first entry.  */
  while (first_entry-- > 0)
    if (! e)
      {
	max_entries = 0;
	break;
      }
    else
      e = e->ordered_next;

  if (max_entries != 0)
    {
      size_t size =
	(max_data_len == 0 || max_data_len > DIRENTS_CHUNK_SIZE
	 ? DIRENTS_CHUNK_SIZE
	 : max_data_len);

      *data = mmap (0, size, PROT_READ|PROT_WRITE,
				   MAP_ANON, 0, 0);
      err = ((void *) *data == (void *) -1) ? errno : 0;

      if (! err)
	{
	  char *p = *data;
	  int count = 0;

	  /* See how much space we need for the result.  */
	  while ((max_entries == -1 || count < max_entries) && e)
	    {
	      struct dirent hdr;
	      size_t name_len = strlen (e->name);
	      size_t sz = DIRENT_LEN (name_len);
	      int entry_type =
		e->stat_timestamp ? IFTODT (e->stat.st_mode) : DT_UNKNOWN;

	      if ((p - *data) + sz > size)
		{
		  if (max_data_len > 0)
		    break;
		  else
		    /* Try to grow our return buffer.  */
		    {
		      vm_address_t extension = (vm_address_t)(*data + size);
		      err = vm_allocate (mach_task_self (), &extension,
					 DIRENTS_CHUNK_SIZE, 0);
		      if (err)
			break;
		      size += DIRENTS_CHUNK_SIZE;
		    }
		}

	      hdr.d_namlen = name_len;
	      hdr.d_fileno = e->stat.st_ino;
	      hdr.d_reclen = sz;
	      hdr.d_type = entry_type;

	      memcpy (p, &hdr, DIRENT_NAME_OFFS);
	      strcpy (p + DIRENT_NAME_OFFS, e->name);
	      p += sz;

	      count++;
	      e = e->ordered_next;
	    }

	  if (err)
	    munmap (*data, size);
	  else
	    {
	      vm_address_t alloc_end = (vm_address_t)(*data + size);
	      vm_address_t real_end = round_page (p);
	      if (alloc_end > real_end)
		munmap ((caddr_t) real_end, alloc_end - real_end);
	      *data_len = p - *data;
	      *data_entries = count;
	    }
	}
    }
  else
    {
      *data_len = 0;
      *data_entries = 0;
    }

  return err;
}
Пример #6
0
/* Implement the netfs_get_directs callback as described in
   <hurd/netfs.h>. */
error_t
netfs_get_dirents (struct iouser *cred, struct node *dir,
		   int first_entry, int num_entries, char **data,
		   mach_msg_type_number_t *data_len,
		   vm_size_t max_data_len, int *data_entries)
{
  error_t err;
  int count;
  size_t size = 0;		/* Total size of our return block.  */
  struct hostmux_name *first_name, *nm;

  /* Add the length of a directory entry for NAME to SIZE and return true,
     unless it would overflow MAX_DATA_LEN or NUM_ENTRIES, in which case
     return false.  */
  int bump_size (const char *name)
    {
      if (num_entries == -1 || count < num_entries)
	{
	  size_t new_size = size + DIRENT_LEN (strlen (name));
	  if (max_data_len > 0 && new_size > max_data_len)
	    return 0;
	  size = new_size;
	  count++;
	  return 1;
	}
      else
	return 0;
    }

  if (dir->nn->name)
    return ENOTDIR;

  pthread_rwlock_rdlock (&dir->nn->mux->names_lock);

  /* Find the first entry.  */
  for (first_name = dir->nn->mux->names, count = 2;
       first_name && first_entry > count;
       first_name = first_name->next)
    if (first_name->node)
      count++;

  count = 0;

  /* Make space for the `.' and `..' entries.  */
  if (first_entry == 0)
    bump_size (".");
  if (first_entry <= 1)
    bump_size ("..");

  /* See how much space we need for the result.  */
  for (nm = first_name; nm; nm = nm->next)
    if (nm->node && !bump_size (nm->name))
      break;

  /* Allocate it.  */
  *data = mmap (0, size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
  err = ((void *) *data == (void *) -1) ? errno : 0;

  if (! err)
    /* Copy out the result.  */
    {
      char *p = *data;

      int add_dir_entry (const char *name, ino_t fileno, int type)
	{
	  if (num_entries == -1 || count < num_entries)
	    {
	      struct dirent hdr;
	      size_t name_len = strlen (name);
	      size_t sz = DIRENT_LEN (name_len);

	      if (sz > size)
		return 0;
	      else
		size -= sz;

	      hdr.d_fileno = fileno;
	      hdr.d_reclen = sz;
	      hdr.d_type = type;
	      hdr.d_namlen = name_len;

	      memcpy (p, &hdr, DIRENT_NAME_OFFS);
	      strcpy (p + DIRENT_NAME_OFFS, name);
	      p += sz;

	      count++;

	      return 1;
	    }
	  else
	    return 0;
	}

      *data_len = size;
      *data_entries = count;

      count = 0;

      /* Add `.' and `..' entries.  */
      if (first_entry == 0)
	add_dir_entry (".", 2, DT_DIR);
      if (first_entry <= 1)
	add_dir_entry ("..", 2, DT_DIR);

      /* Fill in the real directory entries.  */
      for (nm = first_name; nm; nm = nm->next)
	if (nm->node
	    && !add_dir_entry (nm->name, nm->fileno,
			       strcmp (nm->canon, nm->name) == 0
			         ? DT_REG : DT_LNK))
	  break;
    }
Пример #7
0
error_t
netfs_get_dirents (struct iouser *cred, struct node *dir,
		   int first_entry, int max_entries, char **data,
		   mach_msg_type_number_t *data_len,
		   vm_size_t max_data_len, int *data_entries)
{
  error_t err;
  int count = 0;
  char *data_p;
  size_t size = (max_data_len == 0 || max_data_len > DIRENTS_CHUNK_SIZE
     ? DIRENTS_CHUNK_SIZE : max_data_len);
  debug ("");
  int
    add_dirent (const char * name, ino_t ino, int type)
      {
	/*If the required number of dirents has not been listed yet*/
	if((max_entries == -1) || (count < max_entries))
	  {
	    struct dirent hdr;
	    size_t name_len = strlen(name);
	    size_t sz = DIRENT_LEN(name_len);

	    /*If there is no room for this dirent*/
	    if ((data_p - *data) + sz > size)
	      {
		if (max_data_len > 0)
		  return 1;
		else
		  /* Try to grow our return buffer.  */
		  {
		    error_t err;
		    vm_address_t extension = (vm_address_t)(*data + size);
		    err = vm_allocate (mach_task_self (), &extension,
				       DIRENTS_CHUNK_SIZE, 0);
		    if (err)
		      {
			munmap (*data, size);
			return 1;
		      }
		    size += DIRENTS_CHUNK_SIZE;
		  }
	      }

	    /*setup the dirent*/
	    hdr.d_ino = ino;
	    hdr.d_reclen = sz;
	    hdr.d_type = type;
	    hdr.d_namlen = name_len;
	    memcpy(data_p, &hdr, DIRENT_NAME_OFFS);
	    strcpy(data_p + DIRENT_NAME_OFFS, name);
	    data_p += sz;

	    /*count the new dirent*/
	    ++count;
	  }
	return 0;
      }
  int add_each_dev (struct vether_device *dev)
    {
      struct lnode *ln = (struct lnode *) dev;
      add_dirent (ln->vdev.name, ln->st.st_ino, DT_CHR);
      return 0;
    }
  if (dir != netfs_root_node)
    return ENOTDIR;

  *data = mmap (0, size, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0);
  err = ((void *) *data == (void *) -1) ? errno : 0;
  if (!err)
    {
      data_p = *data;
      if (first_entry < 2 + get_dev_num ())
	{
	  add_dirent (".", 2, DT_DIR);
	  add_dirent ("..", 2, DT_DIR);
	  foreach_dev_do (add_each_dev);
	}

      vm_address_t alloc_end = (vm_address_t)(*data + size);
      vm_address_t real_end = round_page (data_p);
      if (alloc_end > real_end)
	munmap ((caddr_t) real_end, alloc_end - real_end);
      *data_entries = count;
      debug ("first_entry is %d, count is %d", first_entry, count);
      *data_len = data_p - *data;
    }
  return err;
}