 22840dea11
			
		
	
	
		22840dea11
		
	
	
	
	
		
			
			The stat.st_ino field must always be filled with the inode number given as part of the fdr_stat request anyway, so libfsdriver can simply fill in the number and allow the file system not to bother. Change-Id: Ia7a849d0b23dfc83010df0d48fa26e4225427694
		
			
				
	
	
		
			177 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* This file contains file metadata retrieval and manipulation routines.
 | |
|  *
 | |
|  * The entry points into this file are:
 | |
|  *   get_mode		return a file's mode
 | |
|  *   do_stat		perform the STAT file system call
 | |
|  *   do_chmod		perform the CHMOD file system call
 | |
|  *   do_utime		perform the UTIME file system call
 | |
|  *
 | |
|  * Created:
 | |
|  *   April 2009 (D.C. van Moolenbroek)
 | |
|  */
 | |
| 
 | |
| #include "inc.h"
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				get_mode				     *
 | |
|  *===========================================================================*/
 | |
| mode_t get_mode(struct inode *ino, int mode)
 | |
| {
 | |
| /* Return the mode for an inode, given the inode and the retrieved mode.
 | |
|  */
 | |
| 
 | |
|   mode &= S_IRWXU;
 | |
|   mode = mode | (mode >> 3) | (mode >> 6);
 | |
| 
 | |
|   if (IS_DIR(ino))
 | |
| 	mode = S_IFDIR | (mode & sffs_params->p_dir_mask);
 | |
|   else
 | |
| 	mode = S_IFREG | (mode & sffs_params->p_file_mask);
 | |
| 
 | |
|   if (read_only)
 | |
| 	mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
 | |
| 
 | |
|   return mode;
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				do_stat					     *
 | |
|  *===========================================================================*/
 | |
| int do_stat(ino_t ino_nr, struct stat *stat)
 | |
| {
 | |
| /* Retrieve inode status.
 | |
|  */
 | |
|   struct inode *ino;
 | |
|   struct sffs_attr attr;
 | |
|   char path[PATH_MAX];
 | |
|   int r;
 | |
| 
 | |
|   /* Don't increase the inode refcount: it's already open anyway */
 | |
|   if ((ino = find_inode(ino_nr)) == NULL)
 | |
| 	return EINVAL;
 | |
| 
 | |
|   attr.a_mask = SFFS_ATTR_MODE | SFFS_ATTR_SIZE | SFFS_ATTR_CRTIME |
 | |
| 		SFFS_ATTR_ATIME | SFFS_ATTR_MTIME | SFFS_ATTR_CTIME;
 | |
| 
 | |
|   if ((r = verify_inode(ino, path, &attr)) != OK)
 | |
| 	return r;
 | |
| 
 | |
|   stat->st_mode = get_mode(ino, attr.a_mode);
 | |
|   stat->st_uid = sffs_params->p_uid;
 | |
|   stat->st_gid = sffs_params->p_gid;
 | |
|   stat->st_rdev = NO_DEV;
 | |
|   stat->st_size = attr.a_size;
 | |
|   stat->st_atimespec = attr.a_atime;
 | |
|   stat->st_mtimespec = attr.a_mtime;
 | |
|   stat->st_ctimespec = attr.a_ctime;
 | |
|   stat->st_birthtimespec = attr.a_crtime;
 | |
| 
 | |
|   stat->st_blocks = stat->st_size / S_BLKSIZE;
 | |
|   if (stat->st_size % S_BLKSIZE != 0)
 | |
| 	stat->st_blocks += 1;
 | |
| 
 | |
|   stat->st_blksize = BLOCK_SIZE;
 | |
| 
 | |
|   /* We could make this more accurate by iterating over directory inodes'
 | |
|    * children, counting how many of those are directories as well.
 | |
|    * It's just not worth it.
 | |
|    */
 | |
|   stat->st_nlink = 0;
 | |
|   if (ino->i_parent != NULL) stat->st_nlink++;
 | |
|   if (IS_DIR(ino)) {
 | |
| 	stat->st_nlink++;
 | |
| 	if (HAS_CHILDREN(ino)) stat->st_nlink++;
 | |
|   }
 | |
| 
 | |
|   return OK;
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				do_chmod				     *
 | |
|  *===========================================================================*/
 | |
| int do_chmod(ino_t ino_nr, mode_t *mode)
 | |
| {
 | |
| /* Change file mode.
 | |
|  */
 | |
|   struct inode *ino;
 | |
|   char path[PATH_MAX];
 | |
|   struct sffs_attr attr;
 | |
|   int r;
 | |
| 
 | |
|   if (read_only)
 | |
| 	return EROFS;
 | |
| 
 | |
|   if ((ino = find_inode(ino_nr)) == NULL)
 | |
| 	return EINVAL;
 | |
| 
 | |
|   if ((r = verify_inode(ino, path, NULL)) != OK)
 | |
| 	return r;
 | |
| 
 | |
|   /* Set the new file mode. */
 | |
|   attr.a_mask = SFFS_ATTR_MODE;
 | |
|   attr.a_mode = *mode; /* no need to convert in this direction */
 | |
| 
 | |
|   if ((r = sffs_table->t_setattr(path, &attr)) != OK)
 | |
| 	return r;
 | |
| 
 | |
|   /* We have no idea what really happened. Query for the mode again. */
 | |
|   if ((r = verify_path(path, ino, &attr, NULL)) != OK)
 | |
| 	return r;
 | |
| 
 | |
|   *mode = get_mode(ino, attr.a_mode);
 | |
| 
 | |
|   return OK;
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				do_utime				     *
 | |
|  *===========================================================================*/
 | |
| int do_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime)
 | |
| {
 | |
| /* Set file times.
 | |
|  */
 | |
|   struct inode *ino;
 | |
|   char path[PATH_MAX];
 | |
|   struct sffs_attr attr;
 | |
|   int r;
 | |
| 
 | |
|   if (read_only)
 | |
| 	return EROFS;
 | |
| 
 | |
|   if ((ino = find_inode(ino_nr)) == NULL)
 | |
| 	return EINVAL;
 | |
| 
 | |
|   if ((r = verify_inode(ino, path, NULL)) != OK)
 | |
| 	return r;
 | |
| 
 | |
|   attr.a_mask = 0;
 | |
| 
 | |
|   switch (atime->tv_nsec) {
 | |
|   case UTIME_OMIT: /* do not touch */
 | |
| 	break;
 | |
|   case UTIME_NOW:
 | |
| 	/* XXX VFS should have time() into ACTIME, for compat; we trust it! */
 | |
| 	atime->tv_nsec = 0;
 | |
| 	/*FALLTHROUGH*/
 | |
|   default:
 | |
| 	attr.a_atime = *atime;
 | |
| 	attr.a_mask |= SFFS_ATTR_ATIME;
 | |
| 	break;
 | |
|   }
 | |
| 
 | |
|   switch (mtime->tv_nsec) {
 | |
|   case UTIME_OMIT: /* do not touch */
 | |
| 	break;
 | |
|   case UTIME_NOW:
 | |
| 	/* XXX VFS should have time() into MODTIME, for compat; we trust it! */
 | |
| 	mtime->tv_nsec = 0;
 | |
| 	/*FALLTHROUGH*/
 | |
|   default:
 | |
| 	attr.a_mtime = *mtime;
 | |
| 	attr.a_mask |= SFFS_ATTR_MTIME;
 | |
| 	break;
 | |
|   }
 | |
| 
 | |
|   return sffs_table->t_setattr(path, &attr);
 | |
| }
 |