udf_dirent_t * udf_fopen(udf_dirent_t *p_udf_root, const char *psz_name) { udf_dirent_t *p_udf_file = NULL; if (p_udf_root) { char tokenline[udf_MAX_PATHLEN]; char *psz_token; /* file position must be reset when accessing a new file */ p_udf_root->p_udf->i_position = 0; strncpy(tokenline, psz_name, udf_MAX_PATHLEN-1); tokenline[udf_MAX_PATHLEN-1] = '\0'; psz_token = strtok(tokenline, udf_PATH_DELIMITERS); if (psz_token) { udf_dirent_t *p_udf_dirent = udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf, p_udf_root->psz_name, p_udf_root->b_dir, p_udf_root->b_parent); p_udf_file = udf_ff_traverse(p_udf_dirent, psz_token); } else if ( 0 == strncmp("/", psz_name, sizeof("/")) ) { return udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf, p_udf_root->psz_name, p_udf_root->b_dir, p_udf_root->b_parent); } } return p_udf_file; }
/* Searches p_udf_dirent for a directory entry called psz_token. Note that p_udf_dirent may be replaced or freed during this call and only the returned udf_dirent_t must be used afterwards. */ static udf_dirent_t * udf_ff_traverse(udf_dirent_t *p_udf_dirent, char *psz_token) { while ((p_udf_dirent = udf_readdir(p_udf_dirent))) { if (strcmp(psz_token, p_udf_dirent->psz_name) == 0) { char *next_tok = strtok(NULL, udf_PATH_DELIMITERS); if (!next_tok) return p_udf_dirent; /* found */ else if (p_udf_dirent->b_dir) { udf_dirent_t * p_udf_dirent_next = udf_opendir(p_udf_dirent); if (p_udf_dirent_next) { /* free p_udf_dirent to avoid leaking memory. */ udf_dirent_free(p_udf_dirent); /* previous p_udf_dirent_next is freed by udf_ff_traverse. */ p_udf_dirent_next = udf_ff_traverse(p_udf_dirent_next, next_tok); return p_udf_dirent_next; } } } } return NULL; }
udf_dirent_t * udf_fopen(udf_dirent_t *p_udf_root, const char *psz_name) { udf_dirent_t *p_udf_file = NULL; if (p_udf_root) { char tokenline[udf_MAX_PATHLEN]; char *psz_token; strncpy(tokenline, psz_name, udf_MAX_PATHLEN); psz_token = strtok(tokenline, udf_PATH_DELIMITERS); if (psz_token) { /*** FIXME??? udf_dirent can be variable size due to the extended attributes and descriptors. Given that, is this correct? */ udf_dirent_t *p_udf_dirent = udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf, p_udf_root->psz_name, p_udf_root->b_dir, p_udf_root->b_parent); p_udf_file = udf_ff_traverse(p_udf_dirent, psz_token); udf_dirent_free(p_udf_dirent); } else if ( 0 == strncmp("/", psz_name, sizeof("/")) ) { return udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf, p_udf_root->psz_name, p_udf_root->b_dir, p_udf_root->b_parent); } } return p_udf_file; }
/* Searches p_udf_dirent a directory entry called psz_token. Note p_udf_dirent is continuously updated. If the entry is not found p_udf_dirent is useless and thus the caller should not use it afterwards. */ static udf_dirent_t * udf_ff_traverse(udf_dirent_t *p_udf_dirent, char *psz_token) { while (udf_readdir(p_udf_dirent)) { if (strcmp(psz_token, p_udf_dirent->psz_name) == 0) { char *next_tok = strtok(NULL, udf_PATH_DELIMITERS); if (!next_tok) return p_udf_dirent; /* found */ else if (p_udf_dirent->b_dir) { udf_dirent_t * p_udf_dirent2 = udf_opendir(p_udf_dirent); if (p_udf_dirent2) { udf_dirent_t * p_udf_dirent3 = udf_ff_traverse(p_udf_dirent2, next_tok); /* if p_udf_dirent3 is null p_udf_dirent2 is free'd. */ return p_udf_dirent3; } } } } free(p_udf_dirent->psz_name); return NULL; }
tp_udf_file udf_find_file(const HANDLE hDrive, const WORD partition, const char *name) { tp_udf_file f = udf_get_root(hDrive, partition), f2 = NULL; if (f) { char tokenline[udf_MAX_PATHLEN]; char *token; strcpy(tokenline, name); token = strtok(tokenline, udf_PATH_DELIMITERS); if (token) { f2 = udf_ff_traverse(hDrive, f, token); } udf_free(f); } return f2; }
static tp_udf_file udf_ff_traverse(const HANDLE hDrive, tp_udf_file f, char *token) { while (udf_get_next(hDrive, f)) { if (stricmp(token, f->name) == 0) { char *next_tok = strtok(NULL, udf_PATH_DELIMITERS); if (!next_tok) { return f; // found } else if (f->is_dir) { tp_udf_file f2 = udf_get_sub(hDrive, f); if (f2) { tp_udf_file f3 = udf_ff_traverse(hDrive, f2, next_tok); if (!f3) { udf_free(f2); } return f3; } } } } return NULL; }