bstreamhandle open_temp_file_stream(void) { bstreamhandle h; char *t; int fd; str_errno = 0; t = (char *)get_tmp_name(); if (strlcat(t, "/cdXXXXXX", PATH_MAX) >= PATH_MAX) return (NULL); fd = mkstemp(t); if (debug) (void) printf("temp is: %s length: %d\n", t, strlen(t)); if (fd < 0) return (NULL); (void) unlink(t); h = (bstreamhandle)my_zalloc(sizeof (*h)); h->bstr_fd = fd; h->bstr_read = file_stream_read; h->bstr_write = file_stream_write; h->bstr_close = file_stream_close; h->bstr_size = file_stream_size; h->bstr_rewind = file_stream_rewind; return (h); }
/* * check_avail_temp_space returns 0 if there is adequate space * in the temporary directory, or a non-zero error code if * something goes wrong */ int check_avail_temp_space(size_t req_size) { struct statvfs buf; u_longlong_t free_size = 0; if (statvfs(get_tmp_name(), &buf) < 0) { return (errno); } free_size = buf.f_bfree * buf.f_frsize; if (free_size <= req_size) return (ENOMEM); return (0); }
static void server_job(snd_pcm_direct_t *dmix) { int ret, sck, i; int max = 128, current = 0; struct pollfd pfds[max + 1]; server_job_dmix = dmix; /* don't allow to be killed */ signal(SIGHUP, server_job_signal); signal(SIGQUIT, server_job_signal); signal(SIGTERM, server_job_signal); signal(SIGKILL, server_job_signal); /* close all files to free resources */ i = sysconf(_SC_OPEN_MAX); #ifdef SERVER_JOB_DEBUG while (--i >= 3) { #else while (--i >= 0) { #endif if (i != dmix->server_fd && i != dmix->hw_fd) close(i); } /* detach from parent */ setsid(); pfds[0].fd = dmix->server_fd; pfds[0].events = POLLIN | POLLERR | POLLHUP; server_printf("DIRECT SERVER STARTED\n"); while (1) { ret = poll(pfds, current + 1, 500); server_printf("DIRECT SERVER: poll ret = %i, revents[0] = 0x%x, errno = %i\n", ret, pfds[0].revents, errno); if (ret < 0) { if (errno == EINTR) continue; /* some error */ break; } if (ret == 0 || (pfds[0].revents & (POLLERR | POLLHUP))) { /* timeout or error? */ struct shmid_ds buf; snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) { _snd_pcm_direct_shm_discard(dmix); snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); continue; } server_printf("DIRECT SERVER: nattch = %i\n", (int)buf.shm_nattch); if (buf.shm_nattch == 1) /* server is the last user, exit */ break; snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); continue; } if (pfds[0].revents & POLLIN) { ret--; sck = accept(dmix->server_fd, 0, 0); if (sck >= 0) { server_printf("DIRECT SERVER: new connection %i\n", sck); if (current == max) { close(sck); } else { unsigned char buf = 'A'; pfds[current+1].fd = sck; pfds[current+1].events = POLLIN | POLLERR | POLLHUP; _snd_send_fd(sck, &buf, 1, dmix->hw_fd); server_printf("DIRECT SERVER: fd sent ok\n"); current++; } } } for (i = 0; i < current && ret > 0; i++) { struct pollfd *pfd = &pfds[i+1]; unsigned char cmd; server_printf("client %i revents = 0x%x\n", pfd->fd, pfd->revents); if (pfd->revents & (POLLERR | POLLHUP)) { ret--; close(pfd->fd); pfd->fd = -1; continue; } if (!(pfd->revents & POLLIN)) continue; ret--; if (read(pfd->fd, &cmd, 1) == 1) cmd = 0 /*process command */; } for (i = 0; i < current; i++) { if (pfds[i+1].fd < 0) { if (i + 1 != max) memcpy(&pfds[i+1], &pfds[i+2], sizeof(struct pollfd) * (max - i - 1)); current--; } } } server_cleanup(dmix); server_printf("DIRECT SERVER EXIT\n"); #ifdef SERVER_JOB_DEBUG close(0); close(1); close(2); #endif _exit(EXIT_SUCCESS); } int snd_pcm_direct_server_create(snd_pcm_direct_t *dmix) { int ret; dmix->server_fd = -1; ret = get_tmp_name(dmix->shmptr->socket_name, sizeof(dmix->shmptr->socket_name)); if (ret < 0) return ret; ret = make_local_socket(dmix->shmptr->socket_name, 1, dmix->ipc_perm, dmix->ipc_gid); if (ret < 0) return ret; dmix->server_fd = ret; ret = listen(dmix->server_fd, 4); if (ret < 0) { close(dmix->server_fd); return ret; } ret = fork(); if (ret < 0) { close(dmix->server_fd); return ret; } else if (ret == 0) { ret = fork(); if (ret == 0) server_job(dmix); _exit(EXIT_SUCCESS); } else { waitpid(ret, NULL, 0); } dmix->server_pid = ret; dmix->server = 1; return 0; }