|
|
1.1 ! root 1: /* ! 2: * Virtio 9p backend ! 3: * ! 4: * Copyright IBM, Corp. 2010 ! 5: * ! 6: * Authors: ! 7: * Anthony Liguori <[email protected]> ! 8: * ! 9: * This work is licensed under the terms of the GNU GPL, version 2. See ! 10: * the COPYING file in the top-level directory. ! 11: * ! 12: */ ! 13: ! 14: #include <glib.h> ! 15: #include <glib/gprintf.h> ! 16: #include <sys/types.h> ! 17: #include <dirent.h> ! 18: #include <sys/time.h> ! 19: #include <utime.h> ! 20: #include <sys/uio.h> ! 21: #include <string.h> ! 22: #include <stdint.h> ! 23: #include <errno.h> ! 24: ! 25: #include "compiler.h" ! 26: #include "virtio-9p-marshal.h" ! 27: #include "bswap.h" ! 28: ! 29: void v9fs_string_free(V9fsString *str) ! 30: { ! 31: g_free(str->data); ! 32: str->data = NULL; ! 33: str->size = 0; ! 34: } ! 35: ! 36: void v9fs_string_null(V9fsString *str) ! 37: { ! 38: v9fs_string_free(str); ! 39: } ! 40: ! 41: void GCC_FMT_ATTR(2, 3) ! 42: v9fs_string_sprintf(V9fsString *str, const char *fmt, ...) ! 43: { ! 44: va_list ap; ! 45: ! 46: v9fs_string_free(str); ! 47: ! 48: va_start(ap, fmt); ! 49: str->size = g_vasprintf(&str->data, fmt, ap); ! 50: va_end(ap); ! 51: } ! 52: ! 53: void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs) ! 54: { ! 55: v9fs_string_free(lhs); ! 56: v9fs_string_sprintf(lhs, "%s", rhs->data); ! 57: } ! 58: ! 59: ! 60: static ssize_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count, ! 61: size_t offset, size_t size, int pack) ! 62: { ! 63: int i = 0; ! 64: size_t copied = 0; ! 65: size_t req_size = size; ! 66: ! 67: ! 68: for (i = 0; size && i < sg_count; i++) { ! 69: size_t len; ! 70: if (offset >= sg[i].iov_len) { ! 71: /* skip this sg */ ! 72: offset -= sg[i].iov_len; ! 73: continue; ! 74: } else { ! 75: len = MIN(sg[i].iov_len - offset, size); ! 76: if (pack) { ! 77: memcpy(sg[i].iov_base + offset, addr, len); ! 78: } else { ! 79: memcpy(addr, sg[i].iov_base + offset, len); ! 80: } ! 81: size -= len; ! 82: copied += len; ! 83: addr += len; ! 84: if (size) { ! 85: offset = 0; ! 86: continue; ! 87: } ! 88: } ! 89: } ! 90: if (copied < req_size) { ! 91: /* ! 92: * We copied less that requested size. error out ! 93: */ ! 94: return -ENOBUFS; ! 95: } ! 96: return copied; ! 97: } ! 98: ! 99: static ssize_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num, ! 100: size_t offset, size_t size) ! 101: { ! 102: return v9fs_packunpack(dst, out_sg, out_num, offset, size, 0); ! 103: } ! 104: ! 105: ssize_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset, ! 106: const void *src, size_t size) ! 107: { ! 108: return v9fs_packunpack((void *)src, in_sg, in_num, offset, size, 1); ! 109: } ! 110: ! 111: ssize_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, ! 112: int bswap, const char *fmt, ...) ! 113: { ! 114: int i; ! 115: va_list ap; ! 116: ssize_t copied = 0; ! 117: size_t old_offset = offset; ! 118: ! 119: va_start(ap, fmt); ! 120: for (i = 0; fmt[i]; i++) { ! 121: switch (fmt[i]) { ! 122: case 'b': { ! 123: uint8_t *valp = va_arg(ap, uint8_t *); ! 124: copied = v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp)); ! 125: break; ! 126: } ! 127: case 'w': { ! 128: uint16_t val, *valp; ! 129: valp = va_arg(ap, uint16_t *); ! 130: copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); ! 131: if (bswap) { ! 132: *valp = le16_to_cpu(val); ! 133: } else { ! 134: *valp = val; ! 135: } ! 136: break; ! 137: } ! 138: case 'd': { ! 139: uint32_t val, *valp; ! 140: valp = va_arg(ap, uint32_t *); ! 141: copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); ! 142: if (bswap) { ! 143: *valp = le32_to_cpu(val); ! 144: } else { ! 145: *valp = val; ! 146: } ! 147: break; ! 148: } ! 149: case 'q': { ! 150: uint64_t val, *valp; ! 151: valp = va_arg(ap, uint64_t *); ! 152: copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); ! 153: if (bswap) { ! 154: *valp = le64_to_cpu(val); ! 155: } else { ! 156: *valp = val; ! 157: } ! 158: break; ! 159: } ! 160: case 's': { ! 161: V9fsString *str = va_arg(ap, V9fsString *); ! 162: copied = v9fs_unmarshal(out_sg, out_num, offset, bswap, ! 163: "w", &str->size); ! 164: if (copied > 0) { ! 165: offset += copied; ! 166: str->data = g_malloc(str->size + 1); ! 167: copied = v9fs_unpack(str->data, out_sg, out_num, offset, ! 168: str->size); ! 169: if (copied > 0) { ! 170: str->data[str->size] = 0; ! 171: } else { ! 172: v9fs_string_free(str); ! 173: } ! 174: } ! 175: break; ! 176: } ! 177: case 'Q': { ! 178: V9fsQID *qidp = va_arg(ap, V9fsQID *); ! 179: copied = v9fs_unmarshal(out_sg, out_num, offset, bswap, "bdq", ! 180: &qidp->type, &qidp->version, &qidp->path); ! 181: break; ! 182: } ! 183: case 'S': { ! 184: V9fsStat *statp = va_arg(ap, V9fsStat *); ! 185: copied = v9fs_unmarshal(out_sg, out_num, offset, bswap, ! 186: "wwdQdddqsssssddd", ! 187: &statp->size, &statp->type, &statp->dev, ! 188: &statp->qid, &statp->mode, &statp->atime, ! 189: &statp->mtime, &statp->length, ! 190: &statp->name, &statp->uid, &statp->gid, ! 191: &statp->muid, &statp->extension, ! 192: &statp->n_uid, &statp->n_gid, ! 193: &statp->n_muid); ! 194: break; ! 195: } ! 196: case 'I': { ! 197: V9fsIattr *iattr = va_arg(ap, V9fsIattr *); ! 198: copied = v9fs_unmarshal(out_sg, out_num, offset, bswap, ! 199: "ddddqqqqq", ! 200: &iattr->valid, &iattr->mode, ! 201: &iattr->uid, &iattr->gid, &iattr->size, ! 202: &iattr->atime_sec, &iattr->atime_nsec, ! 203: &iattr->mtime_sec, &iattr->mtime_nsec); ! 204: break; ! 205: } ! 206: default: ! 207: break; ! 208: } ! 209: if (copied < 0) { ! 210: va_end(ap); ! 211: return copied; ! 212: } ! 213: offset += copied; ! 214: } ! 215: va_end(ap); ! 216: ! 217: return offset - old_offset; ! 218: } ! 219: ! 220: ssize_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, ! 221: int bswap, const char *fmt, ...) ! 222: { ! 223: int i; ! 224: va_list ap; ! 225: ssize_t copied = 0; ! 226: size_t old_offset = offset; ! 227: ! 228: va_start(ap, fmt); ! 229: for (i = 0; fmt[i]; i++) { ! 230: switch (fmt[i]) { ! 231: case 'b': { ! 232: uint8_t val = va_arg(ap, int); ! 233: copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); ! 234: break; ! 235: } ! 236: case 'w': { ! 237: uint16_t val; ! 238: if (bswap) { ! 239: cpu_to_le16w(&val, va_arg(ap, int)); ! 240: } else { ! 241: val = va_arg(ap, int); ! 242: } ! 243: copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); ! 244: break; ! 245: } ! 246: case 'd': { ! 247: uint32_t val; ! 248: if (bswap) { ! 249: cpu_to_le32w(&val, va_arg(ap, uint32_t)); ! 250: } else { ! 251: val = va_arg(ap, uint32_t); ! 252: } ! 253: copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); ! 254: break; ! 255: } ! 256: case 'q': { ! 257: uint64_t val; ! 258: if (bswap) { ! 259: cpu_to_le64w(&val, va_arg(ap, uint64_t)); ! 260: } else { ! 261: val = va_arg(ap, uint64_t); ! 262: } ! 263: copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); ! 264: break; ! 265: } ! 266: case 's': { ! 267: V9fsString *str = va_arg(ap, V9fsString *); ! 268: copied = v9fs_marshal(in_sg, in_num, offset, bswap, ! 269: "w", str->size); ! 270: if (copied > 0) { ! 271: offset += copied; ! 272: copied = v9fs_pack(in_sg, in_num, offset, str->data, str->size); ! 273: } ! 274: break; ! 275: } ! 276: case 'Q': { ! 277: V9fsQID *qidp = va_arg(ap, V9fsQID *); ! 278: copied = v9fs_marshal(in_sg, in_num, offset, bswap, "bdq", ! 279: qidp->type, qidp->version, qidp->path); ! 280: break; ! 281: } ! 282: case 'S': { ! 283: V9fsStat *statp = va_arg(ap, V9fsStat *); ! 284: copied = v9fs_marshal(in_sg, in_num, offset, bswap, ! 285: "wwdQdddqsssssddd", ! 286: statp->size, statp->type, statp->dev, ! 287: &statp->qid, statp->mode, statp->atime, ! 288: statp->mtime, statp->length, &statp->name, ! 289: &statp->uid, &statp->gid, &statp->muid, ! 290: &statp->extension, statp->n_uid, ! 291: statp->n_gid, statp->n_muid); ! 292: break; ! 293: } ! 294: case 'A': { ! 295: V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *); ! 296: copied = v9fs_marshal(in_sg, in_num, offset, bswap, ! 297: "qQdddqqqqqqqqqqqqqqq", ! 298: statp->st_result_mask, ! 299: &statp->qid, statp->st_mode, ! 300: statp->st_uid, statp->st_gid, ! 301: statp->st_nlink, statp->st_rdev, ! 302: statp->st_size, statp->st_blksize, ! 303: statp->st_blocks, statp->st_atime_sec, ! 304: statp->st_atime_nsec, statp->st_mtime_sec, ! 305: statp->st_mtime_nsec, statp->st_ctime_sec, ! 306: statp->st_ctime_nsec, statp->st_btime_sec, ! 307: statp->st_btime_nsec, statp->st_gen, ! 308: statp->st_data_version); ! 309: break; ! 310: } ! 311: default: ! 312: break; ! 313: } ! 314: if (copied < 0) { ! 315: va_end(ap); ! 316: return copied; ! 317: } ! 318: offset += copied; ! 319: } ! 320: va_end(ap); ! 321: ! 322: return offset - old_offset; ! 323: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.