7 static bool makedir(const char *path, mode_t mode) {
10 if(mkdir(path, mode)) {
16 fprintf(stderr, "Could not create directory %s: %s\n", path, strerror(errno));
23 bool makedirs(tinc_dir_t dirs) {
29 bool need_confbase = dirs & ~((unsigned)DIR_CONFDIR);
31 if(need_confbase && (!confbase || !makedir(confbase, 0755))) {
35 if(dirs & DIR_CONFDIR && !confbase_given && (!confdir || !makedir(confdir, 0755))) {
39 if(dirs & DIR_INVITATIONS) {
40 snprintf(path, sizeof(path), "%s" SLASH "invitations", confbase);
42 if(!makedir(path, 0700)) {
47 if(dirs & DIR_CACHE) {
48 snprintf(path, sizeof(path), "%s" SLASH "cache", confbase);
50 if(!makedir(path, 0755)) {
55 if(dirs & DIR_HOSTS) {
56 snprintf(path, sizeof(path), "%s" SLASH "hosts", confbase);
58 if(!makedir(path, 0755)) {
67 /* Open a file with the desired permissions, minus the umask.
68 Also, if we want to create an executable file, we call fchmod()
69 to set the executable bits. */
71 FILE *fopenmask(const char *filename, const char *mode, mode_t perms) {
72 mode_t mask = umask(0);
75 FILE *f = fopen(filename, mode);
78 fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
85 fchmod(fileno(f), perms);
93 char *absolute_path(const char *path) {
95 // Works for nonexistent paths
96 return _fullpath(NULL, path, 0);
103 // If an absolute path was passed, return its copy
105 return xstrdup(path);
108 // Try using realpath. If it fails for any reason
109 // other than that the file was not found, bail out.
110 char *abs = realpath(path, NULL);
112 if(abs || errno != ENOENT) {
116 // Since the file does not exist, we're forced to use a fallback.
117 // Get current working directory and concatenate it with the argument.
120 if(!getcwd(cwd, sizeof(cwd))) {
124 // Remove trailing slash if present since we'll be adding our own
125 size_t cwdlen = strlen(cwd);
127 if(cwdlen && cwd[cwdlen - 1] == '/') {
128 cwd[cwdlen - 1] = '\0';
131 // We don't do any normalization because it's complicated, and the payoff is small.
132 // If user passed something like '.././../foo' — that's their choice; fopen works either way.
133 xasprintf(&abs, "%s/%s", cwd, path);
135 if(strlen(abs) >= PATH_MAX) {