]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfs_readwrite.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / bsd / hfs / hfs_readwrite.c
index 91cf8b7f773ec225468503d644661b04579c6a1c..c3a2de87b30351d935fb66ce0fb730363a47f106 100644 (file)
@@ -865,6 +865,18 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
 
        switch (ap->a_command) {
 
+       case HFS_RESIZE_PROGRESS: {
+
+               vfsp = vfs_statfs(HFSTOVFS(hfsmp));
+               if (suser(cred, NULL) &&
+                       kauth_cred_getuid(cred) != vfsp->f_owner) {
+                       return (EACCES); /* must be owner of file system */
+               }
+               if (!vnode_isvroot(vp)) {
+                       return (EINVAL);
+               }
+               return hfs_resize_progress(hfsmp, (u_int32_t *)ap->a_data);
+       }
        case HFS_RESIZE_VOLUME: {
                u_int64_t newsize;
                u_int64_t cursize;
@@ -1076,7 +1088,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
                dev_t dev = VTOC(vp)->c_dev;
                
                short flags;
-               struct ucred myucred;   /* XXX ILLEGAL */
+               struct ucred myucred;
                int num_files;
                int *file_ids = NULL;
                short *access = NULL;
@@ -1090,6 +1102,9 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
                struct cnode *skip_cp = VTOC(vp);
                struct vfs_context      my_context;
 
+               /* set up front for common exit code */
+               my_context.vc_ucred = NOCRED;
+
                /* first, return error if not run as root */
                if (cred->cr_ruid != 0) {
                        return EPERM;
@@ -1160,6 +1175,12 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
                        check_leaf = false;
                }
                
+               /*
+                * Create a templated credential; this credential may *NOT*
+                * be used unless instantiated with a kauth_cred_create();
+                * there must be a correcponding kauth_cred_unref() when it
+                * is no longer in use (i.e. before it goes out of scope).
+                */
                memset(&myucred, 0, sizeof(myucred));
                myucred.cr_ref = 1;
                myucred.cr_uid = myucred.cr_ruid = myucred.cr_svuid = user_access_structp->uid;
@@ -1174,7 +1195,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
                myucred.cr_gmuid = myucred.cr_uid;
                
                my_context.vc_proc = p;
-               my_context.vc_ucred = &myucred;
+               my_context.vc_ucred = kauth_cred_create(&myucred);
 
                /* Check access to each file_id passed in */
                for (i = 0; i < num_files; i++) {
@@ -1182,7 +1203,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
                        cnid = (cnid_t) file_ids[i];
                        
                        /* root always has access */
-                       if (!suser(&myucred, NULL)) {
+                       if (!suser(my_context.vc_ucred, NULL)) {
                                access[i] = 0;
                                continue;
                        }
@@ -1198,7 +1219,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
                                                        
                                /* before calling CheckAccess(), check the target file for read access */
                                myPerms = DerivePermissionSummary(cnattr.ca_uid, cnattr.ca_gid,
-                                                                 cnattr.ca_mode, hfsmp->hfs_mp, &myucred, p  );
+                                                                 cnattr.ca_mode, hfsmp->hfs_mp, my_context.vc_ucred, p  );
                                
                                
                                /* fail fast if no access */ 
@@ -1219,7 +1240,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
                        }
                        
                        myaccess = do_access_check(hfsmp, &error, &cache, catkey.hfsPlus.parentID, 
-                                                  skip_cp, p, &myucred, dev);
+                                                  skip_cp, p, my_context.vc_ucred, dev);
                        
                        if ( myaccess ) {
                                access[i] = 0; // have access.. no errors to report
@@ -1245,6 +1266,12 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
 
                            hfs_unlock(VTOC(vp));
                            if (vnode_vtype(vp) == VDIR) {
+                               /*
+                                * XXX This code assumes that none of the
+                                * XXX callbacks from vnode_authorize() will
+                                * XXX take a persistent ref on the context
+                                * XXX credential, which is a bad assumption.
+                                */
                                myErr = vnode_authorize(vp, NULL, (KAUTH_VNODE_SEARCH | KAUTH_VNODE_LIST_DIRECTORY), &my_context);
                            } else {
                                myErr = vnode_authorize(vp, NULL, KAUTH_VNODE_READ_DATA, &my_context);
@@ -1272,6 +1299,9 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
                release_pathbuff((char *) cache.haveaccess);
                release_pathbuff((char *) file_ids);
                release_pathbuff((char *) access);
+               /* clean up local context, if needed */
+               if (IS_VALID_CRED(my_context.vc_ucred))
+                       kauth_cred_unref(&my_context.vc_ucred);
                
                return (error);
        } /* HFS_BULKACCESS */
@@ -2157,7 +2187,7 @@ hfs_truncate(struct vnode *vp, off_t length, int flags, int skipsetsize,
 
        if (length < filebytes) {
                while (filebytes > length) {
-                       if ((filebytes - length) > HFS_BIGFILE_SIZE) {
+                       if ((filebytes - length) > HFS_BIGFILE_SIZE && overflow_extents(fp)) {
                                filebytes -= HFS_BIGFILE_SIZE;
                        } else {
                                filebytes = length;
@@ -2169,7 +2199,7 @@ hfs_truncate(struct vnode *vp, off_t length, int flags, int skipsetsize,
                }
        } else if (length > filebytes) {
                while (filebytes < length) {
-                       if ((length - filebytes) > HFS_BIGFILE_SIZE) {
+                       if ((length - filebytes) > HFS_BIGFILE_SIZE && overflow_extents(fp)) {
                                filebytes += HFS_BIGFILE_SIZE;
                        } else {
                                filebytes = length;
@@ -2566,7 +2596,8 @@ hfs_vnop_bwrite(struct vnop_bwrite_args *ap)
        /* Trap B-Tree writes */
        if ((VTOC(vp)->c_fileid == kHFSExtentsFileID) ||
            (VTOC(vp)->c_fileid == kHFSCatalogFileID) ||
-           (VTOC(vp)->c_fileid == kHFSAttributesFileID)) {
+           (VTOC(vp)->c_fileid == kHFSAttributesFileID) ||
+           (vp == VTOHFS(vp)->hfc_filevp)) {
 
                /* 
                 * Swap and validate the node if it is in native byte order.
@@ -2835,10 +2866,10 @@ out:
                lockflags = 0;
        }
 
-       // See comment up above about calls to hfs_fsync()
-       //
-       //if (retval == 0)
-       //      retval = hfs_fsync(vp, MNT_WAIT, 0, p);
+       /* Push cnode's new extent data to disk. */
+       if (retval == 0) {
+               (void) hfs_update(vp, MNT_WAIT);
+       }
 
        if (hfsmp->jnl) {
                if (cp->c_cnid < kHFSFirstUserCatalogNodeID)
@@ -2932,7 +2963,7 @@ hfs_clonefile(struct vnode *vp, int blkstart, int blkcnt, int blksize)
        filesize = VTOF(vp)->ff_blocks * blksize;  /* virtual file size */
        writebase = blkstart * blksize;
        copysize = blkcnt * blksize;
-       iosize = bufsize = MIN(copysize, 4096 * 16);
+       iosize = bufsize = MIN(copysize, 128 * 1024);
        offset = 0;
 
        if (kmem_alloc(kernel_map, (vm_offset_t *)&bufp, bufsize)) {