Changeset 30446 in vbox
- Timestamp:
- Jun 25, 2010 9:51:58 AM (15 years ago)
- Location:
- trunk/src/VBox/Additions/solaris/SharedFolders
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c
r30433 r30446 30 30 #include <sys/ddi.h> 31 31 #include <sys/sunddi.h> 32 #include <sys/dirent.h> 32 33 #include "vboxfs_prov.h" 33 34 #ifdef u … … 776 777 * - EINVAL - Internal error of some kind 777 778 * 778 * On successful return, buffer[0] is the start of an array of "char *" 779 * pointers to the filenames. The array ends with a NULL pointer. 780 * The remaining storage in buffer after that NULL pointer is where the 781 * filename strings actually are. 782 * 783 * On input nents is the max number of filenames the requestor can handle. 784 * On output nents is the number of entries at buff[0] 785 * 786 * The caller is responsible for freeing the returned buffer. 779 * On successful return, *dirents points to a list of sffs_dirents_t; 780 * for each dirent, all fields except the d_ino will be set appropriately. 781 * The caller is responsible for freeing the dirents buffer. 787 782 */ 788 783 int … … 790 785 sfp_mount_t *mnt, 791 786 char *path, 792 void **buffer, 793 size_t *buffersize, 794 uint32_t *nents) 787 sffs_dirents_t **dirents) 795 788 { 796 789 int error; … … 800 793 int mask_size; 801 794 sfp_file_t *fp; 802 void *buff_start = NULL;803 size_t buff_size;804 795 static char infobuff[2 * MAXNAMELEN]; /* not on stack!! */ 805 796 SHFLDIRINFO *info = (SHFLDIRINFO *)&infobuff; 806 uint32_t numbytes = sizeof (infobuff);797 uint32_t numbytes; 807 798 uint32_t justone; 808 799 uint32_t cnt; 809 char **name_ptrs;810 811 *buffer = NULL;812 *buffersize = 0; 813 if (*nents == 0)814 return (EINVAL); 800 sffs_dirents_t *cur_buf; 801 struct dirent64 *dirent; 802 unsigned short reclen; 803 804 *dirents = NULL; 805 815 806 error = sfprov_open(mnt, path, &fp); 816 807 if (error != 0) 817 808 return (ENOENT); 809 810 /* 811 * Allocate the first dirents buffer. 812 */ 813 *dirents = kmem_alloc(SFFS_DIRENTS_SIZE, KM_SLEEP); 814 if (*dirents == NULL) { 815 error = (ENOSPC); 816 goto done; 817 } 818 cur_buf = *dirents; 819 cur_buf->sf_next = NULL; 820 cur_buf->sf_len = 0; 818 821 819 822 /* … … 823 826 len = strlen(path) + 3; 824 827 cp = kmem_alloc(len, KM_SLEEP); 828 if (cp == NULL) { 829 error = (ENOSPC); 830 goto done; 831 } 825 832 strcpy(cp, path); 826 833 strcat(cp, "/*"); 827 834 mask_str = sfprov_string(cp, &mask_size); 828 835 kmem_free(cp, len); 829 830 /*831 * Allocate the buffer to use for return values. Each entry832 * in the buffer will have a pointer and the string itself.833 * The pointers go in the front of the buffer, the strings834 * at the end.835 */836 buff_size = *nents * (sizeof(char *) + MAXNAMELEN);837 name_ptrs = buff_start = kmem_alloc(buff_size, KM_SLEEP);838 cp = (char *)buff_start + buff_size;839 836 840 837 /* … … 860 857 861 858 /* 862 * Put this name in the buffer, stopif we run out of room.859 * Put this name in the buffer, expand if we run out of room. 863 860 */ 864 cp -= strlen(info->name.String.utf8) + 1; 865 if (cp < (char *)(&name_ptrs[cnt + 2])) 866 break; 867 strcpy(cp, info->name.String.utf8); 868 name_ptrs[cnt] = cp; 861 reclen = DIRENT64_RECLEN(strlen(info->name.String.utf8)); 862 if (SFFS_DIRENTS_OFF + cur_buf->sf_len + reclen > SFFS_DIRENTS_SIZE) { 863 cur_buf->sf_next = kmem_alloc(SFFS_DIRENTS_SIZE, KM_SLEEP); 864 if (cur_buf->sf_next == NULL) { 865 error = ENOSPC; 866 goto done; 867 } 868 cur_buf = cur_buf->sf_next; 869 cur_buf->sf_next = NULL; 870 cur_buf->sf_len = 0; 871 } 872 873 dirent = (dirent64_t *) 874 (((char *) &cur_buf->sf_entries[0]) + cur_buf->sf_len); 875 strcpy(&dirent->d_name[0], info->name.String.utf8); 876 dirent->d_reclen = reclen; 877 dirent->d_off = cnt; 878 879 cur_buf->sf_len += reclen; 869 880 ++cnt; 870 881 } 871 882 error = 0; 872 name_ptrs[cnt] = NULL; 873 *nents = cnt; 874 *buffer = buff_start; 875 *buffersize = buff_size; 883 876 884 done: 877 if (error != 0) 878 kmem_free(buff_start, buff_size); 879 kmem_free(mask_str, mask_size); 885 if (error != 0) { 886 while (*dirents) { 887 cur_buf = (*dirents)->sf_next; 888 kmem_free(*dirents, SFFS_DIRENTS_SIZE); 889 *dirents = cur_buf; 890 } 891 } 892 if (mask_str != NULL) 893 kmem_free(mask_str, mask_size); 880 894 sfprov_close(fp); 881 895 return (error); -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h
r30417 r30446 111 111 * Read directory entries. 112 112 */ 113 extern int sfprov_readdir(sfp_mount_t *mnt, char *path, void **buffer, 114 size_t *buffersize, uint32_t *nents); 113 /* 114 * a singly linked list of buffers, each containing an array of dirent's. 115 * sf_len is length of the sf_entries array, in bytes. 116 */ 117 typedef struct sffs_dirents { 118 struct sffs_dirents *sf_next; 119 len_t sf_len; 120 dirent64_t sf_entries[1]; 121 } sffs_dirents_t; 122 123 extern int sfprov_readdir(sfp_mount_t *mnt, char *path, sffs_dirents_t **dirents); 124 125 #define SFFS_DIRENTS_SIZE 8192 126 #define SFFS_DIRENTS_OFF (offsetof(sffs_dirents_t, sf_entries[0])) 115 127 116 128 #ifdef __cplusplus -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c
r30435 r30446 144 144 145 145 /* 146 * Clears the (cached) directory listing for the node. 147 */ 148 static void 149 sfnode_clear_dir_list(sfnode_t *node) 150 { 151 ASSERT(MUTEX_HELD(&sffs_lock)); 152 153 while (node->sf_dir_list != NULL) { 154 sffs_dirents_t *next = node->sf_dir_list->sf_next; 155 kmem_free(node->sf_dir_list, SFFS_DIRENTS_SIZE); 156 node->sf_dir_list = next; 157 } 158 } 159 160 /* 146 161 * Open the provider file associated with a vnode. Holding the file open is 147 162 * the only way we have of trying to have a vnode continue to refer to the … … 220 235 if (parent) 221 236 ++parent->sf_children; 237 node->sf_dir_list = NULL; 222 238 223 239 /* … … 258 274 259 275 VFS_RELE(node->sf_sffs->sf_vfsp); 276 sfnode_clear_dir_list(node); 260 277 kmem_free(node->sf_path, strlen(node->sf_path) + 1); 261 278 kmem_free(node, sizeof (*node)); 262 279 if (parent != NULL) { 280 sfnode_clear_dir_list(parent); 263 281 if (parent->sf_children == 0) 264 282 panic("sfnode_destroy(%s) parent has no child", node->sf_path); … … 313 331 } else { 314 332 LogFlowFunc(("sffs_make_stale(%s) sub\n", n->sf_path)); 333 sfnode_clear_dir_list(n); 315 334 if (avl_find(&sfnodes, n, &where) == NULL) 316 335 panic("sfnode_make_stale(%s)" … … 333 352 } else if (!node->sf_is_stale) { 334 353 LogFlowFunc(("sffs_make_stale(%s)\n", node->sf_path)); 354 sfnode_clear_dir_list(node); 355 if (node->sf_parent) 356 sfnode_clear_dir_list(node->sf_parent); 335 357 if (avl_find(&sfnodes, node, &where) == NULL) 336 358 panic("sfnode_make_stale(%s) not in sfnodes", … … 433 455 if (node->sf_parent->sf_children == 0) 434 456 panic("sfnode_rename(%s) parent has no child", node->sf_path); 457 sfnode_clear_dir_list(node->sf_parent); 458 sfnode_clear_dir_list(newparent); 435 459 --node->sf_parent->sf_children; 436 460 node->sf_parent = newparent; … … 584 608 sfnode_t *node; 585 609 struct dirent64 *dirent; 610 sffs_dirents_t *cur_buf; 611 offset_t offset; 586 612 int dummy_eof; 587 613 int error = 0; 588 int namelen;589 void *prov_buff = NULL;590 size_t prov_buff_size;591 char **names;592 uint32_t nents;593 uint32_t index;594 614 595 615 if (uiop->uio_iovcnt != 1) … … 608 628 } 609 629 610 dirent = kmem_zalloc(DIRENT64_RECLEN(MAXNAMELEN), KM_SLEEP);611 612 630 /* 613 631 * Get the directory entry names from the host. This gets all 614 * entries, so add in starting offset. Max the caller can expect 615 * would be the size of the UIO buffer / sizeof of a dirent for 616 * file with name of length 1 632 * entries. These are stored in a linked list of sffs_dirents_t 633 * buffers, each of which contains a list of dirent64_t's. 617 634 */ 618 635 mutex_enter(&sffs_lock); 619 index = uiop->uio_loffset; 620 nents = index + (uiop->uio_resid / DIRENT64_RECLEN(1)); 621 error = sfprov_readdir(dir->sf_sffs->sf_handle, dir->sf_path, 622 &prov_buff, &prov_buff_size, &nents); 623 if (error != 0) 624 goto done; 625 if (nents <= index) { 626 *eofp = 1; 627 goto done; 628 } 629 names = (void *)prov_buff; 630 631 /* 632 * Lookup each of the names, so that we have ino's. 633 */ 634 for (; index < nents; ++index) { 635 if (strcmp(names[index], ".") == 0) { 636 637 if (dir->sf_dir_list == NULL) { 638 error = sfprov_readdir(dir->sf_sffs->sf_handle, dir->sf_path, 639 &dir->sf_dir_list); 640 if (error != 0) 641 goto done; 642 } 643 644 /* 645 * Lookup each of the names, so that we have ino's, and copy to 646 * result buffer. 647 */ 648 offset = 0; 649 cur_buf = dir->sf_dir_list; 650 while (cur_buf != NULL) { 651 if (offset + cur_buf->sf_len <= uiop->uio_loffset) { 652 offset += cur_buf->sf_len; 653 cur_buf = cur_buf->sf_next; 654 continue; 655 } 656 657 dirent = (dirent64_t *) 658 (((char *) &cur_buf->sf_entries[0]) + 659 (uiop->uio_loffset - offset)); 660 if (dirent->d_reclen > uiop->uio_resid) 661 break; 662 663 if (strcmp(dirent->d_name, ".") == 0) { 636 664 node = dir; 637 } else if (strcmp( names[index], "..") == 0) {665 } else if (strcmp(dirent->d_name, "..") == 0) { 638 666 node = dir->sf_parent; 639 667 if (node == NULL) 640 668 node = dir; 641 669 } else { 642 node = sfnode_lookup(dir, names[index], VNON);670 node = sfnode_lookup(dir, dirent->d_name, VNON); 643 671 if (node == NULL) 644 672 panic("sffs_readdir() lookup failed"); 645 673 } 646 namelen = strlen(names[index]);647 strcpy(&dirent->d_name[0], names[index]);648 dirent->d_reclen = DIRENT64_RECLEN(namelen);649 dirent->d_off = index;650 674 dirent->d_ino = node->sf_ino; 651 if (dirent->d_reclen > uiop->uio_resid) { 652 error = ENOSPC; 653 break; 654 } 675 655 676 error = uiomove(dirent, dirent->d_reclen, UIO_READ, uiop); 656 677 if (error != 0) 657 678 break; 658 bzero(&dirent->d_name[0], namelen); 659 } 660 if (error == 0 && index >= nents) 679 } 680 if (error == 0 && cur_buf == NULL) 661 681 *eofp = 1; 662 682 done: 663 683 mutex_exit(&sffs_lock); 664 if (prov_buff != NULL)665 kmem_free(prov_buff, prov_buff_size);666 kmem_free(dirent, DIRENT64_RECLEN(MAXNAMELEN));667 684 return (error); 668 685 } … … 1188 1205 } 1189 1206 1207 if (node->sf_parent) 1208 sfnode_clear_dir_list(node->sf_parent); 1209 1190 1210 mutex_exit(&sffs_lock); 1191 1211 if (node == NULL) … … 1250 1270 } 1251 1271 1272 if (node->sf_parent) 1273 sfnode_clear_dir_list(node->sf_parent); 1274 1252 1275 mutex_exit(&sffs_lock); 1253 1276 if (node == NULL) … … 1328 1351 if (error == ENOENT || error == 0) 1329 1352 sfnode_make_stale(node); 1353 1354 if (node->sf_parent) 1355 sfnode_clear_dir_list(node->sf_parent); 1330 1356 done: 1331 1357 mutex_exit(&sffs_lock); … … 1387 1413 if (error == ENOENT || error == 0) 1388 1414 sfnode_make_stale(node); 1415 1416 if (node->sf_parent) 1417 sfnode_clear_dir_list(node->sf_parent); 1389 1418 done: 1390 1419 mutex_exit(&sffs_lock); … … 1523 1552 1524 1553 /* 1554 * Free the directory entries for the node. This should normally 1555 * have been taken care of in sffs_close(), but better safe than 1556 * sorry. 1557 */ 1558 sfnode_clear_dir_list(node); 1559 1560 /* 1525 1561 * If the node is stale, we can also destroy it. 1526 1562 */ … … 1555 1591 caller_context_t *ct) 1556 1592 { 1593 sfnode_t *node; 1594 1595 mutex_enter(&sffs_lock); 1596 node = VN2SFN(vp); 1597 1598 /* 1599 * Free the directory entries for the node. We do this on this call 1600 * here because the directory node may not become inactive for a long 1601 * time after the readdir is over. Case in point, if somebody cd's into 1602 * the directory then it won't become inactive until they cd away again. 1603 * In such a case we would end up with the directory listing not getting 1604 * updated (i.e. the result of 'ls' always being the same) until they 1605 * change the working directory. 1606 */ 1607 sfnode_clear_dir_list(node); 1608 1609 mutex_exit(&sffs_lock); 1557 1610 return (0); 1558 1611 } … … 1716 1769 } 1717 1770 } 1718 done:1719 1771 mutex_exit(&sffs_lock); 1720 1772 return (0); -
trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.h
r28800 r30446 48 48 uint8_t sf_type; /* VDIR or VREG */ 49 49 uint8_t sf_is_stale; /* this is stale and should be purged */ 50 sffs_dirents_t *sf_dir_list; /* list of entries for this directory */ 50 51 } sfnode_t; 51 52
Note:
See TracChangeset
for help on using the changeset viewer.