12#define PCRE2_CODE_UNIT_WIDTH 8
19#define BLACKLIST_FILENAME "naev.BLACKLIST"
24typedef struct BlkFile_ {
47static PHYSFS_Io *blk_unsupportedIO(
void *opaque,
const char *filename );
48static int blk_unsupported(
void *opaque,
const char *name );
49static void *blk_openArchive( PHYSFS_Io *io,
const char *name,
int forWrite,
51static PHYSFS_EnumerateCallbackResult
52blk_enumerate(
void *opaque,
const char *dirname, PHYSFS_EnumerateCallback cb,
53 const char *origdir,
void *callbackdata );
54static PHYSFS_Io *blk_openRead(
void *opaque,
const char *fnm );
55static int blk_stat(
void *opaque,
const char *fn, PHYSFS_Stat *stat );
56static void blk_closeArchive(
void *opaque );
65 .extension =
"BLACKLIST",
66 .description =
"Naev blacklist archiver.",
67 .author =
"Naev DevTeam",
68 .url =
"https://naev.org",
69 .supportsSymlinks = 0,
71 .openArchive = blk_openArchive,
72 .enumerate = blk_enumerate,
73 .openRead = blk_openRead,
74 .openWrite = blk_unsupportedIO,
75 .openAppend = blk_unsupportedIO,
76 .remove = blk_unsupported,
77 .mkdir = blk_unsupported,
79 .closeArchive = blk_closeArchive,
82static PHYSFS_sint64 blk_read(
struct PHYSFS_Io *io,
void *buf,
84static PHYSFS_sint64 blk_write(
struct PHYSFS_Io *io,
const void *buffer,
86static int blk_seek(
struct PHYSFS_Io *io, PHYSFS_uint64 offset );
87static PHYSFS_sint64 blk_tell(
struct PHYSFS_Io *io );
88static PHYSFS_sint64 blk_length(
struct PHYSFS_Io *io );
89static struct PHYSFS_Io *blk_duplicate(
struct PHYSFS_Io *io );
90static int blk_flush(
struct PHYSFS_Io *io );
91static void blk_destroy(
struct PHYSFS_Io *io );
103 .length = blk_length,
104 .duplicate = blk_duplicate,
106 .destroy = blk_destroy,
117 .filetype = PHYSFS_FILETYPE_REGULAR,
129 .filetype = PHYSFS_FILETYPE_DIRECTORY,
145 dir_len = strlen( origdir );
146 fmt = ( ( dir_len && origdir[dir_len - 1] ==
'/' ) || dir_len == 0 )
149 SDL_asprintf( &path, fmt, origdir, fname );
150 if ( !PHYSFS_stat( path, &stat ) ) {
151 PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
152 if ( err != PHYSFS_ERR_BAD_FILENAME )
153 WARN( _(
"PhysicsFS: Cannot stat %s: %s" ), path,
154 _( PHYSFS_getErrorByCode( err ) ) );
156 }
else if ( stat.filetype == PHYSFS_FILETYPE_REGULAR ) {
161 rc = pcre2_match(
wht_re, (PCRE2_SPTR)path, strlen( path ), 0, 0,
165 case PCRE2_ERROR_NOMATCH:
168 WARN( _(
"Matching error %d" ), rc );
171 }
else if ( rc > 0 ) {
173 return PHYSFS_ENUM_OK;
178 rc = pcre2_match(
blk_re, (PCRE2_SPTR)path, strlen( path ), 0, 0,
182 case PCRE2_ERROR_NOMATCH:
186 WARN( _(
"Matching error %d" ), rc );
190 }
else if ( rc == 0 )
196 .filename = strdup( fname ),
197 .dirname = strdup( origdir ),
214 }
else if ( stat.filetype == PHYSFS_FILETYPE_DIRECTORY ) {
219 .filename = strdup( fname ),
220 .dirname = strdup( origdir ),
228 return PHYSFS_ENUM_OK;
231static pcre2_code *regex_make(
char *
const *lst )
237 PCRE2_SIZE erroroffset;
244 l +=
scnprintf( &buf[l],
sizeof( buf ) - l - 1,
"%s%s",
245 ( i == 0 ) ?
"" :
"|", lst[i] );
248 re = pcre2_compile( (PCRE2_SPTR)buf, PCRE2_ZERO_TERMINATED, 0, &errornumber,
249 &erroroffset, NULL );
251 PCRE2_UCHAR buffer[256];
252 pcre2_get_error_message( errornumber, buffer,
sizeof( buffer ) );
253 WARN( _(
"Blacklist PCRE2 compilation failed at offset %d: %s" ),
254 (
int)erroroffset, buffer );
295 pcre2_code_free(
blk_re );
298 pcre2_code_free(
wht_re );
309 PHYSFS_mountMemory( &
blk_archiver, 0, NULL, BLACKLIST_FILENAME, NULL, 0 );
311 WARN( _(
"PhysicsFS: %s" ),
312 _( PHYSFS_getErrorByCode( PHYSFS_getLastErrorCode() ) ) );
362 free(
blk_fs[i].filename );
363 free(
blk_fs[i].dirname );
384 const char *str = bsearch( &filename, lst,
array_size( lst ),
385 sizeof(
const char * ),
strsort );
386 return ( str != NULL );
389static PHYSFS_Io *blk_unsupportedIO(
void *opaque,
const char *filename )
396static int blk_unsupported(
void *opaque,
const char *filename )
403static void *blk_openArchive( PHYSFS_Io *io,
const char *name,
int forWrite,
408 if ( strcmp( name, BLACKLIST_FILENAME ) == 0 ) {
415static PHYSFS_EnumerateCallbackResult
416blk_enumerate(
void *opaque,
const char *dirname, PHYSFS_EnumerateCallback cb,
417 const char *origdir,
void *callbackdata )
421 PHYSFS_EnumerateCallbackResult retval = PHYSFS_ENUM_OK;
424 if ( strcmp(
blk_fs[i].dirname, origdir ) != 0 )
427 retval = cb( callbackdata, origdir,
blk_fs[i].filename );
428 if ( retval == PHYSFS_ENUM_ERROR )
429 PHYSFS_setErrorCode( PHYSFS_ERR_APP_CALLBACK );
430 if ( retval != PHYSFS_ENUM_OK )
437static PHYSFS_Io *blk_openRead(
void *opaque,
const char *fnm )
441 PHYSFS_Io *io = malloc(
sizeof( PHYSFS_Io ) );
448static int blk_stat(
void *opaque,
const char *fn, PHYSFS_Stat *stat )
462static void blk_closeArchive(
void *opaque )
467static PHYSFS_sint64 blk_read(
struct PHYSFS_Io *io,
void *buf,
476static PHYSFS_sint64 blk_write(
struct PHYSFS_Io *io,
const void *buffer,
485static int blk_seek(
struct PHYSFS_Io *io, PHYSFS_uint64 offset )
492static PHYSFS_sint64 blk_tell(
struct PHYSFS_Io *io )
498static PHYSFS_sint64 blk_length(
struct PHYSFS_Io *io )
504static struct PHYSFS_Io *blk_duplicate(
struct PHYSFS_Io *io )
509static int blk_flush(
struct PHYSFS_Io *io )
515static void blk_destroy(
struct PHYSFS_Io *io )
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Header file with generic functions and naev-specifics.
int strsort(const void *p1, const void *p2)
Sort function for sorting strings with qsort().
int scnprintf(char *text, size_t maxlen, const char *fmt,...)
Like snprintf(), but returns the number of characters ACTUALLY "printed" into the buffer....
static pcre2_code * blk_re
int blacklist_init(void)
Initializes the blacklist system if necessary. If no plugin is blacklisting, it will not do anything.
static const PHYSFS_Stat blk_emptystat
Stat for an empty regular file.
static int blk_matches(char **lst, const char *filename)
Tries to match a string in an array of strings that are sorted.
int blacklist_append(const char *path)
Appends a regex string to be blacklisted.
int whitelist_append(const char *path)
Appends a regex string to be whitelisted.
static char ** blk_dirnames
static pcre2_code * wht_re
static const PHYSFS_Stat blk_emptystatdir
Stat for a fake directory.
static char ** blk_blacklists
static char ** blk_blacklists_re
static const PHYSFS_Io blk_emptyio
Mimicks an empty file.
void blacklist_exit(void)
Exits the blacklist system and cleans up as necessary.
static char ** wht_blacklists_re
static pcre2_match_data * wht_match
static pcre2_match_data * blk_match
static const PHYSFS_Archiver blk_archiver
The archiver for blacklists.
static int blk_enumerateCallback(void *data, const char *origdir, const char *fname)
Used to build the blacklist and pseudo filesystem when iterating over real files.
Represents a file in a directory. Used to enumerate files.