diff --git a/filesel/mdb.c b/filesel/mdb.c index 426c5c61..4a878dc8 100644 --- a/filesel/mdb.c +++ b/filesel/mdb.c @@ -493,7 +493,8 @@ int mdbWriteModuleInfo (uint32_t mdb_ref, struct moduleinfostruct *m) return !retval; } -void mdbScan (struct ocpfile_t *file, uint32_t mdb_ref) +/* if retain is non-zero, do not unref filehandle, but pass it to caller when done */ +void mdbScan (struct ocpfile_t *file, uint32_t mdb_ref, struct ocpfilehandle_t **retain) { DEBUG_PRINT ("mdbScan(file=%p, mdb_ref=0x%08"PRIx32")\n", file, mdb_ref); assert (mdb_ref > 0); @@ -519,7 +520,12 @@ void mdbScan (struct ocpfile_t *file, uint32_t mdb_ref) } mdbGetModuleInfo(&mdbEditBuf, mdb_ref); mdbReadInfo(&mdbEditBuf, f); - f->unref (f); + if (retain) + { + *retain = f; + } else { + f->unref (f); + } mdbWriteModuleInfo(mdb_ref, &mdbEditBuf); } } diff --git a/filesel/mdb.h b/filesel/mdb.h index 9ce707d0..a9de0cc9 100644 --- a/filesel/mdb.h +++ b/filesel/mdb.h @@ -79,7 +79,7 @@ int mdbGetModuleType (uint32_t fileref, struct moduletype *dst); int mdbInfoIsAvailable (uint32_t fileref); // used to be mdbInfoRead int mdbReadInfo(struct moduleinfostruct *m, struct ocpfilehandle_t *f); int mdbWriteModuleInfo(uint32_t fileref, struct moduleinfostruct *m); // returns zero on error -void mdbScan(struct ocpfile_t *file, uint32_t mdb_ref); +void mdbScan(struct ocpfile_t *file, uint32_t mdb_ref, struct ocpfilehandle_t **retain); // if retain is non-zero, do not unref filehandle, but pass it to caller int mdbInit (const struct configAPI_t *configAPI); // returns zero on error void mdbUpdate(void); void mdbClose(void); diff --git a/filesel/modlist.c b/filesel/modlist.c index 7250e232..67b76ede 100644 --- a/filesel/modlist.c +++ b/filesel/modlist.c @@ -185,7 +185,7 @@ void modlist_append_drive (struct modlist *modlist, struct dmDrive *drive) modlist_append (modlist, &entry); } -void modlist_append_file (struct modlist *modlist, struct ocpfile_t *file, int ismod, int prescanhint) +void modlist_append_file (struct modlist *modlist, struct ocpfile_t *file, int ismod, int prescanhint, struct ocpfilehandle_t **retain) { struct modlistentry entry = {{0}}; const char *childpath = 0; @@ -216,7 +216,7 @@ void modlist_append_file (struct modlist *modlist, struct ocpfile_t *file, int i { if (prescanhint && (!mdbInfoIsAvailable(entry.mdb_ref))) { - mdbScan (file, entry.mdb_ref); + mdbScan (file, entry.mdb_ref, retain); entry.flags |= MODLIST_FLAG_SCANNED; } } diff --git a/filesel/modlist.h b/filesel/modlist.h index c01c798c..4c8380fe 100644 --- a/filesel/modlist.h +++ b/filesel/modlist.h @@ -42,7 +42,7 @@ void modlist_append(struct modlist *modlist, struct modlistentry *entry); void modlist_append_dir (struct modlist *modlist, struct ocpdir_t *dir); void modlist_append_dotdot (struct modlist *modlist, struct ocpdir_t *dir); void modlist_append_drive (struct modlist *modlist, struct dmDrive *drive); -void modlist_append_file (struct modlist *modlist, struct ocpfile_t *file, int ismod, int prescanhint); /* if file is stored SOLID, trigger a mdb scan if needed */ +void modlist_append_file (struct modlist *modlist, struct ocpfile_t *file, int ismod, int prescanhint, struct ocpfilehandle_t **retain); /* if file is stored SOLID, trigger a mdb scan if needed */ void modlist_swap(struct modlist *modlist, unsigned int index1, unsigned int index2); void modlist_clear(struct modlist *modlist); diff --git a/filesel/pfilesel.c b/filesel/pfilesel.c index 3c887fc7..11fd457f 100644 --- a/filesel/pfilesel.c +++ b/filesel/pfilesel.c @@ -133,6 +133,8 @@ struct fsReadDir_token_t int cancel_recursive; char *parent_displaydir; + + struct ocpfilehandle_t *fileretain; /* hack to keep one file open in archives, to ensure they remain open while scanning their content */ }; static void fsReadDir_file (void *_token, struct ocpfile_t *file) @@ -172,11 +174,6 @@ static void fsReadDir_file (void *_token, struct ocpfile_t *file) { unsigned int mlTop=plScrHeight/2-2; unsigned int i; - char *oldparent_displaydir; - - /* store the callers directory - we might be running recursive */ - oldparent_displaydir = token->parent_displaydir; - token->parent_displaydir = 0; /* draw a box and information to the display... resize of the display will not be gracefull during a directory scan */ displayvoid(mlTop+1, 5, plScrWidth-10); @@ -202,13 +199,17 @@ static void fsReadDir_file (void *_token, struct ocpfile_t *file) displaystr(mlTop+4, plScrWidth-5, 0x04, "\xd9", 1); } displaystr (mlTop + 1, 5, 0x09, "Scanning content of the given file. Press space to cancel", plScrWidth - 10); - dirdbGetFullname_malloc (dir->dirdb_ref, &token->parent_displaydir, DIRDB_FULLNAME_ENDSLASH); - displaystr_utf8_overflowleft (mlTop + 3, 5, 0x0a, token->parent_displaydir, plScrWidth - 10); + { /* do the actual scan */ + struct fsReadDir_token_t innertoken = *token; + innertoken.parent_displaydir = 0; + innertoken.fileretain = 0; - { /* do the actual scan */ - ocpdirhandle_pt dh = dir->readflatdir_start (dir, fsReadDir_file, token); /* recycle the same token... */ - while (dir->readdir_iterate (dh) && (!token->cancel_recursive)) + dirdbGetFullname_malloc (dir->dirdb_ref, &innertoken.parent_displaydir, DIRDB_FULLNAME_ENDSLASH); + displaystr_utf8_overflowleft (mlTop + 3, 5, 0x0a, innertoken.parent_displaydir, plScrWidth - 10); + + ocpdirhandle_pt dh = dir->readflatdir_start (dir, fsReadDir_file, &innertoken); + while (dir->readdir_iterate (dh) && (!innertoken.cancel_recursive)) { if (poll_framelock()) { @@ -217,7 +218,7 @@ static void fsReadDir_file (void *_token, struct ocpfile_t *file) int key = Console.KeyboardGetChar(); if ((key == ' ') || (key == KEY_EXIT)) { - token->cancel_recursive = 1; + innertoken.cancel_recursive = 1; } if (key == VIRT_KEY_RESIZE) { @@ -227,11 +228,18 @@ static void fsReadDir_file (void *_token, struct ocpfile_t *file) } } } + + free (innertoken.parent_displaydir); + if (innertoken.fileretain) + { + innertoken.fileretain->unref (innertoken.fileretain); + innertoken.fileretain = 0; + } + token->cancel_recursive |= innertoken.cancel_recursive; dir->readdir_cancel (dh); } /* undo the filename displayed */ - free (token->parent_displaydir); token->parent_displaydir = oldparent_displaydir; if (token->parent_displaydir) { displaystr_utf8_overflowleft (mlTop + 3, 5, 0x0a, token->parent_displaydir, plScrWidth - 10); @@ -284,7 +292,7 @@ static void fsReadDir_file (void *_token, struct ocpfile_t *file) if (ismod || // always include if file is an actual module (fsShowAllFiles && (!(token->opt & RD_ISMODONLY)))) // force include if fsShowAllFiles is true, except if RD_ISMODONLY { - modlist_append_file (token->ml, file, ismod, file->compression >= COMPRESSION_SOLID && (file->compression < COMPRESSION_REMOTE)); /* modlist_append() will do refcount on the file */ + modlist_append_file (token->ml, file, ismod, file->compression >= COMPRESSION_SOLID && (file->compression < COMPRESSION_REMOTE), token->fileretain ? 0 : &token->fileretain); /* modlist_append() will do refcount on the file */ } out: free (curext); @@ -342,6 +350,7 @@ int fsReadDir (struct modlist *ml, struct ocpdir_t *dir, const char *mask, unsig token.mask = (char *)mask; #endif token.opt = opt & ~(RD_SUBSORT); + token.fileretain = 0; if ((opt & RD_PUTRSUBS) && dir->readflatdir_start) { @@ -355,6 +364,11 @@ int fsReadDir (struct modlist *ml, struct ocpdir_t *dir, const char *mask, unsig #ifndef FNM_CASEFOLD free (token.mask); #endif + if (token.fileretain) + { + token.fileretain->unref (token.fileretain); + token.fileretain = 0; + } return 0; } while (dir->readdir_iterate (dh)) @@ -377,6 +391,11 @@ int fsReadDir (struct modlist *ml, struct ocpdir_t *dir, const char *mask, unsig #ifndef FNM_CASEFOLD free (token.mask); #endif + if (token.fileretain) + { + token.fileretain->unref (token.fileretain); + token.fileretain = 0; + } if (opt & RD_SUBSORT) { @@ -520,7 +539,7 @@ static void addfiles_file (void *token, struct ocpfile_t *file) } if (fsIsModule(curext)) { - modlist_append_file (playlist, file, 1, 0); /* modlist_append calls file->ref (file); for us */ + modlist_append_file (playlist, file, 1, 0, 0); /* modlist_append calls file->ref (file); for us */ } free (curext); } @@ -3299,7 +3318,7 @@ signed int fsFileSelect(void) int poll = 1; if ((m->file && (m->file->compression < COMPRESSION_REMOTE) && (m->flags & MODLIST_FLAG_ISMOD)) && (!mdbInfoIsAvailable(m->mdb_ref)) && (!(m->flags&MODLIST_FLAG_SCANNED))) { - mdbScan(m->file, m->mdb_ref); + mdbScan(m->file, m->mdb_ref, 0); m->flags |= MODLIST_FLAG_SCANNED; } @@ -3312,7 +3331,7 @@ signed int fsFileSelect(void) { if (!mdbInfoIsAvailable(scanm->mdb_ref)) { - mdbScan(scanm->file, scanm->mdb_ref); + mdbScan(scanm->file, scanm->mdb_ref, 0); scanm->flags |= MODLIST_FLAG_SCANNED; if (poll_framelock()) @@ -3333,7 +3352,7 @@ signed int fsFileSelect(void) { if (!mdbInfoIsAvailable(scanm->mdb_ref)) { - mdbScan(scanm->file, scanm->mdb_ref); + mdbScan(scanm->file, scanm->mdb_ref, 0); scanm->flags |= MODLIST_FLAG_SCANNED; if (poll_framelock()) @@ -3470,7 +3489,7 @@ signed int fsFileSelect(void) mdbEditBuf.modtype.integer.i = mtUnRead; if (!mdbWriteModuleInfo(m->mdb_ref, &mdbEditBuf)) return -1; - mdbScan(m->file, m->mdb_ref); + mdbScan(m->file, m->mdb_ref, 0); m->flags |= MODLIST_FLAG_SCANNED; } break; @@ -3539,7 +3558,7 @@ signed int fsFileSelect(void) /* We delay mdbScan for remote files until this stage */ if (m && m->file && (m->file->compression >= COMPRESSION_REMOTE) && !(m->flags & MODLIST_FLAG_SCANNED)) { - mdbScan (m->file, m->mdb_ref); + mdbScan (m->file, m->mdb_ref, 0); m->flags |= MODLIST_FLAG_SCANNED; } if (win) diff --git a/medialib/medialib-scan.c b/medialib/medialib-scan.c index aa4c2f8f..cc5058a8 100644 --- a/medialib/medialib-scan.c +++ b/medialib/medialib-scan.c @@ -29,6 +29,7 @@ struct scanlist_t int entries; int size; int abort; + struct ocpfilehandle_t *retain; /* hack to keep one file open in archives, to ensure they remain open while scanning their content */ }; static void mlScanDraw(const char *title, struct scanlist_t *token) @@ -193,7 +194,7 @@ static void mlScan_file (void *_token, struct ocpfile_t *file) mdbref = mdbGetModuleReference2 (file->dirdb_ref, file->filesize(file)); if (!mdbInfoIsAvailable (mdbref)) { - mdbScan(file, mdbref); + mdbScan(file, mdbref, token->retain ? 0 : &token->retain); } dirdbMakeMdbRef(file->dirdb_ref, mdbref); @@ -231,6 +232,11 @@ static int mlScan(struct ocpdir_t *dir) if (!handle) { free (token.path); + if (token.retain) + { + token.retain->unref (token.retain); + token.retain = 0; + } return 0; } while (dir->readdir_iterate (handle) && (!token.abort)) @@ -249,5 +255,12 @@ static int mlScan(struct ocpdir_t *dir) free (token.files); free (token.path); + + if (token.retain) + { + token.retain->unref (token.retain); + token.retain = 0; + } + return token.abort; }