diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30bb815 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# test binaries +/teststandardpaths +/teststandardpaths*.exe + +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e3d7bf8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "cutf"] + path = cutf + url = https://github.com/tapika/cutf.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..97f77c9 --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +CC ?= gcc +CXX ?= g++ +TARGET_MACHINE := $(shell $(CC) -dumpmachine) +ifneq ($(LINUX),true) +ifneq ($(MACOS),true) +ifneq ($(WINDOWS),true) + +ifneq (,$(findstring linux,$(TARGET_MACHINE))) +LINUX=true +endif +ifneq (,$(findstring apple,$(TARGET_MACHINE))) +MACOS=true +endif +ifneq (,$(findstring mingw,$(TARGET_MACHINE))) +WINDOWS=true +endif +ifneq (,$(findstring windows,$(TARGET_MACHINE))) +WINDOWS=true +endif + +endif +endif +endif + + +CFLAGS += -std=c++17 -I. + +ifeq ($(WINDOWS),true) +APP_EXT ?= .exe +CFLAGS += -I./cutf +endif + +PROG = teststandardpaths +SOURCES = \ + standardpaths.cpp \ + teststandardpaths.cpp + +ifeq ($(WINDOWS),true) +SOURCES += cutf/cutf.cpp +endif + +all: $(PROG)$(APP_EXT) + +$(PROG)$(APP_EXT): $(SOURCES) + $(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +clean: + -rm -f $(PROG)$(APP_EXT) *.o diff --git a/build-win32.sh b/build-win32.sh new file mode 100755 index 0000000..d476c8a --- /dev/null +++ b/build-win32.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e + +# Preparation +_FLAGS="-DPTW32_STATIC_LIB -Werror" +_ARCH=i686-w64-mingw32 +_PREFIX="/usr/${_ARCH}" + +source win.env + +# Build now +make "$@" diff --git a/build-win64.sh b/build-win64.sh new file mode 100755 index 0000000..2dfede8 --- /dev/null +++ b/build-win64.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e + +# Preparation +_FLAGS="-DPTW32_STATIC_LIB -Werror" +_ARCH=x86_64-w64-mingw32 +_PREFIX="/usr/${_ARCH}" + +source win.env + +# Build now +make APP_EXT="-64.exe" "$@" diff --git a/cutf b/cutf new file mode 160000 index 0000000..ca60c39 --- /dev/null +++ b/cutf @@ -0,0 +1 @@ +Subproject commit ca60c39e1815ae6bc7f7c9fa880dc5d9b8ed0edc diff --git a/standardpaths.cpp b/standardpaths.cpp new file mode 100644 index 0000000..cc3ac09 --- /dev/null +++ b/standardpaths.cpp @@ -0,0 +1,113 @@ +/* Re-implemented in C++ after GLib's gutils.c */ + +#include "standardpaths.hpp" + +namespace fs = std::filesystem; + +#ifdef _WIN32 +fs::path getWindowsDirectory(void) { + wchar_t wcp[MAX_PATH]; + fs::path windowsDir(""); + + if (GetWindowsDirectoryW(wcp, MAX_PATH)) { + // Usually X:\Windows, but in terminal server environments + // might be an UNC path, AFAIK. + windowsDir = widetoutf8(wcp); + } + + if (windowsDir.empty()) + windowsDir = "C:\\"; + + return windowsDir; +} + + +fs::path getWindowsKnownFolder(REFKNOWNFOLDERID folder_guid) { + wchar_t *wcp = NULL; + fs::path specialFolder(""); + HRESULT hr; + + hr = SHGetKnownFolderPath(folder_guid, 0, NULL, &wcp); + + if (SUCCEEDED (hr)) { + specialFolder = widetoutf8(wcp); // XXX: convert to UTF-8 + } + + CoTaskMemFree(wcp); + + return specialFolder; +} +#endif + +fs::path getHomeDir() { + const char *path_p; + fs::path homeDir(""); + + /* We first check HOME and use it if it is set */ + if (path_p = std::getenv("HOME")) { + homeDir = path_p; + } + +#ifdef _WIN32 + /* Only believe HOME if it is an absolute path and exists. + * + * We only do this check on Windows fnot on UNIX because + * of things like autofs. If the user has a bogus value in + * $HOME they're repsonsible + */ + if (!homeDir.empty() && !(homeDir.is_absolute() && fs::is_directory(homeDir))) { + homeDir.clear(); + } + + if (homeDir.empty()) { + /* USERPROFILE is probably the closest equivalent to $HOME? */ + if (path_p = std::getenv("USERPROFILE")) + homeDir = path_p; + } + + if (homeDir.empty()) { + homeDir = getWindowsKnownFolder(FOLDERID_Profile); + } + + if (homeDir.empty()) { + homeDir = getWindowsDirectory(); + } +#endif /* _WIN32 */ + +#ifndef _WIN32 + if (homeDir.empty()) { + /* If we didn't get it from any of those methods, we will have + * to read the user database entry. + */ + homeDir = getpwuid(getuid())->pw_dir; + } +#endif + + /* If we have been denied access to /etc/passwd (for example, by an + * overly-zealous LSM), make up a junk value. */ + if (homeDir.empty()) { + homeDir = "/"; + } + + return homeDir; +} + + +fs::path getUserConfigDir() { + const char *path_p; + fs::path configDir(""); + + if (path_p = std::getenv("XDG_CONFIG_HOME")) + configDir = path_p; + +#ifdef _WIN32 + else + configDir = getWindowsKnownFolder(FOLDERID_LocalAppData); +#endif + if (configDir.empty()) { + configDir = getHomeDir() / ".config", NULL; + } + + return configDir; +} + diff --git a/standardpaths.hpp b/standardpaths.hpp new file mode 100644 index 0000000..27eb424 --- /dev/null +++ b/standardpaths.hpp @@ -0,0 +1,24 @@ +#pragma once + +#ifdef _WIN32 +#include +#include +#include + +#include "cutf.h" +#else +#include +#include +#include +#endif + +#include +#include + + +#ifdef _WIN32 +std::filesystem::path getWindowsDirectory(void); +std::filesystem::path getWindowsKnownFolder(REFKNOWNFOLDERID folder_guid); +#endif +std::filesystem::path getHomeDir(); +std::filesystem::path getUserConfigDir(); diff --git a/teststandardpaths.cpp b/teststandardpaths.cpp new file mode 100644 index 0000000..b7aaf98 --- /dev/null +++ b/teststandardpaths.cpp @@ -0,0 +1,13 @@ +#include + +#include "standardpaths.hpp" + +int main() { + std::cout << "Home dir = " << getHomeDir() << std::endl; +#ifdef _WIN32 + std::cout << "Windows dir = " << getWindowsDirectory() << std::endl; + std::cout << "Profile dir = " << getWindowsKnownFolder(FOLDERID_Profile) << std::endl; +#endif + std::cout << "User config dir = " << getUserConfigDir() << std::endl; + return 0; +} diff --git a/win.env b/win.env new file mode 100644 index 0000000..41b6ba1 --- /dev/null +++ b/win.env @@ -0,0 +1,10 @@ +export AR=${_ARCH}-ar +export CC=${_ARCH}-gcc +export CFLAGS="${_FLAGS}" +export CROSS_COMPILING=true +export CXX=${_ARCH}-g++ +export CXXFLAGS="${_FLAGS}" +export LDFLAGS="-static -luuid -lole32" +export PATH=${_PREFIX}/bin:$PATH +export PKG_CONFIG_PATH=${_PREFIX}/lib/pkgconfig +export WIN32=true