virtual void listen() { if(::bind(m_socket, m_addr.native_address(), m_addr.native_size()) == -1) throw std::runtime_error{"bind(): " + errno_string(errno)}; if(::listen(m_socket, 10) == -1) throw std::runtime_error{"listen(): " + errno_string(errno)}; }
virtual size_t write(char const *src, size_t size) { // Retry on EINTR. while(true) { // MSG_NOSIGNAL: Return EPIPE instead of sending a SIGPIPE signal if the connection has // been closed. auto send_res = ::send(m_socket, src, size, MSG_NOSIGNAL); if(send_res == -1) { if(errno == EPIPE || errno == ECONNRESET) { // Connection has been closed return 0; } else if(errno != EINTR) throw std::runtime_error{"send(): " + errno_string(errno)}; } else { socket_logger().add_bytes_written(send_res); return send_res; } } }
explicit TCPSocket(Address const &addr) : m_addr{addr}, m_socket{::socket(m_addr.family(), m_addr.type(), 0)} { if(m_socket == -1) throw std::runtime_error{"socket(): " + errno_string(errno)}; }
T setsockopt(int sock, int level, int opt_name, T val) { socklen_t len = sizeof(T); if(setsockopt(sock, level, opt_name, (void*)&val, len) == -1) throw std::runtime_error{"setsockopt(): " + errno_string(errno)}; return val; }
virtual void print_statistics() { tcp_info info; socklen_t info_size = sizeof(info); if(getsockopt(m_socket, SOL_TCP, TCP_INFO, (void*)&info, &info_size) != 0) throw std::runtime_error{"getsockopt(): " + errno_string(errno)}; std::cout << "RTT: " << info.tcpi_rtt / 1000.0 << " ms\n" << "Lost packets: " << info.tcpi_lost << '\n' << "Retrans: " << info.tcpi_retrans << '\n' << "Total retransmits: " << info.tcpi_total_retrans << std::endl; }
virtual void connect() { // Retry on EINTR. // It seems this only works on Linux, see http://www.madore.org/~david/computers/connect-intr.html // for more information. while(true) { if(::connect(m_socket, m_addr.native_address(), m_addr.native_size()) == -1) { if(errno != EINTR) throw std::runtime_error{"connect(): " + errno_string(errno)}; } else break; } }
virtual std::ostream& stats_csv(std::ostream &os) { tcp_info info; socklen_t info_size = sizeof(info); if(getsockopt(m_socket, SOL_TCP, TCP_INFO, (void*)&info, &info_size) != 0) throw std::runtime_error{"getsockopt(): " + errno_string(errno)}; os << Milliseconds{info.tcpi_rtt / 1000.0}.count() << ',' << info.tcpi_snd_cwnd << ',' << info.tcpi_snd_mss << ',' << info.tcpi_rcv_mss << ',' << info.tcpi_reordering << ',' << info.tcpi_snd_ssthresh << ',' << info.tcpi_rcv_ssthresh ; return os; }
v8::Local<v8::Value> ErrnoException(v8::Isolate* isolate, int errorno, const char *syscall, const char *msg, const char *path) { Environment* env = Environment::GetCurrent(isolate); v8::Local<v8::Value> e; v8::Local<v8::String> estring = OneByteString(env->isolate(), errno_string(errorno)); if (msg == NULL || msg[0] == '\0') { msg = strerror(errorno); } v8::Local<v8::String> message = OneByteString(env->isolate(), msg); v8::Local<v8::String> cons1 = v8::String::Concat(estring, FIXED_UTF8_STRING(env->isolate(), ", ")); v8::Local<v8::String> cons2 = v8::String::Concat(cons1, message); if (path) { v8::Local<v8::String> cons3 = v8::String::Concat(cons2, FIXED_UTF8_STRING(env->isolate(), " '")); v8::Local<v8::String> cons4 = v8::String::Concat(cons3, v8::String::NewFromUtf8(env->isolate(), path)); v8::Local<v8::String> cons5 = v8::String::Concat(cons4, FIXED_UTF8_STRING(env->isolate(), "'")); e = v8::Exception::Error(cons5); } else { e = v8::Exception::Error(cons2); } v8::Local<v8::Object> obj = e->ToObject(); obj->Set(env->errno_string(), v8::Integer::New(env->isolate(), errorno)); obj->Set(env->code_string(), estring); if (path != NULL) { obj->Set(env->path_string(), v8::String::NewFromUtf8(env->isolate(), path)); } if (syscall != NULL) { obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall)); } return e; }
virtual size_t read(char *dest, size_t size) { // Retry on EINTR. while(true) { auto recv_res = ::recv(m_socket, dest, size, 0); if(recv_res == -1) { if(errno != EINTR) throw std::runtime_error{"recv(): " + errno_string(errno)}; } else { socket_logger().add_bytes_read(recv_res); // If recv_res == 0 the connection has been closed. return recv_res; } } }
virtual std::unique_ptr<Socket> accept() { // Retry on EINTR and ECONNABORTED. while(true) { ::sockaddr_storage client_addr; socklen_t addr_size = sizeof(client_addr); int client_sock = ::accept(m_socket, (::sockaddr*)&client_addr, &addr_size); if(client_sock == -1) { if(errno != EINTR && errno != ECONNABORTED) throw std::runtime_error{"accept(): " + errno_string(errno)}; } else { Address addr{m_addr.type(), "", (::sockaddr*)&client_addr, addr_size}; return std::unique_ptr<TCPSocket>{new TCPSocket{addr, client_sock}}; } } }
directory_open_failed_exc_t(int err, const base_path_t &path) { info = strprintf("Could not open directory '%s': %s", path.path().c_str(), errno_string(err).c_str()); }
SNMP_pdu *request_send_to_port_time_out_blocking(IPAddress *ip_address, int port,struct timeval *timeout,SNMP_pdu *request, char *error_label) { int sd; Address address; SNMP_pdu *response; Address me; int numfds; fd_set fdset; int count; error_label[0] = '\0'; if(request == NULL) { sprintf(error_label, "BUG: request_send_blocking(): request is NULL"); return NULL; } switch(request->type) { case GET_REQ_MSG: case GETNEXT_REQ_MSG: case SET_REQ_MSG: break; default: sprintf(error_label, "BUG: request_send_blocking(): bad type (0x%x)", request->type); return NULL; } /* sd */ sd = socket(AF_INET, SOCK_DGRAM, 0); if(sd < 0) { sprintf(error_label, ERR_MSG_SOCKET, errno_string()); return (NULL); } memset(&me, 0, sizeof (Address)); me.sin_family = AF_INET; if ((request->type) == SET_REQ_MSG) me.sin_addr.s_addr = htonl(INADDR_LOOPBACK); else me.sin_addr.s_addr = htonl(INADDR_ANY); me.sin_port = htons(0); if(bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0) { sprintf(error_label, ERR_MSG_BIND, errno_string()); (void)close(sd); return NULL; } /* address */ memset(&address, 0, sizeof(Address)); address.sin_family = AF_INET; /* LINTED */ address.sin_port = (short)port; address.sin_addr.s_addr = ip_address->s_addr; if(snmp_pdu_send(sd, &address, request, error_label)) { (void)close(sd); return NULL; } for (;;) { numfds = 0; FD_ZERO(&fdset); numfds = sd + 1; FD_SET(sd, &fdset); count = select(numfds, &fdset, 0, 0, timeout); if(count > 0) { if(FD_ISSET(sd, &fdset)) { response = snmp_pdu_receive(sd, &address, error_label); if(response == NULL) { (void)close(sd); return NULL; } (void)close(sd); return response; } } else { switch(count) { case 0: sprintf(error_label, ERR_MSG_TIMEOUT); (void)close(sd); return NULL; case -1: if(errno == EINTR) { continue; } else { sprintf(error_label, ERR_MSG_SELECT, errno_string()); (void)close(sd); return NULL; } } } } /* NOTREACHED */ }
/* * This function calls the CDE message logging service. */ static void log_message( char *progName, char *help, char *message, DtSeverity severity, int errnoset ) { char * errmsg = NULL; char * errname = NULL; char format[25]; DtMsgLogType msg_type; char buff[40]; (void) strcpy (format, "%s"); if (help) (void) strcat (format, "\n %s"); if (errnoset) { unsigned int errn; if (errnoset == TRUE) /* Use "errno" from <errno.h> ? */ errn = errno; /* --- yep. */ else errn = errnoset; /* No, not the magic value, use parm */ errname = errno_string(errn, buff); if (!(errmsg = strerror(errn))) errmsg = "unknown"; } /* * Must map the old message types to the new */ switch (severity) { case DtError: DtFatalError: DtInternalError: msg_type = DtMsgLogError; break; case DtIgnore: DtInformation: msg_type = DtMsgLogInformation; break; case DtWarning: msg_type = DtMsgLogWarning; break; default: msg_type = DtMsgLogError; } if (errmsg) (void) strcat (format, "\n [%s] %s"); if (help) { if (errmsg) DtMsgLogMessage (progName, msg_type, format, message, help, errname, errmsg); else DtMsgLogMessage (progName, msg_type, format, message, help); } else { if (errmsg) DtMsgLogMessage (progName, msg_type, format, message, errname, errmsg); else DtMsgLogMessage (progName, msg_type, format, message); } }
int main(int argc, char *argv[]) { int arg; int Fails ; char *str; int level; char *error_file = NULL; extern char *optarg; extern int optind; int opt; error_init(argv[0], application_end); optind = 1; { char domain_path[MAXPATHLEN]; setlocale(LC_ALL, ""); sprintf(domain_path, SEA_LOCALE_PATH); bindtextdomain(DOMAIN_MGET, domain_path); bindtextdomain(DOMAIN_SGET, domain_path); bindtextdomain(DOMAIN_LIBGET, domain_path); bindtextdomain(DOMAIN_LGET, domain_path); bindtextdomain(DOMAIN_FGET, domain_path); /* formatting string */ } /* parse arguments */ while((opt = getopt(argc,argv,"c:i:hr:m:o:p:a:d:yf:n:?"))!=EOF){ switch(opt){ case 'h': case '?': print_usage(); break; case 'f': Fails = strtol (optarg, &str, 10) ; if (optarg == str) { fprintf (stderr, "Invalid number following the -t option: %s\n", optarg ) ; print_usage () ; } else { SetFailThreshold (Fails) ; } break ; case 'y': recovery_on=TRUE; break; case 'p': port = strtol(optarg, &str, 10); if(optarg == str) { fprintf(stderr, "Not a valid integer following the -p option: %s\n", optarg); print_usage(); } break; case 'n': relay_agent_name = strdup(optarg); if(relay_agent_name == NULL) { fprintf(stderr, "%s\n", ERR_MSG_ALLOC); exit(1); } break; case 'o': if(optind > argc) { fprintf(stderr, "must have the enterprise name-oid file\n"); print_usage(); } name_oid_file= strdup(optarg); if(name_oid_file == NULL) { fprintf(stderr, "%s\n", ERR_MSG_ALLOC); exit(1); } break; case 'c': if(optind > argc) { fprintf(stderr, "Must have a configuration directory name following the -c option\n"); print_usage(); } config_dir = strdup(optarg); if(config_dir == NULL) { fprintf(stderr, "%s\n", ERR_MSG_ALLOC); exit(1); } break; case 'a': if(optind > argc) { fprintf(stderr, "Must have a access control filename following the -a option\n"); print_usage(); } sec_config_file = strdup(optarg); if(sec_config_file == NULL) { fprintf(stderr, "%s\n", ERR_MSG_ALLOC); exit(1); } break; case 'r': if(optind > argc) { fprintf(stderr, "Must have a resource file name following the -r option\n"); print_usage(); } resource_file = strdup(optarg); if(resource_file == NULL) { fprintf(stderr, "%s\n", ERR_MSG_ALLOC); exit(1); } break; case 'i': if(optind > argc) { fprintf(stderr, "Must have a pid file name following the -i option\n"); print_usage(); } pid_file = strdup(optarg); if(pid_file == NULL) { fprintf(stderr, "%s\n", ERR_MSG_ALLOC); exit(1); } break; case 'd': if(optind> argc) { fprintf(stderr, "Must have a trace-level following the -d option\n"); print_usage(); } level = strtol(optarg, &str, 10); if(optarg == str) { fprintf(stderr, "Not a valid integer following the -d option: %s\n", optarg); print_usage(); } if(trace_set(level, error_label)) { print_usage(); } break; case 'm': if(optind > argc) { fprintf(stderr, "Must have GROUP or SPLIT following the -m option\n"); print_usage(); } if(strcmp(optarg, "GROUP") == 0) { mode = MODE_GROUP; } else if(strcmp(optarg, "SPLIT") == 0) { mode = MODE_SPLIT; } else { fprintf(stderr, "Invalid mode: %s\n", optarg); print_usage(); } break; default: fprintf(stderr, "Invalid Option: -%c\n", optarg); print_usage(); break; } } /* if(error_file == NULL) { error_file = default_error_file; } error_open(error_file); */ if(trace_level == 0) { /* run the daemon in backgound */ int pid; pid = fork(); switch(pid) { case -1: error_exit(ERR_MSG_FORK, errno_string()); break; case 0: /* child process */ break; default: /* parent process */ exit(0); break; } } if(fclose(stdin) == EOF) { error(ERR_MSG_FCLOSE, "stdin", errno_string()); } dispatcher_init(); if(signals_init(signals_sighup, signals_exit, error_label)) { error_exit("signals_init() failed: %s", error_label); } if(trace_level == 0) { if(fclose(stdout) == EOF) { error(ERR_MSG_FCLOSE, "stdout", errno_string()); } } if(trace_level == 0) { /* background */ if(chdir("/") == -1) { error(ERR_MSG_CHDIR, "/", errno_string()); } /* set process group ID */ setpgrp(); error_close_stderr(); } dispatcher_loop(); return (0); }
static void dispatcher_loop() { int numfds; fd_set fdset; int count; struct timeval timeout; timeout.tv_usec = 0; while(1) { if(sighup) { resource_update(config_dir); sighup = False; } if(trace_level > 1) { trace_sessions(); } numfds = 0; FD_ZERO(&fdset); numfds = MAX(clients_sd, agents_sd); numfds = MAX(numfds,trap_sd); numfds++; FD_SET(clients_sd, &fdset); FD_SET(agents_sd, &fdset); FD_SET(trap_sd, &fdset); timeout.tv_sec = relay_agent_poll_interval; /* we compute the timeout according to the */ /* timeout of the pending requests */ session_select_info(&timeout); count = select(numfds, &fdset, 0, 0, &timeout); if(count > 0) { if(FD_ISSET(agents_sd, &fdset)) { /* we read the responses of the agents */ session_read(); continue; } if(FD_ISSET(trap_sd, &fdset)) { /* working on the trap */ trap_processing(); continue; } if(FD_ISSET(clients_sd, &fdset)) { /* we dispatch the requests of the application */ session_dispatch(); session_timeout(); continue; } } else { switch(count) { case 0: /* we check if some requests have timeout */ session_timeout(); watch_dog_in_action(); break; case -1: if(errno == EINTR) { break; } else { error_exit(ERR_MSG_SELECT, errno_string()); } } } } }
static void dispatcher_init() { struct sockaddr_in me; socklen_t len; /* init my_ip_address (we need it before parsing the config file) */ if(get_my_ip_address(&my_ip_address, error_label)) error_exit(ERR_MSG_MY_IP_ADDRESS, error_label); if(trace_level > 0) trace("Local IP Addresss : %s\n\n", inet_ntoa(my_ip_address)); /* init the config_dir pointer and then parse the configuration files */ if(config_dir == NULL) config_dir = default_config_dir; config_init(config_dir); /* read enterprise name-oid file */ if(name_oid_file == NULL) name_oid_file = default_name_oid_file; load_enterprise_oid(name_oid_file); /* set up the relay agent name */ if(sec_config_file == NULL) sec_config_file = default_sec_config_file; sec_config_init(sec_config_file); if(relay_agent_name == NULL) relay_agent_name = default_relay_agent_name; init_relay_agent(); /* read the resource file */ if(resource_file == NULL) resource_file = default_resource_file; if(pid_file == NULL) pid_file = default_pid_file; write_pid_file1(pid_file); res_config_init(config_dir); /* init clients_sd and agents_sd */ clients_sd = socket(AF_INET, SOCK_DGRAM, 0); if(clients_sd < 0) error_exit(ERR_MSG_SOCKET, errno_string()); memset(&me, 0, sizeof(me)); me.sin_family = AF_INET; me.sin_addr.s_addr = htonl(INADDR_ANY); me.sin_port = htons(port); if(trace_level > 0) trace("Waiting for incoming SNMP requests on UDP port %d\n\n", port); if (bind(clients_sd, (struct sockaddr *)&me, sizeof(me)) != 0) error_exit(ERR_MSG_BIND, port, errno_string()); agents_sd = socket(AF_INET, SOCK_DGRAM, 0); if (agents_sd < 0) error_exit(ERR_MSG_SOCKET, errno_string()); me.sin_family = AF_INET; me.sin_addr.s_addr = htonl(INADDR_ANY); me.sin_port = htons(0); if (bind(agents_sd, (struct sockaddr *)&me, sizeof(me)) != 0) error_exit(ERR_MSG_BIND, 0, errno_string()); trap_sd = socket(AF_INET, SOCK_DGRAM, 0); if (trap_sd < 0) error_exit(ERR_MSG_SOCKET, errno_string()); me.sin_family = AF_INET; me.sin_addr.s_addr = htonl(INADDR_ANY); me.sin_port = htons(0); if(bind(trap_sd, (struct sockaddr *)&me, sizeof(me)) != 0) error_exit(ERR_MSG_BIND, 0, errno_string()); len = (socklen_t)sizeof(me); if (getsockname(trap_sd, (struct sockaddr *)&me, &len) == -1) error_exit(ERR_MSG_BIND, 0, errno_string()); relay_agent_trap_port = ntohs(me.sin_port); write_pid_file(pid_file); }
std::pair<int,int> persistent_tests() { int num_tests_run = 0; int num_tests_failed = 0; // does it appear that this test code has run in the past? struct stat st; if (stat("/persistent/file_system_example/root", &st) == 0) { if (S_ISDIR(st.st_mode)) { fs_postHeading("Persistent File Tests: Data previously stored, running validate and delete tests"); // is the access mode set to 0777? ++num_tests_run; if ((st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != (S_IRWXU | S_IRWXG | S_IRWXO)) { ++num_tests_failed; fs_postError("stat(\"/persistent/file_system_example/root\", &st) incorrectly reported access as " << to_octal_string(st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) << " instead of 0777"); } else fs_postLine("stat(\"/persistent/file_system_example/root\", &st) correctly reported access as 0777"); // there should be exactly 4 files in persistent/file_system_example/root, // one named empty_file, one named small_file, one named write_only_file, and one named big_file (plus '.' and '..') ++num_tests_run; DIR* dir = opendir("/persistent/file_system_example/root"); if (dir == 0) { ++num_tests_failed; fs_postError("opendir(\"/persistent/file_system_example/root\") failed with errno: " << errno_string()); } else { fs_postLine("opendir(\"/persistent/file_system_example/root\")"); struct dirent *ent; while ((ent = readdir(dir)) != 0) { ++num_tests_run; fs_postLine("readdir returned \"" << ent->d_name << "\""); if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) { if (strcmp(ent->d_name,"small_file") == 0) { ++num_tests_run; struct stat st; if (stat("/persistent/file_system_example/root/small_file",&st) != 0) { ++num_tests_failed; fs_postError("stat(\"/persistent/file_system_example/root/small_file\",&st) failed with errno: " << errno_string()); } else { fs_postLine("stat(\"/persistent/file_system_example/root/small_file\",&st)"); ++num_tests_run; if (S_ISREG(st.st_mode)) { fs_postLine("S_ISREG reported \"/persistent/file_system_example/root/small_file\" as a file (not directory)"); ++num_tests_run; if (st.st_size == 20) { fs_postLine("stat correctly reported the file size for \"/persistent/file_system_example/root/small_file\" as 20 bytes"); ++num_tests_run; char rd_buf[32]; char b[32]; memcpy(&b[0], "hello world goodbye", 20); b[11] = b[12] = 0; auto fd = open("/persistent/file_system_example/root/small_file", O_RDONLY); read(fd, &rd_buf, sizeof(rd_buf)); if (memcmp(&b[0], &rd_buf[0], 20) != 0) { ++num_tests_failed; rd_buf[20] = 0; for (int i = 0; i < 20; i++) if (rd_buf[i] == 0) rd_buf[i] = 'Z'; fs_postError("file should have contained \"hello worldZZgoodbye\", but it did not. It contained: \"" << &rd_buf[0] << "\""); } else fs_postLine("file correctly contained \"hello worldZZgoodbye\" (with the Z's as NULL bytes)"); } else { ++num_tests_failed; fs_postError("stat incorrectly reported the file size for \"/persistent/file_system_example/root/small_file\" as " << st.st_size << " bytes instead of 20"); } } else { ++num_tests_failed; fs_postError("S_ISREG incorrectly reported \"/persistent/file_system_example/root/small_file\" as something other than a file"); } } } else if (strcmp(ent->d_name,"write_only_file") == 0) { ++num_tests_run; struct stat st; if (stat("/persistent/file_system_example/root/write_only_file",&st) != 0) { ++num_tests_failed; fs_postError("stat(\"/persistent/file_system_example/root/write_only_file\",&st) failed with errno: " << errno_string()); } else { fs_postLine("stat(\"/persistent/file_system_example/root/write_only_file\",&st)"); ++num_tests_run; if ((st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != (S_IWUSR | S_IWGRP | S_IWOTH)) { ++num_tests_failed; fs_postError("stat(\"/persistent/file_system_example/root/write_only_file\",&st) incorrectly reported access as " << to_octal_string(st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) << " instead of " << to_octal_string(S_IWUSR | S_IWGRP | S_IWOTH)); } else fs_postLine("stat(\"/persistent/file_system_example/root/write_only_file\",&st) correctly reported access as " << to_octal_string(S_IWUSR | S_IWGRP | S_IWOTH)); ++num_tests_run; if (st.st_mtime != 17) { ++num_tests_failed; fs_postError("write_only_file mod time incorrectly reported as " << st.st_mtime << ", instead of 17"); } else fs_postLine("write_only_file mod time correctly reported as 17"); } } else if (strcmp(ent->d_name,"big_file") == 0) { ++num_tests_run; struct stat st; if (stat("/persistent/file_system_example/root/big_file",&st) != 0) { ++num_tests_failed; fs_postError("stat(\"/persistent/file_system_example/root/big_file\",&st) failed with errno: " << errno_string()); } else { fs_postLine("stat(\"/persistent/file_system_example/root/big_file\",&st)"); ++num_tests_run; if (S_ISREG(st.st_mode)) { fs_postLine("S_ISREG reported \"/persistent/file_system_example/root/big_file\" as a file (not directory)"); ++num_tests_run; if (st.st_size == kReallyBigFileSize*strlen(kReallyBigFileString)) fs_postLine("stat correctly reported the file size of \"/persistent/file_system_example/root/big_file\" as " << kReallyBigFileSize*strlen(kReallyBigFileString) << " bytes"); else { ++num_tests_failed; fs_postError("stat incorrectly reported the file size of \"/persistent/file_system_example/root/big_file\" as " << st.st_size << " bytes"); } } else { ++num_tests_failed; fs_postError("S_ISREG incorrectly reported \"/persistent/file_system_example/root/big_file\" as something other than a file"); } } } } } closedir(dir); } ++num_tests_run; if (truncate("/persistent/file_system_example/root/big_file",10) != 0) { ++num_tests_failed; fs_postError("truncate(\"/persistent/file_system_example/root/big_file\",10) failed with errno: " << errno_string()); } else { fs_postLine("truncate(\"/persistent/file_system_example/root/big_file\",10)"); ++num_tests_run; struct stat st; if (stat("/persistent/file_system_example/root/big_file",&st) != 0) { ++num_tests_failed; fs_postError("stat(\"/persistent/file_system_example/root/big_file\",&st) failed with errno: " << errno_string()); } else { fs_postLine("stat(\"/persistent/file_system_example/root/big_file\",&st)"); ++num_tests_run; if (st.st_size == 10) fs_postLine("stat correctly reported the new, truncated file size of \"/persistent/file_system_example/root/big_file\" as 10 bytes"); else { ++num_tests_failed; fs_postError("stat incorrectly reported the file new, truncated size of \"/persistent/file_system_example/root/big_file\" as " << st.st_size << " bytes"); } } } ++num_tests_run; struct stat st; if (stat("persistent/file_system_example/root/empty_file", &st) != 0) { ++num_tests_failed; fs_postError("stat(\"persistent/file_system_example/root/empty_file\", &st) failed with errno: " << errno_string()); } else { fs_postLine("stat(\"persistent/file_system_example/root/empty_file\", &st)"); ++num_tests_run; if (st.st_size == 0) fs_postLine("stat correctly reported the size of \"/persistent/file_system_example/root/empty_file\" as 0 bytes"); else { ++num_tests_failed; fs_postError("stat incorrectly reported the size of \"/persistent/file_system_example/root/empty_file\" as " << st.st_size << " bytes"); } } clear_all("/persistent/file_system_example/root"); } else { fs_postError("/persistent/file_system_example/root exists but does not appear to be a directory, attempting to delete"); unlink("/persistent/file_system_example/root"); } } else { fs_postHeading("Persistent File Tests: No data previously stored, running create and store tests"); // can we make our root directory? // we handle failure a little differently on this one. If this fails we don't // attempt to run further tests ++num_tests_run; if (mkdir("/persistent/file_system_example/root",0777) != 0) { ++num_tests_failed; fs_postError("mkdir(\"/persistent/file_system_example/root\",0777) failed with errno: " << errno_string()); return std::make_pair(num_tests_run, num_tests_failed); } fs_postLine("mkdir(\"/persistent/file_system_example/root\",0777)"); // does a file which does not exist fail to open as expected? ++num_tests_run; auto fd = open("/persistent/file_system_example/root/does_not_exist", O_RDONLY); if (fd != -1 || errno != ENOENT) { ++num_tests_failed; fs_postError("open(\"/persistent/file_system_example/root/does_not_exist\",O_RDONLY) should have failed with errno = ENOENT, but did not. It returned " << fd << ", and errno: " << errno_string()); } else fs_postLine("open(\"/persistent/file_system_example/root/does_not_exist\", O_RDONLY) correctly failed with errno = ENOENT"); // can we make an empty file and will it persist? ++num_tests_run; fd = open("/persistent/file_system_example/root/empty_file",O_RDWR | O_CREAT, 0666); if (fd == -1) { ++num_tests_failed; fs_postError("open(\"/persistent/file_system_example/root/empty_file\",O_RDWR | O_CREAT, 0666) should have succeeded, but did not. It returned -1, and errno: " << errno_string()); } else { close(fd); fs_postLine("open(\"/persistent/file_system_example/root/empty_file\", O_RDWR | O_CREAT, 0666)"); } // can we create a new read-only file? ++num_tests_run; fd = open("/persistent/file_system_example/root/small_file",O_RDONLY | O_CREAT, 0666); if (fd == -1) { ++num_tests_failed; fs_postError("open(\"/persistent/file_system_example/root/small_file\",O_RDONLY | O_CREAT, 0666) should have succeeded, but did not. It returned -1, and errno: " << errno_string()); } else { close(fd); fs_postLine("open(\"/persistent/file_system_example/root/small_file\", O_RDONLY | O_CREAT, 0666)"); } // can we create a file with write-only access, and does this access persist? ++num_tests_run; fd = open("/persistent/file_system_example/root/write_only_file",O_WRONLY | O_CREAT, S_IWUSR | S_IWGRP | S_IWOTH); if (fd == -1) { ++num_tests_failed; fs_postError("open(\"/persistent/file_system_example/root/write_only_file\",O_WRONLY | O_CREAT, S_IWUSR | S_IWGRP | S_IWOTH) should have succeeded, but did not. It returned -1, and errno: " << errno_string()); } else { close(fd); fs_postLine("open(\"/persistent/file_system_example/root/write_only_file\", O_WRONLY | O_CREAT, S_IWUSR | S_IWGRP | S_IWOTH)"); // imediately after creation is the access mode S_IWUSR | S_IWGRP | S_IWOTH? ++num_tests_run; struct stat st; stat("/persistent/file_system_example/root/write_only_file",&st); int mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); if (mode != (S_IWUSR | S_IWGRP | S_IWOTH)) { ++num_tests_failed; fs_postError("stat(\"/persistent/file_system_example/root/write_only_file\",&st) incorrectly reported access as " << to_octal_string(mode) << " instead of " << to_octal_string(S_IWUSR | S_IWGRP | S_IWOTH)); } else fs_postLine("stat(\"/persistent/file_system_example/root/write_only_file\",&st) correctly reported access as " << to_octal_string(S_IWUSR | S_IWGRP | S_IWOTH)); ++num_tests_run; #if !defined(__native_client__) || PPAPI_RELEASE >= 39 // can we set the access time of this file and does that persist? struct timeval tv[2] = {{0, 0}, {17, 0}}; if (utimes("/persistent/file_system_example/root/write_only_file", tv) != 0) { ++num_tests_failed; fs_postError("utimes(\"/persistent/file_system_example/root/write_only_file\", tv) failed with errno: " << errno_string()); } else { fs_postLine("utimes(\"/persistent/file_system_example/root/write_only_file\", tv)"); // can we read them back right now? ++num_tests_run; struct stat st; stat("/persistent/file_system_example/root/write_only_file", &st); // although the code above does set the atime field, following the // "Criticism of atime" issues, we don't verify that it was set, or // care whether it was set. if (st.st_mtime != 17) { ++num_tests_failed; fs_postError("immediately after setting with utime, file mod time should have been 17. Instead is " << st.st_mtime); } else fs_postLine("immediately after setting with utime, file mod time was read as 17"); } #elif defined(__native_client__) ++num_tests_failed; fs_postError("Pepper_" << PPAPI_RELEASE << " is too old to run file modification time tests - it doesn't implement utime, please consider updating to at least Pepper_39"); #endif } // can we open, read-only, an existing file (the one we just created above) ++num_tests_run; fd = open("/persistent/file_system_example/root/small_file",O_RDONLY); if (fd == 1) { ++num_tests_failed; fs_postError("open(\"/persistent/file_system_example/root/small_file\",O_RDONLY) should have succeeded, but did not. It returned -1, and errno: " << errno_string()); } else { fs_postLine("open(\"/persistent/file_system_example/root/small_file\", O_RDONLY)"); // are we correctly blocked from writing to this file - we opened it O_RDONLY ++num_tests_run; const char* buf = "hello"; auto written = write(fd, buf, strlen(buf)); if (written != -1 || errno != EBADF) { ++num_tests_failed; fs_postError("write(read-only-fd, \"hello\", 5) should have failed with EBADF, but did not. It returned " << written << ", and errno: " << errno_string()); } else fs_postLine("write(read-only-fd, \"hello\", 5) correctly failed with errno = EBADF"); close(fd); } const char* hello = "hello"; const char* hello_world = "hello world"; // can we open, write-only, an existing file ++num_tests_run; fd = open("/persistent/file_system_example/root/small_file",O_WRONLY); if (fd == -1) { ++num_tests_failed; fs_postError("open(\"/persistent/file_system_example/root/small_file\",O_WRONLY) should have succeeded, but did not. It returned -1, and errno: " << errno_string()); } else { fs_postLine("open(\"/persistent/file_system_example/root/small_file\", O_WRONLY)"); // are we correctly blocked from reading from this file? ++num_tests_run; char b; auto bytes_read = read(fd, &b, 1); if (bytes_read != -1 || errno != EBADF) { ++num_tests_failed; fs_postError("read(write-only-fd, &b, 1) should have failed with errno EBADF, but did not. It returned " << bytes_read << ", and errno: " << errno_string()); } else fs_postLine("read(write-only-fd, &b, 1) correctly failed with errno = EBADF"); // can we write to this file? ++num_tests_run; auto written = write(fd, hello, strlen(hello)); if (written != strlen(hello)) { ++num_tests_failed; fs_postError("write(write-only-fd, \"hello\", 5) should have succeeded, but did not. It returned " << written << ", and errno: " << errno_string()); } else fs_postLine("write(write-only-fd, \"hello\", 5)"); close(fd); } // can we open, read-write, an existing file? ++num_tests_run; fd = open("/persistent/file_system_example/root/small_file",O_RDWR); if (fd == -1) { ++num_tests_failed; fs_postError("open(\"/persistent/file_system_example/root/small_file\",O_RDWR) should have succeeded, but did not. It returned -1, and errno: " << errno_string()); } else { fs_postLine("open(\"/persistent/file_system_example/root/small_file\", O_RDWR)"); // can we read from this file, and does it contain "hello"? ++num_tests_run; char rd_buf[32] = {0}; auto bytes_read = read(fd, &rd_buf[0], sizeof(rd_buf)); if (bytes_read != strlen(hello)) { ++num_tests_failed; fs_postError("read(read-write-fd, &rd_buf, " << sizeof(rd_buf) << ") should have returned 5, but did not. It returned " << bytes_read << (bytes_read == -1 ? (std::string(", and errno: ") + errno_string()) : std::string(""))); } else if (memcmp(rd_buf, hello, strlen(hello)) != 0) { ++num_tests_failed; fs_postError("read(read-write-fd, &rd_buf, " << sizeof(rd_buf) << ") should have read \"hello\", but did not. It read: \"" << &rd_buf[0] << "\""); } else fs_postLine("read(read-write-fd, &rd_buf, " << sizeof(rd_buf) << ")"); // can we also write (append) to this file? ++num_tests_run; const char* buf = " world"; auto written = write(fd, buf, strlen(buf)); if (written != strlen(buf)) { ++num_tests_failed; fs_postError("write(read-write-fd, \" world\", 6) should have succeeded, but did not. It returned " << written << ", and errno: " << errno_string()); } else fs_postLine("write(read-write-fd, \" world\", 6)"); // can we lseek to the middle and read the right stuff? ++num_tests_run; auto reslt = lseek(fd, 3, SEEK_SET); if (reslt != 3) { ++num_tests_failed; fs_postError("lseek(fd, 3, SEEK_SET) should have returned 3, but did not. It returned: " << reslt); } else { fs_postLine("lseek(fd, 3, SEEK_SET)"); ++num_tests_run; bytes_read = read(fd, &rd_buf[0], 3); if ((bytes_read != 3) || (memcmp(&rd_buf[0], "lo ", 3) != 0)) { ++num_tests_failed; rd_buf[3] = 0; fs_postError("read(fd, &rd_buf[0], 3) should have read \"lo \", but did not. It returned: " << bytes_read << " and read: \"" << &rd_buf[0] << "\""); } else fs_postLine("read(fd, &rd_buf[0], 3) correctly read \"lo \""); } // can we seek past the end of the file and write some new data and does that cause // the gap between the old and new data to be zero? ++num_tests_run; reslt = lseek(fd, 2, SEEK_END); if (reslt != 13) { ++num_tests_failed; fs_postError("lseek(fd, 2, SEEK_END) should have returned 13, but did not. It returned: " << reslt); } else { fs_postLine("lseek(fd, 2, SEEK_END)"); ++num_tests_run; reslt = write(fd, "goodbye", 7); if (reslt != 7) { ++num_tests_failed; fs_postError("write(fd, \"goodbye\", 7), should have returned 7 but did not. It returned: " << reslt); } else { fs_postLine("write(fd, \"goodbye\", 7)"); ++num_tests_run; lseek(fd, 0, SEEK_SET); read(fd, &rd_buf[0], sizeof(rd_buf)); char b[32]; memcpy(b, "hello world goodbye", 20); b[11] = b[12] = 0; if (memcmp(&rd_buf[0], &b[0], 20) != 0) { ++num_tests_failed; rd_buf[20] = 0; fs_postError("file should have contained \"hello worldZZgoodbye\" (with the Z's being NULL bytes), but did not, it contained: \"" << &rd_buf[0] << "\""); } else fs_postLine("file correctly contained \"hello worldZZgoodbye\" (with the Z's being NULL bytes)"); } } close(fd); } // can we create and write to a really big file? ++num_tests_run; fd = open("/persistent/file_system_example/root/big_file",O_RDWR | O_CREAT, 0666); if (fd == -1) { ++num_tests_failed; fs_postError("open(\"/persistent/file_system_example/root/big_file\",O_RDWR | O_CREAT, 0666) should have succeeded, but did not. It returned -1, and errno: " << errno_string()); } else { auto len = strlen(kReallyBigFileString); for (int i = 0; i < kReallyBigFileSize; i++) { auto bytes_written = write(fd, kReallyBigFileString, len); if (bytes_written != len) { ++num_tests_failed; fs_postError("write to really big file failed after writing " << i*len << " bytes"); break; } } fs_postLine("wrote " << kReallyBigFileSize*len << " bytes to \"/persistent/file_system_example/root/big_file\""); close(fd); } } return std::make_pair(num_tests_run, num_tests_failed); }