static void _idr2statbuf (const iso9660_dir_t *idr, iso9660_stat_t *stat, bool is_mode2) { iso9660_xa_t *xa_data = NULL; uint8_t dir_len= iso9660_get_dir_len(idr); memset ((void *) stat, 0, sizeof (iso9660_stat_t)); if (!dir_len) return; stat->type = (idr->file_flags & ISO_DIRECTORY) ? _STAT_DIR : _STAT_FILE; stat->lsn = from_733 (idr->extent); stat->size = from_733 (idr->size); stat->secsize = _cdio_len2blocks (stat->size, ISO_BLOCKSIZE); iso9660_get_dtime(&(idr->recording_time), true, &(stat->tm)); cdio_assert (dir_len >= sizeof (iso9660_dir_t)); if (is_mode2) { int su_length = iso9660_get_dir_len(idr) - sizeof (iso9660_dir_t); su_length -= idr->filename_len; if (su_length % 2) su_length--; if (su_length < 0 || su_length < sizeof (iso9660_xa_t)) return; xa_data = (void *) (((char *) idr) + (iso9660_get_dir_len(idr) - su_length)); if (xa_data->signature[0] != 'X' || xa_data->signature[1] != 'A') { cdio_warn ("XA signature not found in ISO9660's system use area;" " ignoring XA attributes for this file entry."); cdio_debug ("%d %d %d, '%c%c' (%d, %d)", iso9660_get_dir_len(idr), idr->filename_len, su_length, xa_data->signature[0], xa_data->signature[1], xa_data->signature[0], xa_data->signature[1]); return; } stat->xa = *xa_data; } }
/*! Return the LSN of the root directory for pvd. If there is an error CDIO_INVALID_LSN is returned. */ lsn_t iso9660_get_root_lsn(const iso9660_pvd_t *pvd) { if (NULL == pvd) return CDIO_INVALID_LSN; else { const iso9660_dir_t *idr = &(pvd->root_directory_record); if (NULL == idr) return CDIO_INVALID_LSN; return(from_733 (idr->extent)); } }
static int parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir, iso9660_stat_t *p_stat, int regard_xa) { int len; unsigned char * chr; int symlink_len = 0; CONTINUE_DECLS; if (nope == p_stat->rr.b3_rock) return 0; SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len); if (regard_xa) { chr+=14; len-=14; if (len<0) len=0; } /* repeat:*/ { int sig; iso_extension_record_t * rr; int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (iso_extension_record_t *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = from_721(*chr); chr += rr->len; len -= rr->len; switch(sig){ case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','E'): CHECK_CE; break; case SIG('E','R'): p_stat->rr.b3_rock = yep; cdio_debug("ISO 9660 Extensions: "); { int p; for(p=0;p<rr->u.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]); } break; case SIG('P','X'): p_stat->rr.st_mode = from_733(rr->u.PX.st_mode); p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks); p_stat->rr.st_uid = from_733(rr->u.PX.st_uid); p_stat->rr.st_gid = from_733(rr->u.PX.st_gid); break; case SIG('P','N'): /* Device major,minor number */ { int32_t high, low; high = from_733(rr->u.PN.dev_high); low = from_733(rr->u.PN.dev_low); /* * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4, * then the high field is unused, and the device number is completely * stored in the low field. Some writers may ignore this subtlety, * and as a result we test to see if the entire device number is * stored in the low field, and use that. */ if((low & ~0xff) && high == 0) { p_stat->rr.i_rdev = CDIO_MKDEV(low >> 8, low & 0xff); } else { p_stat->rr.i_rdev = CDIO_MKDEV(high, low); } } break; case SIG('T','F'): /* Time stamp(s) for a file */ { int cnt = 0; add_time(ISO_ROCK_TF_CREATE, create); add_time(ISO_ROCK_TF_MODIFY, modify); add_time(ISO_ROCK_TF_ACCESS, access); add_time(ISO_ROCK_TF_ATTRIBUTES, attributes); add_time(ISO_ROCK_TF_BACKUP, backup); add_time(ISO_ROCK_TF_EXPIRATION, expiration); add_time(ISO_ROCK_TF_EFFECTIVE, effective); p_stat->rr.b3_rock = yep; break; } case SIG('S','L'): { /* Symbolic link */ uint8_t slen; iso_rock_sl_part_t * p_sl; iso_rock_sl_part_t * p_oldsl; slen = rr->len - 5; p_sl = &rr->u.SL.link; p_stat->rr.i_symlink = symlink_len; while (slen > 1){ rootflag = 0; switch(p_sl->flags &~1){ case 0: realloc_symlink(p_stat, p_sl->len); memcpy(&(p_stat->rr.psz_symlink[p_stat->rr.i_symlink]), p_sl->text, p_sl->len); p_stat->rr.i_symlink += p_sl->len; break; case 4: realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; /* continue into next case. */ case 2: realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; break; case 8: rootflag = 1; realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; p_stat->rr.i_symlink++; break; default: cdio_warn("Symlink component flag not implemented"); } slen -= p_sl->len + 2; p_oldsl = p_sl; p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2); if (slen < 2) { if (((rr->u.SL.flags & 1) != 0) && ((p_oldsl->flags & 1) == 0)) p_stat->rr.i_symlink += 1; break; } /* * If this component record isn't continued, then append a '/'. */ if (!rootflag && (p_oldsl->flags & 1) == 0) { realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; } } } symlink_len = p_stat->rr.i_symlink; realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[symlink_len]='\0'; break; case SIG('R','E'): cdio_warn("Attempt to read p_stat for relocated directory"); goto out; #ifdef FINISHED case SIG('C','L'): { iso9660_stat_t * reloc; ISOFS_I(p_stat)->i_first_extent = from_733(rr->u.CL.location); reloc = isofs_iget(p_stat->rr.i_sb, p_stat->rr.i_first_extent, 0); if (!reloc) goto out; p_stat->rr.st_mode = reloc->st_mode; p_stat->rr.st_nlinks = reloc->st_nlinks; p_stat->rr.st_uid = reloc->st_uid; p_stat->rr.st_gid = reloc->st_gid; p_stat->rr.i_rdev = reloc->i_rdev; p_stat->rr.i_symlink = reloc->i_symlink; p_stat->rr.i_blocks = reloc->i_blocks; p_stat->rr.i_atime = reloc->i_atime; p_stat->rr.i_ctime = reloc->i_ctime; p_stat->rr.i_mtime = reloc->i_mtime; iput(reloc); } break; #endif default: break; } }
/*! Get @return length of name field; 0: not found, -1: to be ignored */ int get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir, /*out*/ char * psz_name, /*in/out*/ iso9660_stat_t *p_stat) { int len; unsigned char *chr; int symlink_len = 0; CONTINUE_DECLS; int i_namelen = 0; int truncate=0; if (!p_stat || nope == p_stat->rr.b3_rock) return 0; *psz_name = 0; SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len); /*repeat:*/ { iso_extension_record_t * rr; int sig; int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (iso_extension_record_t *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = *chr+(*(chr+1) << 8); chr += rr->len; len -= rr->len; switch(sig){ case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','E'): { iso711_t i_fname = from_711(p_iso9660_dir->filename.len); if ('\0' == p_iso9660_dir->filename.str[1] && 1 == i_fname) break; if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname) break; } CHECK_CE; break; case SIG('E','R'): p_stat->rr.b3_rock = yep; cdio_debug("ISO 9660 Extensions: "); { int p; for(p=0;p<rr->u.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]); } break; case SIG('N','M'): /* Alternate name */ p_stat->rr.b3_rock = yep; if (truncate) break; if (rr->u.NM.flags & ISO_ROCK_NM_PARENT) { i_namelen = sizeof(".."); strncat(psz_name, "..", i_namelen); } else if (rr->u.NM.flags & ISO_ROCK_NM_CURRENT) { i_namelen = sizeof("."); strncat(psz_name, ".", i_namelen); break; } if (rr->u.NM.flags & ~1) { cdio_info("Unsupported NM flag settings (%d)",rr->u.NM.flags); break; } if((strlen(psz_name) + rr->len - 5) >= 254) { truncate = 1; break; } strncat(psz_name, rr->u.NM.name, rr->len - 5); i_namelen += rr->len - 5; break; case SIG('P','X'): /* POSIX file attributes */ p_stat->rr.st_mode = from_733(rr->u.PX.st_mode); p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks); p_stat->rr.st_uid = from_733(rr->u.PX.st_uid); p_stat->rr.st_gid = from_733(rr->u.PX.st_gid); p_stat->rr.b3_rock = yep; break; case SIG('S','L'): { /* Symbolic link */ uint8_t slen; iso_rock_sl_part_t * p_sl; iso_rock_sl_part_t * p_oldsl; slen = rr->len - 5; p_sl = &rr->u.SL.link; p_stat->rr.i_symlink = symlink_len; while (slen > 1){ rootflag = 0; switch(p_sl->flags &~1){ case 0: realloc_symlink(p_stat, p_sl->len); memcpy(&(p_stat->rr.psz_symlink[p_stat->rr.i_symlink]), p_sl->text, p_sl->len); p_stat->rr.i_symlink += p_sl->len; break; case 4: realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; /* continue into next case. */ case 2: realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; break; case 8: rootflag = 1; realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; break; default: cdio_warn("Symlink component flag not implemented"); } slen -= p_sl->len + 2; p_oldsl = p_sl; p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2); if (slen < 2) { if (((rr->u.SL.flags & 1) != 0) && ((p_oldsl->flags & 1) == 0)) p_stat->rr.i_symlink += 1; break; } /* * If this component record isn't continued, then append a '/'. */ if (!rootflag && (p_oldsl->flags & 1) == 0) { realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; } } } symlink_len = p_stat->rr.i_symlink; realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[symlink_len]='\0'; break; case SIG('R','E'): free(buffer); return -1; case SIG('T','F'): /* Time stamp(s) for a file */ { int cnt = 0; add_time(ISO_ROCK_TF_CREATE, create); add_time(ISO_ROCK_TF_MODIFY, modify); add_time(ISO_ROCK_TF_ACCESS, access); add_time(ISO_ROCK_TF_ATTRIBUTES, attributes); add_time(ISO_ROCK_TF_BACKUP, backup); add_time(ISO_ROCK_TF_EXPIRATION, expiration); add_time(ISO_ROCK_TF_EFFECTIVE, effective); p_stat->rr.b3_rock = yep; break; } default: break; } } } free(buffer); return i_namelen; /* If 0, this file did not have a NM field */ out: free(buffer); return 0; }
static iso9660_stat_t * _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa, uint8_t i_joliet_level) { uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir); iso711_t i_fname; unsigned int stat_len; iso9660_stat_t *p_stat; if (!dir_len) return NULL; i_fname = from_711(p_iso9660_dir->filename_len); /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */ stat_len = sizeof(iso9660_stat_t)+i_fname+2; p_stat = calloc(1, stat_len); if (!p_stat) { cdio_warn("Couldn't calloc(1, %d)", stat_len); return NULL; } p_stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY) ? _STAT_DIR : _STAT_FILE; p_stat->lsn = from_733 (p_iso9660_dir->extent); p_stat->size = from_733 (p_iso9660_dir->size); p_stat->secsize = _cdio_len2blocks (p_stat->size, ISO_BLOCKSIZE); p_stat->rr.b3_rock = dunno; /*FIXME should do based on mask */ p_stat->b_xa = false; { char rr_fname[256] = ""; int i_rr_fname = #ifdef HAVE_ROCK get_rock_ridge_filename(p_iso9660_dir, rr_fname, p_stat); #else 0; #endif if (i_rr_fname > 0) { if (i_rr_fname > i_fname) { /* realloc gives valgrind errors */ iso9660_stat_t *p_stat_new = calloc(1, sizeof(iso9660_stat_t)+i_rr_fname+2); if (!p_stat_new) { cdio_warn("Couldn't calloc(1, %d)", sizeof(iso9660_stat_t)+i_rr_fname+2); return NULL; } memcpy(p_stat_new, p_stat, stat_len); free(p_stat); p_stat = p_stat_new; } strncpy(p_stat->filename, rr_fname, i_rr_fname+1); } else { if ('\0' == p_iso9660_dir->filename[0] && 1 == i_fname) strncpy (p_stat->filename, ".", sizeof(".")); else if ('\1' == p_iso9660_dir->filename[0] && 1 == i_fname) strncpy (p_stat->filename, "..", sizeof("..")); #ifdef HAVE_JOLIET else if (i_joliet_level) { int i_inlen = i_fname; cdio_utf8_t *p_psz_out = NULL; if (cdio_charset_to_utf8(p_iso9660_dir->filename, i_inlen, &p_psz_out, "UCS-2BE")) { strncpy(p_stat->filename, p_psz_out, i_fname); free(p_psz_out); } else { return NULL; } } #endif /*HAVE_JOLIET*/ else { strncpy (p_stat->filename, p_iso9660_dir->filename, i_fname); } } } iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(p_stat->tm)); if (dir_len < sizeof (iso9660_dir_t)) { free(p_stat->rr.psz_symlink); free(p_stat); return NULL; } { int su_length = iso9660_get_dir_len(p_iso9660_dir) - sizeof (iso9660_dir_t); su_length -= i_fname; if (su_length % 2) su_length--; if (su_length < 0 || su_length < sizeof (iso9660_xa_t)) return p_stat; if (nope == b_xa) { return p_stat; } else { iso9660_xa_t *xa_data = (void *) (((char *) p_iso9660_dir) + (iso9660_get_dir_len(p_iso9660_dir) - su_length)); cdio_log_level_t loglevel = (yep == b_xa) ? CDIO_LOG_WARN : CDIO_LOG_INFO; if (xa_data->signature[0] != 'X' || xa_data->signature[1] != 'A') { cdio_log (loglevel, "XA signature not found in ISO9660's system use area;" " ignoring XA attributes for this file entry."); cdio_debug ("%d %d %d, '%c%c' (%d, %d)", iso9660_get_dir_len(p_iso9660_dir), i_fname, su_length, xa_data->signature[0], xa_data->signature[1], xa_data->signature[0], xa_data->signature[1]); return p_stat; } p_stat->b_xa = true; p_stat->xa = *xa_data; } } return p_stat; }
void iso9660_dir_add_entry_su(void *dir, const char filename[], uint32_t extent, uint32_t size, uint8_t file_flags, const void *su_data, unsigned int su_size, const time_t *entry_time) { iso9660_dir_t *idr = dir; uint8_t *dir8 = dir; unsigned int offset = 0; uint32_t dsize = from_733(idr->size); int length, su_offset; struct tm temp_tm; cdio_assert (sizeof(iso9660_dir_t) == 33); if (!dsize && !idr->length) dsize = ISO_BLOCKSIZE; /* for when dir lacks '.' entry */ cdio_assert (dsize > 0 && !(dsize % ISO_BLOCKSIZE)); cdio_assert (dir != NULL); cdio_assert (extent > 17); cdio_assert (filename != NULL); cdio_assert (strlen(filename) <= MAX_ISOPATHNAME); length = sizeof(iso9660_dir_t); length += strlen(filename); length = _cdio_ceil2block (length, 2); /* pad to word boundary */ su_offset = length; length += su_size; length = _cdio_ceil2block (length, 2); /* pad to word boundary again */ /* find the last entry's end */ { unsigned int ofs_last_rec = 0; offset = 0; while (offset < dsize) { if (!dir8[offset]) { offset++; continue; } offset += dir8[offset]; ofs_last_rec = offset; } cdio_assert (offset == dsize); offset = ofs_last_rec; } /* be sure we don't cross sectors boundaries */ offset = _cdio_ofs_add (offset, length, ISO_BLOCKSIZE); offset -= length; cdio_assert (offset + length <= dsize); idr = (iso9660_dir_t *) &dir8[offset]; cdio_assert (offset+length < dsize); memset(idr, 0, length); idr->length = to_711(length); idr->extent = to_733(extent); idr->size = to_733(size); gmtime_r(entry_time, &temp_tm); iso9660_set_dtime (&temp_tm, &(idr->recording_time)); idr->file_flags = to_711(file_flags); idr->volume_sequence_number = to_723(1); idr->filename.len = to_711(strlen(filename) ? strlen(filename) : 1); /* working hack! */ memcpy(&idr->filename.str[1], filename, from_711(idr->filename.len)); memcpy(&dir8[offset] + su_offset, su_data, su_size); }
int iso9660_get_pvd_space_size(const iso9660_pvd_t *pvd) { if (NULL == pvd) return 0; return from_733(pvd->volume_space_size); }
uint8_t iso9660_get_dir_size(const iso9660_dir_t *idr) { if (NULL == idr) return 0; return from_733(idr->size); }
lsn_t iso9660_get_dir_extent(const iso9660_dir_t *idr) { if (NULL == idr) return 0; return from_733(idr->extent); }
void iso9660::Scan() { if (m_hCDROM != NULL) return ; m_hCDROM = CIoSupport::OpenCDROM(); CIoSupport::AllocReadBuffer(); m_paths = 0; m_lastpath = 0; memset(&m_info, 0, sizeof(m_info)); m_info.ISO_HANDLE = m_hCDROM ; m_info.Curr_dir_cache = 0; m_info.Curr_dir = (char*)malloc( 4096 ); strcpy( m_info.Curr_dir, "\\" ); CSingleLock lock(m_critSection); DWORD lpNumberOfBytesRead = 0; ::SetFilePointer( m_info.ISO_HANDLE, 0x8000, 0, FILE_BEGIN ); ::ReadFile( m_info.ISO_HANDLE, &m_info.iso, sizeof(m_info.iso), &lpNumberOfBytesRead, NULL ); if (strncmp(m_info.iso.szSignature, "CD001", 5)) { CIoSupport::CloseCDROM( m_info.ISO_HANDLE); CIoSupport::FreeReadBuffer(); m_info.ISO_HANDLE = NULL; m_hCDROM = NULL; m_info.iso9660 = 0; return ; } else { m_info.iso9660 = 1; m_info.joliet = 0; m_info.HeaderPos = 0x8000; int current = 0x8000; WORD wSectorSize = from_723(m_info.iso.logical_block_size); // first check if first file in the current VD has a rock-ridge NM. if it has, disable joliet iso9660_Directory *dirPointer = reinterpret_cast<iso9660_Directory*>(&m_info.iso.szRootDir); ::SetFilePointer( m_info.ISO_HANDLE, wSectorSize * from_733(dirPointer->extent), 0, FILE_BEGIN ); DWORD lpNumberOfBytesRead; char* pCurr_dir_cache = (char*)malloc( 16*wSectorSize ); iso9660_Directory isodir; BOOL bResult = ::ReadFile( m_info.ISO_HANDLE, pCurr_dir_cache, wSectorSize, &lpNumberOfBytesRead, NULL ); memcpy( &isodir, pCurr_dir_cache, sizeof(isodir)); int iso9660searchpointer=0; if ( isodir.ucRecordLength ) iso9660searchpointer += isodir.ucRecordLength; else iso9660searchpointer = (iso9660searchpointer - (iso9660searchpointer % wSectorSize)) + wSectorSize; memcpy( &isodir, pCurr_dir_cache + iso9660searchpointer, std::min(sizeof(isodir), sizeof(m_info.isodir))); free(pCurr_dir_cache); if (bResult && lpNumberOfBytesRead == wSectorSize) bResult = IsRockRidge(isodir); while ( m_info.iso.byOne != 255) { if ( ( m_info.iso.byZero3[0] == 0x25 ) && ( m_info.iso.byZero3[1] == 0x2f ) && !bResult ) { switch ( m_info.iso.byZero3[2] ) { case 0x45 : case 0x40 : case 0x43 : m_info.HeaderPos = current; m_info.joliet = 1; } // 25 2f 45 or 25 2f 40 or 25 2f 43 = jouliet, and best fitted for reading } current += 0x800; ::SetFilePointer( m_info.ISO_HANDLE, current, 0, FILE_BEGIN ); ::ReadFile( m_info.ISO_HANDLE, &m_info.iso, sizeof(m_info.iso), &lpNumberOfBytesRead, NULL ); } ::SetFilePointer( m_info.ISO_HANDLE, m_info.HeaderPos, 0, FILE_BEGIN ); ::ReadFile( m_info.ISO_HANDLE, &m_info.iso, sizeof(m_info.iso), &lpNumberOfBytesRead, NULL ); memcpy( &m_info.isodir, m_info.iso.szRootDir, sizeof(m_info.isodir)); } memcpy( &m_info.isodir, &m_info.iso.szRootDir, sizeof(m_info.isodir) ); ReadRecursiveDirFromSector( from_733(m_info.isodir.extent), "\\" ); }
//****************************************************************************************************************** struct iso_dirtree *iso9660::ReadRecursiveDirFromSector( DWORD sector, const char *path ) { struct iso_dirtree* pDir = NULL; struct iso_dirtree* pFile_Pointer = NULL; char* pCurr_dir_cache = NULL; DWORD iso9660searchpointer; struct iso9660_Directory isodir; struct iso9660_Directory curr_dir; WORD wSectorSize = from_723(m_info.iso.logical_block_size); struct iso_directories *point = m_lastpath; if (point) { while ( point->next ) { if (strcmp(path, point->path) == 0) return NULL; point = point->next; } } #ifdef _DEBUG_OUTPUT std::string strTmp; strTmp = StringUtils::Format("****************** Adding dir : %s\r", path); OutputDebugString( strTmp.c_str() ); #endif pDir = (struct iso_dirtree *)malloc(sizeof(struct iso_dirtree)); if (!pDir) return NULL; pDir->next = NULL; pDir->path = NULL; pDir->name = NULL; pDir->dirpointer = NULL; pFile_Pointer = pDir; m_vecDirsAndFiles.push_back(pDir); ::SetFilePointer( m_info.ISO_HANDLE, wSectorSize * sector, 0, FILE_BEGIN ); DWORD lpNumberOfBytesRead = 0; pCurr_dir_cache = (char*)malloc( 16*wSectorSize ); if (!pCurr_dir_cache ) return NULL; BOOL bResult = ::ReadFile( m_info.ISO_HANDLE, pCurr_dir_cache, wSectorSize, &lpNumberOfBytesRead, NULL ); if (!bResult || lpNumberOfBytesRead != wSectorSize) { CLog::Log(LOGERROR, "%s: unable to read", __FUNCTION__); free(pCurr_dir_cache); return NULL; } memcpy( &isodir, pCurr_dir_cache, sizeof(isodir) ); memcpy( &curr_dir, pCurr_dir_cache, sizeof(isodir) ); DWORD curr_dirSize = from_733(curr_dir.size); if ( curr_dirSize > wSectorSize ) { free( pCurr_dir_cache ); pCurr_dir_cache = (char*)malloc( 16 * from_733(isodir.size) ); if (!pCurr_dir_cache ) return NULL; ::SetFilePointer( m_info.ISO_HANDLE, wSectorSize * sector, 0, FILE_BEGIN ); bResult = ::ReadFile( m_info.ISO_HANDLE, pCurr_dir_cache , curr_dirSize, &lpNumberOfBytesRead, NULL ); if (!bResult || lpNumberOfBytesRead != curr_dirSize) { CLog::Log(LOGERROR, "%s: unable to read", __FUNCTION__); free(pCurr_dir_cache); return NULL; } } iso9660searchpointer = 0; if (!m_lastpath) { m_lastpath = m_paths; if ( !m_lastpath ) { m_paths = (struct iso_directories *)malloc(sizeof(struct iso_directories)); if (!m_paths ) { free(pCurr_dir_cache); return NULL; } m_paths->path = NULL; m_paths->dir = NULL; m_paths->next = NULL; m_lastpath = m_paths; } else { while ( m_lastpath->next ) m_lastpath = m_lastpath->next; } } m_lastpath->next = ( struct iso_directories *)malloc( sizeof( struct iso_directories ) ); if (!m_lastpath->next ) { free(pCurr_dir_cache); return NULL; } m_lastpath = m_lastpath->next; m_lastpath->next = NULL; m_lastpath->dir = pDir; m_lastpath->path = (char *)malloc(strlen(path) + 1); if (!m_lastpath->path ) { free(pCurr_dir_cache); return NULL; } strcpy( m_lastpath->path, path ); while ( 1 ) { if ( isodir.ucRecordLength ) iso9660searchpointer += isodir.ucRecordLength; else { iso9660searchpointer = (iso9660searchpointer - (iso9660searchpointer % wSectorSize)) + wSectorSize; } if ( curr_dirSize <= iso9660searchpointer ) { break; } int isize = std::min(sizeof(isodir), sizeof(m_info.isodir)); memcpy( &isodir, pCurr_dir_cache + iso9660searchpointer, isize); if (!isodir.ucRecordLength) continue; if ( !(isodir.byFlags & Flag_NotExist) ) { if ( (!( isodir.byFlags & Flag_Directory )) && ( isodir.Len_Fi > 1) ) { std::string temp_text ; bool bContinue = false; if ( m_info.joliet ) { bContinue = true; isodir.FileName[isodir.Len_Fi] = isodir.FileName[isodir.Len_Fi + 1] = 0; //put terminator by its length temp_text = GetThinText(isodir.FileName, isodir.Len_Fi ); // temp_text.resize(isodir.Len_Fi); } if (!m_info.joliet && isodir.FileName[0] >= 0x20 ) { temp_text = ParseName(isodir); bContinue = true; } if (bContinue) { int semipos = temp_text.find(";", 0); if (semipos >= 0) temp_text.erase(semipos, temp_text.length() - semipos); pFile_Pointer->next = (struct iso_dirtree *)malloc(sizeof(struct iso_dirtree)); if (!pFile_Pointer->next) break; m_vecDirsAndFiles.push_back(pFile_Pointer->next); pFile_Pointer = pFile_Pointer->next; pFile_Pointer->next = 0; pFile_Pointer->dirpointer = NULL; pFile_Pointer->path = (char *)malloc(strlen(path) + 1); if (!pFile_Pointer->path) { free(pCurr_dir_cache); return NULL; } strcpy( pFile_Pointer->path, path ); pFile_Pointer->name = (char *)malloc( temp_text.length() + 1); if (!pFile_Pointer->name) { free(pCurr_dir_cache); return NULL; } strcpy( pFile_Pointer->name , temp_text.c_str()); #ifdef _DEBUG_OUTPUT //std::string strTmp; //strTmp = StringUtils::Format("adding sector : %X, File : %s size = %u pos = %x\r",sector,temp_text.c_str(), isodir.dwFileLengthLE, isodir.dwFileLocationLE ); //OutputDebugString( strTmp.c_str()); #endif pFile_Pointer->Location = from_733(isodir.extent); pFile_Pointer->dirpointer = NULL; pFile_Pointer ->Length = from_733(isodir.size); IsoDateTimeToFileTime(&isodir.DateTime, &pFile_Pointer->filetime); pFile_Pointer->type = 1; } } } } iso9660searchpointer = 0; memcpy( &curr_dir, pCurr_dir_cache, sizeof(isodir) ); memcpy( &isodir, pCurr_dir_cache, sizeof(isodir) ); while ( 1 ) { if ( isodir.ucRecordLength ) iso9660searchpointer += isodir.ucRecordLength; else { iso9660searchpointer = (iso9660searchpointer - (iso9660searchpointer % wSectorSize)) + wSectorSize; } if ( from_733(curr_dir.size) <= iso9660searchpointer ) { free( pCurr_dir_cache ); pCurr_dir_cache = NULL; return pDir; } memcpy( &isodir, pCurr_dir_cache + iso9660searchpointer, std::min(sizeof(isodir), sizeof(m_info.isodir))); if (!isodir.ucRecordLength) continue; if ( !(isodir.byFlags & Flag_NotExist) ) { if ( (( isodir.byFlags & Flag_Directory )) && ( isodir.Len_Fi > 1) ) { std::string temp_text ; bool bContinue = false; if ( m_info.joliet ) { bContinue = true; isodir.FileName[isodir.Len_Fi] = isodir.FileName[isodir.Len_Fi + 1] = 0; //put terminator by its length temp_text = GetThinText(isodir.FileName, isodir.Len_Fi); // temp_text.resize(isodir.Len_Fi); } if (!m_info.joliet && isodir.FileName[0] >= 0x20 ) { temp_text = ParseName(isodir); bContinue = true; } if (bContinue) { // int semipos = temp_text.find(";",0); //the directory is not seperate by ";",but by its length // if (semipos >= 0) // temp_text.erase(semipos,temp_text.length()-semipos); pFile_Pointer->next = (struct iso_dirtree *)malloc(sizeof(struct iso_dirtree)); if (!pFile_Pointer->next) { free(pCurr_dir_cache); return NULL; } m_vecDirsAndFiles.push_back(pFile_Pointer->next); pFile_Pointer = pFile_Pointer->next; pFile_Pointer->next = 0; pFile_Pointer->dirpointer = NULL; pFile_Pointer->path = (char *)malloc(strlen(path) + 1); if (!pFile_Pointer->path) { free(pCurr_dir_cache); return NULL; } strcpy( pFile_Pointer->path, path ); pFile_Pointer->name = (char *)malloc( temp_text.length() + 1); if (!pFile_Pointer->name) { free(pCurr_dir_cache); return NULL; } strcpy( pFile_Pointer->name , temp_text.c_str()); DWORD dwFileLocation = from_733(isodir.extent); #ifdef _DEBUG_OUTPUT std::string strTmp; strTmp = StringUtils::Format("adding directory sector : %X, File : %s size = %u pos = %x\r", sector, temp_text.c_str(), from_733(isodir.size), dwFileLocation ); OutputDebugString( strTmp.c_str()); #endif pFile_Pointer->Location = dwFileLocation; pFile_Pointer->dirpointer = NULL; pFile_Pointer->Length = from_733(isodir.size); IsoDateTimeToFileTime(&isodir.DateTime, &pFile_Pointer->filetime); std::string strPath = path; if ( strlen( path ) > 1 ) strPath += "\\"; strPath += temp_text; pFile_Pointer->dirpointer = ReadRecursiveDirFromSector( dwFileLocation, strPath.c_str() ); pFile_Pointer->type = 2; } } } } return NULL; }
static iso9660_stat_t * _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool b_mode2, uint8_t i_joliet_level) { iso9660_xa_t *xa_data = NULL; uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir); unsigned int filename_len; unsigned int stat_len; iso9660_stat_t *stat; if (!dir_len) return NULL; filename_len = from_711(p_iso9660_dir->filename_len); /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */ stat_len = sizeof(iso9660_stat_t)+filename_len+2; stat = _cdio_malloc(stat_len); stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY) ? _STAT_DIR : _STAT_FILE; stat->lsn = from_733 (p_iso9660_dir->extent); stat->size = from_733 (p_iso9660_dir->size); stat->secsize = _cdio_len2blocks (stat->size, ISO_BLOCKSIZE); if ('\0' == p_iso9660_dir->filename[0] && 1 == filename_len) strcpy (stat->filename, "."); else if ('\1' == p_iso9660_dir->filename[0] && 1 == filename_len) strcpy (stat->filename, ".."); else { #ifdef HAVE_JOLIET if (i_joliet_level) { int i_inlen = filename_len; int i_outlen = (i_inlen / 2); char *p_psz_out = NULL; ucs2be_to_locale(p_iso9660_dir->filename, i_inlen, &p_psz_out, i_outlen); strncpy(stat->filename, p_psz_out, filename_len); free(p_psz_out); } else #endif /*HAVE_JOLIET*/ strncpy (stat->filename, p_iso9660_dir->filename, filename_len); } iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(stat->tm)); cdio_assert (dir_len >= sizeof (iso9660_dir_t)); if (b_mode2) { int su_length = iso9660_get_dir_len(p_iso9660_dir) - sizeof (iso9660_dir_t); su_length -= filename_len; if (su_length % 2) su_length--; if (su_length < 0 || su_length < sizeof (iso9660_xa_t)) return stat; xa_data = (void *) (((char *) p_iso9660_dir) + (iso9660_get_dir_len(p_iso9660_dir) - su_length)); if (xa_data->signature[0] != 'X' || xa_data->signature[1] != 'A') { cdio_warn ("XA signature not found in ISO9660's system use area;" " ignoring XA attributes for this file entry."); cdio_debug ("%d %d %d, '%c%c' (%d, %d)", iso9660_get_dir_len(p_iso9660_dir), filename_len, su_length, xa_data->signature[0], xa_data->signature[1], xa_data->signature[0], xa_data->signature[1]); return stat; } stat->xa = *xa_data; } return stat; }