static NEOERR *wdb_save_defn (WDB *wdb, const char *name) { char path[_POSIX_PATH_MAX]; char path2[_POSIX_PATH_MAX]; FILE *fp; NEOERR *err = STATUS_OK; int r; snprintf (path, sizeof(path), "%s.wdf.new", name); snprintf (path2, sizeof(path2), "%s.wdf", name); fp = fopen (path, "w"); if (fp == NULL) return nerr_raise_errno (NERR_IO, "Unable to open defn %s", name); err = wdb_save_defn_v1 (wdb, fp); fclose (fp); if (err != STATUS_OK) { unlink (path); return nerr_pass (err); } r = unlink (path2); if (r == -1 && errno != ENOENT) return nerr_raise_errno (NERR_IO, "Unable to unlink %s", path2); r = link (path, path2); if (r == -1) return nerr_raise_errno (NERR_IO, "Unable to link %s to %s", path, path2); r = unlink (path); wdb->defn_dirty = 0; wdb->table_version = rand(); return STATUS_OK; }
/* Also, an annoyance here... what to do with the EOF case? Currently, * we're just returing with a ol of 0, which means in most cases when * calling this we have to check that case as well as standard errors. * We could raise an NERR_EOF or something, but that seems like * overkill. We should probably have a ret arg for the case... */ static NEOERR *ne_net_fill(NSOCK *sock) { NEOERR *err; struct timeval tv; fd_set fds; int r; /* Ok, we are assuming a model where one side of the connection is the * consumer and the other the producer... and then it switches. So we * flush the output buffer (if any) before we read */ if (sock->ol) { err = ne_net_flush(sock); if (err) return nerr_pass(err); } /* Ok, we want connections to fail if they don't connect in * conn_timeout... but with higher listen queues, the connection could * actually connect, but the remote server won't get to it within the * conn_timeout, we still want it to fail. We do that by using the * conn_timeout on the first read ... this isn't quite the same as we * might actually timeout at almost 2x conn_timeout (if we had to wait * for connect and the first read) but its still better then waiting * the full data timeout */ if (sock->conn_timeout) { tv.tv_sec = sock->conn_timeout; sock->conn_timeout = 0; } else { tv.tv_sec = sock->data_timeout; } tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(sock->fd, &fds); r = select(sock->fd+1, &fds, NULL, NULL, &tv); if (r == 0) { return nerr_raise(NERR_IO, "read failed: Timeout"); } if (r < 0) { return nerr_raise_errno(NERR_IO, "select for read failed"); } sock->ibuf[0] = '\0'; r = read(sock->fd, sock->ibuf, NET_BUFSIZE); if (r < 0) { return nerr_raise_errno(NERR_IO, "read failed"); } sock->ib = 0; sock->il = r; return STATUS_OK; }
/* The search path is part of the HDF by convention */ NEOERR* hdf_search_path (HDF *hdf, const char *path, char *full, int full_len) { HDF *paths; struct stat s; for (paths = hdf_get_child (hdf, "hdf.loadpaths"); paths; paths = hdf_obj_next (paths)) { snprintf (full, full_len, "%s/%s", hdf_obj_value(paths), path); errno = 0; if (stat (full, &s) == -1) { if (errno != ENOENT) return nerr_raise_errno (NERR_SYSTEM, "Stat of %s failed", full); } else { return STATUS_OK; } } strncpy (full, path, full_len); if (stat (full, &s) == -1) { if (errno != ENOENT) return nerr_raise_errno (NERR_SYSTEM, "Stat of %s failed", full); } else return STATUS_OK; return nerr_raise (NERR_NOT_FOUND, "Path %s not found", path); }
NEOERR *hdf_write_file_atomic (HDF *hdf, const char *path) { NEOERR *err; FILE *fp; char tpath[PATH_BUF_SIZE]; static int count = 0; snprintf(tpath, sizeof(tpath), "%s.%5.5f.%d", path, ne_timef(), count++); fp = fopen(tpath, "w"); if (fp == NULL) return nerr_raise_errno (NERR_IO, "Unable to open %s for writing", tpath); err = hdf_dump_format (hdf, 0, fp); fclose (fp); if (err) { unlink(tpath); return nerr_pass(err); } if (rename(tpath, path) == -1) { unlink (tpath); return nerr_raise_errno (NERR_IO, "Unable to rename file %s to %s", tpath, path); } return STATUS_OK; }
NEOERR *ne_remove_dir (const char *path) { NEOERR *err; DIR *dp; struct stat s; struct dirent *de; char npath[PATH_BUF_SIZE]; if (stat(path, &s) == -1) { if (errno == ENOENT) return STATUS_OK; return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path); } if (!S_ISDIR(s.st_mode)) { return nerr_raise (NERR_ASSERT, "Path %s is not a directory", path); } dp = opendir(path); if (dp == NULL) return nerr_raise_errno (NERR_IO, "Unable to open directory %s", path); while ((de = readdir (dp)) != NULL) { if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) { snprintf (npath, sizeof(npath), "%s/%s", path, de->d_name); if (stat(npath, &s) == -1) { if (errno == ENOENT) continue; closedir(dp); return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", npath); } if (S_ISDIR(s.st_mode)) { err = ne_remove_dir(npath); if (err) break; } else { if (unlink(npath) == -1) { if (errno == ENOENT) continue; closedir(dp); return nerr_raise_errno (NERR_SYSTEM, "Unable to unlink file %s", npath); } } } } closedir(dp); if (rmdir(path) == -1) { return nerr_raise_errno (NERR_SYSTEM, "Unable to rmdir %s", path); } return STATUS_OK; }
NEOERR *ne_load_file_len (const char *path, char **str, int *out_len) { struct stat s; int fd; int len; int bytes_read; *str = NULL; if (out_len) *out_len = 0; if (stat(path, &s) == -1) { if (errno == ENOENT) return nerr_raise (NERR_NOT_FOUND, "File %s not found", path); return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path); } if (s.st_size >= INT_MAX) return nerr_raise (NERR_ASSERT, "File %s too large (%ld >= INT_MAX)", path, s.st_size); if (s.st_size < 0) return nerr_raise (NERR_ASSERT, "File %s size error? (%ld < 0)", path, s.st_size); fd = open (path, O_RDONLY); if (fd == -1) { return nerr_raise_errno (NERR_SYSTEM, "Unable to open file %s", path); } len = s.st_size; *str = (char *) malloc (len + 1); if (*str == NULL) { close(fd); return nerr_raise (NERR_NOMEM, "Unable to allocate memory (%d) to load file %s", len + 1, path); } if ((bytes_read = read (fd, *str, len)) == -1) { close(fd); free(*str); return nerr_raise_errno (NERR_SYSTEM, "Unable to read file %s", path); } (*str)[bytes_read] = '\0'; close(fd); if (out_len) *out_len = bytes_read; return STATUS_OK; }
NEOERR *ne_mkdirs (const char *path, mode_t mode) { char mypath[PATH_BUF_SIZE]; int x; int r; strncpy (mypath, path, sizeof(mypath)); x = strlen(mypath); if (((size_t)x < sizeof(mypath)) && (mypath[x-1] != '/')) { mypath[x] = '/'; mypath[x+1] = '\0'; } for (x = 1; mypath[x]; x++) { if (mypath[x] == '/') { mypath[x] = '\0'; #ifdef __MINGW32__ /* Braindead MINGW32 doesn't just have a dummy argument for mode */ r = mkdir (mypath); #else r = mkdir (mypath, mode); #endif if (r == -1 && errno != EEXIST) { return nerr_raise_errno(NERR_SYSTEM, "ne_mkdirs: mkdir(%s, %x) failed", mypath, mode); } mypath[x] = '/'; } } return STATUS_OK; }
NEOERR *fLock(int lock) { if(lockf(lock, F_LOCK, 0) < 0) return nerr_raise_errno (NERR_LOCK, "File lock failed"); return STATUS_OK; }
NEOERR *filter_create_fp(const char *cmd, FILE **in, FILE **out, FILE **err, pid_t *pid) { NEOERR *nerr; int fdin = 0, fdout = 0, fderr = 0; int *pfdin = NULL, *pfdout = NULL, *pfderr = NULL; if (in) pfdin = &fdin; if (out) pfdout = &fdout; if (err) pfderr = &fderr; nerr = filter_create_fd(cmd, pfdin, pfdout, pfderr, pid); if (nerr) return nerr_pass(nerr); if (in) { *in = fdopen (fdin, "w"); if (*in == NULL) return nerr_raise_errno(NERR_IO, "Unable to fdopen in for command: %s", cmd); } if (out) { *out = fdopen (fdout, "r"); if (*out == NULL) { if (in) fclose(*in); return nerr_raise_errno(NERR_IO, "Unable to fdopen out for command: %s", cmd); } } if (err) { *err = fdopen (fderr, "r"); if (*err == NULL) { if (in) fclose(*in); if (out) fclose(*out); return nerr_raise_errno(NERR_IO, "Unable to fdopen err for command: %s", cmd); } } return STATUS_OK; }
NEOERR *cgiwrap_write (const char *buf, int buf_len) { int r; if (GlobalWrapper.write_cb != NULL) { r = GlobalWrapper.write_cb (GlobalWrapper.data, buf, buf_len); if (r != buf_len) return nerr_raise_errno (NERR_IO, "write_cb returned %d<%d", r, buf_len); } else { /* r = fwrite(buf, sizeof(char), buf_len, stderr); */ r = fwrite(buf, sizeof(char), buf_len, stdout); if (r != buf_len) return nerr_raise_errno (NERR_IO, "fwrite returned %d<%d", r, buf_len); } return STATUS_OK; }
NEOERR *ne_net_flush(NSOCK *sock) { fd_set fds; struct timeval tv; int r; int x = 0; if (sock->conn_timeout) { tv.tv_sec = sock->conn_timeout; } else { tv.tv_sec = sock->data_timeout; } tv.tv_usec = 0; x = 0; while (x < sock->ol) { FD_ZERO(&fds); FD_SET(sock->fd, &fds); r = select(sock->fd+1, NULL, &fds, NULL, &tv); if (r == 0) { return nerr_raise(NERR_IO, "write failed: Timeout"); } if (r < 0) { return nerr_raise_errno(NERR_IO, "select for write failed"); } r = write(sock->fd, sock->obuf + x, sock->ol - x); if (r < 0) { return nerr_raise_errno(NERR_IO, "select for write failed"); } x += r; } sock->ol = 0; return STATUS_OK; }
static NEOERR *wdb_load_defn (WDB *wdb, const char *name) { char path[_POSIX_PATH_MAX]; char line[1024]; FILE *fp; NEOERR *err = STATUS_OK; snprintf (path, sizeof(path), "%s.wdf", name); fp = fopen (path, "r"); if (fp == NULL) { if (errno == ENOENT) return nerr_raise (NERR_NOT_FOUND, "Unable to open defn %s", name); return nerr_raise_errno (NERR_IO, "Unable to open defn %s", name); } /* Read Version string */ if (fgets (line, sizeof(line), fp) == NULL) { fclose(fp); return nerr_raise_errno (NERR_IO, "Unable to read defn %s", name); } string_rstrip(line); if (!strcmp(line, DEFN_VERSION_1)) { err = wdb_load_defn_v1(wdb, fp); fclose(fp); if (err) return nerr_pass(err); } else { fclose(fp); return nerr_raise (NERR_ASSERT, "Unknown defn version %s: %s", line, name); } wdb->table_version = rand(); return STATUS_OK; }
NEOERR *ne_save_file (const char *path, char *str) { NEOERR *err; int fd; int w, l; fd = open (path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); if (fd == -1) { return nerr_raise_errno (NERR_IO, "Unable to create file %s", path); } l = strlen(str); w = write (fd, str, l); if (w != l) { err = nerr_raise_errno (NERR_IO, "Unable to write file %s", path); close (fd); return err; } close (fd); return STATUS_OK; }
NEOERR * rcfs_listdir (const char *path, ULIST **list) { NEOERR *err; DIR *dp; ULIST *files; struct dirent *de; int l; char *f; *list = NULL; err = uListInit (&files, 10, 0); if (err) return nerr_pass (err); dp = opendir(path); if (dp == NULL) { uListDestroy(&files, ULIST_FREE); if (errno == ENOENT) return nerr_raise (NERR_NOT_FOUND, "Directory %s doesn't exist", path); return nerr_raise_errno (NERR_IO, "Unable to open directory %s", path); } while ((de = readdir (dp)) != NULL) { l = strlen (de->d_name); if (l>4 && !strcmp (de->d_name+l-4, ",log")) { f = (char *) malloc ((l-3) * sizeof(char)); if (f == NULL) { uListDestroy (&files, ULIST_FREE); closedir(dp); return nerr_raise (NERR_NOMEM, "Unable to allocate memory for filename %s", de->d_name); } strncpy (f, de->d_name, l-4); f[l-4] = '\0'; err = uListAppend (files, f); if (err) { free (f); uListDestroy (&files, ULIST_FREE); closedir(dp); return nerr_pass (err); } } } *list = files; closedir(dp); return STATUS_OK; }
NEOERR *fFind(int *plock, const char *file) { int lock; *plock = -1; if((lock = open(file, O_WRONLY|O_NDELAY|O_APPEND, 0666)) < 0) { if (errno == ENOENT) return nerr_raise (NERR_NOT_FOUND, "Unable to find lock file %s", file); return nerr_raise_errno (NERR_IO, "Unable to open lock file %s", file); } *plock = lock; return STATUS_OK; }
NEOERR *ne_listdir_fmatch(const char *path, ULIST **files, MATCH_FUNC fmatch, void *rock) { DIR *dp; struct dirent *de; ULIST *myfiles = NULL; NEOERR *err = STATUS_OK; if (files == NULL) return nerr_raise(NERR_ASSERT, "Invalid call to ne_listdir_fmatch"); if (*files == NULL) { err = uListInit(&myfiles, 10, 0); if (err) return nerr_pass(err); } else { myfiles = *files; } if ((dp = opendir (path)) == NULL) { return nerr_raise_errno(NERR_IO, "Unable to opendir %s", path); } while ((de = readdir (dp)) != NULL) { if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; if (fmatch != NULL && !fmatch(rock, de->d_name)) continue; err = uListAppend(myfiles, strdup(de->d_name)); if (err) break; } closedir(dp); if (err && *files == NULL) { uListDestroy(&myfiles, ULIST_FREE); } else if (*files == NULL) { *files = myfiles; } return nerr_pass(err); }
NEOERR *cgiwrap_writevf (const char *fmt, va_list ap) { int r; if (GlobalWrapper.writef_cb != NULL) { r = GlobalWrapper.writef_cb (GlobalWrapper.data, fmt, ap); if (r) return nerr_raise_errno (NERR_IO, "writef_cb returned %d", r); } else { vprintf (fmt, ap); /* vfprintf(stderr, fmt, ap); */ } return STATUS_OK; }
NEOERR *hdf_write_file (HDF *hdf, const char *path) { NEOERR *err; FILE *fp; fp = fopen(path, "w"); if (fp == NULL) return nerr_raise_errno (NERR_IO, "Unable to open %s for writing", path); err = hdf_dump_format (hdf, 0, fp); fclose (fp); if (err) { unlink(path); } return nerr_pass(err); }
static NEOERR * _meta_save (const char *path, HDF *meta) { NEOERR *err; char ftmp[_POSIX_PATH_MAX]; char fpath[_POSIX_PATH_MAX]; snprintf (ftmp, sizeof(ftmp), "%s,log.tmp", path); snprintf (fpath, sizeof(fpath), "%s,log", path); err = hdf_write_file (meta, ftmp); if (err) return nerr_pass (err); if (rename (ftmp, fpath) == -1) { unlink (ftmp); return nerr_raise_errno (NERR_IO, "Unable to rename file %s", ftmp); } return STATUS_OK; }
NEOERR *ne_net_accept(NSOCK **sock, int sfd, int data_timeout) { NSOCK *my_sock; int fd; struct sockaddr_in client_addr; socklen_t len; len = sizeof(struct sockaddr_in); while (1) { fd = accept(sfd, (struct sockaddr *)&client_addr, &len); if (fd >= 0) break; if (ShutdownAccept || errno != EINTR) { return nerr_raise_errno(NERR_IO, "accept() returned error"); } if (errno == EINTR) { ne_warn("accept received EINTR"); } } my_sock = (NSOCK *) calloc(1, sizeof(NSOCK)); if (my_sock == NULL) { close(fd); return nerr_raise(NERR_NOMEM, "Unable to allocate memory for NSOCK"); } my_sock->fd = fd; my_sock->remote_ip = ntohl(client_addr.sin_addr.s_addr); my_sock->remote_port = ntohs(client_addr.sin_port); my_sock->data_timeout = data_timeout; *sock = my_sock; return STATUS_OK; }
NEOERR *fCreate(int *plock, const char *file) { NEOERR *err; int lock; char *p; *plock = -1; /* note the default mode of 666 is possibly a security hole in that * someone else can grab your lock and DoS you. For internal use, who * cares? */ if((lock = open(file, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT|O_EXCL, 0666)) < 0) { if (errno == ENOENT) { p = strrchr (file, '/'); if (p != NULL) { *p = '\0'; err = ne_mkdirs(file, 0777); *p = '/'; if (err != STATUS_OK) return nerr_pass(err); lock = open(file, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0666); } } if (errno == EEXIST) return nerr_pass(fFind(plock, file)); if (lock < 0) return nerr_raise_errno (NERR_IO, "Unable to open lock file %s", file); } *plock = lock; return STATUS_OK; }
NEOERR *filter_create_fd (const char *cmd, int *fdin, int *fdout, int *fderr, pid_t *pid) { int pi[2]={-1,-1}, po[2]={-1,-1}, pe[2]={-1,-1}; int rpid; *pid = 0; if (fdin) { *fdin = 0; if (pipe (pi) == -1) return nerr_raise_errno(NERR_SYSTEM, "Unable to open in pipe for command: %s", cmd); } if (fdout) { *fdout = 0; if (pipe (po) == -1) { if (fdin) { close (pi[0]); close (pi[1]); } return nerr_raise_errno(NERR_SYSTEM, "Unable to open out pipe for command: %s", cmd); } } if (fderr) { *fderr = 0; if (pipe (pe) == -1) { if (fdin) { close (pi[0]); close (pi[1]); } if (fdout) { close (po[0]); close (po[1]); } return nerr_raise_errno(NERR_SYSTEM, "Unable to open err pipe for command: %s", cmd); } } /* block signals */ if ((rpid = fork ()) == 0) { /* unblock signals */ if (fdin) { close (pi[1]); dup2 (pi[0], 0); close (pi[0]); } if (fdout) { close (po[0]); dup2 (po[1], 1); close (po[1]); } if (fderr) { close (pe[0]); dup2 (pe[1], 2); close (pe[1]); } execl ("/bin/sh", "sh", "-c", cmd, (void *)NULL); _exit (127); } else if (rpid == -1) { /* unblock signals */ if (fdin) { close (pi[0]); close (pi[1]); } if (fdout) { close (po[0]); close (po[1]); } if (fderr) { close (pe[0]); close (pe[1]); } return nerr_raise_errno(NERR_SYSTEM, "Unable to fork for command: %s", cmd); } if (fdout) { close (po[1]); *fdout = po[0]; } if (fdin) { close (pi[0]); *fdin = pi[1]; } if (fderr) { close (pe[1]); *fderr = pe[0]; } *pid = rpid; return STATUS_OK; }
/* Client side */ NEOERR *ne_net_connect(NSOCK **sock, const char *host, int port, int conn_timeout, int data_timeout) { struct sockaddr_in serv_addr; struct hostent hp; struct hostent *php; int fd; int r = 0, x; int flags; struct timeval tv; fd_set fds; int optval; socklen_t optlen; NSOCK *my_sock; /* FIXME: This isn't thread safe... but there's no man entry for the _r * version? */ php = gethostbyname(host); if (php == NULL) { return nerr_raise(NERR_IO, "Host not found: %s", hstrerror(h_errno)); } hp = *php; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) return nerr_raise_errno(NERR_IO, "Unable to create socket"); flags = fcntl(fd, F_GETFL, 0 ); if (flags == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to get socket flags"); } if (fcntl(fd, F_SETFL, flags | O_NDELAY) == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to set O_NDELAY"); } x = 0; while (hp.h_addr_list[x] != NULL) { memcpy(&(serv_addr.sin_addr), hp.h_addr_list[x], sizeof(struct in_addr)); errno = 0; r = connect(fd, (struct sockaddr *) &(serv_addr), sizeof(struct sockaddr_in)); if (r == 0 || errno == EINPROGRESS) break; x++; } if (r != 0) { if (errno != EINPROGRESS) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to connect to %s:%d", host, port); } tv.tv_sec = conn_timeout; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(fd, &fds); r = select(fd+1, NULL, &fds, NULL, &tv); if (r == 0) { close(fd); return nerr_raise(NERR_IO, "Connection to %s:%d failed: Timeout", host, port); } if (r < 0) { close(fd); return nerr_raise_errno(NERR_IO, "Connection to %s:%d failed", host, port); } optlen = sizeof(optval); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to getsockopt to determine connection error"); } if (optval) { close(fd); errno = optval; return nerr_raise_errno(NERR_IO, "Connection to %s:%d failed", host, port); } } /* Re-enable blocking... we'll use select on read/write for timeouts * anyways, and if we want non-blocking version in the future we'll * add a flag or something. */ flags = fcntl(fd, F_GETFL, 0 ); if (flags == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to get socket flags"); } if (fcntl(fd, F_SETFL, flags & ~O_NDELAY) == -1) { close(fd); return nerr_raise_errno(NERR_IO, "Unable to set O_NDELAY"); } my_sock = (NSOCK *) calloc(1, sizeof(NSOCK)); if (my_sock == NULL) { close(fd); return nerr_raise(NERR_NOMEM, "Unable to allocate memory for NSOCK"); } my_sock->fd = fd; my_sock->remote_ip = ntohl(serv_addr.sin_addr.s_addr); my_sock->remote_port = port; my_sock->data_timeout = data_timeout; my_sock->conn_timeout = conn_timeout; *sock = my_sock; return STATUS_OK; }
NEOERR *ne_remove_dir (const char *path) { #ifdef _MSC_VER SHFILEOPSTRUCT op; op.hwnd = NULL; op.wFunc = FO_DELETE; char* tmp = (char*)calloc(1, strlen(path) + 2); memcpy(tmp, path, strlen(path)); op.pFrom = tmp; op.pTo = NULL; op.fFlags = FOF_SILENT; op.hNameMappings = NULL; op.lpszProgressTitle = NULL; int res = SHFileOperation(&op); free(tmp); if (res != 0) return nerr_raise_errno(NERR_SYSTEM, "Unable to stat file %s", path); #else NEOERR *err; DIR *dp; struct stat s; struct dirent *de; char npath[PATH_BUF_SIZE]; if (stat(path, &s) == -1) { if (errno == ENOENT) return STATUS_OK; return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path); } if (!S_ISDIR(s.st_mode)) { return nerr_raise (NERR_ASSERT, "Path %s is not a directory", path); } dp = opendir(path); if (dp == NULL) return nerr_raise_errno (NERR_IO, "Unable to open directory %s", path); while ((de = readdir (dp)) != NULL) { if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) { snprintf (npath, sizeof(npath), "%s/%s", path, de->d_name); if (stat(npath, &s) == -1) { if (errno == ENOENT) continue; closedir(dp); return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", npath); } if (S_ISDIR(s.st_mode)) { err = ne_remove_dir(npath); if (err) break; } else { if (unlink(npath) == -1) { if (errno == ENOENT) continue; closedir(dp); return nerr_raise_errno (NERR_SYSTEM, "Unable to unlink file %s", npath); } } } } closedir(dp); if (rmdir(path) == -1) { return nerr_raise_errno (NERR_SYSTEM, "Unable to rmdir %s", path); } #endif return STATUS_OK; }
NEOERR *ne_listdir_fmatch(const char *path, ULIST **files, MATCH_FUNC fmatch, void *rock) { NEOERR *err = STATUS_OK; ULIST *myfiles = NULL; if (files == NULL) return nerr_raise(NERR_ASSERT, "Invalid call to ne_listdir_fmatch"); if (*files == NULL) { err = uListInit(&myfiles, 10, 0); if (err) return nerr_pass(err); } else { myfiles = *files; } #ifdef _MSC_VER HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; CHAR rootDir[MAX_PATH]; StringCchCopy(rootDir, MAX_PATH, path); StringCchCat(rootDir, MAX_PATH, TEXT("\\*")); hFind = FindFirstFile(rootDir, &ffd); if (hFind == INVALID_HANDLE_VALUE) return nerr_raise_errno(NERR_IO, "Unable to opendir %s", path); do { if (!strcmp(ffd.cFileName, ".") || !strcmp(ffd.cFileName, "..")) continue; if (fmatch != NULL && !fmatch(rock, ffd.cFileName)) continue; err = uListAppend(myfiles, strdup(ffd.cFileName)); if (err) break; } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else DIR *dp; struct dirent *de; if ((dp = opendir (path)) == NULL) { return nerr_raise_errno(NERR_IO, "Unable to opendir %s", path); } while ((de = readdir (dp)) != NULL) { if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; if (fmatch != NULL && !fmatch(rock, de->d_name)) continue; err = uListAppend(myfiles, strdup(de->d_name)); if (err) break; } closedir(dp); #endif if (err && *files == NULL) { uListDestroy(&myfiles, ULIST_FREE); } else if (*files == NULL) { *files = myfiles; } return nerr_pass(err); }
/* Server side */ NEOERR *ne_net_listen(int port, int *fd) { int sfd = 0; int on = 1; /* int flags; */ struct sockaddr_in serv_addr; if ((sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) return nerr_raise_errno(NERR_IO, "Unable to create socket"); if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) == -1) { close(sfd); return nerr_raise_errno(NERR_IO, "Unable to setsockopt(SO_REUSEADDR)"); } if(setsockopt (sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)) == -1) { close(sfd); return nerr_raise_errno(NERR_IO, "Unable to setsockopt(SO_KEEPALIVE)"); } if(setsockopt (sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)) == -1) { close(sfd); return nerr_raise_errno(NERR_IO, "Unable to setsockopt(TCP_NODELAY)"); } serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(port); if (bind(sfd,(struct sockaddr *)&(serv_addr),sizeof(struct sockaddr)) == -1) { close(sfd); return nerr_raise_errno(NERR_IO, "Unable to bind to port %d", port); } /* If set non-block, then we have to use select prior to accept... * typically we don't, so we'll leave this out until we have a need * for it and then figure out how to work it into the common code */ /* flags = fcntl(sfd, F_GETFL, 0 ); if (flags == -1) { close(sfd); return nerr_raise_errno(NERR_IO, "Unable to get socket flags for port %d", port); } if (fcntl(sfd, F_SETFL, flags | O_NDELAY) == -1) { close(sfd); return nerr_raise_errno(NERR_IO, "Unable to set O_NDELAY for port %d", port); } */ if (listen(sfd, 100) == -1) { close(sfd); return nerr_raise_errno(NERR_IO, "Unable to listen on port %d", port); } *fd = sfd; return STATUS_OK; }
NEOERR * rcfs_save (const char *path, const char *data, const char *user, const char *log) { NEOERR *err; HDF *meta = NULL, *vers; char fpath[_POSIX_PATH_MAX]; char buf[256]; int version = 0; int fd; int lock; int x, l, w; err = rcfs_lock (path, &lock); if (err) return nerr_pass (err); do { err = rcfs_meta_load (path, &meta); if (err && nerr_handle (&err, NERR_NOT_FOUND)) { /* new file! */ err = hdf_init (&meta); } if (err) return nerr_pass (err); for (vers = hdf_get_child (meta, "Versions"); vers; vers = hdf_obj_next (vers)) { x = atoi (hdf_obj_name (vers)); if (x > version) version = x; } /* new version */ version++; snprintf (fpath, sizeof (fpath), "%s,%d", path, version); fd = open (fpath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (fd == -1) { err = nerr_raise_errno (NERR_IO, "Unable to create file %s", fpath); break; } l = strlen(data); w = write (fd, data, l); if (w != l) { err = nerr_raise_errno (NERR_IO, "Unable to write file %s", fpath); close (fd); break; } close (fd); snprintf (buf, sizeof(buf), "Versions.%d.Log", version); err = hdf_set_value (meta, buf, log); if (err) break; snprintf (buf, sizeof(buf), "Versions.%d.User", version); err = hdf_set_value (meta, buf, user); if (err) break; snprintf (buf, sizeof(buf), "Versions.%d.Date", version); err = hdf_set_int_value (meta, buf, ne_timef()); if (err) break; err = _meta_save (path, meta); } while (0); rcfs_unlock (lock); hdf_destroy (&meta); return nerr_pass (err); }