[BACK]Return to file.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / aucat

Diff for /src/usr.bin/aucat/Attic/file.c between version 1.3 and 1.4

version 1.3, 2008/08/14 09:58:55 version 1.4, 2008/10/26 08:49:44
Line 31 
Line 31 
 #include <signal.h>  #include <signal.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  
 #include <unistd.h>  
   
 #include "conf.h"  #include "conf.h"
 #include "file.h"  #include "file.h"
 #include "aproc.h"  #include "aproc.h"
 #include "abuf.h"  #include "abuf.h"
 #include "dev.h"  
   
 #define MAXFDS 100  #define MAXFDS 100
   
   extern struct fileops listen_ops, pipe_ops;
 struct filelist file_list;  struct filelist file_list;
   
 void  void
 file_dprint(int n, struct file *f)  file_dprint(int n, struct file *f)
 {  {
         if (debug_level >= n) {          if (debug_level < n)
                 fprintf(stderr, "%s <", f->name);                  return;
                 if (f->state & FILE_ROK)          fprintf(stderr, "%s:%s <", f->ops->name, f->name);
                         fprintf(stderr, "ROK");          if (f->state & FILE_ROK)
                 if (f->state & FILE_WOK)                  fprintf(stderr, "ROK");
                         fprintf(stderr, "WOK");          if (f->state & FILE_WOK)
                 if (f->state & FILE_EOF)                  fprintf(stderr, "WOK");
                         fprintf(stderr, "EOF");          if (f->state & FILE_EOF)
                 if (f->state & FILE_HUP)                  fprintf(stderr, "EOF");
                         fprintf(stderr, "HUP");          if (f->state & FILE_HUP)
                 fprintf(stderr, ">");                  fprintf(stderr, "HUP");
         }          fprintf(stderr, ">");
 }  }
   
 struct file *  struct file *
 file_new(int fd, char *name)  file_new(struct fileops *ops, char *name, unsigned nfds)
 {  {
         unsigned i;  
         struct file *f;          struct file *f;
   
         i = 0;  
         LIST_FOREACH(f, &file_list, entry)          LIST_FOREACH(f, &file_list, entry)
                 i++;                  nfds += f->ops->nfds(f);
         if (i >= MAXFDS)          if (nfds > MAXFDS)
                 err(1, "%s: too many polled files", name);                  err(1, "%s: too many polled files", name);
   
         f = malloc(sizeof(struct file));          f = malloc(ops->size);
         if (f == NULL)          if (f == NULL)
                 err(1, "%s", name);                  err(1, "file_new: %s", ops->name);
           f->ops = ops;
         f->fd = fd;  
         f->events = 0;  
         f->rbytes = -1;  
         f->wbytes = -1;  
         f->name = name;          f->name = name;
         f->state = 0;          f->state = 0;
         f->rproc = NULL;          f->rproc = NULL;
         f->wproc = NULL;          f->wproc = NULL;
           f->refs = 0;
         LIST_INSERT_HEAD(&file_list, f, entry);          LIST_INSERT_HEAD(&file_list, f, entry);
         DPRINTF("file_new: %s\n", f->name);          DPRINTF("file_new: %s:%s\n", ops->name, f->name);
         return f;          return f;
 }  }
   
Line 95 
Line 88 
 {  {
         DPRINTF("file_del: ");          DPRINTF("file_del: ");
         file_dprint(1, f);          file_dprint(1, f);
         DPRINTF("\n");          if (f->refs > 0) {
                   DPRINTF(": delayed\n");
         if (f->hdr == HDR_WAV)                  f->state |= FILE_ZOMB;
                 wav_writehdr(f->fd, &f->hpar);                  return;
         close(f->fd);          } else {
         free(f);                  DPRINTF(": immediate\n");
                   LIST_REMOVE(f, entry);
                   f->ops->close(f);
                   free(f);
           }
 }  }
   
 int  int
 file_poll(void)  file_poll(void)
 {  {
 #ifdef DEBUG          nfds_t nfds, n;
         int ndead;          short events, revents;
 #endif  
         nfds_t nfds;  
         struct pollfd pfds[MAXFDS];          struct pollfd pfds[MAXFDS];
         struct pollfd *pfd;  
         struct file *f, *fnext;          struct file *f, *fnext;
         struct aproc *p;          struct aproc *p;
   
           /*
            * fill the pfds[] array with files that are blocked on reading
            * and/or writing, skipping those that're just waiting
            */
           DPRINTFN(4, "file_poll:");
         nfds = 0;          nfds = 0;
 #ifdef DEBUG  
         ndead = 0;  
 #endif  
         LIST_FOREACH(f, &file_list, entry) {          LIST_FOREACH(f, &file_list, entry) {
                 if (!f->events) {                  events = 0;
 #ifdef DEBUG                  if (f->rproc && !(f->state & FILE_ROK))
                         if (f->state & (FILE_EOF | FILE_HUP))                          events |= POLLIN;
                                 ndead++;                  if (f->wproc && !(f->state & FILE_WOK))
 #endif                          events |= POLLOUT;
                   DPRINTFN(4, " %s(%x)", f->name, events);
                   n = f->ops->pollfd(f, pfds + nfds, events);
                   if (n == 0) {
                         f->pfd = NULL;                          f->pfd = NULL;
                         continue;                          continue;
                 }                  }
                 pfd = &pfds[nfds++];                  f->pfd = pfds + nfds;
                 f->pfd = pfd;                  nfds += n;
                 pfd->fd = f->fd;  
                 pfd->events = f->events;  
         }          }
           DPRINTFN(4, "\n");
   
 #ifdef DEBUG  #ifdef DEBUG
         if (debug_level >= 4) {          if (nfds == 0 && !LIST_EMPTY(&file_list)) {
                 fprintf(stderr, "file_poll:");  
                 LIST_FOREACH(f, &file_list, entry) {  
                         fprintf(stderr, " %s(%x)", f->name, f->events);  
                 }  
                 fprintf(stderr, "\n");  
         }  
         if (nfds == 0 && ndead == 0 && !LIST_EMPTY(&file_list)) {  
                 fprintf(stderr, "file_poll: deadlock\n");                  fprintf(stderr, "file_poll: deadlock\n");
                 abort();                  abort();
         }          }
Line 151 
Line 142 
                 DPRINTF("file_poll: nothing to do...\n");                  DPRINTF("file_poll: nothing to do...\n");
                 return 0;                  return 0;
         }          }
         if (nfds) {          if (poll(pfds, nfds, -1) < 0) {
                 while (poll(pfds, nfds, -1) < 0) {                  if (errno == EINTR)
                         if (errno != EINTR)                          return 1;
                                 err(1, "file_poll: poll failed");                  err(1, "file_poll: poll failed");
                 }  
         }          }
         LIST_FOREACH(f, &file_list, entry) {          f = LIST_FIRST(&file_list);
                 pfd = f->pfd;          while (f != LIST_END(&file_list)) {
                 if (pfd == NULL)                  if (f->pfd == NULL) {
                           f = LIST_NEXT(f, entry);
                         continue;                          continue;
                 if ((f->events & POLLIN) && (pfd->revents & POLLIN)) {                  }
                         f->events &= ~POLLIN;                  f->refs++;
                   revents = f->ops->revents(f, f->pfd);
                   if (!(f->state & FILE_ZOMB) && (revents & POLLIN)) {
                           revents &= ~POLLIN;
                         f->state |= FILE_ROK;                          f->state |= FILE_ROK;
                         DPRINTFN(3, "file_poll: %s rok\n", f->name);                          DPRINTFN(3, "file_poll: %s rok\n", f->name);
                         while (f->state & FILE_ROK) {                          for (;;) {
                                 p = f->rproc;                                  p = f->rproc;
                                 if (!p || !p->ops->in(p, NULL))                                  if (!p || !p->ops->in(p, NULL))
                                         break;                                          break;
                         }                          }
                 }                  }
                 if ((f->events & POLLOUT) && (pfd->revents & POLLOUT)) {                  if (!(f->state & FILE_ZOMB) && (revents & POLLOUT)) {
                         f->events &= ~POLLOUT;                          revents &= ~POLLOUT;
                         f->state |= FILE_WOK;                          f->state |= FILE_WOK;
                         DPRINTFN(3, "file_poll: %s wok\n", f->name);                          DPRINTFN(3, "file_poll: %s wok\n", f->name);
                         while (f->state & FILE_WOK) {                          for (;;) {
                                 p = f->wproc;                                  p = f->wproc;
                                 if (!p || !p->ops->out(p, NULL))                                  if (!p || !p->ops->out(p, NULL))
                                         break;                                          break;
                         }                          }
                 }                  }
         }                  if (!(f->state & FILE_ZOMB) && (f->state & FILE_EOF)) {
         LIST_FOREACH(f, &file_list, entry) {  
                 if (f->state & FILE_EOF) {  
                         DPRINTFN(2, "file_poll: %s: eof\n", f->name);                          DPRINTFN(2, "file_poll: %s: eof\n", f->name);
                         p = f->rproc;                          p = f->rproc;
                         if (p)                          if (p)
                                 p->ops->eof(p, NULL);                                  p->ops->eof(p, NULL);
                         f->state &= ~FILE_EOF;                          f->state &= ~FILE_EOF;
                 }                  }
                 if (f->state & FILE_HUP) {                  if (!(f->state & FILE_ZOMB) && (f->state & FILE_HUP)) {
                         DPRINTFN(2, "file_poll: %s hup\n", f->name);                          DPRINTFN(2, "file_poll: %s hup\n", f->name);
                         p = f->wproc;                          p = f->wproc;
                         if (p)                          if (p)
                                 p->ops->hup(p, NULL);                                  p->ops->hup(p, NULL);
                         f->state &= ~FILE_HUP;                          f->state &= ~FILE_HUP;
                 }                  }
         }                  f->refs--;
         for (f = LIST_FIRST(&file_list); f != NULL; f = fnext) {  
                 fnext = LIST_NEXT(f, entry);                  fnext = LIST_NEXT(f, entry);
                 if (f->rproc == NULL && f->wproc == NULL) {                  if (f->state & FILE_ZOMB)
                         LIST_REMOVE(f, entry);  
                         DPRINTF("file_poll: %s: removed\n", f->name);  
                         file_del(f);                          file_del(f);
                 }                  f = fnext;
         }          }
         if (LIST_EMPTY(&file_list)) {          if (LIST_EMPTY(&file_list)) {
                 DPRINTFN(2, "file_poll: terminated\n");                  DPRINTFN(2, "file_poll: terminated\n");
Line 214 
Line 203 
 }  }
   
 void  void
 file_start(void)  filelist_init(void)
 {  {
         sigset_t set;          sigset_t set;
   
Line 227 
Line 216 
 }  }
   
 void  void
 file_stop(void)  filelist_done(void)
 {  {
         struct file *f;          struct file *f;
   
         if (!LIST_EMPTY(&file_list)) {          if (!LIST_EMPTY(&file_list)) {
                 fprintf(stderr, "file_stop:");                  fprintf(stderr, "filelist_done: list not empty:\n");
                 LIST_FOREACH(f, &file_list, entry) {                  LIST_FOREACH(f, &file_list, entry) {
                         fprintf(stderr, " %s(%x)", f->name, f->events);                          fprintf(stderr, "\t");
                           file_dprint(0, f);
                           fprintf(stderr, "\n");
                 }                  }
                 fprintf(stderr, "\nfile_stop: list not empty\n");                  abort();
                 exit(1);  
         }          }
 }  }
   
 unsigned  /*
 file_read(struct file *file, unsigned char *data, unsigned count)   * close all listening sockets
    *
    * XXX: remove this
    */
   void
   filelist_unlisten(void)
 {  {
         int n;          struct file *f, *fnext;
   
         if (file->rbytes >= 0 && count > file->rbytes) {          for (f = LIST_FIRST(&file_list); f != NULL; f = fnext) {
                 count = file->rbytes; /* file->rbytes fits in count */                  fnext = LIST_NEXT(f, entry);
                 if (count == 0) {                  if (f->ops == &listen_ops)
                         DPRINTFN(2, "file_read: %s: complete\n", file->name);                          file_del(f);
                         file->state &= ~FILE_ROK;  
                         file->state |= FILE_EOF;  
                         return 0;  
                 }  
         }          }
         while ((n = read(file->fd, data, count)) < 0) {  
                 if (errno == EINTR)  
                         continue;  
                 file->state &= ~FILE_ROK;  
                 if (errno == EAGAIN) {  
                         DPRINTFN(3, "file_read: %s: blocking...\n",  
                             file->name);  
                         file->events |= POLLIN;  
                 } else {  
                         warn("%s", file->name);  
                         file->state |= FILE_EOF;  
                 }  
                 return 0;  
         }  
         if (n == 0) {  
                 DPRINTFN(2, "file_read: %s: eof\n", file->name);  
                 file->state &= ~FILE_ROK;  
                 file->state |= FILE_EOF;  
                 return 0;  
         }  
         if (file->rbytes >= 0)  
                 file->rbytes -= n;  
         DPRINTFN(4, "file_read: %s: got %d bytes\n", file->name, n);  
         return n;  
 }  }
   
   unsigned
   file_read(struct file *file, unsigned char *data, unsigned count)
   {
           return file->ops->read(file, data, count);
   }
   
 unsigned  unsigned
 file_write(struct file *file, unsigned char *data, unsigned count)  file_write(struct file *file, unsigned char *data, unsigned count)
 {  {
         int n;          return file->ops->write(file, data, count);
   
         if (file->wbytes >= 0 && count > file->wbytes) {  
                 count = file->wbytes; /* file->wbytes fits in count */  
                 if (count == 0) {  
                         DPRINTFN(2, "file_write: %s: complete\n", file->name);  
                         file->state &= ~FILE_WOK;  
                         file->state |= FILE_HUP;  
                         return 0;  
                 }  
         }  
         while ((n = write(file->fd, data, count)) < 0) {  
                 if (errno == EINTR)  
                         continue;  
                 file->state &= ~FILE_WOK;  
                 if (errno == EAGAIN) {  
                         DPRINTFN(3, "file_write: %s: blocking...\n",  
                             file->name);  
                         file->events |= POLLOUT;  
                 } else {  
                         warn("%s", file->name);  
                         file->state |= FILE_HUP;  
                 }  
                 return 0;  
         }  
         if (file->wbytes >= 0)  
                 file->wbytes -= n;  
         DPRINTFN(4, "file_write: %s: wrote %d bytes\n", file->name, n);  
         return n;  
 }  }
   
 void  void
 file_eof(struct file *f)  file_eof(struct file *f)
 {  {
         DPRINTFN(2, "file_eof: %s: scheduled for eof\n", f->name);          struct aproc *p;
         f->events &= ~POLLIN;  
         f->state &= ~FILE_ROK;          if (f->refs == 0) {
         f->state |= FILE_EOF;                  DPRINTFN(2, "file_eof: %s: immediate\n", f->name);
                   f->refs++;
                   p = f->rproc;
                   if (p)
                           p->ops->eof(p, NULL);
                   f->refs--;
                   if (f->state & FILE_ZOMB)
                           file_del(f);
           } else {
                   DPRINTFN(2, "file_eof: %s: delayed\n", f->name);
                   f->state &= ~FILE_ROK;
                   f->state |= FILE_EOF;
           }
 }  }
   
 void  void
 file_hup(struct file *f)  file_hup(struct file *f)
 {  {
         DPRINTFN(2, "file_hup: %s: scheduled for hup\n", f->name);          struct aproc *p;
         f->events &= ~POLLOUT;  
         f->state &= ~FILE_WOK;          if (f->refs == 0) {
         f->state |= FILE_HUP;                  DPRINTFN(2, "file_hup: %s immediate\n", f->name);
                   f->refs++;
                   p = f->wproc;
                   if (p)
                           p->ops->hup(p, NULL);
                   f->refs--;
                   if (f->state & FILE_ZOMB)
                           file_del(f);
           } else {
                   DPRINTFN(2, "file_hup: %s: delayed\n", f->name);
                   f->state &= ~FILE_WOK;
                   f->state |= FILE_HUP;
           }
 }  }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4