debuggers.hg

changeset 21182:df34011884a3

libxl: New utility functions in for reading and writing files.

We introduce these functions in libxl_utils.h:

int libxl_read_file_contents(struct libxl_ctx *ctx, const char
*filename,
void **data_r, int *datalen_r);
int libxl_read_exactly(struct libxl_ctx *ctx, int fd, void *data,
ssize_t sz,
const char *filename, const char *what);
int libxl_write_exactly(struct libxl_ctx *ctx, int fd, const void
*data,
ssize_t sz, const char *filename, const char
*what);

They will be needed by the following patches. They have to be in
libxl.a rather than libxutil.a because they will be used, amongst
other places, in libxl itself.

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Apr 12 17:39:29 2010 +0100 (2010-04-12)
parents 37e4d8e11554
children c031244c190e
files tools/libxl/libxl_utils.c tools/libxl/libxl_utils.h
line diff
     1.1 --- a/tools/libxl/libxl_utils.c	Mon Apr 12 17:38:42 2010 +0100
     1.2 +++ b/tools/libxl/libxl_utils.c	Mon Apr 12 17:39:29 2010 +0100
     1.3 @@ -26,6 +26,7 @@
     1.4  #include <sys/stat.h>
     1.5  #include <sys/types.h>
     1.6  #include <unistd.h>
     1.7 +#include <assert.h>
     1.8  
     1.9  #include "libxl_utils.h"
    1.10  #include "libxl_internal.h"
    1.11 @@ -177,3 +178,105 @@ out:
    1.12      return rc;
    1.13  }
    1.14  
    1.15 +int libxl_read_file_contents(struct libxl_ctx *ctx, const char *filename,
    1.16 +                             void **data_r, int *datalen_r) {
    1.17 +    FILE *f = 0;
    1.18 +    uint8_t *data = 0;
    1.19 +    int datalen = 0;
    1.20 +    int e;
    1.21 +    struct stat stab;
    1.22 +    ssize_t rs;
    1.23 +    
    1.24 +    f = fopen(filename, "r");
    1.25 +    if (!f) {
    1.26 +        if (errno == ENOENT) return ENOENT;
    1.27 +        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to open %s", filename);
    1.28 +        goto xe;
    1.29 +    }
    1.30 +
    1.31 +    if (fstat(fileno(f), &stab)) {
    1.32 +        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to fstat %s", filename);
    1.33 +        goto xe;
    1.34 +    }
    1.35 +
    1.36 +    if (!S_ISREG(stab.st_mode)) {
    1.37 +        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "%s is not a plain file", filename);
    1.38 +        errno = ENOTTY;
    1.39 +        goto xe;
    1.40 +    }
    1.41 +
    1.42 +    if (stab.st_size > INT_MAX) {
    1.43 +        XL_LOG(ctx, XL_LOG_ERROR, "file %s is far too large", filename);
    1.44 +        errno = EFBIG;
    1.45 +        goto xe;
    1.46 +    }
    1.47 +
    1.48 +    datalen = stab.st_size;
    1.49 +
    1.50 +    if (stab.st_size && data_r) {
    1.51 +        data = malloc(datalen);
    1.52 +        if (!data) goto xe;
    1.53 +
    1.54 +        rs = fread(data, 1, datalen, f);
    1.55 +        if (rs != datalen) {
    1.56 +            if (ferror(f))
    1.57 +                XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to read %s", filename);
    1.58 +            else if (feof(f))
    1.59 +                XL_LOG(ctx, XL_LOG_ERROR, "%s changed size while we"
    1.60 +                       " were reading it", filename);
    1.61 +            else
    1.62 +                abort();
    1.63 +            goto xe;
    1.64 +        }
    1.65 +    }
    1.66 +
    1.67 +    if (fclose(f)) {
    1.68 +        f = 0;
    1.69 +        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to close %s", filename);
    1.70 +        goto xe;
    1.71 +    }
    1.72 +
    1.73 +    if (data_r) *data_r = data;
    1.74 +    if (datalen_r) *datalen_r = datalen;
    1.75 +
    1.76 +    return 0;
    1.77 +
    1.78 + xe:
    1.79 +    e = errno;
    1.80 +    assert(e != ENOENT);
    1.81 +    if (f) fclose(f);
    1.82 +    if (data) free(data);
    1.83 +    return e;
    1.84 +}
    1.85 +
    1.86 +#define READ_WRITE_EXACTLY(rw, zero_is_eof, constdata)                    \
    1.87 +                                                                          \
    1.88 +  int libxl_##rw##_exactly(struct libxl_ctx *ctx, int fd,                 \
    1.89 +                           constdata void *data, ssize_t sz,              \
    1.90 +                           const char *filename, const char *what) {      \
    1.91 +      ssize_t got;                                                        \
    1.92 +                                                                          \
    1.93 +      while (sz > 0) {                                                    \
    1.94 +          got = rw(fd, data, sz);                                         \
    1.95 +          if (got == -1) {                                                \
    1.96 +              if (errno == EINTR) continue;                               \
    1.97 +              XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to " #rw " %s%s%s", \
    1.98 +                           what?what:"", what?" from ":"", filename);     \
    1.99 +              return errno;                                               \
   1.100 +          }                                                               \
   1.101 +          if (got == 0) {                                                 \
   1.102 +              XL_LOG(ctx, XL_LOG_ERROR,                                   \
   1.103 +                     zero_is_eof                                          \
   1.104 +                     ? "file/stream truncated reading %s%s%s"             \
   1.105 +                     : "file/stream write returned 0! writing %s%s%s",    \
   1.106 +                     what?what:"", what?" from ":"", filename);           \
   1.107 +              return EPROTO;                                              \
   1.108 +          }                                                               \
   1.109 +          sz -= got;                                                      \
   1.110 +          data = (char*)data + got;                                       \
   1.111 +      }                                                                   \
   1.112 +      return 0;                                                           \
   1.113 +  }
   1.114 +
   1.115 +READ_WRITE_EXACTLY(read, 1, /* */)
   1.116 +READ_WRITE_EXACTLY(write, 0, const)
     2.1 --- a/tools/libxl/libxl_utils.h	Mon Apr 12 17:38:42 2010 +0100
     2.2 +++ b/tools/libxl/libxl_utils.h	Mon Apr 12 17:39:29 2010 +0100
     2.3 @@ -26,5 +26,23 @@ int libxl_is_stubdom(struct libxl_ctx *c
     2.4  int libxl_create_logfile(struct libxl_ctx *ctx, char *name, char **full_name);
     2.5  int libxl_string_to_phystype(struct libxl_ctx *ctx, char *s, libxl_disk_phystype *phystype);
     2.6  
     2.7 +int libxl_read_file_contents(struct libxl_ctx *ctx, const char *filename,
     2.8 +                             void **data_r, int *datalen_r);
     2.9 +  /* Reads the contents of the plain file filename into a mallocd
    2.10 +   * buffer.  Returns 0 or errno.  Any errors other than ENOENT are logged.
    2.11 +   * If the file is empty, *data_r and *datalen_r are set to 0.
    2.12 +   * On error, *data_r and *datalen_r are undefined.
    2.13 +   * data_r and/or datalen_r may be 0.
    2.14 +   */
    2.15 +
    2.16 +int libxl_read_exactly(struct libxl_ctx *ctx, int fd, void *data, ssize_t sz,
    2.17 +                       const char *filename, const char *what);
    2.18 +int libxl_write_exactly(struct libxl_ctx *ctx, int fd, const void *data,
    2.19 +                        ssize_t sz, const char *filename, const char *what);
    2.20 +  /* Returns 0 or errno.  If file is truncated on reading, returns
    2.21 +   * EPROTO and you have no way to tell how much was read.  Errors are
    2.22 +   * logged using filename (which is only used for logging) and what
    2.23 +   * (which may be 0). */
    2.24 +    
    2.25  #endif
    2.26