Annotation of qemu/fsdev/virtio-9p-marshal.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.