/*
- * Copyright (c) 2009, 2010, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "pcap-file.h"
#include <errno.h>
#include <inttypes.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include "byte-order.h"
#include "compiler.h"
#include "ofpbuf.h"
#include "vlog.h"
FILE *
pcap_open(const char *file_name, const char *mode)
{
+ struct stat s;
FILE *file;
+ int error;
- ovs_assert(!strcmp(mode, "rb") || !strcmp(mode, "wb"));
+ ovs_assert(!strcmp(mode, "rb") ||
+ !strcmp(mode, "wb") ||
+ !strcmp(mode, "ab"));
file = fopen(file_name, mode);
if (file == NULL) {
- VLOG_WARN("%s: failed to open pcap file for %s",
- file_name, mode[0] == 'r' ? "reading" : "writing");
+ VLOG_WARN("%s: failed to open pcap file for %s (%s)", file_name,
+ (mode[0] == 'r' ? "reading"
+ : mode[0] == 'w' ? "writing"
+ : "appending"),
+ ovs_strerror(errno));
return NULL;
}
- if (mode[0] == 'r') {
- if (!pcap_read_header(file)) {
+ switch (mode[0]) {
+ case 'r':
+ error = pcap_read_header(file);
+ if (error) {
+ errno = error;
fclose(file);
return NULL;
}
- } else {
+ break;
+
+ case 'w':
pcap_write_header(file);
+ break;
+
+ case 'a':
+ if (!fstat(fileno(file), &s) && !s.st_size) {
+ pcap_write_header(file);
+ }
+ break;
+
+ default:
+ NOT_REACHED();
}
return file;
}
/* Read header. */
if (fread(&prh, sizeof prh, 1, file) != 1) {
- int error = ferror(file) ? errno : EOF;
- VLOG_WARN("failed to read pcap record header: %s",
- ovs_retval_to_string(error));
- return error;
+ if (ferror(file)) {
+ int error = errno;
+ VLOG_WARN("failed to read pcap record header: %s",
+ ovs_retval_to_string(error));
+ return error;
+ } else {
+ return EOF;
+ }
}
/* Calculate length. */
len = prh.incl_len;
if (len > 0xffff) {
- uint32_t swapped_len = (((len & 0xff000000) >> 24) |
- ((len & 0x00ff0000) >> 8) |
- ((len & 0x0000ff00) << 8) |
- ((len & 0x000000ff) << 24));
+ uint32_t swapped_len = uint32_byteswap(len);
if (swapped_len > 0xffff) {
- VLOG_WARN("bad packet length %zu or %"PRIu32" "
+ VLOG_WARN("bad packet length %"PRIuSIZE" or %"PRIu32" "
"reading pcap file",
len, swapped_len);
return EPROTO;