/** * 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, 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) { uint8_t data[UDF_BLOCKSIZE]; logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data; char* r; int logvolid_len; /* 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; 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); return logvolid_len; }
/** * 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) { 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; volid_len = p_pvd->vol_ident[UDF_VOLID_SIZE-1]; if(volid_len > UDF_VOLID_SIZE-1) { /* this field is only UDF_VOLID_SIZE bytes something is wrong */ volid_len = UDF_VOLID_SIZE-1; } 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 */ } free(r); return volid_len; }
/** * Gets the Volume Identifier string, in 8bit unicode (latin-1) * psz_volid, place to put the string * i_volid_size, size of the buffer volid points to * returns the size of buffer needed for all data */ 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; unsigned int volid_len; /* get primary volume descriptor */ if ( DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &data, p_udf->pvd_lba, 1) ) return 0; volid_len = p_pvd->vol_ident[UDF_VOLID_SIZE-1]; if(volid_len > UDF_VOLID_SIZE-1) { /* 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; } unicode16_decode((uint8_t *) p_pvd->vol_ident, i_volid, psz_volid); return volid_len; }
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); return NULL; } /* file position must be reset when accessing a new file */ p_udf = p_udf_dirent->p_udf; p_udf->i_position = 0; if (p_udf_dirent->fid) { /* advance to next File Identifier Descriptor */ /* FIXME: need to advance file entry (fe) as well. */ uint32_t ofs = 4 * ((sizeof(*(p_udf_dirent->fid)) + p_udf_dirent->fid->u.i_imp_use + p_udf_dirent->fid->i_file_id + 3) / 4); p_udf_dirent->fid = (udf_fileid_desc_t *)((uint8_t *)p_udf_dirent->fid + ofs); } if (!p_udf_dirent->fid) { uint32_t i_sectors = (p_udf_dirent->i_loc_end - p_udf_dirent->i_loc + 1); uint32_t size = UDF_BLOCKSIZE * i_sectors; driver_return_code_t i_ret; if (!p_udf_dirent->sector) p_udf_dirent->sector = (uint8_t*) malloc(size); i_ret = udf_read_sectors(p_udf, p_udf_dirent->sector, p_udf_dirent->i_part_start+p_udf_dirent->i_loc, i_sectors); if (DRIVER_OP_SUCCESS == i_ret) p_udf_dirent->fid = (udf_fileid_desc_t *) p_udf_dirent->sector; else p_udf_dirent->fid = NULL; } if (p_udf_dirent->fid && !udf_checktag(&(p_udf_dirent->fid->tag), TAGID_FID)) { uint32_t ofs = 4 * ((sizeof(*p_udf_dirent->fid) + p_udf_dirent->fid->u.i_imp_use + p_udf_dirent->fid->i_file_id + 3) / 4); p_udf_dirent->dir_left -= ofs; p_udf_dirent->b_dir = (p_udf_dirent->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0; p_udf_dirent->b_parent = (p_udf_dirent->fid->file_characteristics & UDF_FILE_PARENT) != 0; { const unsigned int i_len = p_udf_dirent->fid->i_file_id; if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &p_udf_dirent->fe, p_udf->i_part_start + uint32_from_le(p_udf_dirent->fid->icb.loc.lba), 1)) { udf_dirent_free(p_udf_dirent); return NULL; } 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; } udf_dirent_free(p_udf_dirent); return NULL; }
udf_dirent_t * udf_readdir(udf_dirent_t *p_udf_dirent) { udf_t *p_udf; if (p_udf_dirent->dir_left <= 0) { udf_dirent_free(p_udf_dirent); return NULL; } p_udf = p_udf_dirent->p_udf; if (p_udf_dirent->fid) { /* advance to next File Identifier Descriptor */ /* FIXME: need to advance file entry (fe) as well. */ uint32_t ofs = 4 * ((sizeof(*(p_udf_dirent->fid)) + p_udf_dirent->fid->i_imp_use + p_udf_dirent->fid->i_file_id + 3) / 4); p_udf_dirent->fid = (udf_fileid_desc_t *)((uint8_t *)p_udf_dirent->fid + ofs); } if (!p_udf_dirent->fid) { uint32_t i_sectors = (p_udf_dirent->i_loc_end - p_udf_dirent->i_loc + 1); uint32_t size = UDF_BLOCKSIZE * i_sectors; driver_return_code_t i_ret; if (!p_udf_dirent->sector) p_udf_dirent->sector = (uint8_t*) malloc(size); i_ret = udf_read_sectors(p_udf, p_udf_dirent->sector, p_udf_dirent->i_part_start+p_udf_dirent->i_loc, i_sectors); if (DRIVER_OP_SUCCESS == i_ret) p_udf_dirent->fid = (udf_fileid_desc_t *) p_udf_dirent->sector; else p_udf_dirent->fid = NULL; } if (p_udf_dirent->fid && !udf_checktag(&(p_udf_dirent->fid->tag), TAGID_FID)) { uint32_t ofs = 4 * ((sizeof(*p_udf_dirent->fid) + p_udf_dirent->fid->i_imp_use + p_udf_dirent->fid->i_file_id + 3) / 4); p_udf_dirent->dir_left -= ofs; p_udf_dirent->b_dir = (p_udf_dirent->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0; p_udf_dirent->b_parent = (p_udf_dirent->fid->file_characteristics & UDF_FILE_PARENT) != 0; { const unsigned int i_len = p_udf_dirent->fid->i_file_id; uint8_t data[UDF_BLOCKSIZE] = {0}; udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) &data; if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, p_udf_fe, p_udf->i_part_start + p_udf_dirent->fid->icb.loc.lba, 1)) return NULL; memcpy(&(p_udf_dirent->fe), p_udf_fe, sizeof(udf_file_entry_t) + p_udf_fe->i_alloc_descs + p_udf_fe->i_extended_attr ); 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->imp_use + p_udf_dirent->fid->i_imp_use, i_len, p_udf_dirent->psz_name); } return p_udf_dirent; } return NULL; }