src/newgrf_config.cpp
changeset 6920 ee15b916f758
parent 6905 c0a93961678a
child 6921 1771ee81a39a
equal deleted inserted replaced
6919:339210ecccd3 6920:ee15b916f758
    33 
    33 
    34 /* Calculate the MD5 Sum for a GRF */
    34 /* Calculate the MD5 Sum for a GRF */
    35 static bool CalcGRFMD5Sum(GRFConfig *config)
    35 static bool CalcGRFMD5Sum(GRFConfig *config)
    36 {
    36 {
    37 	FILE *f;
    37 	FILE *f;
    38 	char filename[MAX_PATH];
       
    39 	md5_state_t md5state;
    38 	md5_state_t md5state;
    40 	md5_byte_t buffer[1024];
    39 	md5_byte_t buffer[1024];
    41 	size_t len;
    40 	size_t len;
    42 
    41 
    43 	/* open the file */
    42 	/* open the file */
    44 	snprintf(filename, lengthof(filename), "%s%s", _paths.data_dir, config->filename);
    43 	f = fopen(config->full_path, "rb");
    45 	f = fopen(filename, "rb");
       
    46 	if (f == NULL) return false;
    44 	if (f == NULL) return false;
    47 
    45 
    48 	/* calculate md5sum */
    46 	/* calculate md5sum */
    49 	md5_init(&md5state);
    47 	md5_init(&md5state);
    50 	while ((len = fread(buffer, 1, sizeof(buffer), f)) != 0) {
    48 	while ((len = fread(buffer, 1, sizeof(buffer), f)) != 0) {
    59 
    57 
    60 
    58 
    61 /* Find the GRFID and calculate the md5sum */
    59 /* Find the GRFID and calculate the md5sum */
    62 bool FillGRFDetails(GRFConfig *config, bool is_static)
    60 bool FillGRFDetails(GRFConfig *config, bool is_static)
    63 {
    61 {
    64 	if (!FioCheckFileExists(config->filename)) {
    62 	if (!FileExists(config->full_path)) {
    65 		config->status = GCS_NOT_FOUND;
    63 		config->status = GCS_NOT_FOUND;
    66 		return false;
    64 		return false;
    67 	}
    65 	}
    68 
    66 
    69 	/* Find and load the Action 8 information */
    67 	/* Find and load the Action 8 information */
    89 void ClearGRFConfig(GRFConfig **config)
    87 void ClearGRFConfig(GRFConfig **config)
    90 {
    88 {
    91 	/* GCF_COPY as in NOT strdupped/alloced the filename, name and info */
    89 	/* GCF_COPY as in NOT strdupped/alloced the filename, name and info */
    92 	if (!HASBIT((*config)->flags, GCF_COPY)) {
    90 	if (!HASBIT((*config)->flags, GCF_COPY)) {
    93 		free((*config)->filename);
    91 		free((*config)->filename);
       
    92 		free((*config)->full_path);
    94 		free((*config)->name);
    93 		free((*config)->name);
    95 		free((*config)->info);
    94 		free((*config)->info);
    96 		free((*config)->error);
    95 		free((*config)->error);
    97 	}
    96 	}
    98 	free(*config);
    97 	free(*config);
   121 	/* Clear destination as it will be overwritten */
   120 	/* Clear destination as it will be overwritten */
   122 	ClearGRFConfigList(dst);
   121 	ClearGRFConfigList(dst);
   123 	for (; src != NULL; src = src->next) {
   122 	for (; src != NULL; src = src->next) {
   124 		GRFConfig *c = CallocT<GRFConfig>(1);
   123 		GRFConfig *c = CallocT<GRFConfig>(1);
   125 		*c = *src;
   124 		*c = *src;
   126 		if (src->filename != NULL) c->filename = strdup(src->filename);
   125 		if (src->filename  != NULL) c->filename  = strdup(src->filename);
   127 		if (src->name     != NULL) c->name     = strdup(src->name);
   126 		if (src->full_path != NULL) c->full_path = strdup(src->full_path);
   128 		if (src->info     != NULL) c->info     = strdup(src->info);
   127 		if (src->name      != NULL) c->name      = strdup(src->name);
   129 		if (src->error    != NULL) {
   128 		if (src->info      != NULL) c->info      = strdup(src->info);
       
   129 		if (src->error     != NULL) {
   130 			c->error = CallocT<GRFError>(1);
   130 			c->error = CallocT<GRFError>(1);
   131 			memcpy(c->error, src->error, sizeof(GRFError));
   131 			memcpy(c->error, src->error, sizeof(GRFError));
   132 		}
   132 		}
   133 
   133 
   134 		*dst = c;
   134 		*dst = c;
   253 			 * in any case and set the name and info when it is not set already.
   253 			 * in any case and set the name and info when it is not set already.
   254 			 * When the GCF_COPY flag is set, it is certain that the filename is
   254 			 * When the GCF_COPY flag is set, it is certain that the filename is
   255 			 * already a local one, so there is no need to replace it. */
   255 			 * already a local one, so there is no need to replace it. */
   256 			if (!HASBIT(c->flags, GCF_COPY)) {
   256 			if (!HASBIT(c->flags, GCF_COPY)) {
   257 				free(c->filename);
   257 				free(c->filename);
       
   258 				free(c->full_path);
   258 				c->filename = strdup(f->filename);
   259 				c->filename = strdup(f->filename);
       
   260 				c->full_path = strdup(f->full_path);
   259 				memcpy(c->md5sum, f->md5sum, sizeof(c->md5sum));
   261 				memcpy(c->md5sum, f->md5sum, sizeof(c->md5sum));
   260 				if (c->name == NULL && f->name != NULL) c->name = strdup(f->name);
   262 				if (c->name == NULL && f->name != NULL) c->name = strdup(f->name);
   261 				if (c->info == NULL && f->info != NULL) c->info = strdup(f->info);
   263 				if (c->info == NULL && f->info != NULL) c->info = strdup(f->info);
   262 				c->error = NULL;
   264 				c->error = NULL;
   263 			}
   265 			}
   276 	uint num = 0;
   278 	uint num = 0;
   277 	struct stat sb;
   279 	struct stat sb;
   278 	struct dirent *dirent;
   280 	struct dirent *dirent;
   279 	DIR *dir;
   281 	DIR *dir;
   280 
   282 
   281 	if ((dir = ttd_opendir(path)) == NULL) return 0;
   283 	if (path == NULL || (dir = ttd_opendir(path)) == NULL) return 0;
   282 
   284 
   283 	while ((dirent = readdir(dir)) != NULL) {
   285 	while ((dirent = readdir(dir)) != NULL) {
   284 		const char *d_name = FS2OTTD(dirent->d_name);
   286 		const char *d_name = FS2OTTD(dirent->d_name);
   285 		char filename[MAX_PATH];
   287 		char filename[MAX_PATH];
   286 
   288 
   287 		if (!FiosIsValidFile(path, dirent, &sb)) continue;
   289 		if (!FiosIsValidFile(path, dirent, &sb)) continue;
   288 
   290 
   289 		snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, d_name);
   291 		snprintf(filename, lengthof(filename), "%s%s", path, d_name);
   290 
   292 
   291 		if (sb.st_mode & S_IFDIR) {
   293 		if (sb.st_mode & S_IFDIR) {
   292 			/* Directory */
   294 			/* Directory */
   293 			if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
   295 			if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
       
   296 			AppendPathSeparator(filename, lengthof(filename));
   294 			num += ScanPath(filename);
   297 			num += ScanPath(filename);
   295 		} else if (sb.st_mode & S_IFREG) {
   298 		} else if (sb.st_mode & S_IFREG) {
   296 			/* File */
   299 			/* File */
   297 			char *ext = strrchr(filename, '.');
   300 			char *ext = strrchr(filename, '.');
   298 			char *file = filename + strlen(_paths.data_dir) + 1; // Crop base path
       
   299 
   301 
   300 			/* If no extension or extension isn't .grf, skip the file */
   302 			/* If no extension or extension isn't .grf, skip the file */
   301 			if (ext == NULL) continue;
   303 			if (ext == NULL) continue;
   302 			if (strcasecmp(ext, ".grf") != 0) continue;
   304 			if (strcasecmp(ext, ".grf") != 0) continue;
   303 
   305 
   304 			GRFConfig *c = CallocT<GRFConfig>(1);
   306 			GRFConfig *c = CallocT<GRFConfig>(1);
   305 			c->filename = strdup(file);
   307 			c->full_path = strdup(filename);
   306 
   308 			c->filename = strdup(strrchr(filename, PATHSEPCHAR) + 1);
       
   309 
       
   310 			bool added = true;
   307 			if (FillGRFDetails(c, false)) {
   311 			if (FillGRFDetails(c, false)) {
   308 				if (_all_grfs == NULL) {
   312 				if (_all_grfs == NULL) {
   309 					_all_grfs = c;
   313 					_all_grfs = c;
   310 				} else {
   314 				} else {
   311 					/* Insert file into list at a position determined by its
   315 					/* Insert file into list at a position determined by its
   312 					 * name, so the list is sorted as we go along */
   316 					 * name, so the list is sorted as we go along */
   313 					GRFConfig **pd, *d;
   317 					GRFConfig **pd, *d;
   314 					for (pd = &_all_grfs; (d = *pd) != NULL; pd = &d->next) {
   318 					for (pd = &_all_grfs; (d = *pd) != NULL; pd = &d->next) {
       
   319 						if (c->grfid == d->grfid && memcmp(c->md5sum, d->md5sum, sizeof(c->md5sum)) == 0) added = false;
   315 						if (strcasecmp(c->name, d->name) <= 0) break;
   320 						if (strcasecmp(c->name, d->name) <= 0) break;
   316 					}
   321 					}
   317 					c->next = d;
   322 					if (added) {
   318 					*pd = c;
   323 						c->next = d;
       
   324 						*pd = c;
       
   325 					}
   319 				}
   326 				}
   320 
       
   321 				num++;
       
   322 			} else {
   327 			} else {
       
   328 				added = false;
       
   329 			}
       
   330 
       
   331 			if (!added) {
   323 				/* File couldn't be opened, or is either not a NewGRF or is a
   332 				/* File couldn't be opened, or is either not a NewGRF or is a
   324 				 * 'system' NewGRF, so forget about it. */
   333 				 * 'system' NewGRF or it's already known, so forget about it. */
   325 				free(c->filename);
   334 				free(c->filename);
       
   335 				free(c->full_path);
   326 				free(c->name);
   336 				free(c->name);
   327 				free(c->info);
   337 				free(c->info);
   328 				free(c);
   338 				free(c);
       
   339 			} else {
       
   340 				num++;
   329 			}
   341 			}
   330 		}
   342 		}
   331 	}
   343 	}
   332 
   344 
   333 	closedir(dir);
   345 	closedir(dir);
   342 	uint num;
   354 	uint num;
   343 
   355 
   344 	ClearGRFConfigList(&_all_grfs);
   356 	ClearGRFConfigList(&_all_grfs);
   345 
   357 
   346 	DEBUG(grf, 1, "Scanning for NewGRFs");
   358 	DEBUG(grf, 1, "Scanning for NewGRFs");
   347 	num = ScanPath(_paths.data_dir);
   359 	num  = ScanPath(_paths.data_dir);
       
   360 	num += ScanPath(_paths.second_data_dir);
   348 	DEBUG(grf, 1, "Scan complete, found %d files", num);
   361 	DEBUG(grf, 1, "Scan complete, found %d files", num);
   349 }
   362 }
   350 
   363 
   351 
   364 
   352 /* Find a NewGRF in the scanned list, if md5sum is NULL, we don't care about it*/
   365 /* Find a NewGRF in the scanned list, if md5sum is NULL, we don't care about it*/