From d0d5ea424f99eb19f1bb50e83a0572b98e50f353 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 11 Apr 2006 05:47:57 +0000 Subject: [PATCH] Make udf_read_block more like 2 read. Implementation is closer to the description (although it needs more work.) udf_fs.h: break out udf_check_tag() *.h: /*! -> /** - is more like Javadoc. --- include/cdio/udf_file.h | 39 +++++++++++++++--------- lib/udf/Makefile.am | 2 +- lib/udf/udf_file.c | 66 +++++++++++++++++++++++++---------------- lib/udf/udf_fs.c | 5 ++-- lib/udf/udf_fs.h | 39 ++++++++++++++++++++++++ lib/udf/udf_private.h | 11 ++----- 6 files changed, 111 insertions(+), 51 deletions(-) create mode 100644 lib/udf/udf_fs.h diff --git a/include/cdio/udf_file.h b/include/cdio/udf_file.h index 99c51217..e4376dd4 100644 --- a/include/cdio/udf_file.h +++ b/include/cdio/udf_file.h @@ -1,6 +1,6 @@ /* - $Id: udf_file.h,v 1.7 2005/11/06 19:12:35 rocky Exp $ - Copyright (C) 2005 Rocky Bernstein + $Id: udf_file.h,v 1.8 2006/04/11 05:47:57 rocky Exp $ + Copyright (C) 2005, 2006 Rocky Bernstein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/*! +/** * \file udf_file.h * * \brief Routines involving UDF file operations @@ -31,44 +31,55 @@ extern "C" { #endif /* __cplusplus */ - /*! + /** Return the file id descriptor of the given file. */ bool udf_get_fileid_descriptor(const udf_dirent_t *p_udf_dirent, /*out*/ udf_fileid_desc_t *p_udf_fid); - /*! + /** Return the name of the file */ const char *udf_get_filename(const udf_dirent_t *p_udf_dirent); - /*! + /** Return the name of the file */ bool udf_get_file_entry(const udf_dirent_t *p_udf_dirent, /*out*/ udf_file_entry_t *p_udf_fe); - /*! + /** Return the number of hard links of the file. Return 0 if error. */ uint16_t udf_get_link_count(const udf_dirent_t *p_udf_dirent); - /*! + /** Return the file length the file. Return 2147483647L if error. */ uint64_t udf_get_file_length(const udf_dirent_t *p_udf_dirent); - /*! + /** Returns a POSIX mode for a given p_udf_dirent. */ mode_t udf_get_posix_filemode(const udf_dirent_t *p_udf_dirent); - /*! + /** Return the next subdirectory. */ udf_dirent_t *udf_opendir(const udf_dirent_t *p_udf_dirent); - /*! + /** + Attempts to read up to count bytes from UDF directory entry + p_udf_dirent into the buffer starting at buf. buf should be a + multiple of UDF_BLOCKSIZE bytes. + + If count is zero, read() returns zero and has no other results. If + count is greater than SSIZE_MAX, the result is unspecified. + + If there is an error, cast the result to driver_return_code_t for + the specific error code. + */ + /** Attempts to read up to count bytes from file descriptor fd into the buffer starting at buf. @@ -78,7 +89,7 @@ extern "C" { driver_return_code_t udf_read_block(const udf_dirent_t *p_udf_dirent, void * buf, size_t count); - /*! + /** Advances p_udf_direct to the the next directory entry in the pointed to by p_udf_dir. It also returns this as the value. NULL is returned on reaching the end-of-file or if an error. Also @@ -88,12 +99,12 @@ extern "C" { */ udf_dirent_t *udf_readdir(udf_dirent_t *p_udf_dirent); - /*! + /** free free resources associated with p_udf_dirent. */ bool udf_dirent_free(udf_dirent_t *p_udf_dirent); - /*! + /** Return true if the file is a directory. */ bool udf_is_dir(const udf_dirent_t *p_udf_dirent); diff --git a/lib/udf/Makefile.am b/lib/udf/Makefile.am index c75d2731..2981ada0 100644 --- a/lib/udf/Makefile.am +++ b/lib/udf/Makefile.am @@ -30,7 +30,7 @@ libudf_la_AGE := 0 EXTRA_DIST = libudf.sym -noinst_HEADERS = udf_private.h +noinst_HEADERS = udf_fs.h udf_private.h lib_LTLIBRARIES = libudf.la diff --git a/lib/udf/udf_file.c b/lib/udf/udf_file.c index 13949089..612b310e 100644 --- a/lib/udf/udf_file.c +++ b/lib/udf/udf_file.c @@ -1,7 +1,7 @@ /* - $Id: udf_file.c,v 1.8 2006/04/11 01:05:44 rocky Exp $ + $Id: udf_file.c,v 1.9 2006/04/11 05:47:58 rocky Exp $ - Copyright (C) 2005 Rocky Bernstein + Copyright (C) 2005, 2006 Rocky Bernstein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ #include #include "udf_private.h" +#include "udf_fs.h" #ifdef HAVE_STRING_H # include @@ -28,6 +29,8 @@ #include /* Remove when adding cdio/logging.h */ +#define MIN(a, b) (a>b) ? (a) : (b) + const char * udf_get_filename(const udf_dirent_t *p_udf_dirent) { @@ -93,36 +96,49 @@ udf_is_dir(const udf_dirent_t *p_udf_dirent) return p_udf_dirent->b_dir; } -/*! - Attempts to read up to count bytes from file descriptor fd into - the buffer starting at buf. +/** + Attempts to read up to count bytes from UDF directory entry + p_udf_dirent into the buffer starting at buf. buf should be a + multiple of UDF_BLOCKSIZE bytes. If count is zero, read() returns zero and has no other results. If count is greater than SSIZE_MAX, the result is unspecified. + + If there is an error, cast the result to driver_return_code_t for + the specific error code. */ -driver_return_code_t +ssize_t udf_read_block(const udf_dirent_t *p_udf_dirent, void * buf, size_t count) { - const udf_t *p_udf = p_udf_dirent->p_udf; - uint8_t data[UDF_BLOCKSIZE]; - udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) data; - driver_return_code_t ret = - udf_read_sectors(p_udf, data, p_udf_dirent->fe.unique_ID, 1); - if (ret == DRIVER_OP_SUCCESS) { - if (!udf_checktag(&p_udf_fe->tag, TAGID_FILE_ENTRY)) { - uint32_t i_lba_start, i_lba_end; - udf_get_lba( p_udf_fe, &i_lba_start, &i_lba_end); - - if ( (i_lba_end - i_lba_start+1) < count ) { - printf("Warning: don't know how to handle yet\n" ); - count = i_lba_end - i_lba_start+1; + if (count == 0) return 0; + else { + const udf_t *p_udf = p_udf_dirent->p_udf; + uint8_t data[UDF_BLOCKSIZE]; + const udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) data; + driver_return_code_t ret; + const unsigned long int i_file_length = udf_get_file_length(p_udf_dirent); + + ret = udf_read_sectors(p_udf, data, p_udf_dirent->fe.unique_ID, 1); + if (ret == DRIVER_OP_SUCCESS) { + if (!udf_checktag(&p_udf_fe->tag, TAGID_FILE_ENTRY)) { + uint32_t i_lba_start, i_lba_end; + udf_get_lba( p_udf_fe, &i_lba_start, &i_lba_end); + + if ( (i_lba_end - i_lba_start+1) < count ) { + printf("Warning: don't know how to handle yet\n" ); + count = i_lba_end - i_lba_start+1; + } else { + const uint32_t i_lba = p_udf->i_part_start+i_lba_start; + ret = udf_read_sectors(p_udf, buf, i_lba, count); + if (DRIVER_OP_SUCCESS == ret) { + return MIN(i_file_length, count * UDF_BLOCKSIZE); + } + } + + } else { + return DRIVER_OP_ERROR; } - return udf_read_sectors(p_udf, buf, p_udf->i_part_start+i_lba_start, - count); - } - else { - return DRIVER_OP_ERROR; } + return ret; } - return ret; } diff --git a/lib/udf/udf_fs.c b/lib/udf/udf_fs.c index 71ea4b4e..a810b36d 100644 --- a/lib/udf/udf_fs.c +++ b/lib/udf/udf_fs.c @@ -1,5 +1,5 @@ /* - $Id: udf_fs.c,v 1.16 2006/04/11 00:26:54 rocky Exp $ + $Id: udf_fs.c,v 1.17 2006/04/11 05:47:58 rocky Exp $ Copyright (C) 2005 Rocky Bernstein @@ -69,6 +69,7 @@ const char VSD_STD_ID_TEA01[] = {'T', 'E', 'A', '0', '1'}; #include #include "udf_private.h" +#include "udf_fs.h" /* * The UDF specs are pretty clear on how each data structure is made @@ -122,7 +123,7 @@ udf_new_dirent(udf_file_entry_t *p_udf_fe, udf_t *p_udf, * Return zero if all is good, -1 if not. */ int -udf_checktag(udf_tag_t *p_tag, udf_Uint16_t tag_id) +udf_checktag(const udf_tag_t *p_tag, udf_Uint16_t tag_id) { uint8_t *itag; uint8_t i; diff --git a/lib/udf/udf_fs.h b/lib/udf/udf_fs.h new file mode 100644 index 00000000..25e5e6f8 --- /dev/null +++ b/lib/udf/udf_fs.h @@ -0,0 +1,39 @@ +/* + $Id: udf_fs.h,v 1.1 2006/04/11 05:47:58 rocky Exp $ + + Copyright (C) 2006 Rocky Bernstein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __CDIO_UDF_FS_H__ +#define __CDIO_UDF_FS_H__ + +/** + * Check the descriptor tag for both the correct id and correct checksum. + * Return zero if all is good, -1 if not. + */ +int udf_checktag(const udf_tag_t *p_tag, udf_Uint16_t tag_id); + +#endif /* __CDIO_UDF_FS_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/lib/udf/udf_private.h b/lib/udf/udf_private.h index cdaa0618..a34d7652 100644 --- a/lib/udf/udf_private.h +++ b/lib/udf/udf_private.h @@ -1,7 +1,7 @@ /* - $Id: udf_private.h,v 1.7 2006/04/11 00:26:54 rocky Exp $ + $Id: udf_private.h,v 1.8 2006/04/11 05:47:58 rocky Exp $ - Copyright (C) 2005, 2006 Rocky Bernstein + Copyright (C) 2005, 2006 Rocky Bernstein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -65,13 +65,6 @@ struct udf_dirent_s bool udf_get_lba(const udf_file_entry_t *p_udf_fe, /*out*/ uint32_t *start, /*out*/ uint32_t *end); -/* FIXME createudf_fs.h and put this in there. */ -/** - * Check the descriptor tag for both the correct id and correct checksum. - * Return zero if all is good, -1 if not. - */ -int udf_checktag(udf_tag_t *p_tag, udf_Uint16_t tag_id); - #endif /* __CDIO_UDF_PRIVATE_H__ */