MFS: getdents fixes
.Use a bigger buffer to hold results .Do not try to store more data than user buffer can hold
This commit is contained in:
		
							parent
							
								
									b6ea15115c
								
							
						
					
					
						commit
						fa9199e049
					
				| @ -11,7 +11,6 @@ | |||||||
| 				 * should be more or less the same as | 				 * should be more or less the same as | ||||||
| 				 * NR_VNODES in vfs | 				 * NR_VNODES in vfs | ||||||
| 				 */ | 				 */ | ||||||
| #define GETDENTS_BUFSIZ  257 |  | ||||||
| 
 | 
 | ||||||
| #define INODE_HASH_LOG2   7     /* 2 based logarithm of the inode hash size */ | #define INODE_HASH_LOG2   7     /* 2 based logarithm of the inode hash size */ | ||||||
| #define INODE_HASH_SIZE   ((unsigned long)1<<INODE_HASH_LOG2) | #define INODE_HASH_SIZE   ((unsigned long)1<<INODE_HASH_LOG2) | ||||||
|  | |||||||
| @ -17,7 +17,6 @@ static int rw_chunk(struct inode *rip, u64_t position, unsigned off, | |||||||
| 	size_t chunk, unsigned left, int rw_flag, cp_grant_id_t gid, unsigned | 	size_t chunk, unsigned left, int rw_flag, cp_grant_id_t gid, unsigned | ||||||
| 	buf_off, unsigned int block_size, int *completed); | 	buf_off, unsigned int block_size, int *completed); | ||||||
| 
 | 
 | ||||||
| static char getdents_buf[GETDENTS_BUFSIZ]; |  | ||||||
| 
 | 
 | ||||||
| /*===========================================================================*
 | /*===========================================================================*
 | ||||||
|  *				fs_readwrite				     * |  *				fs_readwrite				     * | ||||||
| @ -538,6 +537,9 @@ unsigned bytes_ahead;		/* bytes beyond position for immediate use */ | |||||||
|  *===========================================================================*/ |  *===========================================================================*/ | ||||||
| int fs_getdents(void) | int fs_getdents(void) | ||||||
| { | { | ||||||
|  | #define GETDENTS_BUFSIZE	(sizeof(struct dirent) + MFS_NAME_MAX + 1) | ||||||
|  | #define GETDENTS_ENTRIES	8 | ||||||
|  |   static char getdents_buf[GETDENTS_BUFSIZE * GETDENTS_ENTRIES]; | ||||||
|   register struct inode *rip; |   register struct inode *rip; | ||||||
|   int o, r, done; |   int o, r, done; | ||||||
|   unsigned int block_size, len, reclen; |   unsigned int block_size, len, reclen; | ||||||
| @ -569,7 +571,7 @@ int fs_getdents(void) | |||||||
|   done = FALSE;		/* Stop processing directory blocks when done is set */ |   done = FALSE;		/* Stop processing directory blocks when done is set */ | ||||||
| 
 | 
 | ||||||
|   tmpbuf_off = 0;	/* Offset in getdents_buf */ |   tmpbuf_off = 0;	/* Offset in getdents_buf */ | ||||||
|   memset(getdents_buf, '\0', GETDENTS_BUFSIZ);	/* Avoid leaking any data */ |   memset(getdents_buf, '\0', sizeof(getdents_buf));	/* Avoid leaking any data */ | ||||||
|   userbuf_off = 0;	/* Offset in the user's buffer */ |   userbuf_off = 0;	/* Offset in the user's buffer */ | ||||||
| 
 | 
 | ||||||
|   /* The default position for the next request is EOF. If the user's buffer
 |   /* The default position for the next request is EOF. If the user's buffer
 | ||||||
| @ -609,7 +611,19 @@ int fs_getdents(void) | |||||||
| 		  /* Need the position of this entry in the directory */ | 		  /* Need the position of this entry in the directory */ | ||||||
| 		  ent_pos = block_pos + ((char *) dp - (bp->b_data)); | 		  ent_pos = block_pos + ((char *) dp - (bp->b_data)); | ||||||
| 
 | 
 | ||||||
| 		  if(tmpbuf_off + reclen > GETDENTS_BUFSIZ) { | 		if (userbuf_off + tmpbuf_off + reclen >= size) { | ||||||
|  | 			  /* The user has no space for one more record */ | ||||||
|  | 			  done = TRUE; | ||||||
|  | 
 | ||||||
|  | 			  /* Record the position of this entry, it is the
 | ||||||
|  | 			   * starting point of the next request (unless the | ||||||
|  | 			   * postion is modified with lseek). | ||||||
|  | 			   */ | ||||||
|  | 			  new_pos = ent_pos; | ||||||
|  | 			  break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (tmpbuf_off + reclen >= GETDENTS_BUFSIZE*GETDENTS_ENTRIES) { | ||||||
| 			  r = sys_safecopyto(VFS_PROC_NR, gid, | 			  r = sys_safecopyto(VFS_PROC_NR, gid, | ||||||
| 			  		     (vir_bytes) userbuf_off,  | 			  		     (vir_bytes) userbuf_off,  | ||||||
| 					     (vir_bytes) getdents_buf, | 					     (vir_bytes) getdents_buf, | ||||||
| @ -623,18 +637,6 @@ int fs_getdents(void) | |||||||
| 			  tmpbuf_off = 0; | 			  tmpbuf_off = 0; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		  if(userbuf_off + tmpbuf_off + reclen > size) { |  | ||||||
| 			  /* The user has no space for one more record */ |  | ||||||
| 			  done = TRUE; |  | ||||||
| 			   |  | ||||||
| 			  /* Record the position of this entry, it is the
 |  | ||||||
| 			   * starting point of the next request (unless the |  | ||||||
| 			   * postion is modified with lseek). |  | ||||||
| 			   */ |  | ||||||
| 			  new_pos = ent_pos; |  | ||||||
| 			  break; |  | ||||||
| 		  } |  | ||||||
| 
 |  | ||||||
| 		dep = (struct dirent *) &getdents_buf[tmpbuf_off]; | 		dep = (struct dirent *) &getdents_buf[tmpbuf_off]; | ||||||
| 		dep->d_ino = dp->mfs_d_ino; | 		dep->d_ino = dp->mfs_d_ino; | ||||||
| 		dep->d_off = ent_pos; | 		dep->d_off = ent_pos; | ||||||
| @ -645,11 +647,11 @@ int fs_getdents(void) | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	put_block(bp, DIRECTORY_BLOCK); | 	put_block(bp, DIRECTORY_BLOCK); | ||||||
| 	  if(done) | 	if (done) | ||||||
| 		break; | 		break; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if(tmpbuf_off != 0) { |   if (tmpbuf_off != 0) { | ||||||
| 	r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) userbuf_off, | 	r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) userbuf_off, | ||||||
| 	  		     (vir_bytes) getdents_buf, (size_t) tmpbuf_off); | 	  		     (vir_bytes) getdents_buf, (size_t) tmpbuf_off); | ||||||
| 	if (r != OK) { | 	if (r != OK) { | ||||||
| @ -660,7 +662,7 @@ int fs_getdents(void) | |||||||
| 	userbuf_off += tmpbuf_off; | 	userbuf_off += tmpbuf_off; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if(done && userbuf_off == 0) |   if (done && userbuf_off == 0) | ||||||
| 	  r = EINVAL;		/* The user's buffer is too small */ | 	  r = EINVAL;		/* The user's buffer is too small */ | ||||||
|   else { |   else { | ||||||
| 	  fs_m_out.RES_NBYTES = userbuf_off; | 	  fs_m_out.RES_NBYTES = userbuf_off; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Thomas Veerman
						Thomas Veerman