patch-2.4.6 linux/fs/udf/dir.c

Next file: linux/fs/udf/directory.c
Previous file: linux/fs/udf/crc.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.5/linux/fs/udf/dir.c linux/fs/udf/dir.c
@@ -7,7 +7,7 @@
  * CONTACTS
  *	E-mail regarding any portion of the Linux UDF file system should be
  *	directed to the development team mailing list (run by majordomo):
- *		linux_udf@hootie.lvld.hp.com
+ *		linux_udf@hpesjro.fc.hp.com
  *
  * COPYRIGHT
  *	This file is distributed under the terms of the GNU General Public
@@ -49,10 +49,10 @@
 /* readdir and lookup functions */
 
 struct file_operations udf_dir_operations = {
-	read:				generic_read_dir,
-	readdir:			udf_readdir,
-	ioctl:				udf_ioctl,
-	fsync:				udf_sync_file,
+	read:			generic_read_dir,
+	readdir:		udf_readdir,
+	ioctl:			udf_ioctl,
+	fsync:			udf_fsync_file,
 };
 
 /*
@@ -88,8 +88,9 @@
 
 	if ( filp->f_pos == 0 ) 
 	{
-		if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR))
+		if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0)
 			return 0;
+		filp->f_pos ++;
 	}
  
 	result = do_udf_readdir(dir, filp, filldir, dirent);
@@ -104,19 +105,21 @@
 	struct FileIdentDesc *fi=NULL;
 	struct FileIdentDesc cfi;
 	int block, iblock;
-	loff_t nf_pos = filp->f_pos;
+	loff_t nf_pos = filp->f_pos - 1;
 	int flen;
 	char fname[255];
 	char *nameptr;
 	Uint16 liu;
 	Uint8 lfi;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
-	struct buffer_head * bh = NULL;
+	struct buffer_head * bh = NULL, * tmp, * bha[16];
 	lb_addr bloc, eloc;
 	Uint32 extoffset, elen, offset;
+	int i, num;
+	unsigned int dt_type;
 
 	if (nf_pos >= size)
-		return 1;
+		return 0;
 
 	if (nf_pos == 0)
 		nf_pos = (udf_ext0_offset(dir) >> 2);
@@ -125,6 +128,7 @@
 	if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
 	{
+		offset >>= dir->i_sb->s_blocksize_bits;
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
@@ -139,18 +143,40 @@
 	else
 	{
 		udf_release_data(bh);
-		return 0;
+		return -ENOENT;
 	}
 
 	if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
 	{
 		udf_release_data(bh);
-		return 0;
+		return -EIO;
+	}
+
+	if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
+	{
+		i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
+		if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
+			i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
+		for (num=0; i>0; i--)
+		{
+			block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
+			tmp = udf_tgetblk(dir->i_sb, block, dir->i_sb->s_blocksize);
+			if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
+				bha[num++] = tmp;
+			else
+				brelse(tmp);
+		}
+		if (num)
+		{
+			ll_rw_block(READA, num, bha);
+			for (i=0; i<num; i++)
+				brelse(bha[i]);
+		}
 	}
 
 	while ( nf_pos < size )
 	{
-		filp->f_pos = nf_pos;
+		filp->f_pos = nf_pos + 1;
 
 		fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
 
@@ -160,7 +186,7 @@
 				udf_release_data(fibh.ebh);
 			udf_release_data(fibh.sbh);
 			udf_release_data(bh);
-			return 1;
+			return -ENOENT;
 		}
 
 		liu = le16_to_cpu(cfi.lengthOfImpUse);
@@ -196,44 +222,39 @@
 				continue;
 		}
 
-		iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0);
- 
- 		if (!lfi) /* parent directory */
- 		{
-			if (filldir(dirent, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR))
+		if ( cfi.fileCharacteristics & FILE_PARENT )
+		{
+			iblock = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(filp->f_dentry->d_parent->d_inode), 0);
+			flen = 2;
+			memcpy(fname, "..", flen);
+			dt_type = DT_DIR;
+		}
+		else
+		{
+			iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0);
+			flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
+			dt_type = DT_UNKNOWN;
+		}
+
+		if (flen)
+		{
+			if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0)
 			{
 				if (fibh.sbh != fibh.ebh)
 					udf_release_data(fibh.ebh);
 				udf_release_data(fibh.sbh);
 				udf_release_data(bh);
- 				return 1;
-			}
-		}
-		else
-		{
-			if ((flen = udf_get_filename(nameptr, fname, lfi)))
-			{
-				if (filldir(dirent, fname, flen, filp->f_pos, iblock, DT_UNKNOWN))
-				{
-					if (fibh.sbh != fibh.ebh)
-						udf_release_data(fibh.ebh);
-					udf_release_data(fibh.sbh);
-					udf_release_data(bh);
-		 			return 1; /* halt enum */
-				}
+	 			return 0;
 			}
 		}
 	} /* end while */
 
-	filp->f_pos = nf_pos;
+	filp->f_pos = nf_pos + 1;
 
 	if (fibh.sbh != fibh.ebh)
 		udf_release_data(fibh.ebh);
 	udf_release_data(fibh.sbh);
 	udf_release_data(bh);
 
-	if ( filp->f_pos >= size)
-		return 1;
-	else
-		return 0;
+	return 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)