+ int error;
+ int my_size, copy_size;
+
+ if (is_64_bit) {
+ struct user_statfs sfs;
+ my_size = copy_size = sizeof(sfs);
+ bzero(&sfs, my_size);
+ sfs.f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ sfs.f_type = mp->mnt_vtable->vfc_typenum;
+ sfs.f_reserved1 = (short)sfsp->f_fssubtype;
+ sfs.f_bsize = (user_long_t)sfsp->f_bsize;
+ sfs.f_iosize = (user_long_t)sfsp->f_iosize;
+ sfs.f_blocks = (user_long_t)sfsp->f_blocks;
+ sfs.f_bfree = (user_long_t)sfsp->f_bfree;
+ sfs.f_bavail = (user_long_t)sfsp->f_bavail;
+ sfs.f_files = (user_long_t)sfsp->f_files;
+ sfs.f_ffree = (user_long_t)sfsp->f_ffree;
+ sfs.f_fsid = sfsp->f_fsid;
+ sfs.f_owner = sfsp->f_owner;
+ strncpy(&sfs.f_fstypename[0], &sfsp->f_fstypename[0], MFSNAMELEN-1);
+ strncpy(&sfs.f_mntonname[0], &sfsp->f_mntonname[0], MNAMELEN-1);
+ strncpy(&sfs.f_mntfromname[0], &sfsp->f_mntfromname[0], MNAMELEN-1);
+
+ if (partial_copy) {
+ copy_size -= (sizeof(sfs.f_reserved3) + sizeof(sfs.f_reserved4));
+ }
+ error = copyout((caddr_t)&sfs, bufp, copy_size);
+ }
+ else {
+ struct statfs sfs;
+ my_size = copy_size = sizeof(sfs);
+ bzero(&sfs, my_size);
+
+ sfs.f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ sfs.f_type = mp->mnt_vtable->vfc_typenum;
+ sfs.f_reserved1 = (short)sfsp->f_fssubtype;
+
+ /*
+ * It's possible for there to be more than 2^^31 blocks in the filesystem, so we
+ * have to fudge the numbers here in that case. We inflate the blocksize in order
+ * to reflect the filesystem size as best we can.
+ */
+ if ((sfsp->f_blocks > LONG_MAX)
+ /* Hack for 4061702 . I think the real fix is for Carbon to
+ * look for some volume capability and not depend on hidden
+ * semantics agreed between a FS and carbon.
+ * f_blocks, f_bfree, and f_bavail set to -1 is the trigger
+ * for Carbon to set bNoVolumeSizes volume attribute.
+ * Without this the webdavfs files cannot be copied onto
+ * disk as they look huge. This change should not affect
+ * XSAN as they should not setting these to -1..
+ */
+ && (sfsp->f_blocks != 0xffffffffffffffff)
+ && (sfsp->f_bfree != 0xffffffffffffffff)
+ && (sfsp->f_bavail != 0xffffffffffffffff)) {
+ int shift;
+
+ /*
+ * Work out how far we have to shift the block count down to make it fit.
+ * Note that it's possible to have to shift so far that the resulting
+ * blocksize would be unreportably large. At that point, we will clip
+ * any values that don't fit.
+ *
+ * For safety's sake, we also ensure that f_iosize is never reported as
+ * being smaller than f_bsize.
+ */
+ for (shift = 0; shift < 32; shift++) {
+ if ((sfsp->f_blocks >> shift) <= LONG_MAX)
+ break;
+ if ((sfsp->f_bsize << (shift + 1)) > LONG_MAX)
+ break;
+ }
+#define __SHIFT_OR_CLIP(x, s) ((((x) >> (s)) > LONG_MAX) ? LONG_MAX : ((x) >> (s)))
+ sfs.f_blocks = (long)__SHIFT_OR_CLIP(sfsp->f_blocks, shift);
+ sfs.f_bfree = (long)__SHIFT_OR_CLIP(sfsp->f_bfree, shift);
+ sfs.f_bavail = (long)__SHIFT_OR_CLIP(sfsp->f_bavail, shift);
+#undef __SHIFT_OR_CLIP
+ sfs.f_bsize = (long)(sfsp->f_bsize << shift);
+ sfs.f_iosize = lmax(sfsp->f_iosize, sfsp->f_bsize);
+ } else {
+ /* filesystem is small enough to be reported honestly */
+ sfs.f_bsize = (long)sfsp->f_bsize;
+ sfs.f_iosize = (long)sfsp->f_iosize;
+ sfs.f_blocks = (long)sfsp->f_blocks;
+ sfs.f_bfree = (long)sfsp->f_bfree;
+ sfs.f_bavail = (long)sfsp->f_bavail;
+ }
+ sfs.f_files = (long)sfsp->f_files;
+ sfs.f_ffree = (long)sfsp->f_ffree;
+ sfs.f_fsid = sfsp->f_fsid;
+ sfs.f_owner = sfsp->f_owner;
+ strncpy(&sfs.f_fstypename[0], &sfsp->f_fstypename[0], MFSNAMELEN-1);
+ strncpy(&sfs.f_mntonname[0], &sfsp->f_mntonname[0], MNAMELEN-1);
+ strncpy(&sfs.f_mntfromname[0], &sfsp->f_mntfromname[0], MNAMELEN-1);
+
+ if (partial_copy) {
+ copy_size -= (sizeof(sfs.f_reserved3) + sizeof(sfs.f_reserved4));
+ }
+ error = copyout((caddr_t)&sfs, bufp, copy_size);
+ }