⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffer.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
字号:
/* * Buffering of output and input.  * Copyright (C) 1998 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2, or (at your * option) any later version. *  * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING.  If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA.  */#include <zebra.h>#include "memory.h"#include "buffer.h"/* Make buffer data. */struct buffer_data *buffer_data_new (size_t size){  struct buffer_data *d;  d = XMALLOC (MTYPE_BUFFER_DATA, sizeof (struct buffer_data));  memset (d, 0, sizeof (struct buffer_data));  d->data = XMALLOC (MTYPE_BUFFER_DATA, size);  return d;}voidbuffer_data_free (struct buffer_data *d){  if (d->data)    XFREE (MTYPE_BUFFER_DATA, d->data);  XFREE (MTYPE_BUFFER_DATA, d);}/* Make new buffer. */struct buffer *buffer_new (size_t size){  struct buffer *b;  b = XMALLOC (MTYPE_BUFFER, sizeof (struct buffer));  memset (b, 0, sizeof (struct buffer));  b->size = size;  return b;}/* Free buffer. */voidbuffer_free (struct buffer *b){  struct buffer_data *d;  struct buffer_data *next;  d = b->head;  while (d)    {      next = d->next;      buffer_data_free (d);      d = next;    }  d = b->unused_head;  while (d)    {      next = d->next;      buffer_data_free (d);      d = next;    }    XFREE (MTYPE_BUFFER, b);}/* Make string clone. */char *buffer_getstr (struct buffer *b){  return strdup ((char *)b->head->data);}/* Return 1 if buffer is empty. */intbuffer_empty (struct buffer *b){  if (b->tail == NULL || b->tail->cp == b->tail->sp)    return 1;  else    return 0;}/* Clear and free all allocated data. */voidbuffer_reset (struct buffer *b){  struct buffer_data *data;  struct buffer_data *next;    for (data = b->head; data; data = next)    {      next = data->next;      buffer_data_free (data);    }  b->head = b->tail = NULL;  b->alloc = 0;  b->length = 0;}/* Add buffer_data to the end of buffer. */voidbuffer_add (struct buffer *b){  struct buffer_data *d;  d = buffer_data_new (b->size);  if (b->tail == NULL)    {      d->prev = NULL;      d->next = NULL;      b->head = d;      b->tail = d;    }  else    {      d->prev = b->tail;      d->next = NULL;      b->tail->next = d;      b->tail = d;    }  b->alloc++;}/* Write data to buffer. */intbuffer_write (struct buffer *b, u_char *ptr, size_t size){  struct buffer_data *data;  data = b->tail;  b->length += size;  /* We use even last one byte of data buffer. */  while (size)        {      /* If there is no data buffer add it. */      if (data == NULL || data->cp == b->size)	{	  buffer_add (b);	  data = b->tail;	}      /* Last data. */      if (size <= (b->size - data->cp))	{	  memcpy ((data->data + data->cp), ptr, size);	  data->cp += size;	  size = 0;	}      else	{	  memcpy ((data->data + data->cp), ptr, (b->size - data->cp));	  size -= (b->size - data->cp);	  ptr += (b->size - data->cp);	  data->cp = b->size;	}    }  return 1;}/* Insert character into the buffer. */intbuffer_putc (struct buffer *b, u_char c){  buffer_write (b, &c, 1);  return 1;}/* Insert word (2 octets) into ther buffer. */intbuffer_putw (struct buffer *b, u_short c){  buffer_write (b, (char *)&c, 2);  return 1;}/* Put string to the buffer. */intbuffer_putstr (struct buffer *b, u_char *c){  size_t size;  size = strlen ((char *)c);  buffer_write (b, c, size);  return 1;}/* Flush specified size to the fd. */voidbuffer_flush (struct buffer *b, int fd, size_t size){  int iov_index;  struct iovec *iovec;  struct buffer_data *data;  struct buffer_data *out;  struct buffer_data *next;  iovec = malloc (sizeof (struct iovec) * b->alloc);  iov_index = 0;  for (data = b->head; data; data = data->next)    {      iovec[iov_index].iov_base = (char *)(data->data + data->sp);      if (size <= (data->cp - data->sp))	{	  iovec[iov_index++].iov_len = size;	  data->sp += size;	  if (data->sp == data->cp)	    data = data->next;	  break;	}      else	{	  iovec[iov_index++].iov_len = data->cp - data->sp;	  size -= data->cp - data->sp;	  data->sp = data->cp;	}    }  /* Write buffer to the fd. */  writev (fd, iovec, iov_index);  /* Free printed buffer data. */  for (out = b->head; out && out != data; out = next)    {      next = out->next;      if (next)	next->prev = NULL;      else	b->tail = next;      b->head = next;      buffer_data_free (out);      b->alloc--;    }  free (iovec);}/* Flush all buffer to the fd. */intbuffer_flush_all (struct buffer *b, int fd){  int ret;  struct buffer_data *d;  int iov_index;  struct iovec *iovec;  if (buffer_empty (b))    return 0;  iovec = malloc (sizeof (struct iovec) * b->alloc);  iov_index = 0;  for (d = b->head; d; d = d->next)    {      iovec[iov_index].iov_base = (char *)(d->data + d->sp);      iovec[iov_index].iov_len = d->cp - d->sp;      iov_index++;    }  ret = writev (fd, iovec, iov_index);  free (iovec);  buffer_reset (b);  return ret;}/* Flush all buffer to the fd. */intbuffer_flush_vty_all (struct buffer *b, int fd, int erase_flag,		      int no_more_flag){  int nbytes;  int iov_index;  struct iovec *iov;  struct iovec small_iov[3];  char more[] = " --More-- ";  char erase[] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,		   ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',		   0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};  struct buffer_data *data;  struct buffer_data *out;  struct buffer_data *next;  /* For erase and more data add two to b's buffer_data count.*/  if (b->alloc == 1)    iov = small_iov;  else    iov = XCALLOC (MTYPE_TMP, sizeof (struct iovec) * (b->alloc + 2));  data = b->head;  iov_index = 0;  /* Previously print out is performed. */  if (erase_flag)    {      iov[iov_index].iov_base = erase;      iov[iov_index].iov_len = sizeof erase;      iov_index++;    }  /* Output data. */  for (data = b->head; data; data = data->next)    {      iov[iov_index].iov_base = (char *)(data->data + data->sp);      iov[iov_index].iov_len = data->cp - data->sp;      iov_index++;    }  /* In case of `more' display need. */  if (! buffer_empty (b) && !no_more_flag)    {      iov[iov_index].iov_base = more;      iov[iov_index].iov_len = sizeof more;      iov_index++;    }  /* We use write or writev*/  nbytes = writev (fd, iov, iov_index);  /* Error treatment. */  if (nbytes < 0)    {      if (errno == EINTR)	;      if (errno == EWOULDBLOCK)	;    }  /* Free printed buffer data. */  for (out = b->head; out && out != data; out = next)    {      next = out->next;      if (next)	next->prev = NULL;      else	b->tail = next;      b->head = next;      buffer_data_free (out);      b->alloc--;    }  if (iov != small_iov)    XFREE (MTYPE_TMP, iov);  return nbytes;}/* Flush buffer to the file descriptor.  Mainly used from vty   interface. */intbuffer_flush_vty (struct buffer *b, int fd, int size, 		  int erase_flag, int no_more_flag){  int nbytes;  int iov_index;  struct iovec *iov;  struct iovec small_iov[3];  char more[] = " --More-- ";  char erase[] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,		   ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',		   0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};  struct buffer_data *data;  struct buffer_data *out;  struct buffer_data *next;#ifdef  IOV_MAX  int iov_size;  int total_size;  struct iovec *c_iov;  int c_nbytes;#endif /* IOV_MAX */  /* For erase and more data add two to b's buffer_data count.*/  if (b->alloc == 1)    iov = small_iov;  else    iov = XCALLOC (MTYPE_TMP, sizeof (struct iovec) * (b->alloc + 2));  data = b->head;  iov_index = 0;  /* Previously print out is performed. */  if (erase_flag)    {      iov[iov_index].iov_base = erase;      iov[iov_index].iov_len = sizeof erase;      iov_index++;    }  /* Output data. */  for (data = b->head; data; data = data->next)    {      iov[iov_index].iov_base = (char *)(data->data + data->sp);      if (size <= (data->cp - data->sp))	{	  iov[iov_index++].iov_len = size;	  data->sp += size;	  if (data->sp == data->cp)	    data = data->next;	  break;	}      else	{	  iov[iov_index++].iov_len = data->cp - data->sp;	  size -= (data->cp - data->sp);	  data->sp = data->cp;	}    }  /* In case of `more' display need. */  if (!buffer_empty (b) && !no_more_flag)    {      iov[iov_index].iov_base = more;      iov[iov_index].iov_len = sizeof more;      iov_index++;    }  /* We use write or writev*/#ifdef IOV_MAX  /* IOV_MAX are normally defined in <sys/uio.h> , Posix.1g.     example: Solaris2.6 are defined IOV_MAX size at 16.     */  c_iov = iov;  total_size = iov_index;  nbytes = 0;  while( total_size > 0 )    {       /* initialize write vector size at once */       iov_size = ( total_size > IOV_MAX ) ? IOV_MAX : total_size;       c_nbytes = writev (fd, c_iov, iov_size );       if( c_nbytes < 0 )         {           if(errno == EINTR)             ;             ;           if(errno == EWOULDBLOCK)             ;             ;           nbytes = c_nbytes;           break;         }        nbytes += c_nbytes;       /* move pointer io-vector */       c_iov += iov_size;       total_size -= iov_size;    }#else  /* IOV_MAX */   nbytes = writev (fd, iov, iov_index);  /* Error treatment. */  if (nbytes < 0)    {      if (errno == EINTR)	;      if (errno == EWOULDBLOCK)	;    }#endif /* IOV_MAX */  /* Free printed buffer data. */  for (out = b->head; out && out != data; out = next)    {      next = out->next;      if (next)	next->prev = NULL;      else	b->tail = next;      b->head = next;      buffer_data_free (out);      b->alloc--;    }  if (iov != small_iov)    XFREE (MTYPE_TMP, iov);  return nbytes;}/* Calculate size of outputs then flush buffer to the file   descriptor. */intbuffer_flush_window (struct buffer *b, int fd, int width, int height, 		     int erase, int no_more){  unsigned long cp;  unsigned long size;  int lp;  int lineno;  struct buffer_data *data;  if (height >= 2)    height--;  /* We have to calculate how many bytes should be written. */  lp = 0;  lineno = 0;  size = 0;    for (data = b->head; data; data = data->next)    {      cp = data->sp;      while (cp < data->cp)	{	  if (data->data[cp] == '\n' || lp == width)	    {	      lineno++;	      if (lineno == height)		{		  cp++;		  size++;		  goto flush;		}	      lp = 0;	    }	  cp++;	  lp++;	  size++;	}    }  /* Write data to the file descriptor. */ flush:  return buffer_flush_vty (b, fd, size, erase, no_more);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -