blob: 50e7cdcf9468294e4dd9b09ccd8278b77d626ac5 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Charmonizer/Core/ConfWriter.h"
#include "Charmonizer/Core/Compiler.h"
#include "Charmonizer/Core/OperatingSystem.h"
#include "Charmonizer/Core/Util.h"
#include "Charmonizer/Core/HeaderChecker.h"
#include "Charmonizer/Probe/DirManip.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
static struct {
int mkdir_num_args;
char mkdir_command[7];
} chaz_DirManip = { 0, "" };
/* Source code for rmdir. */
static int
chaz_DirManip_compile_posix_mkdir(const char *header) {
static const char posix_mkdir_code[] =
CHAZ_QUOTE( #include <%s> )
CHAZ_QUOTE( int main(int argc, char **argv) { )
CHAZ_QUOTE( if (argc != 2) { return 1; } )
CHAZ_QUOTE( if (mkdir(argv[1], 0777) != 0) { return 2; } )
CHAZ_QUOTE( return 0; )
CHAZ_QUOTE( } );
char code_buf[sizeof(posix_mkdir_code) + 30];
int mkdir_available;
if (strlen(header) > 25) {
chaz_Util_die("Header name too long: '%s'", header);
}
/* Attempt compilation. */
sprintf(code_buf, posix_mkdir_code, header);
mkdir_available = chaz_CC_test_compile(code_buf);
/* Set vars on success. */
if (mkdir_available) {
strcpy(chaz_DirManip.mkdir_command, "mkdir");
if (strcmp(header, "direct.h") == 0) {
chaz_DirManip.mkdir_num_args = 1;
}
else {
chaz_DirManip.mkdir_num_args = 2;
}
}
return mkdir_available;
}
static int
chaz_DirManip_compile_win_mkdir(void) {
static const char win_mkdir_code[] =
CHAZ_QUOTE( #include <direct.h> )
CHAZ_QUOTE( int main(int argc, char **argv) { )
CHAZ_QUOTE( if (argc != 2) { return 1; } )
CHAZ_QUOTE( if (_mkdir(argv[1]) != 0) { return 2; } )
CHAZ_QUOTE( return 0; )
CHAZ_QUOTE( } );
int mkdir_available;
mkdir_available = chaz_CC_test_compile(win_mkdir_code);
if (mkdir_available) {
strcpy(chaz_DirManip.mkdir_command, "_mkdir");
chaz_DirManip.mkdir_num_args = 1;
}
return mkdir_available;
}
static void
chaz_DirManip_try_mkdir(void) {
if (chaz_HeadCheck_check_header("windows.h")) {
if (chaz_DirManip_compile_win_mkdir()) { return; }
if (chaz_DirManip_compile_posix_mkdir("direct.h")) { return; }
}
if (chaz_DirManip_compile_posix_mkdir("sys/stat.h")) { return; }
}
static int
chaz_DirManip_compile_rmdir(const char *header) {
static const char rmdir_code[] =
CHAZ_QUOTE( #include <%s> )
CHAZ_QUOTE( int main(int argc, char **argv) { )
CHAZ_QUOTE( if (argc != 2) { return 1; } )
CHAZ_QUOTE( if (rmdir(argv[1]) != 0) { return 2; } )
CHAZ_QUOTE( return 0; )
CHAZ_QUOTE( } );
char code_buf[sizeof(rmdir_code) + 30];
int rmdir_available;
if (strlen(header) > 25) {
chaz_Util_die("Header name too long: '%s'", header);
}
sprintf(code_buf, rmdir_code, header);
rmdir_available = chaz_CC_test_compile(code_buf);
return rmdir_available;
}
static void
chaz_DirManip_try_rmdir(void) {
if (chaz_DirManip_compile_rmdir("unistd.h")) { return; }
if (chaz_DirManip_compile_rmdir("dirent.h")) { return; }
if (chaz_DirManip_compile_rmdir("direct.h")) { return; }
}
void
chaz_DirManip_run(void) {
int has_dirent_h = chaz_HeadCheck_check_header("dirent.h");
int has_direct_h = chaz_HeadCheck_check_header("direct.h");
int has_dirent_d_namlen = false;
int has_dirent_d_type = false;
chaz_ConfWriter_start_module("DirManip");
chaz_DirManip_try_mkdir();
chaz_DirManip_try_rmdir();
/* Header checks. */
if (has_dirent_h) {
chaz_ConfWriter_add_def("HAS_DIRENT_H", NULL);
}
if (has_direct_h) {
chaz_ConfWriter_add_def("HAS_DIRECT_H", NULL);
}
/* Check for members in struct dirent. */
if (has_dirent_h) {
has_dirent_d_namlen = chaz_HeadCheck_contains_member(
"struct dirent", "d_namlen",
"#include <sys/types.h>\n#include <dirent.h>"
);
if (has_dirent_d_namlen) {
chaz_ConfWriter_add_def("HAS_DIRENT_D_NAMLEN", NULL);
}
has_dirent_d_type = chaz_HeadCheck_contains_member(
"struct dirent", "d_type",
"#include <sys/types.h>\n#include <dirent.h>"
);
if (has_dirent_d_type) {
chaz_ConfWriter_add_def("HAS_DIRENT_D_TYPE", NULL);
}
}
if (chaz_DirManip.mkdir_num_args == 2) {
/* It's two args, but the command isn't "mkdir". */
char scratch[50];
if (strlen(chaz_DirManip.mkdir_command) > 30) {
chaz_Util_die("Command too long: '%s'", chaz_DirManip.mkdir_command);
}
sprintf(scratch, "%s(_dir, _mode)", chaz_DirManip.mkdir_command);
chaz_ConfWriter_add_def("makedir(_dir, _mode)", scratch);
chaz_ConfWriter_add_def("MAKEDIR_MODE_IGNORED", "0");
}
else if (chaz_DirManip.mkdir_num_args == 1) {
/* It's one arg... mode arg will be ignored. */
char scratch[50];
if (strlen(chaz_DirManip.mkdir_command) > 30) {
chaz_Util_die("Command too long: '%s'", chaz_DirManip.mkdir_command);
}
sprintf(scratch, "%s(_dir)", chaz_DirManip.mkdir_command);
chaz_ConfWriter_add_def("makedir(_dir, _mode)", scratch);
chaz_ConfWriter_add_def("MAKEDIR_MODE_IGNORED", "1");
}
if (chaz_CC_has_macro("_WIN32") && !chaz_CC_is_cygwin()) {
chaz_ConfWriter_add_def("DIR_SEP", "\"\\\\\"");
chaz_ConfWriter_add_def("DIR_SEP_CHAR", "'\\\\'");
}
else {
chaz_ConfWriter_add_def("DIR_SEP", "\"/\"");
chaz_ConfWriter_add_def("DIR_SEP_CHAR", "'/'");
}
/* See whether remove works on directories. */
chaz_OS_mkdir("_charm_test_remove_me");
if (0 == remove("_charm_test_remove_me")) {
chaz_ConfWriter_add_def("REMOVE_ZAPS_DIRS", NULL);
}
chaz_OS_rmdir("_charm_test_remove_me");
chaz_ConfWriter_end_module();
}