166 lines
4.5 KiB
C
166 lines
4.5 KiB
C
/*
|
|
* This file is part of uIRCd. (https://git.redxen.eu/caskd/uIRCd)
|
|
* Copyright (c) 2019, 2020 Alex-David Denes
|
|
*
|
|
* uIRCd is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* any later version.
|
|
*
|
|
* uIRCd is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with uIRCd. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "filesystem.h"
|
|
|
|
#include "connection.h"
|
|
#include "limits.h"
|
|
#include "logging.h"
|
|
|
|
#include <ctype.h> // isalpha() isdigit()
|
|
#include <errno.h> // errno
|
|
#include <fcntl.h> // fnctl()
|
|
#include <limits.h> // ??
|
|
#include <stdbool.h> // bool
|
|
#include <stdio.h> // fopen() FILE fprintf()
|
|
#include <string.h> // strerror()
|
|
#include <sys/stat.h> // mkfifo() mkdir()
|
|
#include <sys/types.h> // size_t ssize_t mode_t
|
|
|
|
int
|
|
mkdir_bottomup(char* path)
|
|
{
|
|
if (path == NULL || *path == '\0') return 0;
|
|
for (char* x = path; x != NULL && *x;) {
|
|
if ((x = strchr(x, '/')) != NULL) {
|
|
char save = *(x + 1);
|
|
*(x + 1) = '\0';
|
|
if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
|
|
if (errno != EEXIST) {
|
|
*(x + 1) = save;
|
|
LOG(LOG_ERROR, "Could not create directory \"%s\".", path);
|
|
return 0;
|
|
}
|
|
} else
|
|
LOG(LOG_DEBUG, "Created directory at: %s", path);
|
|
*(x + 1) = save;
|
|
x++;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
makeinput(const char* path)
|
|
{
|
|
if (path == NULL) return -1;
|
|
if (mkfifo(path, S_IRUSR | S_IWUSR | S_IWGRP) == 0) {
|
|
LOG(LOG_VERBOSE, "Created a FIFO pipe for input at %s.", path);
|
|
} else if (errno != EEXIST) {
|
|
LOG(LOG_WARN, "Couldn't create FIFO at \"%s\" for input. " ERRNOFMT, path, strerror(errno), errno);
|
|
return -1;
|
|
}
|
|
int fd;
|
|
if ((fd = open(path, O_RDONLY | O_NONBLOCK)) == -1) {
|
|
LOG(LOG_WARN, "Couldn't open FIFO pipe \"%s\" for reading. " ERRNOFMT, path, strerror(errno), errno);
|
|
} else
|
|
LOG(LOG_DEBUG, "Opened \"%s\" for reading.", path);
|
|
return fd;
|
|
}
|
|
|
|
bool
|
|
write_log(const char* path, const char* message)
|
|
{
|
|
FILE* logfile;
|
|
if ((logfile = fopen(path, "a")) != NULL) {
|
|
fprintf(logfile, "%s", message);
|
|
LOG(LOG_DEBUG, "Wrote to log %s.", path);
|
|
fclose(logfile);
|
|
return 1;
|
|
} else
|
|
LOG(LOG_WARN, "Couldn't open file \"%s\" for appending.", path);
|
|
return 0;
|
|
}
|
|
|
|
bool
|
|
cleanup_path_names(char* name)
|
|
{
|
|
if (name == NULL) return 0;
|
|
if (!strcmp("..", name) || !strcmp(".", name)) *name = '_';
|
|
for (; *name; name++) {
|
|
if (isalpha(*name)) *name = (char) tolower(*name);
|
|
else if (strchr(".+-_#&", *name) == NULL && !isdigit(*name))
|
|
*name = '_';
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
bool
|
|
add_socket_flags(int fd, int flags)
|
|
{
|
|
int cflgs;
|
|
if ((cflgs = fcntl(fd, F_GETFL)) != -1) {
|
|
if (fcntl(fd, F_SETFL, cflgs | flags) == -1) {
|
|
LOG(LOG_WARN, "Couldn't add socket flags. " ERRNOFMT, strerror(errno), errno);
|
|
} else
|
|
return 1;
|
|
} else
|
|
LOG(LOG_WARN, "Failed to get socket flags. " ERRNOFMT, strerror(errno), errno);
|
|
return 0;
|
|
}
|
|
|
|
ssize_t
|
|
get_path(char* buf, size_t lim, Connection* conn, IRC_Message* msg, bool global, bool input, bool output)
|
|
{
|
|
if (buf == NULL || conn == NULL) return -1;
|
|
ssize_t res;
|
|
const char* save = buf;
|
|
|
|
int ci = -1;
|
|
const char *dir = NULL, *subdir = NULL;
|
|
if (global) {
|
|
dir = "global";
|
|
} else if (msg != NULL && (ci = get_msgchannel(msg)) != -1 && msg->args[ci] != NULL) {
|
|
dir = "channel";
|
|
subdir = msg->args[ci];
|
|
} else if (msg != NULL && msg->name.nick != NULL) {
|
|
dir = "user";
|
|
subdir = msg->name.nick;
|
|
} else
|
|
return -1;
|
|
if ((res = snprintf(buf, lim, "%s", dir)) == -1) return -1;
|
|
clean_and_push(&lim, (size_t) res, &buf, true);
|
|
if (subdir != NULL) {
|
|
if ((res = snprintf(buf, lim, "%s", subdir)) == -1) return -1;
|
|
clean_and_push(&lim, (size_t) res, &buf, true);
|
|
}
|
|
|
|
const char* category = NULL;
|
|
if (input) {
|
|
category = "in";
|
|
} else if (output) {
|
|
category = "out";
|
|
} else {
|
|
if ((category = get_categ(msg)) == NULL) return -1;
|
|
}
|
|
if ((res = snprintf(buf, lim, "%s", category)) == -1) return -1;
|
|
clean_and_push(&lim, (size_t) res, &buf, false);
|
|
|
|
return (buf - save);
|
|
}
|
|
|
|
void
|
|
clean_and_push(size_t* lim, size_t res, char** buf, bool dir)
|
|
{
|
|
cleanup_path_names(*buf);
|
|
if (dir) *(*(buf) + res) = '/';
|
|
*lim -= (size_t) res + dir;
|
|
*buf += (size_t) res + dir;
|
|
}
|
|
|