Revision a6568fe2

b/hw/file-op-9p.h
32 32
    int (*setuid)(FsContext *, uid_t);
33 33
    int (*close)(FsContext *, int);
34 34
    int (*closedir)(FsContext *, DIR *);
35
    DIR *(*opendir)(FsContext *, const char *);
36
    int (*open)(FsContext *, const char *, int);
35 37
    void *opaque;
36 38
} FileOperations;
37 39
#endif
b/hw/virtio-9p-local.c
86 86
    return closedir(dir);
87 87
}
88 88

  
89
static int local_open(FsContext *ctx, const char *path, int flags)
90
{
91
    return open(rpath(ctx, path), flags);
92
}
93

  
94
static DIR *local_opendir(FsContext *ctx, const char *path)
95
{
96
    return opendir(rpath(ctx, path));
97
}
98

  
89 99
FileOperations local_ops = {
90 100
    .lstat = local_lstat,
91 101
    .setuid = local_setuid,
92 102
    .readlink = local_readlink,
93 103
    .close = local_close,
94 104
    .closedir = local_closedir,
105
    .open = local_open,
106
    .opendir = local_opendir,
95 107
};
b/hw/virtio-9p.c
56 56
    return s->ops->closedir(&s->ctx, dir);
57 57
}
58 58

  
59
static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags)
60
{
61
    return s->ops->open(&s->ctx, path->data, flags);
62
}
63

  
64
static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
65
{
66
    return s->ops->opendir(&s->ctx, path->data);
67
}
68

  
59 69
static void v9fs_string_init(V9fsString *str)
60 70
{
61 71
    str->data = NULL;
......
1129 1139
    v9fs_walk_complete(s, vs, err);
1130 1140
}
1131 1141

  
1132
static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
1142
typedef struct V9fsOpenState {
1143
    V9fsPDU *pdu;
1144
    size_t offset;
1145
    int8_t mode;
1146
    V9fsFidState *fidp;
1147
    V9fsQID qid;
1148
    struct stat stbuf;
1149

  
1150
} V9fsOpenState;
1151

  
1152
enum {
1153
    Oread   = 0x00,
1154
    Owrite  = 0x01,
1155
    Ordwr   = 0x02,
1156
    Oexec   = 0x03,
1157
    Oexcl   = 0x04,
1158
    Otrunc  = 0x10,
1159
    Orexec  = 0x20,
1160
    Orclose = 0x40,
1161
    Oappend = 0x80,
1162
};
1163

  
1164
static int omode_to_uflags(int8_t mode)
1133 1165
{
1134
    if (debug_9p_pdu) {
1135
        pprint_pdu(pdu);
1166
    int ret = 0;
1167

  
1168
    switch (mode & 3) {
1169
    case Oread:
1170
        ret = O_RDONLY;
1171
        break;
1172
    case Ordwr:
1173
        ret = O_RDWR;
1174
        break;
1175
    case Owrite:
1176
        ret = O_WRONLY;
1177
        break;
1178
    case Oexec:
1179
        ret = O_RDONLY;
1180
        break;
1136 1181
    }
1182

  
1183
    if (mode & Otrunc) {
1184
        ret |= O_TRUNC;
1185
    }
1186

  
1187
    if (mode & Oappend) {
1188
        ret |= O_APPEND;
1189
    }
1190

  
1191
    if (mode & Oexcl) {
1192
        ret |= O_EXCL;
1193
    }
1194

  
1195
    return ret;
1196
}
1197

  
1198
static void v9fs_open_post_opendir(V9fsState *s, V9fsOpenState *vs, int err)
1199
{
1200
    if (vs->fidp->dir == NULL) {
1201
        err = -errno;
1202
        goto out;
1203
    }
1204

  
1205
    vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
1206
    err = vs->offset;
1207
out:
1208
    complete_pdu(s, vs->pdu, err);
1209
    qemu_free(vs);
1210

  
1211
}
1212

  
1213
static void v9fs_open_post_open(V9fsState *s, V9fsOpenState *vs, int err)
1214
{
1215
    if (vs->fidp->fd == -1) {
1216
        err = -errno;
1217
        goto out;
1218
    }
1219

  
1220
    vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
1221
    err = vs->offset;
1222
out:
1223
    complete_pdu(s, vs->pdu, err);
1224
    qemu_free(vs);
1225
}
1226

  
1227
static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err)
1228
{
1229
    if (err) {
1230
        err = -errno;
1231
        goto out;
1232
    }
1233

  
1234
    stat_to_qid(&vs->stbuf, &vs->qid);
1235

  
1236
    if (S_ISDIR(vs->stbuf.st_mode)) {
1237
        vs->fidp->dir = v9fs_do_opendir(s, &vs->fidp->path);
1238
        v9fs_open_post_opendir(s, vs, err);
1239
    } else {
1240
        vs->fidp->fd = v9fs_do_open(s, &vs->fidp->path,
1241
                                    omode_to_uflags(vs->mode));
1242
        v9fs_open_post_open(s, vs, err);
1243
    }
1244
    return;
1245
out:
1246
    complete_pdu(s, vs->pdu, err);
1247
    qemu_free(vs);
1137 1248
}
1138 1249

  
1139 1250
static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
1140
{    if (debug_9p_pdu) {
1251
{
1252
    int32_t fid;
1253
    V9fsOpenState *vs;
1254
    ssize_t err = 0;
1255

  
1256

  
1257
    vs = qemu_malloc(sizeof(*vs));
1258
    vs->pdu = pdu;
1259
    vs->offset = 7;
1260

  
1261
    pdu_unmarshal(vs->pdu, vs->offset, "db", &fid, &vs->mode);
1262

  
1263
    vs->fidp = lookup_fid(s, fid);
1264
    if (vs->fidp == NULL) {
1265
        err = -ENOENT;
1266
        goto out;
1267
    }
1268

  
1269
    BUG_ON(vs->fidp->fd != -1);
1270
    BUG_ON(vs->fidp->dir);
1271

  
1272
    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
1273

  
1274
    v9fs_open_post_lstat(s, vs, err);
1275
    return;
1276
out:
1277
    complete_pdu(s, pdu, err);
1278
    qemu_free(vs);
1279
}
1280

  
1281
static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
1282
{
1283
    if (debug_9p_pdu) {
1141 1284
        pprint_pdu(pdu);
1142
     }
1285
    }
1143 1286
}
1144 1287

  
1145 1288
static void v9fs_read(V9fsState *s, V9fsPDU *pdu)

Also available in: Unified diff