Files
retrobsd/tools/virtualmips/utils.c
2014-04-09 14:27:18 +01:00

517 lines
11 KiB
C

/*
* Cisco router simulation platform.
* Copyright (c) 2005,2006 Christophe Fillot. All rights reserved.
*
* Utility functions.
*/
/*
* Copyright (C) yajin 2008 <yajinzhou@gmail.com >
*
* This file is part of the virtualmips distribution.
* See LICENSE file for terms of the license.
*
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#ifdef __CYGWIN__
#include <malloc.h>
#endif
#include "utils.h"
extern FILE *log_file;
unsigned int get_file_size (const char *file_path)
{
struct stat statbuf;
if (stat (file_path, &statbuf) == -1) {
printf ("Get stat on %s Error:%s\n", file_path, strerror (errno));
return (0);
}
if (S_ISDIR (statbuf.st_mode))
return (0);
if (S_ISREG (statbuf.st_mode))
return (statbuf.st_size);
return 0;
}
/* Dynamic sprintf */
char *dyn_sprintf (const char *fmt, ...)
{
int n, size = 512;
va_list ap;
char *p, *p2;
if ((p = malloc (size)) == NULL) {
perror ("dyn_sprintf: malloc");
return NULL;
}
for (;;) {
/* Try to print in the allocated space */
va_start (ap, fmt);
n = vsnprintf (p, size, fmt, ap);
va_end (ap);
/* If that worked, return the string */
if ((n > -1) && (n < size))
return p;
/* Else try again with more space. */
if (n > -1)
size = n + 1;
else
size *= 2;
free (p);
if ((p2 = malloc (size)) == NULL) {
perror ("dyn_sprintf: realloc");
return NULL;
}
p = p2;
}
free (p2);
}
/* Split a string */
int m_strsplit (char *str, char delim, char **array, int max_count)
{
int i, pos = 0;
size_t len;
char *ptr;
for (i = 0; i < max_count; i++)
array[i] = NULL;
do {
if (pos == max_count)
goto error;
ptr = strchr (str, delim);
if (!ptr)
ptr = str + strlen (str);
len = ptr - str;
if (!(array[pos] = malloc (len + 1)))
goto error;
memcpy (array[pos], str, len);
array[pos][len] = 0;
str = ptr + 1;
pos++;
}
while (*ptr);
return (pos);
error:
for (i = 0; i < max_count; i++)
free (array[i]);
return (-1);
}
/* Tokenize a string */
int m_strtok (char *str, char delim, char **array, int max_count)
{
int i, pos = 0;
size_t len;
char *ptr;
for (i = 0; i < max_count; i++)
array[i] = NULL;
do {
if (pos == max_count)
goto error;
ptr = strchr (str, delim);
if (!ptr)
ptr = str + strlen (str);
len = ptr - str;
if (!(array[pos] = malloc (len + 1)))
goto error;
memcpy (array[pos], str, len);
array[pos][len] = 0;
while (*ptr == delim)
ptr++;
str = ptr;
pos++;
}
while (*ptr);
return (pos);
error:
for (i = 0; i < max_count; i++)
free (array[i]);
return (-1);
}
/* Quote a string */
char *m_strquote (char *buffer, size_t buf_len, char *str)
{
char *p;
if (!(p = strpbrk (str, " \t\"'")))
return str;
snprintf (buffer, buf_len, "\"%s\"", str);
return buffer;
}
/* Ugly function that dumps a structure in hexa and ascii. */
void mem_dump (FILE * f_output, u_char * pkt, u_int len)
{
u_int x, i = 0, tmp;
while (i < len) {
if ((len - i) > 16)
x = 16;
else
x = len - i;
fprintf (f_output, "%4.4x: ", i);
for (tmp = 0; tmp < x; tmp++)
fprintf (f_output, "%2.2x ", pkt[i + tmp]);
for (tmp = x; tmp < 16; tmp++)
fprintf (f_output, " ");
for (tmp = 0; tmp < x; tmp++) {
char c = pkt[i + tmp];
if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))
|| ((c >= '0') && (c <= '9')))
fprintf (f_output, "%c", c);
else
fputs (".", f_output);
}
i += x;
fprintf (f_output, "\n");
}
fprintf (f_output, "\n");
}
/* Logging function */
void m_flog (FILE * fd, char *module, char *fmt, va_list ap)
{
struct timeval now;
static char buf[256];
time_t ct;
gettimeofday (&now, 0);
ct = now.tv_sec;
strftime (buf, sizeof (buf), "%b %d %H:%M:%S", localtime (&ct));
if (fd) {
fprintf (fd, "%s.%03ld %s: ", buf, (long) now.tv_usec / 1000, module);
vfprintf (fd, fmt, ap);
fflush (fd);
}
}
#if 0
/* Logging function */
void m_log (char *module, char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
m_flog (log_file, module, fmt, ap);
va_end (ap);
}
#endif
/* Returns a line from specified file (remove trailing '\n') */
char *m_fgets (char *buffer, int size, FILE * fd)
{
int len;
buffer[0] = '\0';
if (fgets (buffer, size, fd) == NULL)
return NULL;
len = strlen (buffer);
if (len == 0)
return NULL;
/* remove trailing '\n' */
if (buffer[len - 1] == '\n')
buffer[len - 1] = '\0';
return buffer;
}
/* Read a file and returns it in a buffer */
ssize_t m_read_file (char *filename, char **buffer)
{
char tmp[256], *ptr, *nptr;
size_t len, tot_len;
FILE *fd;
*buffer = ptr = NULL;
tot_len = 0;
/* Open file for reading */
if ((fd = fopen (filename, "r")) == NULL)
return (-1);
while ((len = fread (tmp, 1, sizeof (tmp), fd)) > 0) {
/* Reallocate memory */
nptr = realloc (ptr, tot_len + len + 1);
if (nptr == NULL) {
if (ptr)
free (ptr);
fclose (fd);
return (-1);
}
ptr = nptr;
/* Ok, memory could be allocated */
memcpy (&ptr[tot_len], tmp, len);
tot_len += len;
}
fclose (fd);
*buffer = ptr;
return (tot_len);
}
/* Allocate aligned memory */
void *m_memalign (size_t boundary, size_t size)
{
void *p;
#if defined(__linux__) || defined(__APPLE__)
if (posix_memalign ((void *) &p, boundary, size))
#else
#if defined(__CYGWIN__) || defined(SUNOS)
if (!(p = memalign (boundary, size)))
#else
if (!(p = malloc (size)))
#endif
#endif
return NULL;
assert (((m_iptr_t) p & (boundary - 1)) == 0);
return p;
}
/* Block specified signal for calling thread */
int m_signal_block (int sig)
{
sigset_t sig_mask;
sigemptyset (&sig_mask);
sigaddset (&sig_mask, sig);
return (pthread_sigmask (SIG_BLOCK, &sig_mask, NULL));
}
/* Unblock specified signal for calling thread */
int m_signal_unblock (int sig)
{
sigset_t sig_mask;
sigemptyset (&sig_mask);
sigaddset (&sig_mask, sig);
return (pthread_sigmask (SIG_UNBLOCK, &sig_mask, NULL));
}
/* Set non-blocking mode on a file descriptor */
int m_fd_set_non_block (int fd)
{
int flags;
if ((flags = fcntl (fd, F_GETFL, 0)) < 1)
return (-1);
return (fcntl (fd, F_SETFL, flags | O_NONBLOCK));
}
/* Map a memory zone from a file */
u_char *memzone_map_file (int fd, size_t len)
{
return (mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
(off_t) 0));
}
/* Map a memory zone from a file, with copy-on-write (COW) */
u_char *memzone_map_cow_file (int fd, size_t len)
{
return (mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd,
(off_t) 0));
}
/* Create a file to serve as a memory zone */
int memzone_create_file (char *filename, size_t len, u_char ** ptr)
{
int fd;
if ((fd = open (filename, O_CREAT | O_RDWR, S_IRWXU)) == -1) {
perror ("memzone_create_file: open");
return (-1);
}
if (ftruncate (fd, len) == -1) {
perror ("memzone_create_file: ftruncate");
close (fd);
return (-1);
}
*ptr = memzone_map_file (fd, len);
if (!*ptr) {
close (fd);
fd = -1;
}
return (fd);
}
/* Open a file to serve as a COW memory zone */
int memzone_open_cow_file (char *filename, size_t len, u_char ** ptr)
{
int fd;
if ((fd = open (filename, O_RDWR, S_IRWXU)) == -1) {
perror ("memzone_open_file: open");
return (-1);
}
*ptr = memzone_map_cow_file (fd, len);
if (!*ptr) {
close (fd);
fd = -1;
}
return (fd);
}
/* Open a file and map it in memory */
int memzone_open_file (char *filename, u_char ** ptr, off_t * fsize)
{
struct stat fprop;
int fd;
if ((fd = open (filename, O_RDWR, S_IRWXU)) == -1)
return (-1);
if (fstat (fd, &fprop) == -1)
goto err_fstat;
*fsize = fprop.st_size;
if (!(*ptr = memzone_map_file (fd, *fsize)))
goto err_mmap;
return (fd);
err_mmap:
err_fstat:
close (fd);
return (-1);
}
/* Compute NVRAM checksum */
m_uint16_t nvram_cksum (m_uint16_t * ptr, size_t count)
{
m_uint32_t sum = 0;
while (count > 1) {
sum = sum + ntohs (*ptr);
ptr++;
count -= sizeof (m_uint16_t);
}
if (count > 0)
sum = sum + ((ntohs (*ptr) & 0xFF) << 8);
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
return (~sum);
}
/* Byte-swap a memory block */
void mem_bswap32 (void *ptr, size_t len)
{
m_uint32_t *p = ptr;
size_t count = len >> 2;
int i;
for (i = 0; i < count; i++, p++)
*p = swap32 (*p);
}
/* Reverse a byte */
m_uint8_t m_reverse_u8 (m_uint8_t val)
{
m_uint8_t res = 0;
int i;
for (i = 0; i < 8; i++)
if (val & (1 << i))
res |= 1 << (7 - i);
return (res);
}
void SubstituteLLx (char *out, const char *text, int maxlen)
{
int i;
for (i = 0; i < maxlen && text[i]; i++) {
out[i] = text[i];
}
out[i] = text[i];
}
/*****************************************************************
* Debug
* Print a debug message, if flag is enabled. Like printf,
* only with an extra argument on the front.
* to output debug infomation , you should excute "simos -d [flag]"
****************************************************************/
void Debug (char flag, char *format, ...)
{
// if (DebugIsEnabled(flag)) {
char llformat[1024];
va_list ap;
va_start (ap, format);
SubstituteLLx (llformat, format, 1024);
/* Make this go to stderr also... */
vfprintf (stderr, llformat, ap);
//vCPUPrint(llformat, ap);
fprintf (stderr, "\r");
fflush (stderr);
va_end (ap);
//}
}