00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _PASSENGER_LOGGING_SERVER_H_
00026 #define _PASSENGER_LOGGING_SERVER_H_
00027
00028 #include <oxt/system_calls.hpp>
00029
00030 #include <string>
00031 #include <vector>
00032
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <cstdio>
00036 #include <cstdlib>
00037 #include <cstring>
00038 #include <grp.h>
00039
00040 #include "MessageServer.h"
00041 #include "Logging.h"
00042 #include "SystemTime.h"
00043 #include "Exceptions.h"
00044 #include "FileDescriptor.h"
00045 #include "Utils.h"
00046
00047 namespace Passenger {
00048
00049 using namespace std;
00050 using namespace oxt;
00051
00052 class LoggingServer: public MessageServer::Handler {
00053 private:
00054 string dir;
00055 string dirPermissions;
00056 mode_t filePermissions;
00057 gid_t gid;
00058
00059 public:
00060 LoggingServer(const string &dir, const string &permissions = "u=rwx,g=rx,o=rx", gid_t gid = GROUP_NOT_GIVEN) {
00061 this->dir = dir;
00062 this->gid = gid;
00063 dirPermissions = permissions;
00064 filePermissions = parseModeString(permissions) & ~(S_IXUSR | S_IXGRP | S_IXOTH);
00065 }
00066
00067 virtual bool processMessage(MessageServer::CommonClientContext &commonContext,
00068 MessageServer::ClientContextPtr &handlerSpecificContext,
00069 const vector<string> &args)
00070 {
00071 if (args[0] == "open log file") {
00072 string groupName = args[1];
00073 unsigned long long timestamp = atoll(args[2].c_str());
00074 string category = args[3];
00075
00076 if (timestamp > SystemTime::getUsec()) {
00077 commonContext.channel.write("error",
00078 "Timestamp may not be in the future", NULL);
00079 return true;
00080 }
00081
00082 string groupDir;
00083 string filename;
00084 try {
00085 groupDir = TxnLogger::determineGroupDir(dir, groupName);
00086 filename = TxnLogger::determineLogFilename(dir,
00087 groupName, category, timestamp);
00088 } catch (const ArgumentException &e) {
00089 commonContext.channel.write("error", e.what(), NULL);
00090 return true;
00091 }
00092
00093 FileDescriptor fd;
00094 int ret;
00095
00096 try {
00097 makeDirTree(extractDirName(filename), dirPermissions,
00098 USER_NOT_GIVEN, gid);
00099 } catch (const FileSystemException &e) {
00100 commonContext.channel.write("error", e.what(), NULL);
00101 return true;
00102 }
00103
00104 try {
00105 createFile(groupDir + "/group_name.txt", groupName,
00106 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH,
00107 USER_NOT_GIVEN, GROUP_NOT_GIVEN,
00108 false);
00109 } catch (const FileSystemException &e) {
00110 commonContext.channel.write("error", e.what(), NULL);
00111 return true;
00112 }
00113
00114 fd = syscalls::open(filename.c_str(),
00115 O_CREAT | O_WRONLY | O_APPEND,
00116 filePermissions);
00117 if (fd == -1) {
00118 const char *message = strerror(errno);
00119 commonContext.channel.write("error", message, NULL);
00120 return true;
00121 }
00122
00123 do {
00124 ret = fchmod(fd, filePermissions);
00125 } while (ret == -1 && errno == EINTR);
00126 commonContext.channel.write("ok", NULL);
00127 commonContext.channel.writeFileDescriptor(fd);
00128 return true;
00129 } else {
00130 return false;
00131 }
00132 }
00133 };
00134
00135 }
00136
00137 #endif