Patch applied in commit 7029581 - thanks. git-apply didn't work while patch mostly worked. So the test image test hasn't been added. Add it as an attachment in https://savannah.gnu.org/patch/?group=libcdio And please double check that the changes are what you expect.
On Wed, Feb 19, 2014 at 9:27 PM, Pete Batard <[email protected]> wrote: > Hi, > > Having recently found that the unicode16_decode() call we use in udf_fs > isn't actually doing any actual Unicode decoding (just strips the MSB from > UTF-16), please find attached a patch that adds Unicode support to udf_fs > and will ensure we always return UTF-8 strings where relevant. > > The patch also contains an associated test as well as the required UDF > image (which was created using ImgBurn). > > Regards, > > /Pete > > From 6310430dd712e9769e49dd942d2200cb27951cec Mon Sep 17 00:00:00 2001 > From: Pete Batard <[email protected]> > Date: Thu, 20 Feb 2014 02:21:27 +0000 > Subject: [PATCH] Add Unicode support for UDF > > --- > lib/driver/utf8.c | 3 -- > lib/udf/udf_fs.c | 104 > ++++++++++++++++++++++++++++++++----------------- > test/check_fuzzyiso.sh | 2 +- > test/data/udf102.iso | Bin 784384 -> 1245184 bytes > test/testudf.c.in | 32 +++++++++++---- > 5 files changed, 94 insertions(+), 47 deletions(-) > > diff --git a/lib/driver/utf8.c b/lib/driver/utf8.c > index db68d5b..b94b833 100644 > --- a/lib/driver/utf8.c > +++ b/lib/driver/utf8.c > @@ -113,7 +113,6 @@ FILE* fopen_utf8(const char* filename, const char* > mode) > } > #endif > > -#ifdef HAVE_JOLIET > #ifdef HAVE_ICONV > #include <iconv.h> > struct cdio_charset_coverter_s > @@ -344,5 +343,3 @@ bool cdio_charset_to_utf8(const char *src, size_t > src_len, cdio_utf8_t **dst, > return (*dst != NULL); > } > #endif /* HAVE_ICONV */ > - > -#endif /* HAVE_JOLIET */ > diff --git a/lib/udf/udf_fs.c b/lib/udf/udf_fs.c > index 81719b6..e21571a 100644 > --- a/lib/udf/udf_fs.c > +++ b/lib/udf/udf_fs.c > @@ -70,6 +70,9 @@ const char VSD_STD_ID_NSR03[] = {'N', 'S', 'R', '0', > '3'}; > const char VSD_STD_ID_TEA01[] = {'T', 'E', 'A', '0', '1'}; > > #include <cdio/bytesex.h> > +#include <cdio/utf8.h> > +#include <cdio/util.h> > + > #include "udf_private.h" > #include "udf_fs.h" > #include "cdio_assert.h" > @@ -274,23 +277,32 @@ udf_fopen(udf_dirent_t *p_udf_root, const char > *psz_name) > return p_udf_file; > } > > -/* Convert unicode16 to 8-bit char by dripping MSB. > - Wonder if iconv can be used here > +/* Convert unicode16 to UTF-8. > + The returned string is allocated and must be freed by the caller > */ > -static int > -unicode16_decode( const uint8_t *data, int i_len, char *target ) > +static char* > +unicode16_decode(const uint8_t *data, int i_len) > { > - int p = 1, i = 0; > - > - if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { > - if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */ > - if( p < i_len ) { > - target[ i++ ] = data[ p++ ]; > - } > - } while( p < i_len ); > + int i; > + char* r = NULL; > > - target[ i ] = '\0'; > - return 0; > + switch (data[0]) > + { > + case 8: > + r = (char*)calloc(i_len, 1); > + if (r == NULL) > + return r; > + for (i=0; i<i_len-1; i++) > + r[i] = data[i+1]; > + return r; > + case 16: > + cdio_charset_to_utf8((char*)&data[1], i_len-1, &r, "UCS-2BE"); > + return r; > + default: > + /* Empty string, as some existing sections can't take a NULL pointer > */ > + r = (char*)calloc(1, 1); > + return r; > + } > } > > > @@ -431,18 +443,24 @@ udf_open (const char *psz_path) > } > > /** > - * Gets the Volume Identifier string, in 8bit unicode (latin-1) > + * Gets the Volume Identifier, as an UTF-8 string > * psz_volid, place to put the string > * i_volid, size of the buffer psz_volid points to > * returns the size of buffer needed for all data > + * Note: this call accepts a NULL psz_volid, to retrieve the length > required. > */ > -int > -udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int > i_volid) > +int > +udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int > i_volid) > { > uint8_t data[UDF_BLOCKSIZE]; > const udf_pvd_t *p_pvd = (udf_pvd_t *) &data; > + char* r; > unsigned int volid_len; > > + /* clear the output to empty string */ > + if (psz_volid != NULL) > + psz_volid[0] = 0; > + > /* get primary volume descriptor */ > if ( DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &data, > p_udf->pvd_lba, 1) ) > return 0; > @@ -452,10 +470,17 @@ udf_get_volume_id(udf_t *p_udf, /*out*/ char > *psz_volid, unsigned int i_volid) > /* this field is only UDF_VOLID_SIZE bytes something is wrong */ > volid_len = UDF_VOLID_SIZE-1; > } > - if(i_volid > volid_len) { > - i_volid = volid_len; > + > + r = unicode16_decode((uint8_t *) p_pvd->vol_ident, volid_len); > + if (r == NULL) > + return 0; > + > + volid_len = strlen(r)+1; /* +1 for NUL terminator */ > + if (psz_volid != NULL) { > + strncpy(psz_volid, r, MIN(volid_len, i_volid)); > + psz_volid[i_volid-1] = 0; /* strncpy does not always terminate the > dest */ > } > - unicode16_decode((uint8_t *) p_pvd->vol_ident, i_volid, psz_volid); > + free(r); > > return volid_len; > } > @@ -490,27 +515,39 @@ udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t > *volsetid, > } > > /** > - * Gets the Logical Volume Identifier string, in 8bit unicode (latin-1) > + * Gets the Logical Volume Identifier string, as an UTF-8 string > * psz_logvolid, place to put the string (should be at least 64 bytes) > * i_logvolid, size of the buffer psz_logvolid points to > - * returns the size of buffer needed for all data > + * returns the size of buffer needed for all data, including NUL > terminator > * A call to udf_get_root() should have been issued before this call > + * Note: this call accepts a NULL psz_volid, to retrieve the length > required. > */ > int > -udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid, > unsigned int i_logvolid) > +udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid, > unsigned int i_logvolid) > { > uint8_t data[UDF_BLOCKSIZE]; > logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data; > + char* r; > int logvolid_len; > > - if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_logvol, > p_udf->lvd_lba, 1) ) > + /* clear the output to empty string */ > + if (psz_logvolid != NULL) > + psz_logvolid[0] = 0; > + > + if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_logvol, > p_udf->lvd_lba, 1) ) > return 0; > > - logvolid_len = (p_logvol->logvol_id[127]+1)/2; > - if (i_logvolid > logvolid_len) > - i_logvolid = logvolid_len; > + r = unicode16_decode((uint8_t *) p_logvol->logvol_id, > p_logvol->logvol_id[127]); > + if (r == NULL) > + return 0; > + > + logvolid_len = strlen(r)+1; /* +1 for NUL terminator */ > + if (psz_logvolid != NULL) { > + strncpy(psz_logvolid, r, MIN(logvolid_len, i_logvolid)); > + psz_logvolid[i_logvolid-1] = 0; /* strncpy does not always > terminate the dest */ > + } > + free(r); > > - unicode16_decode((uint8_t *) p_logvol->logvol_id, 2*i_logvolid, > psz_logvolid); > return logvolid_len; > } > > @@ -651,6 +688,7 @@ udf_dirent_t * > udf_readdir(udf_dirent_t *p_udf_dirent) > { > udf_t *p_udf; > + uint8_t* p; > > if (p_udf_dirent->dir_left <= 0) { > udf_dirent_free(p_udf_dirent); > @@ -710,13 +748,9 @@ udf_readdir(udf_dirent_t *p_udf_dirent) > return NULL; > } > > - if (strlen(p_udf_dirent->psz_name) < i_len) > - p_udf_dirent->psz_name = (char *) > - realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1); > - > - unicode16_decode(p_udf_dirent->fid->u.imp_use.data > - + p_udf_dirent->fid->u.i_imp_use, > - i_len, p_udf_dirent->psz_name); > + free_and_null(p_udf_dirent->psz_name); > + p = (uint8_t*)p_udf_dirent->fid->u.imp_use.data + > p_udf_dirent->fid->u.i_imp_use; > + p_udf_dirent->psz_name = unicode16_decode(p, i_len); > } > return p_udf_dirent; > } > diff --git a/test/check_fuzzyiso.sh b/test/check_fuzzyiso.sh > index 0eb71d9..cef7a5a 100755 > --- a/test/check_fuzzyiso.sh > +++ b/test/check_fuzzyiso.sh > @@ -22,7 +22,7 @@ fi > cd $srcdir; src_dir=`pwd` > for file in $src_dir/data/*.bin $src_dir/data/*.iso $src_dir/data/*.nrg ; > do > case "$file" in > - $src_dir/data/p1.nrg | $src_dir/data/p1.bin | $src_dir/data/cdda.bin | > $src_dir/data/cdda-mcn.nrg | $src_dir/data/svcdgs.nrg | > $src_dir/data/cdtext.bin ) > + $src_dir/data/p1.nrg | $src_dir/data/p1.bin | $src_dir/data/cdda.bin | > $src_dir/data/cdda-mcn.nrg | $src_dir/data/svcdgs.nrg | > $src_dir/data/cdtext.bin | $src_dir/data/udf102.iso ) > good_rc=1 > ;; > *) > diff --git a/test/data/udf102.iso b/test/data/udf102.iso > index > 9e088313db7e397052e6a764757643078a41c8f7..2639d0d451f920c69511b6a58bc453a3b05b03b1 > 100644 > GIT binary patch > delta 1545 > zcmd5+O-vI}5T4mxwvUZ9+q7V*2B}CiMoVca6fQy&tR@^pjd+r1tY890Fyf&Hnvf>m > zOoQyhi=c@yUNoyQo{SufiB}JBFnZwT#jGB@`7^V$bcw~pgoE?)_Px%VdEd-8Z(4BL > z3x&a@!h?me`)2qKYPq+7FmlSl7O08|$KbQpr7plUOu-e%(bpqEBp-zal9HzhoitK3 > z<B*|mKdqIKAbocU&tp`^)1prb#G%eZCniQSH>R$(OebQgSUMK>+|FC`lTQg@By`pQ > zsMy+gUAF{k`g_8h>6M1S{RpyMU^ehaxFsCNU<oHg)m!S8N#3pGJ#0(E#Aksa1wd!K > zs#Vfwg;Dc=A*)B@Pq38^RoNkMpeBYI1R?MBh&=~XzJ{6DBz!p&v;k1Ug_m{{p1z!0 > zp#$dKoBDsvd;J<kJk#r7hx7}K{yX*cNxERzb}%9RCO-WO`#;H$*-sL4+s^)7V!!Ps > zA;{)w=;PveUYlDi){z8CxYsg;Hb1Bc|E6a$ci~o~m{*E<wV2n6`MP3WFXnx=>C9~Z > zToDmesH+f?5obNTYP@oHS`62GnHc1D%QRDGz)?7}MI)E6UlRa|obM5BsM<K7TL)1S > zKL`%M!RM2+w>8_$saBuRMn96)*|$uMzb+arWXB6h3;Zg}!%+FvllGE(R{iZIdyD<t > zwb{mvzNH$ph3O885_BTs10fo(gc}3vc`^pYPOW=fXbtbkB6~3m+>vDKx+?N(Rs>V8 > zN%45?aQO(Rc{idbW0o2nXyc-f(;s_7-izm!EBU%BrC+!1Sv!4#cZKP6g=-fuLXFY> > z`f~bBJ5EMp-u>L<Y=bBNT}LW^DqbGA7R&>aU*Unl>X-*3-jPUlrn<V*JvM&NT1!GR > R+Q|V|9UM_!>=fU8zX2rRFfafB > > literal 784384 > zcmeI*Yj<4Nec$l`Em8Eusg%^YDA!{;jz}4zNXn8$Q*k^5h9qnfpmCAHUOfN~h_Qef > zWCkFG-c}yx9rOh>t6g2oD{0?AS6)E-AXzIfp!YUy)%(5a@Au#P%nZOoU82aAj=qp- > z00(Ez+559E|GoFw1GHLvAb<b@2q1s}0tg_000IagfB*srAb<b@2q1s}0tg_000Iag > zfB*srAb<b@2q1s}0tg_000IagfB*srAb<b@2q1s}0tg_000IagfB*srAb<b@2q1s} > z0tg_000IagfB*srAb<b@2q1s}0tg_000IagfB*srAb<b@2q1s}0tg_000IagfB*sr > zAb<b@2q1s}0tg_000IagfWX|s;^oU%=32%3d@Of2-t&w~@^|L^)!gq?-#_WIPMh<; > z*12=7b~>r;1L<S#j6a`mJ)N%hbnBeIKiAql`~0)7x6bLO>GkiKB!2j@3oLh6SBe`O > ztIJEvw~E!3yC3@vf3!EadinC#F28p5)hn;Q`r2iEoO|qmkIsIyX20>*uDE<4fB*uY > z1c5U-{<n(v{IAtoZgpE5N^$*pldM$n|0^$dC&%i(P&YW|f3xxbb2^Yd=AQEB^R2US > zWbW*f;(x0?H9xGQt<U`Zms@3P)Edg+M(apl4O)Hud!X-ETPv-*AG6N~^Z!7J_&_H; > z7VaNA@L0Hi?7&>E;(S5?0R(=;0)JA){~vKWxIF?0Ab<b@2>cKQZge|d|K|e%1Q0*~ > z0R%on0?TWwm#-54KSL!>RuMn|0R#|ewbq&cQw<P6009ILKmY**5I_I{1Q0*~0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL__G$6Yn^HR?bclD_x|ABxnkzx > z&rSZ|@65sJm(R@UHD~mn|8ju;oqOf-;<c~ey!zUL{=KfRr|14KzWRyQ%G!FTSQzdf > zjLPx2+%7f-{jK44`GIf#QD6UoZ<J1a<GDY4=Iry&Ui*T-eX(=9+gU7@%hB-UWu89y > zE#D!400Iag@Mk3Olw$aOMey}Mes}Imx@P<(pcgk5Zx(mnES3g4vjOSMT#iQ{F;>3M > z*y7J9XHUG$Gf(`<$MFMV`^TZmH4#7n0R%pxz|)HV&nxQR`@y?&=XI?!`WIt>uf`t+ > z{D@co_+IWbY7wIK<G#fcVl1=gkI$bgBY*$`2z<H)&MM+Rqlkaz#UIRlSy}m<v-4@6 > z-=9++UW`n5A;S*^_WHfSp|f^oE^?>`7XEJfaaLcZwU1BuTKsdZ*0-G2vys|q2KWjA > z1Q0*~fe#_@jN<=4P~_Wx_FU^%^tz`$#A`Vf0R#|0009I(odV|+|GyM7-*@M}^6AV1 > zsYU<+1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0;r6DOd*{L}h-`u)GZ_XqFJU7ktZ`}~bw{pmfw@=W~ZVE-kWbFW-py!Q2*S6^Gu > zzt{Ek%(Z?9U;e~L{hLJ}`Sl+%lW#othtHgS{@H6^@avxN_X}Gs{(|9$WaV@O5I_Kd > z4=C`IVt8LseEpB#ox7sfq`!gZKbv>w&0=Y=Gn~23nYkQ~KJ9-Wa3)V5`<KM_kDZts > zAb<b@2z+>frxpJ%D(c_+!Mk%;_3|_N7h{00F0ZX#_K{EKhtsG<h}Mrgc~6M3%$`4) > zWk;$IKmY**e)Ixo74d&Y5&z7KKbU(($@!d<^l6{ppHm)Qj7)eTV_~>|u-ESm4xP0# > zbCE+mu<&=&kF)wRt$lQEcRP#4aygn^`p{25A)|@sTCHz6t!E>(`ic((5I_I{1U|gL > zGm8JeugJIm?77z0^zx@Z{3Un=0tg_000Ibn$^_0S{$Gii@4Iuae#+8LauGlP0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#~EqzZgq > zzyJ5=^!tC$-Fp~+S7!F_($D^dnJ>Oi27K<Ne9i~?n|was|IW<$zx+ZzA%Fk^2q1vK > z4@JPg|NqzW@Bi=oQ0~Z05I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL > zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ > z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** > z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL > zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ > z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** > z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL > zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ > z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** > z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL > zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ > z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** > z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL > zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ > z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** > z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL > zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ > z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** > z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL > zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ > z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** > z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 > z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ > z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL > zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0;L|E_rgf(EPg--Wxj%YW > z|EFC1R;yJwGx~hlpZP!l0R#|00D;B{%(b3Y)OX<L0|5jOKmY**J}Ux_{But;0Qjtw > zH~B;W0R#|0zyfovv&{dg3J4&800Ibn#sp&if0p_GXRO%CE&>Q3fWT*5;Cwv)k7oeq > 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 > > diff --git a/test/testudf.c.in b/test/testudf.c.in > index 210bd12..3d22c6e 100644 > --- a/test/testudf.c.in > +++ b/test/testudf.c.in > @@ -1,6 +1,6 @@ > /* > Copyright (C) 2013 Rocky Bernstein <[email protected]> > - Copyright (C) 2013 Pete Batard <[email protected]> > + Copyright (C) 2013-2014 Pete Batard <[email protected]> > > 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 > @@ -44,18 +44,22 @@ > #include <cdio/cdio.h> > #include <cdio/udf.h> > > +#define EXPECTED_NAME "FÃ(c)жÎ~vrier" > +#define EXPECTED_LENGTH 10 > + > int > main(int argc, const char *argv[]) > { > char const *psz_fname = UDF_IMAGE; > char volume_id[192]; /* 3*64 to account for UTF-8 */ > udf_t* p_udf = NULL; > - udf_dirent_t* p_udf_root; > + udf_dirent_t *p_udf_root, *p_udf_file; > + int64_t file_length; > > p_udf = udf_open(psz_fname); > > if (NULL == p_udf) { > - fprintf(stderr, "Sorry, couldn't open %s as an UDF image\n", > + fprintf(stderr, "Couldn't open %s as an UDF image\n", > psz_fname); > return 1; > } > @@ -66,14 +70,26 @@ main(int argc, const char *argv[]) > return 2; > } > > - if (udf_get_logical_volume_id(p_udf, volume_id, sizeof(volume_id)) <= > 0) { > - fprintf(stderr, "UDF image %s has no logical volume ID\n", > - psz_fname); > + if ( (udf_get_logical_volume_id(p_udf, volume_id, sizeof(volume_id)) <= > 0) > + || (strcmp(EXPECTED_NAME, volume_id) != 0) ) { > + fprintf(stderr, "Unexpected UDF logical volume ID\n"); > return 3; > } > - printf("-- Volume id: %s\n", volume_id); > + printf("-- Good! Volume id matches expected UTF-8 data\n"); > > - udf_close(p_udf); > + p_udf_file = udf_fopen(p_udf_root, EXPECTED_NAME); > + if (!p_udf_file) { > + fprintf(stderr, "Could not locate expected file in UDF image\n"); > + return 4; > + } > + printf("-- Good! File name matches expected UTF-8 data\n"); > + > + file_length = udf_get_file_length(p_udf_file); > + if (file_length != EXPECTED_LENGTH) { > + fprintf(stderr, "Unexpected UDF file length\n"); > + return 5; > + } > + printf("-- Good! File length matches expected length\n"); > > return 0; > } > -- > 1.8.5.2.msysgit.0 > > >
