X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Futils%2Fos.c;h=70142f7ba8d6ab093bf907e38e47cc8e8ae30159;hp=747a3700014bd248f19230bfd0363ccba55437ee;hb=2d74729ad602709cae9f48c96c2810ee0c5e340b;hpb=e2258e6ee3c933351f81490bac576438ff973ae4 diff --git a/src/utils/os.c b/src/utils/os.c index 747a370..70142f7 100644 --- a/src/utils/os.c +++ b/src/utils/os.c @@ -35,7 +35,11 @@ #include #include +#include +#include #include +#include +#include #include @@ -45,12 +49,68 @@ #include #include +#include #include +#include /* * public API */ +char * +sdb_get_homedir(void) +{ + char *username = sdb_get_current_user(); + + struct passwd pw_entry; + struct passwd *result = NULL; + + char buf[4096]; + + int status; + + if (username) { + memset(&pw_entry, 0, sizeof(pw_entry)); + status = getpwnam_r(username, &pw_entry, buf, sizeof(buf), &result); + } + else + status = -1; + + if (status || (! result)) { + char errbuf[1024]; + sdb_log(SDB_LOG_WARNING, "os: Failed to determine home directory " + "for user %s: %s", username, + sdb_strerror(errno, errbuf, sizeof(errbuf))); + free(username); + return NULL; + } + free(username); + return strdup(result->pw_dir); +} /* sdb_get_homedir */ + +char * +sdb_realpath(const char *path) +{ + if (! path) + return NULL; + + if ((strlen(path) >= 2) && (path[0] == '~') && (path[1] == '/')) { + char *homedir = sdb_get_homedir(); + char tmp[(homedir ? strlen(homedir) : 0) + strlen(path)]; + char *ret; + + if (! homedir) + return NULL; + + snprintf(tmp, sizeof(tmp), "%s/%s", homedir, path + 2); + ret = realpath(tmp, NULL); + free(homedir); + return ret; + } + + return realpath(path, NULL); +} /* sdb_realpath */ + int sdb_mkdir_all(const char *pathname, mode_t mode) { @@ -112,26 +172,25 @@ sdb_remove_all(const char *pathname) return -1; while (42) { - struct dirent de; - struct dirent *res = NULL; + struct dirent *de; + char filename[strlen(pathname) + sizeof(de->d_name) + 2]; - char filename[strlen(pathname) + sizeof(de.d_name) + 2]; + errno = 0; + de = readdir(d); + if (! de) { + if (errno == 0) + break; - memset(&de, 0, sizeof(de)); - if (readdir_r(d, &de, &res)) { closedir(d); return -1; } - if (! res) - break; - - if ((de.d_name[0] == '.') && ((de.d_name[1] == '\0') - || ((de.d_name[1] == '.')&& (de.d_name[2] == '\0')))) + if ((de->d_name[0] == '.') && ((de->d_name[1] == '\0') + || ((de->d_name[1] == '.')&& (de->d_name[2] == '\0')))) continue; snprintf(filename, sizeof(filename), - "%s/%s", pathname, de.d_name); + "%s/%s", pathname, de->d_name); if (sdb_remove_all(filename)) { closedir(d); return -1; @@ -150,7 +209,7 @@ sdb_get_current_user(void) uid_t uid; - char buf[1024]; + char buf[4096]; int status; uid = geteuid(); @@ -248,5 +307,63 @@ sdb_write(int fd, size_t msg_len, const void *msg) return (ssize_t)msg_len; } /* sdb_write */ +int +sdb_resolve(int network, const char *address, struct addrinfo **res) +{ + struct addrinfo ai_hints; + const char *host; + char *port; + int status; + + if (! res) { + errno = EINVAL; + return EAI_SYSTEM; + } + + if (address) { + host = address; + port = strrchr(host, ':'); + if (port) { + *port = '\0'; + ++port; + } + if (! *host) + host = NULL; + } + else { + host = NULL; + port = NULL; + } + + memset(&ai_hints, 0, sizeof(ai_hints)); + ai_hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + if (network & SDB_NET_V4) + ai_hints.ai_family = AF_INET; + else if (network & SDB_NET_V6) + ai_hints.ai_family = AF_INET6; + else + ai_hints.ai_family = AF_UNSPEC; + + if ((network & SDB_NET_IP) == SDB_NET_IP) { + ai_hints.ai_socktype = 0; + ai_hints.ai_protocol = 0; + } + else if (network & SDB_NET_TCP) { + ai_hints.ai_socktype = SOCK_STREAM; + ai_hints.ai_protocol = IPPROTO_TCP; + } + else if (network & SDB_NET_UDP) { + ai_hints.ai_socktype = SOCK_DGRAM; + ai_hints.ai_protocol = IPPROTO_UDP; + } + + status = getaddrinfo(host, port, &ai_hints, res); + if (port) { + --port; + *port = ':'; + } + return status; +} /* sdb_resolve */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */