/* ISC license. */ #include #include #include #include #include #include #include #include static int s6rc_db_check_valid_string (char const *string, size_t stringlen, size_t pos) { if (pos >= stringlen) return 0 ; if (strnlen(string + pos, stringlen - pos) == stringlen - pos) return 0 ; return 1 ; } static inline int s6rc_db_check_valid_strings (char const *string, size_t stringlen, size_t pos, unsigned int n) { while (n--) { if (!s6rc_db_check_valid_string(string, stringlen, pos)) return 0 ; pos += strlen(string + pos) + 1 ; } return 1 ; } static inline int s6rc_db_read_uints (buffer *b, unsigned int max, uint32_t *p, unsigned int n) { uint32_t x ; while (n--) { if (!s6rc_db_read_uint32(b, &x)) return -1 ; if (x >= max) return 0 ; *p++ = x ; } return 1 ; } static inline int s6rc_db_read_services (buffer *b, s6rc_db_t *db) { unsigned int n = db->nshort + db->nlong ; unsigned int nargvs = db->nargvs ; unsigned int argvpos = 0 ; unsigned int i = 0 ; for (; i < n ; i++) { s6rc_service_t *sv = db->services + i ; if (!s6rc_db_read_uint32(b, &sv->name)) return -1 ; if (sv->name >= db->stringlen) return 0 ; if (!s6rc_db_check_valid_string(db->string, db->stringlen, sv->name)) return 0 ; if (!s6rc_db_read_uint32(b, &sv->flags)) return -1 ; if (!s6rc_db_read_uint32(b, &sv->timeout[0])) return -1 ; if (!s6rc_db_read_uint32(b, &sv->timeout[1])) return -1 ; if (!s6rc_db_read_uint32(b, &sv->ndeps[0])) return -1 ; if (!s6rc_db_read_uint32(b, &sv->ndeps[1])) return -1 ; if (!s6rc_db_read_uint32(b, &sv->deps[0])) return -1 ; if (sv->deps[0] > db->ndeps || sv->deps[0] + sv->ndeps[0] > db->ndeps) return 0 ; if (!s6rc_db_read_uint32(b, &sv->deps[1])) return -1 ; if (sv->deps[1] > db->ndeps || sv->deps[1] + sv->ndeps[1] > db->ndeps) return 0 ; if (i < db->nlong) { if (!s6rc_db_read_uint32(b, &sv->x.longrun.consumer)) return -1 ; if (!s6rc_db_read_uint32(b, &sv->x.longrun.nproducers)) return -1 ; if (!s6rc_db_read_uint32(b, &sv->x.longrun.producers)) return -1 ; } else { unsigned int j = 0 ; for (; j < 2 ; j++) { uint32_t pos, argc ; if (!s6rc_db_read_uint32(b, &argc)) return -1 ; if (argc > nargvs) return 0 ; if (!s6rc_db_read_uint32(b, &pos)) return -1 ; if (!s6rc_db_check_valid_strings(db->string, db->stringlen, pos, argc)) return 0 ; if (!env_make((char const **)db->argvs + argvpos, argc, db->string + pos, db->stringlen - pos)) return -1 ; sv->x.oneshot.argv[j] = argvpos ; sv->x.oneshot.argc[j] = argc ; argvpos += argc ; nargvs -= argc ; if (!nargvs--) return 0 ; db->argvs[argvpos++] = 0 ; } } { char c ; if (buffer_get(b, &c, 1) < 1) return -1 ; if (c != '\376') return 0 ; } } if (nargvs) return 0 ; return 1 ; } static inline int s6rc_db_read_string (buffer *b, char *string, size_t len) { if (buffer_get(b, string, len) < (ssize_t)len) return -1 ; return 1 ; } static inline int s6rc_db_read_buffer (buffer *b, s6rc_db_t *db) { { char banner[S6RC_DB_BANNER_START_LEN] ; if (buffer_get(b, banner, S6RC_DB_BANNER_START_LEN) < S6RC_DB_BANNER_START_LEN) return -1 ; if (memcmp(banner, S6RC_DB_BANNER_START, S6RC_DB_BANNER_START_LEN)) return 0 ; } { int r = s6rc_db_read_string(b, db->string, db->stringlen) ; if (r < 1) return r ; r = s6rc_db_read_uints(b, db->nshort + db->nlong, db->deps, db->ndeps << 1) ; if (r < 1) return r ; r = s6rc_db_read_uints(b, db->nlong, db->producers, db->nproducers) ; if (r < 1) return r ; r = s6rc_db_read_services(b, db) ; if (r < 1) return r ; } { char banner[S6RC_DB_BANNER_END_LEN] ; if (buffer_get(b, banner, S6RC_DB_BANNER_END_LEN) < S6RC_DB_BANNER_END_LEN) return -1 ; if (memcmp(banner, S6RC_DB_BANNER_END, S6RC_DB_BANNER_END_LEN)) return 0 ; } return 1 ; } int s6rc_db_read (int fdcompiled, s6rc_db_t *db) { int r ; buffer b ; char buf[BUFFER_INSIZE] ; int fd = open_readatb(fdcompiled, "db") ; if (fd < 0) return -1 ; buffer_init(&b, &buffer_read, fd, buf, BUFFER_INSIZE) ; r = s6rc_db_read_buffer(&b, db) ; fd_close(fd) ; return r ; }