xref: /qemu/hw/9pfs/cofs.c (revision 02cb7f3a)
1 
2 /*
3  * Virtio 9p backend
4  *
5  * Copyright IBM, Corp. 2011
6  *
7  * Authors:
8  *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
9  *
10  * This work is licensed under the terms of the GNU GPL, version 2.  See
11  * the COPYING file in the top-level directory.
12  *
13  */
14 
15 #include "fsdev/qemu-fsdev.h"
16 #include "qemu-thread.h"
17 #include "qemu-coroutine.h"
18 #include "virtio-9p-coth.h"
19 
20 int v9fs_co_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
21 {
22     int err;
23     ssize_t len;
24 
25     buf->data = g_malloc(PATH_MAX);
26     qemu_co_rwlock_rdlock(&s->rename_lock);
27 
28     v9fs_co_run_in_worker(
29         {
30             len = s->ops->readlink(&s->ctx, path->data,
31                                    buf->data, PATH_MAX - 1);
32             if (len > -1) {
33                 buf->size = len;
34                 buf->data[len] = 0;
35                 err = 0;
36             } else {
37                 err = -errno;
38             }
39         });
40     qemu_co_rwlock_unlock(&s->rename_lock);
41     if (err) {
42         g_free(buf->data);
43         buf->data = NULL;
44         buf->size = 0;
45     }
46     return err;
47 }
48 
49 int v9fs_co_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
50 {
51     int err;
52 
53     qemu_co_rwlock_rdlock(&s->rename_lock);
54     v9fs_co_run_in_worker(
55         {
56             err = s->ops->statfs(&s->ctx, path->data, stbuf);
57             if (err < 0) {
58                 err = -errno;
59             }
60         });
61     qemu_co_rwlock_unlock(&s->rename_lock);
62     return err;
63 }
64 
65 int v9fs_co_chmod(V9fsState *s, V9fsString *path, mode_t mode)
66 {
67     int err;
68     FsCred cred;
69 
70     cred_init(&cred);
71     cred.fc_mode = mode;
72     qemu_co_rwlock_rdlock(&s->rename_lock);
73     v9fs_co_run_in_worker(
74         {
75             err = s->ops->chmod(&s->ctx, path->data, &cred);
76             if (err < 0) {
77                 err = -errno;
78             }
79         });
80     qemu_co_rwlock_unlock(&s->rename_lock);
81     return err;
82 }
83 
84 int v9fs_co_utimensat(V9fsState *s, V9fsString *path,
85                       struct timespec times[2])
86 {
87     int err;
88 
89     qemu_co_rwlock_rdlock(&s->rename_lock);
90     v9fs_co_run_in_worker(
91         {
92             err = s->ops->utimensat(&s->ctx, path->data, times);
93             if (err < 0) {
94                 err = -errno;
95             }
96         });
97     qemu_co_rwlock_unlock(&s->rename_lock);
98     return err;
99 }
100 
101 int v9fs_co_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
102 {
103     int err;
104     FsCred cred;
105 
106     cred_init(&cred);
107     cred.fc_uid = uid;
108     cred.fc_gid = gid;
109     qemu_co_rwlock_rdlock(&s->rename_lock);
110     v9fs_co_run_in_worker(
111         {
112             err = s->ops->chown(&s->ctx, path->data, &cred);
113             if (err < 0) {
114                 err = -errno;
115             }
116         });
117     qemu_co_rwlock_unlock(&s->rename_lock);
118     return err;
119 }
120 
121 int v9fs_co_truncate(V9fsState *s, V9fsString *path, off_t size)
122 {
123     int err;
124 
125     qemu_co_rwlock_rdlock(&s->rename_lock);
126     v9fs_co_run_in_worker(
127         {
128             err = s->ops->truncate(&s->ctx, path->data, size);
129             if (err < 0) {
130                 err = -errno;
131             }
132         });
133     qemu_co_rwlock_unlock(&s->rename_lock);
134     return err;
135 }
136 
137 int v9fs_co_mknod(V9fsState *s, V9fsFidState *fidp, V9fsString *name, uid_t uid,
138                   gid_t gid, dev_t dev, mode_t mode, struct stat *stbuf)
139 {
140     int err;
141     FsCred cred;
142     V9fsString fullname;
143 
144     cred_init(&cred);
145     cred.fc_uid  = uid;
146     cred.fc_gid  = gid;
147     cred.fc_mode = mode;
148     cred.fc_rdev = dev;
149     v9fs_string_init(&fullname);
150     qemu_co_rwlock_rdlock(&s->rename_lock);
151     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name->data);
152     v9fs_co_run_in_worker(
153         {
154             err = s->ops->mknod(&s->ctx, fullname.data, &cred);
155             if (err < 0) {
156                 err = -errno;
157             } else {
158                 err = s->ops->lstat(&s->ctx, fullname.data, stbuf);
159                 if (err < 0) {
160                     err = -errno;
161                 }
162             }
163         });
164     qemu_co_rwlock_unlock(&s->rename_lock);
165     v9fs_string_free(&fullname);
166     return err;
167 }
168 
169 int v9fs_co_remove(V9fsState *s, V9fsString *path)
170 {
171     int err;
172 
173     qemu_co_rwlock_rdlock(&s->rename_lock);
174     v9fs_co_run_in_worker(
175         {
176             err = s->ops->remove(&s->ctx, path->data);
177             if (err < 0) {
178                 err = -errno;
179             }
180         });
181     qemu_co_rwlock_unlock(&s->rename_lock);
182     return err;
183 }
184 
185 int v9fs_co_rename(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
186 {
187     int err;
188 
189     v9fs_co_run_in_worker(
190         {
191             err = s->ops->rename(&s->ctx, oldpath->data, newpath->data);
192             if (err < 0) {
193                 err = -errno;
194             }
195         });
196     return err;
197 }
198 
199 int v9fs_co_symlink(V9fsState *s, V9fsFidState *dfidp, V9fsString *name,
200                     const char *oldpath, gid_t gid, struct stat *stbuf)
201 {
202     int err;
203     FsCred cred;
204     V9fsString fullname;
205 
206 
207     cred_init(&cred);
208     cred.fc_uid = dfidp->uid;
209     cred.fc_gid = gid;
210     cred.fc_mode = 0777;
211     v9fs_string_init(&fullname);
212     qemu_co_rwlock_rdlock(&s->rename_lock);
213     v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name->data);
214     v9fs_co_run_in_worker(
215         {
216             err = s->ops->symlink(&s->ctx, oldpath, fullname.data, &cred);
217             if (err < 0) {
218                 err = -errno;
219             } else {
220                 err = s->ops->lstat(&s->ctx, fullname.data, stbuf);
221                 if (err < 0) {
222                     err = -errno;
223                 }
224             }
225         });
226     qemu_co_rwlock_unlock(&s->rename_lock);
227     v9fs_string_free(&fullname);
228     return err;
229 }
230