Skip to content

Commit e36e9ff

Browse files
committed
Merge pull request #473 from rtoijala/unix_modlist
Unix modlist
2 parents 01e4741 + 3287ff6 commit e36e9ff

File tree

1 file changed

+96
-41
lines changed

1 file changed

+96
-41
lines changed

code/cmdline/cmdline.cpp

Lines changed: 96 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,100 @@ char *cmdline_parm::str()
10361036
return args;
10371037
}
10381038

1039+
#ifdef SCP_UNIX
1040+
// Return a vector with all filesystem names of "parent/dir" relative to parent.
1041+
// dir must not contain a slash.
1042+
static SCP_vector<SCP_string> unix_get_single_dir_names(SCP_string parent, SCP_string dir)
1043+
{
1044+
SCP_vector<SCP_string> ret;
1045+
1046+
DIR *dp;
1047+
if ((dp = opendir(parent.c_str())) == NULL) {
1048+
Warning(LOCATION, "Can't open directory '%s' when searching mod paths. Ignoring. errno=%d", parent.c_str(), errno);
1049+
return ret;
1050+
}
1051+
1052+
dirent *dirp;
1053+
while ((dirp = readdir(dp)) != NULL) {
1054+
if (!stricmp(dirp->d_name, dir.c_str())) {
1055+
ret.push_back(dirp->d_name);
1056+
}
1057+
}
1058+
(void)closedir(dp);
1059+
1060+
return ret;
1061+
}
1062+
1063+
// Return a vector with all filesystem names of "parent/dir" relative to parent.
1064+
// Recurses to deal with slashes in dir.
1065+
static SCP_vector<SCP_string> unix_get_dir_names(SCP_string parent, SCP_string dir)
1066+
{
1067+
size_t slash = dir.find_first_of("/\\");
1068+
1069+
// no subdirectories, no need to recurse
1070+
if (slash == std::string::npos) {
1071+
return unix_get_single_dir_names(parent, dir);
1072+
}
1073+
1074+
// get the names of the first component of dir
1075+
SCP_vector<SCP_string> this_dir_names = unix_get_single_dir_names(parent, dir.substr(0, slash));
1076+
1077+
SCP_string rest = dir.substr(slash + 1);
1078+
1079+
SCP_vector<SCP_string> ret;
1080+
1081+
// search for the rest of dir in each of these
1082+
SCP_vector<SCP_string>::iterator ii, end = this_dir_names.end();
1083+
for (ii = this_dir_names.begin(); ii != end; ++ii) {
1084+
SCP_string this_dir_path = parent + "/" + *ii;
1085+
SCP_vector<SCP_string> mod_path = unix_get_dir_names(this_dir_path, rest);
1086+
1087+
// add all found paths relative to parent
1088+
SCP_vector<SCP_string>::iterator ii2, end2 = mod_path.end();
1089+
for (ii2 = mod_path.begin(); ii2 != end2; ++ii2) {
1090+
ret.push_back(*ii + "/" + *ii2);
1091+
}
1092+
}
1093+
1094+
return ret;
1095+
}
1096+
1097+
// For case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches.
1098+
static void handle_unix_modlist(char **modlist, int *len)
1099+
{
1100+
// search filesystem for given paths
1101+
SCP_vector<SCP_string> mod_paths;
1102+
for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ","))
1103+
{
1104+
SCP_vector<SCP_string> this_mod_paths = unix_get_dir_names(".", cur_mod);
1105+
if (this_mod_paths.empty()) {
1106+
ReleaseWarning(LOCATION, "Can't find mod '%s'. Ignoring.", cur_mod);
1107+
}
1108+
mod_paths.insert(mod_paths.end(), this_mod_paths.begin(), this_mod_paths.end());
1109+
}
1110+
1111+
// create new char[] to replace modlist
1112+
size_t total_len = 0;
1113+
SCP_vector<SCP_string>::iterator ii, end = mod_paths.end();
1114+
for (ii = mod_paths.begin(); ii != end; ++ii) {
1115+
total_len += ii->length() + 1;
1116+
}
1117+
1118+
char *new_modlist = new char[total_len + 1];
1119+
memset(new_modlist, 0, total_len + 1);
1120+
end = mod_paths.end();
1121+
for (ii = mod_paths.begin(); ii != end; ++ii) {
1122+
strcat_s(new_modlist, total_len + 1, ii->c_str());
1123+
strcat_s(new_modlist, total_len + 1, ","); // replace later with NUL
1124+
}
1125+
1126+
// make the rest of the modlist manipulation unaware that anything happened here
1127+
delete [] *modlist;
1128+
*modlist = new_modlist;
1129+
*len = total_len;
1130+
}
1131+
#endif /* SCP_UNIX */
1132+
10391133
// external entry point into this modules
10401134

10411135
bool SetCmdlineParams()
@@ -1318,47 +1412,8 @@ bool SetCmdlineParams()
13181412
strcpy_s(modlist, len+2, Cmdline_mod);
13191413

13201414
#ifdef SCP_UNIX
1321-
// for case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches
1322-
DIR *dp;
1323-
dirent *dirp;
1324-
char *cur_pos, *temp;
1325-
char cur_dir[CF_MAX_PATHNAME_LENGTH], delim[] = ",";
1326-
SCP_vector<SCP_string> temp_modlist;
1327-
size_t total_len = 0;
1328-
1329-
if ( !_getcwd(cur_dir, CF_MAX_PATHNAME_LENGTH ) ) {
1330-
Error(LOCATION, "Can't get current working directory -- %d", errno );
1331-
}
1332-
1333-
for (cur_pos = strtok(modlist, delim); cur_pos != NULL; cur_pos = strtok(NULL, delim))
1334-
{
1335-
if ((dp = opendir(cur_dir)) == NULL) {
1336-
Error(LOCATION, "Can't open directory '%s' -- %d", cur_dir, errno );
1337-
}
1338-
1339-
while ((dirp = readdir(dp)) != NULL) {
1340-
if (!stricmp(dirp->d_name, cur_pos)) {
1341-
temp_modlist.push_back(dirp->d_name);
1342-
total_len += (strlen(dirp->d_name) + 1);
1343-
}
1344-
}
1345-
(void)closedir(dp);
1346-
}
1347-
1348-
// create new char[] to replace modlist
1349-
char *new_modlist = new char[total_len+1];
1350-
memset( new_modlist, 0, total_len + 1 );
1351-
SCP_vector<SCP_string>::iterator ii, end = temp_modlist.end();
1352-
for (ii = temp_modlist.begin(); ii != end; ++ii) {
1353-
strcat_s(new_modlist, total_len+1, ii->c_str());
1354-
strcat_s(new_modlist, total_len+1, ","); // replace later with NUL
1355-
}
1356-
1357-
// make the rest of the function unaware that anything happened here
1358-
temp = modlist;
1359-
modlist = new_modlist;
1360-
delete [] temp;
1361-
len = total_len;
1415+
// handle case-insensitive searching
1416+
handle_unix_modlist(&modlist, &len);
13621417
#endif
13631418

13641419
// null terminate each individual

0 commit comments

Comments
 (0)