Changes in uspace/srv/vfs/vfs_ops.c [ed903174:6a4e972] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_ops.c
red903174 r6a4e972 38 38 #include "vfs.h" 39 39 #include <ipc/ipc.h> 40 #include <macros.h>41 #include <limits.h>42 40 #include <async.h> 43 41 #include <errno.h> … … 55 53 56 54 /* Forward declarations of static functions. */ 57 static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, aoff64_t);55 static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t); 58 56 59 57 /** … … 268 266 269 267 /* We want the client to send us the mount point. */ 270 char *mp; 271 int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN, 272 0, NULL); 273 if (rc != EOK) { 274 ipc_answer_0(rid, rc); 275 return; 276 } 268 ipc_callid_t callid; 269 size_t size; 270 if (!async_data_write_receive(&callid, &size)) { 271 ipc_answer_0(callid, EINVAL); 272 ipc_answer_0(rid, EINVAL); 273 return; 274 } 275 276 /* Check whether size is reasonable wrt. the mount point. */ 277 if ((size < 1) || (size > MAX_PATH_LEN)) { 278 ipc_answer_0(callid, EINVAL); 279 ipc_answer_0(rid, EINVAL); 280 return; 281 } 282 283 /* Allocate buffer for the mount point data being received. */ 284 char *mp = malloc(size + 1); 285 if (!mp) { 286 ipc_answer_0(callid, ENOMEM); 287 ipc_answer_0(rid, ENOMEM); 288 return; 289 } 290 291 /* Deliver the mount point. */ 292 ipcarg_t retval = async_data_write_finalize(callid, mp, size); 293 if (retval != EOK) { 294 ipc_answer_0(rid, retval); 295 free(mp); 296 return; 297 } 298 mp[size] = '\0'; 277 299 278 300 /* Now we expect to receive the mount options. */ 279 char *opts; 280 rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN, 281 0, NULL); 282 if (rc != EOK) { 301 if (!async_data_write_receive(&callid, &size)) { 302 ipc_answer_0(callid, EINVAL); 303 ipc_answer_0(rid, EINVAL); 283 304 free(mp); 284 ipc_answer_0(rid, rc); 285 return; 286 } 305 return; 306 } 307 308 /* Check the offered options size. */ 309 if (size > MAX_MNTOPTS_LEN) { 310 ipc_answer_0(callid, EINVAL); 311 ipc_answer_0(rid, EINVAL); 312 free(mp); 313 return; 314 } 315 316 /* Allocate buffer for the mount options. */ 317 char *opts = (char *) malloc(size + 1); 318 if (!opts) { 319 ipc_answer_0(callid, ENOMEM); 320 ipc_answer_0(rid, ENOMEM); 321 free(mp); 322 return; 323 } 324 325 /* Deliver the mount options. */ 326 retval = async_data_write_finalize(callid, opts, size); 327 if (retval != EOK) { 328 ipc_answer_0(rid, retval); 329 free(mp); 330 free(opts); 331 return; 332 } 333 opts[size] = '\0'; 287 334 288 335 /* … … 290 337 * system. 291 338 */ 292 char *fs_name; 293 rc = async_data_write_accept((void **) &fs_name, true, 0, FS_NAME_MAXLEN, 294 0, NULL); 295 if (rc != EOK) { 339 if (!async_data_write_receive(&callid, &size)) { 340 ipc_answer_0(callid, EINVAL); 341 ipc_answer_0(rid, EINVAL); 296 342 free(mp); 297 343 free(opts); 298 ipc_answer_0(rid, rc); 299 return; 300 } 301 344 return; 345 } 346 347 /* 348 * Don't receive more than is necessary for storing a full file system 349 * name. 350 */ 351 if ((size < 1) || (size > FS_NAME_MAXLEN)) { 352 ipc_answer_0(callid, EINVAL); 353 ipc_answer_0(rid, EINVAL); 354 free(mp); 355 free(opts); 356 return; 357 } 358 359 /* 360 * Allocate buffer for file system name. 361 */ 362 char *fs_name = (char *) malloc(size + 1); 363 if (fs_name == NULL) { 364 ipc_answer_0(callid, ENOMEM); 365 ipc_answer_0(rid, ENOMEM); 366 free(mp); 367 free(opts); 368 return; 369 } 370 371 /* Deliver the file system name. */ 372 retval = async_data_write_finalize(callid, fs_name, size); 373 if (retval != EOK) { 374 ipc_answer_0(rid, retval); 375 free(mp); 376 free(opts); 377 free(fs_name); 378 return; 379 } 380 fs_name[size] = '\0'; 381 302 382 /* 303 383 * Wait for IPC_M_PING so that we can return an error if we don't know … … 305 385 */ 306 386 ipc_call_t data; 307 ipc_callid_tcallid = async_get_call(&data);387 callid = async_get_call(&data); 308 388 if (IPC_GET_METHOD(data) != IPC_M_PING) { 309 389 ipc_answer_0(callid, ENOTSUP); … … 355 435 vfs_lookup_res_t mp_res; 356 436 vfs_lookup_res_t mr_res; 437 vfs_node_t *mp_node; 357 438 vfs_node_t *mr_node; 358 439 int phone; … … 361 442 * Receive the mount point path. 362 443 */ 363 rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN, 364 0, NULL); 444 rc = async_data_string_receive(&mp, MAX_PATH_LEN); 365 445 if (rc != EOK) 366 446 ipc_answer_0(rid, rc); … … 504 584 int oflag = IPC_GET_ARG2(*request); 505 585 int mode = IPC_GET_ARG3(*request); 586 size_t len; 506 587 507 588 /* Ignore mode for now. */ … … 525 606 lflag |= L_EXCLUSIVE; 526 607 527 char *path; 528 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 529 if (rc != EOK) { 530 ipc_answer_0(rid, rc); 531 return; 532 } 608 ipc_callid_t callid; 609 if (!async_data_write_receive(&callid, &len)) { 610 ipc_answer_0(callid, EINVAL); 611 ipc_answer_0(rid, EINVAL); 612 return; 613 } 614 615 char *path = malloc(len + 1); 616 if (!path) { 617 ipc_answer_0(callid, ENOMEM); 618 ipc_answer_0(rid, ENOMEM); 619 return; 620 } 621 622 int rc; 623 if ((rc = async_data_write_finalize(callid, path, len))) { 624 ipc_answer_0(rid, rc); 625 free(path); 626 return; 627 } 628 path[len] = '\0'; 533 629 534 630 /* … … 721 817 } 722 818 723 int vfs_close_internal(vfs_file_t *file)819 static int vfs_close_internal(vfs_file_t *file) 724 820 { 725 821 /* … … 798 894 799 895 /* 896 * Now we need to receive a call with client's 897 * IPC_M_DATA_READ/IPC_M_DATA_WRITE request. 898 */ 899 ipc_callid_t callid; 900 int res; 901 if (read) 902 res = async_data_read_receive(&callid, NULL); 903 else 904 res = async_data_write_receive(&callid, NULL); 905 if (!res) { 906 ipc_answer_0(callid, EINVAL); 907 ipc_answer_0(rid, EINVAL); 908 return; 909 } 910 911 /* 800 912 * Lock the open file structure so that no other thread can manipulate 801 913 * the same open file at a time. … … 821 933 } 822 934 823 int fs_phone = vfs_grab_phone(file->node->fs_handle); 824 825 /* 826 * Make a VFS_READ/VFS_WRITE request at the destination FS server 827 * and forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the 935 int fs_phone = vfs_grab_phone(file->node->fs_handle); 936 937 /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */ 938 aid_t msg; 939 ipc_call_t answer; 940 if (!read && file->append) 941 file->pos = file->node->size; 942 msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE, 943 file->node->dev_handle, file->node->index, file->pos, &answer); 944 945 /* 946 * Forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the 828 947 * destination FS server. The call will be routed as if sent by 829 948 * ourselves. Note that call arguments are immutable in this case so we 830 949 * don't have to bother. 831 950 */ 951 ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); 952 953 /* Wait for reply from the FS server. */ 832 954 ipcarg_t rc; 833 ipc_call_t answer; 834 if (read) { 835 if (file->append) 836 file->pos = file->node->size; 837 838 rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ, 839 file->node->dev_handle, file->node->index, file->pos, 840 &answer); 841 } else { 842 rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE, 843 file->node->dev_handle, file->node->index, file->pos, 844 &answer); 845 } 955 async_wait_for(msg, &rc); 846 956 847 957 vfs_release_phone(fs_phone); 848 958 849 959 size_t bytes = IPC_GET_ARG1(answer); 850 960 851 961 if (file->node->type == VFS_NODE_DIRECTORY) 852 962 fibril_rwlock_read_unlock(&namespace_rwlock); … … 887 997 { 888 998 int fd = (int) IPC_GET_ARG1(*request); 889 off 64_t off =890 (off64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), IPC_GET_ARG3(*request));891 int whence = (int) IPC_GET_ARG4(*request); 892 999 off_t off = (off_t) IPC_GET_ARG2(*request); 1000 int whence = (int) IPC_GET_ARG3(*request); 1001 1002 893 1003 /* Lookup the file structure corresponding to the file descriptor. */ 894 1004 vfs_file_t *file = vfs_file_get(fd); … … 897 1007 return; 898 1008 } 899 1009 1010 off_t newpos; 900 1011 fibril_mutex_lock(&file->lock); 901 902 off64_t newoff; 903 switch (whence) { 904 case SEEK_SET: 905 if (off >= 0) { 906 file->pos = (aoff64_t) off; 907 fibril_mutex_unlock(&file->lock); 908 ipc_answer_1(rid, EOK, off); 909 return; 910 } 911 break; 912 case SEEK_CUR: 913 if ((off >= 0) && (file->pos + off < file->pos)) { 914 fibril_mutex_unlock(&file->lock); 915 ipc_answer_0(rid, EOVERFLOW); 916 return; 917 } 918 919 if ((off < 0) && (file->pos < (aoff64_t) -off)) { 920 fibril_mutex_unlock(&file->lock); 921 ipc_answer_0(rid, EOVERFLOW); 922 return; 923 } 924 925 file->pos += off; 926 newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos; 927 1012 if (whence == SEEK_SET) { 1013 file->pos = off; 1014 fibril_mutex_unlock(&file->lock); 1015 ipc_answer_1(rid, EOK, off); 1016 return; 1017 } 1018 if (whence == SEEK_CUR) { 1019 if (file->pos + off < file->pos) { 928 1020 fibril_mutex_unlock(&file->lock); 929 ipc_answer_ 2(rid, EOK, LOWER32(newoff), UPPER32(newoff));1021 ipc_answer_0(rid, EOVERFLOW); 930 1022 return; 931 case SEEK_END: 932 fibril_rwlock_read_lock(&file->node->contents_rwlock); 933 aoff64_t size = file->node->size; 934 935 if ((off >= 0) && (size + off < size)) { 936 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 937 fibril_mutex_unlock(&file->lock); 938 ipc_answer_0(rid, EOVERFLOW); 939 return; 940 } 941 942 if ((off < 0) && (size < (aoff64_t) -off)) { 943 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 944 fibril_mutex_unlock(&file->lock); 945 ipc_answer_0(rid, EOVERFLOW); 946 return; 947 } 948 949 file->pos = size + off; 950 newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos; 951 952 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 1023 } 1024 file->pos += off; 1025 newpos = file->pos; 1026 fibril_mutex_unlock(&file->lock); 1027 ipc_answer_1(rid, EOK, newpos); 1028 return; 1029 } 1030 if (whence == SEEK_END) { 1031 fibril_rwlock_read_lock(&file->node->contents_rwlock); 1032 size_t size = file->node->size; 1033 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 1034 if (size + off < size) { 953 1035 fibril_mutex_unlock(&file->lock); 954 ipc_answer_ 2(rid, EOK, LOWER32(newoff), UPPER32(newoff));1036 ipc_answer_0(rid, EOVERFLOW); 955 1037 return; 956 } 957 1038 } 1039 newpos = size + off; 1040 file->pos = newpos; 1041 fibril_mutex_unlock(&file->lock); 1042 ipc_answer_1(rid, EOK, newpos); 1043 return; 1044 } 958 1045 fibril_mutex_unlock(&file->lock); 959 1046 ipc_answer_0(rid, EINVAL); 960 1047 } 961 1048 962 int vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle, 963 fs_index_t index, aoff64_t size) 1049 int 1050 vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle, 1051 fs_index_t index, size_t size) 964 1052 { 965 1053 ipcarg_t rc; … … 967 1055 968 1056 fs_phone = vfs_grab_phone(fs_handle); 969 rc = async_req_ 4_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle,970 (ipcarg_t) index, LOWER32(size), UPPER32(size));1057 rc = async_req_3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle, 1058 (ipcarg_t)index, (ipcarg_t)size); 971 1059 vfs_release_phone(fs_phone); 972 1060 return (int)rc; … … 976 1064 { 977 1065 int fd = IPC_GET_ARG1(*request); 978 aoff64_t size = 979 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), IPC_GET_ARG3(*request)); 1066 size_t size = IPC_GET_ARG2(*request); 980 1067 int rc; 981 1068 … … 1033 1120 void vfs_stat(ipc_callid_t rid, ipc_call_t *request) 1034 1121 { 1035 char *path; 1036 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 1037 if (rc != EOK) { 1038 ipc_answer_0(rid, rc); 1039 return; 1040 } 1041 1122 size_t len; 1042 1123 ipc_callid_t callid; 1124 1125 if (!async_data_write_receive(&callid, &len)) { 1126 ipc_answer_0(callid, EINVAL); 1127 ipc_answer_0(rid, EINVAL); 1128 return; 1129 } 1130 char *path = malloc(len + 1); 1131 if (!path) { 1132 ipc_answer_0(callid, ENOMEM); 1133 ipc_answer_0(rid, ENOMEM); 1134 return; 1135 } 1136 int rc; 1137 if ((rc = async_data_write_finalize(callid, path, len))) { 1138 ipc_answer_0(rid, rc); 1139 free(path); 1140 return; 1141 } 1142 path[len] = '\0'; 1143 1043 1144 if (!async_data_read_receive(&callid, NULL)) { 1044 1145 free(path); … … 1086 1187 { 1087 1188 int mode = IPC_GET_ARG1(*request); 1088 1089 char *path; 1090 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 1091 if (rc != EOK) { 1092 ipc_answer_0(rid, rc); 1093 return; 1094 } 1095 1189 1190 size_t len; 1191 ipc_callid_t callid; 1192 1193 if (!async_data_write_receive(&callid, &len)) { 1194 ipc_answer_0(callid, EINVAL); 1195 ipc_answer_0(rid, EINVAL); 1196 return; 1197 } 1198 char *path = malloc(len + 1); 1199 if (!path) { 1200 ipc_answer_0(callid, ENOMEM); 1201 ipc_answer_0(rid, ENOMEM); 1202 return; 1203 } 1204 int rc; 1205 if ((rc = async_data_write_finalize(callid, path, len))) { 1206 ipc_answer_0(rid, rc); 1207 free(path); 1208 return; 1209 } 1210 path[len] = '\0'; 1211 1096 1212 /* Ignore mode for now. */ 1097 1213 (void) mode; … … 1108 1224 { 1109 1225 int lflag = IPC_GET_ARG1(*request); 1110 1111 char *path; 1112 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 1113 if (rc != EOK) { 1114 ipc_answer_0(rid, rc); 1115 return; 1116 } 1226 1227 size_t len; 1228 ipc_callid_t callid; 1229 1230 if (!async_data_write_receive(&callid, &len)) { 1231 ipc_answer_0(callid, EINVAL); 1232 ipc_answer_0(rid, EINVAL); 1233 return; 1234 } 1235 char *path = malloc(len + 1); 1236 if (!path) { 1237 ipc_answer_0(callid, ENOMEM); 1238 ipc_answer_0(rid, ENOMEM); 1239 return; 1240 } 1241 int rc; 1242 if ((rc = async_data_write_finalize(callid, path, len))) { 1243 ipc_answer_0(rid, rc); 1244 free(path); 1245 return; 1246 } 1247 path[len] = '\0'; 1117 1248 1118 1249 fibril_rwlock_write_lock(&namespace_rwlock); … … 1143 1274 void vfs_rename(ipc_callid_t rid, ipc_call_t *request) 1144 1275 { 1276 size_t olen, nlen; 1277 ipc_callid_t callid; 1278 int rc; 1279 1145 1280 /* Retrieve the old path. */ 1146 char *old; 1147 int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL); 1148 if (rc != EOK) { 1149 ipc_answer_0(rid, rc); 1150 return; 1151 } 1281 if (!async_data_write_receive(&callid, &olen)) { 1282 ipc_answer_0(callid, EINVAL); 1283 ipc_answer_0(rid, EINVAL); 1284 return; 1285 } 1286 char *old = malloc(olen + 1); 1287 if (!old) { 1288 ipc_answer_0(callid, ENOMEM); 1289 ipc_answer_0(rid, ENOMEM); 1290 return; 1291 } 1292 if ((rc = async_data_write_finalize(callid, old, olen))) { 1293 ipc_answer_0(rid, rc); 1294 free(old); 1295 return; 1296 } 1297 old[olen] = '\0'; 1152 1298 1153 1299 /* Retrieve the new path. */ 1154 char *new;1155 rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL);1156 if (rc != EOK) {1300 if (!async_data_write_receive(&callid, &nlen)) { 1301 ipc_answer_0(callid, EINVAL); 1302 ipc_answer_0(rid, EINVAL); 1157 1303 free(old); 1158 ipc_answer_0(rid, rc); 1159 return; 1160 } 1161 1162 size_t olen; 1163 size_t nlen; 1304 return; 1305 } 1306 char *new = malloc(nlen + 1); 1307 if (!new) { 1308 ipc_answer_0(callid, ENOMEM); 1309 ipc_answer_0(rid, ENOMEM); 1310 free(old); 1311 return; 1312 } 1313 if ((rc = async_data_write_finalize(callid, new, nlen))) { 1314 ipc_answer_0(rid, rc); 1315 free(old); 1316 free(new); 1317 return; 1318 } 1319 new[nlen] = '\0'; 1320 1164 1321 char *oldc = canonify(old, &olen); 1165 1322 char *newc = canonify(new, &nlen); 1166 1167 if ((!oldc) || (!newc)) { 1323 if (!oldc || !newc) { 1168 1324 ipc_answer_0(rid, EINVAL); 1169 1325 free(old); … … 1171 1327 return; 1172 1328 } 1173 1174 1329 oldc[olen] = '\0'; 1175 1330 newc[nlen] = '\0'; 1176 1177 1331 if ((!str_lcmp(newc, oldc, str_length(oldc))) && 1178 1332 ((newc[str_length(oldc)] == '/') || … … 1195 1349 vfs_lookup_res_t new_par_lr; 1196 1350 fibril_rwlock_write_lock(&namespace_rwlock); 1197 1198 1351 /* Lookup the node belonging to the old file name. */ 1199 1352 rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL); … … 1205 1358 return; 1206 1359 } 1207 1208 1360 vfs_node_t *old_node = vfs_node_get(&old_lr); 1209 1361 if (!old_node) { … … 1214 1366 return; 1215 1367 } 1216 1217 1368 /* Determine the path to the parent of the node with the new name. */ 1218 1369 char *parentc = str_dup(newc); … … 1224 1375 return; 1225 1376 } 1226 1227 1377 char *lastsl = str_rchr(parentc + 1, '/'); 1228 1378 if (lastsl) … … 1230 1380 else 1231 1381 parentc[1] = '\0'; 1232 1233 1382 /* Lookup parent of the new file name. */ 1234 1383 rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL); … … 1241 1390 return; 1242 1391 } 1243 1244 1392 /* Check whether linking to the same file system instance. */ 1245 1393 if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) || … … 1251 1399 return; 1252 1400 } 1253 1254 1401 /* Destroy the old link for the new name. */ 1255 1402 vfs_node_t *new_node = NULL; 1256 1403 rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL); 1257 1258 1404 switch (rc) { 1259 1405 case ENOENT: … … 1280 1426 return; 1281 1427 } 1282 1283 1428 /* Create the new link for the new name. */ 1284 1429 rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index); … … 1292 1437 return; 1293 1438 } 1294 1295 1439 fibril_mutex_lock(&nodes_mutex); 1296 1440 old_node->lnkcnt++; 1297 1441 fibril_mutex_unlock(&nodes_mutex); 1298 1299 1442 /* Destroy the link for the old name. */ 1300 1443 rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL); … … 1309 1452 return; 1310 1453 } 1311 1312 1454 fibril_mutex_lock(&nodes_mutex); 1313 1455 old_node->lnkcnt--; … … 1315 1457 fibril_rwlock_write_unlock(&namespace_rwlock); 1316 1458 vfs_node_put(old_node); 1317 1318 1459 if (new_node) 1319 1460 vfs_node_put(new_node); 1320 1321 1461 free(old); 1322 1462 free(new);
Note:
See TracChangeset
for help on using the changeset viewer.