PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
filemap.h File Reference
#include "storage/relfilenode.h"
#include "storage/block.h"
#include "datapagemap.h"
Include dependency graph for filemap.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  file_entry_t
 
struct  filemap_t
 

Typedefs

typedef struct file_entry_t file_entry_t
 
typedef struct filemap_t filemap_t
 

Enumerations

enum  file_action_t {
  FILE_ACTION_CREATE, FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_ACTION_NONE,
  FILE_ACTION_TRUNCATE, FILE_ACTION_REMOVE
}
 
enum  file_type_t { FILE_TYPE_REGULAR, FILE_TYPE_DIRECTORY, FILE_TYPE_SYMLINK }
 

Functions

void filemap_create (void)
 
void calculate_totals (void)
 
void print_filemap (void)
 
void process_source_file (const char *path, file_type_t type, size_t newsize, const char *link_target)
 
void process_target_file (const char *path, file_type_t type, size_t newsize, const char *link_target)
 
void process_block_change (ForkNumber forknum, RelFileNode rnode, BlockNumber blkno)
 
void filemap_finalize (void)
 

Variables

filemap_tfilemap
 

Typedef Documentation

Enumeration Type Documentation

Enumerator
FILE_ACTION_CREATE 
FILE_ACTION_COPY 
FILE_ACTION_COPY_TAIL 
FILE_ACTION_NONE 
FILE_ACTION_TRUNCATE 
FILE_ACTION_REMOVE 

Definition at line 24 of file filemap.h.

25 {
26  FILE_ACTION_CREATE, /* create local directory or symbolic link */
27  FILE_ACTION_COPY, /* copy whole file, overwriting if exists */
28  FILE_ACTION_COPY_TAIL, /* copy tail from 'oldsize' to 'newsize' */
29  FILE_ACTION_NONE, /* no action (we might still copy modified
30  * blocks based on the parsed WAL) */
31  FILE_ACTION_TRUNCATE, /* truncate local file to 'newsize' bytes */
32  FILE_ACTION_REMOVE /* remove local file / directory / symlink */
file_action_t
Definition: filemap.h:24
Enumerator
FILE_TYPE_REGULAR 
FILE_TYPE_DIRECTORY 
FILE_TYPE_SYMLINK 

Definition at line 35 of file filemap.h.

Function Documentation

void calculate_totals ( void  )

Definition at line 479 of file filemap.c.

References file_entry_t::action, filemap_t::array, datapagemap::bitmapsize, datapagemap_iterate(), datapagemap_next(), filemap_t::fetch_size, FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_TYPE_REGULAR, filemap, i, filemap_t::narray, file_entry_t::newsize, file_entry_t::oldsize, file_entry_t::pagemap, pg_free(), filemap_t::total_size, and file_entry_t::type.

Referenced by main().

480 {
481  file_entry_t *entry;
482  int i;
483  filemap_t *map = filemap;
484 
485  map->total_size = 0;
486  map->fetch_size = 0;
487 
488  for (i = 0; i < map->narray; i++)
489  {
490  entry = map->array[i];
491 
492  if (entry->type != FILE_TYPE_REGULAR)
493  continue;
494 
495  map->total_size += entry->newsize;
496 
497  if (entry->action == FILE_ACTION_COPY)
498  {
499  map->fetch_size += entry->newsize;
500  continue;
501  }
502 
503  if (entry->action == FILE_ACTION_COPY_TAIL)
504  map->fetch_size += (entry->newsize - entry->oldsize);
505 
506  if (entry->pagemap.bitmapsize > 0)
507  {
509  BlockNumber blk;
510 
511  iter = datapagemap_iterate(&entry->pagemap);
512  while (datapagemap_next(iter, &blk))
513  map->fetch_size += BLCKSZ;
514 
515  pg_free(iter);
516  }
517  }
518 }
file_entry_t ** array
Definition: filemap.h:79
size_t newsize
Definition: filemap.h:51
uint32 BlockNumber
Definition: block.h:31
datapagemap_t pagemap
Definition: filemap.h:54
int narray
Definition: filemap.h:80
uint64 fetch_size
Definition: filemap.h:87
file_type_t type
Definition: filemap.h:45
bool datapagemap_next(datapagemap_iterator_t *iter, BlockNumber *blkno)
Definition: datapagemap.c:87
file_action_t action
Definition: filemap.h:47
filemap_t * filemap
Definition: filemap.c:25
size_t oldsize
Definition: filemap.h:50
uint64 total_size
Definition: filemap.h:86
int bitmapsize
Definition: datapagemap.h:19
datapagemap_iterator_t * datapagemap_iterate(datapagemap_t *map)
Definition: datapagemap.c:75
void pg_free(void *ptr)
Definition: fe_memutils.c:105
int i
Definition: filemap.h:42
void filemap_create ( void  )

Definition at line 38 of file filemap.c.

References filemap_t::array, Assert, filemap_t::first, filemap_t::last, filemap_t::narray, filemap_t::nlist, NULL, and pg_malloc().

Referenced by main().

39 {
40  filemap_t *map;
41 
42  map = pg_malloc(sizeof(filemap_t));
43  map->first = map->last = NULL;
44  map->nlist = 0;
45  map->array = NULL;
46  map->narray = 0;
47 
48  Assert(filemap == NULL);
49  filemap = map;
50 }
file_entry_t * first
Definition: filemap.h:68
file_entry_t ** array
Definition: filemap.h:79
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
int narray
Definition: filemap.h:80
int nlist
Definition: filemap.h:70
filemap_t * filemap
Definition: filemap.c:25
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
file_entry_t * last
Definition: filemap.h:69
void filemap_finalize ( void  )

Definition at line 443 of file filemap.c.

References filemap_t::array, filemap, filemap_list_to_array(), final_filemap_cmp(), filemap_t::narray, and qsort.

Referenced by main().

444 {
445  filemap_t *map = filemap;
446 
448  qsort(map->array, map->narray, sizeof(file_entry_t *),
450 }
static int final_filemap_cmp(const void *a, const void *b)
Definition: filemap.c:677
file_entry_t ** array
Definition: filemap.h:79
int narray
Definition: filemap.h:80
filemap_t * filemap
Definition: filemap.c:25
static void filemap_list_to_array(filemap_t *map)
Definition: filemap.c:419
Definition: filemap.h:42
#define qsort(a, b, c, d)
Definition: port.h:440
void print_filemap ( void  )

Definition at line 521 of file filemap.c.

References file_entry_t::action, action_to_str(), filemap_t::array, datapagemap::bitmapsize, datapagemap_print(), FILE_ACTION_NONE, filemap, i, filemap_t::narray, file_entry_t::pagemap, file_entry_t::path, PG_DEBUG, and pg_log().

Referenced by main().

522 {
523  filemap_t *map = filemap;
524  file_entry_t *entry;
525  int i;
526 
527  for (i = 0; i < map->narray; i++)
528  {
529  entry = map->array[i];
530  if (entry->action != FILE_ACTION_NONE ||
531  entry->pagemap.bitmapsize > 0)
532  {
534  /*------
535  translator: first %s is a file path, second is a keyword such as COPY */
536  "%s (%s)\n", entry->path,
537  action_to_str(entry->action));
538 
539  if (entry->pagemap.bitmapsize > 0)
540  datapagemap_print(&entry->pagemap);
541  }
542  }
543  fflush(stdout);
544 }
file_entry_t ** array
Definition: filemap.h:79
datapagemap_t pagemap
Definition: filemap.h:54
int narray
Definition: filemap.h:80
file_action_t action
Definition: filemap.h:47
filemap_t * filemap
Definition: filemap.c:25
static const char * action_to_str(file_action_t action)
Definition: filemap.c:453
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69
void datapagemap_print(datapagemap_t *map)
Definition: datapagemap.c:117
int bitmapsize
Definition: datapagemap.h:19
char * path
Definition: filemap.h:44
int i
Definition: filemap.h:42
void process_block_change ( ForkNumber  forknum,
RelFileNode  rnode,
BlockNumber  blkno 
)

Definition at line 343 of file filemap.c.

References file_entry_t::action, filemap_t::array, Assert, datapagemap_add(), datasegpath(), FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_ACTION_CREATE, FILE_ACTION_NONE, FILE_ACTION_REMOVE, FILE_ACTION_TRUNCATE, filemap, file_entry_t::isrelfile, filemap_t::narray, NULL, file_entry_t::pagemap, file_entry_t::path, path_cmp(), pfree(), and pg_fatal().

Referenced by extractPageInfo().

344 {
345  char *path;
346  file_entry_t key;
347  file_entry_t *key_ptr;
348  file_entry_t *entry;
349  BlockNumber blkno_inseg;
350  int segno;
351  filemap_t *map = filemap;
352  file_entry_t **e;
353 
354  Assert(map->array);
355 
356  segno = blkno / RELSEG_SIZE;
357  blkno_inseg = blkno % RELSEG_SIZE;
358 
359  path = datasegpath(rnode, forknum, segno);
360 
361  key.path = (char *) path;
362  key_ptr = &key;
363 
364  e = bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
365  path_cmp);
366  if (e)
367  entry = *e;
368  else
369  entry = NULL;
370  pfree(path);
371 
372  if (entry)
373  {
374  Assert(entry->isrelfile);
375 
376  switch (entry->action)
377  {
378  case FILE_ACTION_NONE:
380  /* skip if we're truncating away the modified block anyway */
381  if ((blkno_inseg + 1) * BLCKSZ <= entry->newsize)
382  datapagemap_add(&entry->pagemap, blkno_inseg);
383  break;
384 
386 
387  /*
388  * skip the modified block if it is part of the "tail" that
389  * we're copying anyway.
390  */
391  if ((blkno_inseg + 1) * BLCKSZ <= entry->oldsize)
392  datapagemap_add(&entry->pagemap, blkno_inseg);
393  break;
394 
395  case FILE_ACTION_COPY:
396  case FILE_ACTION_REMOVE:
397  break;
398 
399  case FILE_ACTION_CREATE:
400  pg_fatal("unexpected page modification for directory or symbolic link \"%s\"\n", entry->path);
401  }
402  }
403  else
404  {
405  /*
406  * If we don't have any record of this file in the file map, it means
407  * that it's a relation that doesn't exist in the source system, and
408  * it was subsequently removed in the target system, too. We can
409  * safely ignore it.
410  */
411  }
412 }
void datapagemap_add(datapagemap_t *map, BlockNumber blkno)
Definition: datapagemap.c:32
file_entry_t ** array
Definition: filemap.h:79
uint32 BlockNumber
Definition: block.h:31
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
datapagemap_t pagemap
Definition: filemap.h:54
int narray
Definition: filemap.h:80
static char * datasegpath(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
Definition: filemap.c:641
bool isrelfile
Definition: filemap.h:52
void pfree(void *pointer)
Definition: mcxt.c:950
file_action_t action
Definition: filemap.h:47
filemap_t * filemap
Definition: filemap.c:25
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
char * path
Definition: filemap.h:44
e
Definition: preproc-init.c:82
Definition: filemap.h:42
static int path_cmp(const void *a, const void *b)
Definition: filemap.c:658
void process_source_file ( const char *  path,
file_type_t  type,
size_t  newsize,
const char *  link_target 
)

Definition at line 60 of file filemap.c.

References file_entry_t::action, Assert, datapagemap::bitmap, datapagemap::bitmapsize, datadir_target, FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_ACTION_CREATE, FILE_ACTION_NONE, FILE_ACTION_TRUNCATE, FILE_TYPE_DIRECTORY, FILE_TYPE_REGULAR, FILE_TYPE_SYMLINK, filemap, isRelDataFile(), file_entry_t::isrelfile, file_entry_t::link_target, lstat, MAXPGPATH, file_entry_t::newsize, file_entry_t::next, NULL, file_entry_t::oldsize, file_entry_t::pagemap, file_entry_t::path, pg_fatal(), pg_malloc(), pg_str_endswith(), pg_strdup(), PG_TEMP_FILE_PREFIX, PG_TEMP_FILES_DIR, snprintf(), strerror(), and file_entry_t::type.

Referenced by fetchSourceFileList(), and libpqProcessFileList().

62 {
63  bool exists;
64  char localpath[MAXPGPATH];
65  struct stat statbuf;
66  filemap_t *map = filemap;
68  size_t oldsize = 0;
69  file_entry_t *entry;
70 
71  Assert(map->array == NULL);
72 
73  /*
74  * Completely ignore some special files in source and destination.
75  */
76  if (strcmp(path, "postmaster.pid") == 0 ||
77  strcmp(path, "postmaster.opts") == 0)
78  return;
79 
80  /*
81  * Pretend that pg_wal is a directory, even if it's really a symlink. We
82  * don't want to mess with the symlink itself, nor complain if it's a
83  * symlink in source but not in target or vice versa.
84  */
85  if (strcmp(path, "pg_wal") == 0 && type == FILE_TYPE_SYMLINK)
86  type = FILE_TYPE_DIRECTORY;
87 
88  /*
89  * Skip temporary files, .../pgsql_tmp/... and .../pgsql_tmp.* in source.
90  * This has the effect that all temporary files in the destination will be
91  * removed.
92  */
93  if (strstr(path, "/" PG_TEMP_FILE_PREFIX) != NULL)
94  return;
95  if (strstr(path, "/" PG_TEMP_FILES_DIR "/") != NULL)
96  return;
97 
98  /*
99  * sanity check: a filename that looks like a data file better be a
100  * regular file
101  */
102  if (type != FILE_TYPE_REGULAR && isRelDataFile(path))
103  pg_fatal("data file \"%s\" in source is not a regular file\n", path);
104 
105  snprintf(localpath, sizeof(localpath), "%s/%s", datadir_target, path);
106 
107  /* Does the corresponding file exist in the target data dir? */
108  if (lstat(localpath, &statbuf) < 0)
109  {
110  if (errno != ENOENT)
111  pg_fatal("could not stat file \"%s\": %s\n",
112  localpath, strerror(errno));
113 
114  exists = false;
115  }
116  else
117  exists = true;
118 
119  switch (type)
120  {
121  case FILE_TYPE_DIRECTORY:
122  if (exists && !S_ISDIR(statbuf.st_mode) && strcmp(path, "pg_wal") != 0)
123  {
124  /* it's a directory in source, but not in target. Strange.. */
125  pg_fatal("\"%s\" is not a directory\n", localpath);
126  }
127 
128  if (!exists)
129  action = FILE_ACTION_CREATE;
130  else
131  action = FILE_ACTION_NONE;
132  oldsize = 0;
133  break;
134 
135  case FILE_TYPE_SYMLINK:
136  if (exists &&
137 #ifndef WIN32
138  !S_ISLNK(statbuf.st_mode)
139 #else
140  !pgwin32_is_junction(localpath)
141 #endif
142  )
143  {
144  /*
145  * It's a symbolic link in source, but not in target.
146  * Strange..
147  */
148  pg_fatal("\"%s\" is not a symbolic link\n", localpath);
149  }
150 
151  if (!exists)
152  action = FILE_ACTION_CREATE;
153  else
154  action = FILE_ACTION_NONE;
155  oldsize = 0;
156  break;
157 
158  case FILE_TYPE_REGULAR:
159  if (exists && !S_ISREG(statbuf.st_mode))
160  pg_fatal("\"%s\" is not a regular file\n", localpath);
161 
162  if (!exists || !isRelDataFile(path))
163  {
164  /*
165  * File exists in source, but not in target. Or it's a
166  * non-data file that we have no special processing for. Copy
167  * it in toto.
168  *
169  * An exception: PG_VERSIONs should be identical, but avoid
170  * overwriting it for paranoia.
171  */
172  if (pg_str_endswith(path, "PG_VERSION"))
173  {
174  action = FILE_ACTION_NONE;
175  oldsize = statbuf.st_size;
176  }
177  else
178  {
179  action = FILE_ACTION_COPY;
180  oldsize = 0;
181  }
182  }
183  else
184  {
185  /*
186  * It's a data file that exists in both.
187  *
188  * If it's larger in target, we can truncate it. There will
189  * also be a WAL record of the truncation in the source
190  * system, so WAL replay would eventually truncate the target
191  * too, but we might as well do it now.
192  *
193  * If it's smaller in the target, it means that it has been
194  * truncated in the target, or enlarged in the source, or
195  * both. If it was truncated in the target, we need to copy
196  * the missing tail from the source system. If it was enlarged
197  * in the source system, there will be WAL records in the
198  * source system for the new blocks, so we wouldn't need to
199  * copy them here. But we don't know which scenario we're
200  * dealing with, and there's no harm in copying the missing
201  * blocks now, so do it now.
202  *
203  * If it's the same size, do nothing here. Any blocks modified
204  * in the target will be copied based on parsing the target
205  * system's WAL, and any blocks modified in the source will be
206  * updated after rewinding, when the source system's WAL is
207  * replayed.
208  */
209  oldsize = statbuf.st_size;
210  if (oldsize < newsize)
211  action = FILE_ACTION_COPY_TAIL;
212  else if (oldsize > newsize)
213  action = FILE_ACTION_TRUNCATE;
214  else
215  action = FILE_ACTION_NONE;
216  }
217  break;
218  }
219 
220  /* Create a new entry for this file */
221  entry = pg_malloc(sizeof(file_entry_t));
222  entry->path = pg_strdup(path);
223  entry->type = type;
224  entry->action = action;
225  entry->oldsize = oldsize;
226  entry->newsize = newsize;
227  entry->link_target = link_target ? pg_strdup(link_target) : NULL;
228  entry->next = NULL;
229  entry->pagemap.bitmap = NULL;
230  entry->pagemap.bitmapsize = 0;
231  entry->isrelfile = isRelDataFile(path);
232 
233  if (map->last)
234  {
235  map->last->next = entry;
236  map->last = entry;
237  }
238  else
239  map->first = map->last = entry;
240  map->nlist++;
241 }
char * datadir_target
Definition: pg_rewind.c:49
bool pg_str_endswith(const char *str, const char *end)
Definition: string.c:31
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
size_t newsize
Definition: filemap.h:51
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define PG_TEMP_FILE_PREFIX
Definition: fd.h:128
char * bitmap
Definition: datapagemap.h:18
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
datapagemap_t pagemap
Definition: filemap.h:54
file_type_t type
Definition: filemap.h:45
bool isrelfile
Definition: filemap.h:52
#define MAXPGPATH
file_action_t action
Definition: filemap.h:47
char * link_target
Definition: filemap.h:57
struct file_entry_t * next
Definition: filemap.h:59
filemap_t * filemap
Definition: filemap.c:25
size_t oldsize
Definition: filemap.h:50
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int bitmapsize
Definition: datapagemap.h:19
#define PG_TEMP_FILES_DIR
Definition: fd.h:127
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
file_action_t
Definition: filemap.h:24
static bool isRelDataFile(const char *path)
Definition: filemap.c:555
char * path
Definition: filemap.h:44
const char * strerror(int errnum)
Definition: strerror.c:19
Definition: filemap.h:42
#define lstat(path, sb)
Definition: win32.h:262
void process_target_file ( const char *  path,
file_type_t  type,
size_t  newsize,
const char *  link_target 
)

Definition at line 251 of file filemap.c.

References file_entry_t::action, filemap_t::array, Assert, datapagemap::bitmap, datapagemap::bitmapsize, datadir_target, FILE_ACTION_REMOVE, FILE_TYPE_DIRECTORY, FILE_TYPE_SYMLINK, filemap, filemap_list_to_array(), filemap_t::first, isRelDataFile(), file_entry_t::isrelfile, filemap_t::last, file_entry_t::link_target, lstat, MAXPGPATH, filemap_t::narray, file_entry_t::newsize, file_entry_t::next, filemap_t::nlist, NULL, file_entry_t::oldsize, file_entry_t::pagemap, file_entry_t::path, path_cmp(), pg_fatal(), pg_malloc(), pg_strdup(), qsort, snprintf(), strerror(), and file_entry_t::type.

Referenced by main().

253 {
254  bool exists;
255  char localpath[MAXPGPATH];
256  struct stat statbuf;
257  file_entry_t key;
258  file_entry_t *key_ptr;
259  filemap_t *map = filemap;
260  file_entry_t *entry;
261 
262  snprintf(localpath, sizeof(localpath), "%s/%s", datadir_target, path);
263  if (lstat(localpath, &statbuf) < 0)
264  {
265  if (errno != ENOENT)
266  pg_fatal("could not stat file \"%s\": %s\n",
267  localpath, strerror(errno));
268 
269  exists = false;
270  }
271 
272  if (map->array == NULL)
273  {
274  /* on first call, initialize lookup array */
275  if (map->nlist == 0)
276  {
277  /* should not happen */
278  pg_fatal("source file list is empty\n");
279  }
280 
282 
283  Assert(map->array != NULL);
284 
285  qsort(map->array, map->narray, sizeof(file_entry_t *), path_cmp);
286  }
287 
288  /*
289  * Completely ignore some special files
290  */
291  if (strcmp(path, "postmaster.pid") == 0 ||
292  strcmp(path, "postmaster.opts") == 0)
293  return;
294 
295  /*
296  * Like in process_source_file, pretend that xlog is always a directory.
297  */
298  if (strcmp(path, "pg_wal") == 0 && type == FILE_TYPE_SYMLINK)
299  type = FILE_TYPE_DIRECTORY;
300 
301  key.path = (char *) path;
302  key_ptr = &key;
303  exists = (bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
304  path_cmp) != NULL);
305 
306  /* Remove any file or folder that doesn't exist in the source system. */
307  if (!exists)
308  {
309  entry = pg_malloc(sizeof(file_entry_t));
310  entry->path = pg_strdup(path);
311  entry->type = type;
312  entry->action = FILE_ACTION_REMOVE;
313  entry->oldsize = oldsize;
314  entry->newsize = 0;
315  entry->link_target = link_target ? pg_strdup(link_target) : NULL;
316  entry->next = NULL;
317  entry->pagemap.bitmap = NULL;
318  entry->pagemap.bitmapsize = 0;
319  entry->isrelfile = isRelDataFile(path);
320 
321  if (map->last == NULL)
322  map->first = entry;
323  else
324  map->last->next = entry;
325  map->last = entry;
326  map->nlist++;
327  }
328  else
329  {
330  /*
331  * We already handled all files that exist in the source system in
332  * process_source_file().
333  */
334  }
335 }
char * datadir_target
Definition: pg_rewind.c:49
file_entry_t * first
Definition: filemap.h:68
file_entry_t ** array
Definition: filemap.h:79
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
size_t newsize
Definition: filemap.h:51
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
char * bitmap
Definition: datapagemap.h:18
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
datapagemap_t pagemap
Definition: filemap.h:54
int narray
Definition: filemap.h:80
file_type_t type
Definition: filemap.h:45
bool isrelfile
Definition: filemap.h:52
int nlist
Definition: filemap.h:70
#define MAXPGPATH
file_action_t action
Definition: filemap.h:47
char * link_target
Definition: filemap.h:57
struct file_entry_t * next
Definition: filemap.h:59
filemap_t * filemap
Definition: filemap.c:25
size_t oldsize
Definition: filemap.h:50
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int bitmapsize
Definition: datapagemap.h:19
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static bool isRelDataFile(const char *path)
Definition: filemap.c:555
char * path
Definition: filemap.h:44
static void filemap_list_to_array(filemap_t *map)
Definition: filemap.c:419
file_entry_t * last
Definition: filemap.h:69
const char * strerror(int errnum)
Definition: strerror.c:19
Definition: filemap.h:42
static int path_cmp(const void *a, const void *b)
Definition: filemap.c:658
#define qsort(a, b, c, d)
Definition: port.h:440
#define lstat(path, sb)
Definition: win32.h:262

Variable Documentation