Annotation of qemu/fsdev/virtio-9p-marshal.c, revision 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.