FREE_ZONE((x), MAXPATHLEN, M_NAMEI);
#endif /* CONFIG_FSE */
+#ifndef HFS_GET_BOOT_INFO
+#define HFS_GET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00004)
+#endif
+
+#ifndef HFS_SET_BOOT_INFO
+#define HFS_SET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00005)
+#endif
+
+#ifndef APFSIOC_REVERT_TO_SNAPSHOT
+#define APFSIOC_REVERT_TO_SNAPSHOT _IOW('J', 1, u_int64_t)
+#endif
+
extern void disk_conditioner_unmount(mount_t mp);
/* struct for checkdirs iteration */
static int getutimes(user_addr_t usrtvp, struct timespec *tsp);
static int setutimes(vfs_context_t ctx, vnode_t vp, const struct timespec *ts, int nullflag);
static int sync_callback(mount_t, void *);
-static void sync_thread(void *, __unused wait_result_t);
-static int sync_async(int);
static int munge_statfs(struct mount *mp, struct vfsstatfs *sfsp,
user_addr_t bufp, int *sizep, boolean_t is_64_bit,
boolean_t partial_copy);
static int relocate_imageboot_source(vnode_t pvp, vnode_t vp, struct componentname *cnp, const char *fsname, vfs_context_t ctx, boolean_t is64bit, user_addr_t fsmountargs, boolean_t by_index);
#endif /* CONFIG_IMGSRC_ACCESS */
+//snapshot functions
+#if CONFIG_MNT_ROOTSNAP
+static int snapshot_root(int dirfd, user_addr_t name, uint32_t flags, vfs_context_t ctx);
+#else
+static int snapshot_root(int dirfd, user_addr_t name, uint32_t flags, vfs_context_t ctx) __attribute__((unused));
+#endif
+
int (*union_dircheckp)(struct vnode **, struct fileproc *, vfs_context_t);
__private_extern__
#endif
int print_vmpage_stat=0;
-int sync_timeout = 60; // Sync time limit (sec)
static int
sync_callback(mount_t mp, __unused void *arg)
return 0;
}
+typedef enum {
+ SYNC_ALL = 0,
+ SYNC_ONLY_RELIABLE_MEDIA = 1,
+ SYNC_ONLY_UNRELIABLE_MEDIA = 2
+} sync_type_t;
+
+static int
+sync_internal_callback(mount_t mp, void *arg)
+{
+ if (arg) {
+ int is_reliable = !(mp->mnt_kern_flag & MNTK_VIRTUALDEV) &&
+ (mp->mnt_flag & MNT_LOCAL);
+ sync_type_t sync_type = *((sync_type_t *)arg);
+
+ if ((sync_type == SYNC_ONLY_RELIABLE_MEDIA) && !is_reliable)
+ return (VFS_RETURNED);
+ else if ((sync_type = SYNC_ONLY_UNRELIABLE_MEDIA) && is_reliable)
+ return (VFS_RETURNED);
+ }
+
+ (void)sync_callback(mp, NULL);
+
+ return (VFS_RETURNED);
+}
+
+int sync_thread_state = 0;
+int sync_timeout_seconds = 5;
+
+#define SYNC_THREAD_RUN 0x0001
+#define SYNC_THREAD_RUNNING 0x0002
+
static void
-sync_thread(void *arg, __unused wait_result_t wr)
+sync_thread(__unused void *arg, __unused wait_result_t wr)
{
- int *timeout = (int *) arg;
+ sync_type_t sync_type;
- vfs_iterate(LK_NOWAIT, sync_callback, NULL);
+ lck_mtx_lock(sync_mtx_lck);
+ while (sync_thread_state & SYNC_THREAD_RUN) {
+ sync_thread_state &= ~SYNC_THREAD_RUN;
+ lck_mtx_unlock(sync_mtx_lck);
+
+ sync_type = SYNC_ONLY_RELIABLE_MEDIA;
+ vfs_iterate(LK_NOWAIT, sync_internal_callback, &sync_type);
+ sync_type = SYNC_ONLY_UNRELIABLE_MEDIA;
+ vfs_iterate(LK_NOWAIT, sync_internal_callback, &sync_type);
+
+ lck_mtx_lock(sync_mtx_lck);
+ }
+ /*
+ * This wakeup _has_ to be issued before the lock is released otherwise
+ * we may end up waking up a thread in sync_internal which is
+ * expecting a wakeup from a thread it just created and not from this
+ * thread which is about to exit.
+ */
+ wakeup(&sync_thread_state);
+ sync_thread_state &= ~SYNC_THREAD_RUNNING;
+ lck_mtx_unlock(sync_mtx_lck);
- if (timeout)
- wakeup((caddr_t) timeout);
if (print_vmpage_stat) {
vm_countdirtypages();
}
#endif /* DIAGNOSTIC */
}
+struct timeval sync_timeout_last_print = {0, 0};
+
/*
- * Sync in a separate thread so we can time out if it blocks.
+ * An in-kernel sync for power management to call.
+ * This function always returns within sync_timeout seconds.
*/
-static int
-sync_async(int timeout)
+__private_extern__ int
+sync_internal(void)
{
thread_t thd;
int error;
- struct timespec ts = {timeout, 0};
+ int thread_created = FALSE;
+ struct timespec ts = {sync_timeout_seconds, 0};
lck_mtx_lock(sync_mtx_lck);
- if (kernel_thread_start(sync_thread, &timeout, &thd) != KERN_SUCCESS) {
- printf("sync_thread failed\n");
- lck_mtx_unlock(sync_mtx_lck);
- return (0);
+ sync_thread_state |= SYNC_THREAD_RUN;
+ if (!(sync_thread_state & SYNC_THREAD_RUNNING)) {
+ int kr;
+
+ sync_thread_state |= SYNC_THREAD_RUNNING;
+ kr = kernel_thread_start(sync_thread, NULL, &thd);
+ if (kr != KERN_SUCCESS) {
+ sync_thread_state &= ~SYNC_THREAD_RUNNING;
+ lck_mtx_unlock(sync_mtx_lck);
+ printf("sync_thread failed\n");
+ return (0);
+ }
+ thread_created = TRUE;
}
- error = msleep((caddr_t) &timeout, sync_mtx_lck, (PVFS | PDROP | PCATCH), "sync_thread", &ts);
+ error = msleep((caddr_t)&sync_thread_state, sync_mtx_lck,
+ (PVFS | PDROP | PCATCH), "sync_thread", &ts);
if (error) {
- printf("sync timed out: %d sec\n", timeout);
- }
- thread_deallocate(thd);
+ struct timeval now;
- return (0);
-}
+ microtime(&now);
+ if (now.tv_sec - sync_timeout_last_print.tv_sec > 120) {
+ printf("sync timed out: %d sec\n", sync_timeout_seconds);
+ sync_timeout_last_print.tv_sec = now.tv_sec;
+ }
+ }
-/*
- * An in-kernel sync for power management to call.
- */
-__private_extern__ int
-sync_internal(void)
-{
- (void) sync_async(sync_timeout);
+ if (thread_created)
+ thread_deallocate(thd);
- return 0;
+ return (0);
} /* end of sync_internal call */
/*
quotactl(proc_t p, struct quotactl_args *uap, __unused int32_t *retval)
{
struct mount *mp;
- int error, quota_cmd, quota_status;
+ int error, quota_cmd, quota_status = 0;
caddr_t datap;
size_t fnamelen;
struct nameidata nd;
vfs_context_t ctx = vfs_context_current();
- struct dqblk my_dqblk;
+ struct dqblk my_dqblk = {};
AUDIT_ARG(uid, uap->uid);
AUDIT_ARG(cmd, uap->cmd);
strlen(vp->v_name)) ||
!strncmp(vp->v_name,
"mediaserverd",
+ strlen(vp->v_name)) ||
+ !strncmp(vp->v_name,
+ "SpringBoard",
+ strlen(vp->v_name)) ||
+ !strncmp(vp->v_name,
+ "backboardd",
strlen(vp->v_name))) {
/*
* This file matters when launching Camera:
error = ENOMEM;
goto out;
}
- MALLOC(result, errno_t *, desc_actual * sizeof(errno_t), M_TEMP, M_WAITOK);
+ MALLOC(result, errno_t *, desc_actual * sizeof(errno_t), M_TEMP, M_WAITOK | M_ZERO);
if (result == NULL) {
error = ENOMEM;
goto out;
union {
struct stat sb;
struct stat64 sb64;
- } source;
+ } source = {};
union {
struct user64_stat user64_sb;
struct user32_stat user32_sb;
struct user64_stat64 user64_sb64;
struct user32_stat64 user32_sb64;
- } dest;
+ } dest = {};
caddr_t sbp;
int error, my_size;
kauth_filesec_t fsec;
}
batched = vnode_compound_rename_available(fdvp);
+
+#if CONFIG_FSE
+ need_event = need_fsevent(FSE_RENAME, fdvp);
+ if (need_event) {
+ if (fvp) {
+ get_fse_info(fvp, &from_finfo, ctx);
+ } else {
+ error = vfs_get_notify_attributes(&__rename_data->fv_attr);
+ if (error) {
+ goto out1;
+ }
+
+ fvap = &__rename_data->fv_attr;
+ }
+
+ if (tvp) {
+ get_fse_info(tvp, &to_finfo, ctx);
+ } else if (batched) {
+ error = vfs_get_notify_attributes(&__rename_data->tv_attr);
+ if (error) {
+ goto out1;
+ }
+
+ tvap = &__rename_data->tv_attr;
+ }
+ }
+#else
+ need_event = 0;
+#endif /* CONFIG_FSE */
+
+ if (need_event || kauth_authorize_fileop_has_listeners()) {
+ if (from_name == NULL) {
+ GET_PATH(from_name);
+ if (from_name == NULL) {
+ error = ENOMEM;
+ goto out1;
+ }
+ }
+
+ from_len = safe_getpath(fdvp, fromnd->ni_cnd.cn_nameptr, from_name, MAXPATHLEN, &from_truncated);
+
+ if (to_name == NULL) {
+ GET_PATH(to_name);
+ if (to_name == NULL) {
+ error = ENOMEM;
+ goto out1;
+ }
+ }
+
+ to_len = safe_getpath(tdvp, tond->ni_cnd.cn_nameptr, to_name, MAXPATHLEN, &to_truncated);
+ }
if (!fvp) {
/*
* Claim: this check will never reject a valid rename.
}
if (!batched) {
- error = vn_authorize_renamex(fdvp, fvp, &fromnd->ni_cnd, tdvp, tvp, &tond->ni_cnd, ctx, flags, NULL);
+ error = vn_authorize_renamex_with_paths(fdvp, fvp, &fromnd->ni_cnd, from_name, tdvp, tvp, &tond->ni_cnd, to_name, ctx, flags, NULL);
if (error) {
if (error == ENOENT) {
assert(retry_count < MAX_AUTHORIZE_ENOENT_RETRIES);
oparent = fvp->v_parent;
skipped_lookup:
-#if CONFIG_FSE
- need_event = need_fsevent(FSE_RENAME, fdvp);
- if (need_event) {
- if (fvp) {
- get_fse_info(fvp, &from_finfo, ctx);
- } else {
- error = vfs_get_notify_attributes(&__rename_data->fv_attr);
- if (error) {
- goto out1;
- }
-
- fvap = &__rename_data->fv_attr;
- }
-
- if (tvp) {
- get_fse_info(tvp, &to_finfo, ctx);
- } else if (batched) {
- error = vfs_get_notify_attributes(&__rename_data->tv_attr);
- if (error) {
- goto out1;
- }
-
- tvap = &__rename_data->tv_attr;
- }
- }
-#else
- need_event = 0;
-#endif /* CONFIG_FSE */
-
- if (need_event || kauth_authorize_fileop_has_listeners()) {
- if (from_name == NULL) {
- GET_PATH(from_name);
- if (from_name == NULL) {
- error = ENOMEM;
- goto out1;
- }
- }
-
- from_len = safe_getpath(fdvp, fromnd->ni_cnd.cn_nameptr, from_name, MAXPATHLEN, &from_truncated);
-
- if (to_name == NULL) {
- GET_PATH(to_name);
- if (to_name == NULL) {
- error = ENOMEM;
- goto out1;
- }
- }
-
- to_len = safe_getpath(tdvp, tond->ni_cnd.cn_nameptr, to_name, MAXPATHLEN, &to_truncated);
- }
error = vn_rename(fdvp, &fvp, &fromnd->ni_cnd, fvap,
tdvp, &tvp, &tond->ni_cnd, tvap,
flags, ctx);
struct fileproc *fp;
uio_t auio = NULL;
int spacetype = proc_is64bit(p) ? UIO_USERSPACE64 : UIO_USERSPACE32;
- uint32_t count, savecount;
- uint32_t newstate;
+ uint32_t count = 0, savecount = 0;
+ uint32_t newstate = 0;
int error, eofflag;
- uint32_t loff;
+ uint32_t loff = 0;
struct attrlist attributelist;
vfs_context_t ctx = vfs_context_current();
int fd = uap->fd;
break;
default: {
+ /* other, known commands shouldn't be passed down here */
+ switch (cmd) {
+ case F_PUNCHHOLE:
+ case F_TRIM_ACTIVE_FILE:
+ case F_RDADVISE:
+ case F_TRANSCODEKEY:
+ case F_GETPROTECTIONLEVEL:
+ case F_GETDEFAULTPROTLEVEL:
+ case F_MAKECOMPRESSED:
+ case F_SET_GREEDY_MODE:
+ case F_SETSTATICCONTENT:
+ case F_SETIOTYPE:
+ case F_SETBACKINGSTORE:
+ case F_GETPATH_MTMINFO:
+ case APFSIOC_REVERT_TO_SNAPSHOT:
+ case FSIOC_FIOSEEKHOLE:
+ case FSIOC_FIOSEEKDATA:
+ case HFS_GET_BOOT_INFO:
+ case HFS_SET_BOOT_INFO:
+ case FIOPINSWAP:
+ case F_CHKCLEAN:
+ case F_FULLFSYNC:
+ case F_BARRIERFSYNC:
+ case F_FREEZE_FS:
+ case F_THAW_FS:
+ error = EINVAL;
+ goto outdrop;
+ }
/* Invoke the filesystem-specific code */
error = VNOP_IOCTL(vp, cmd, data, options, ctx);
}
if (error == 0 && (cmd & IOC_OUT) && size)
error = copyout(data, udata, size);
+outdrop:
if (memp) {
kfree(memp, size);
}
vp = nd.ni_vp;
nameidone(&nd);
- if ((error = copyinstr(uap->attrname, attrname, sizeof(attrname), &namelen) != 0)) {
+ error = copyinstr(uap->attrname, attrname, sizeof(attrname), &namelen);
+ if (error != 0) {
goto out;
}
if (xattr_protected(attrname)) {
file_drop(uap->fd);
return(error);
}
- if ((error = copyinstr(uap->attrname, attrname, sizeof(attrname), &namelen) != 0)) {
+ error = copyinstr(uap->attrname, attrname, sizeof(attrname), &namelen);
+ if (error != 0) {
goto out;
}
if (xattr_protected(attrname)) {
if (uap->options & (XATTR_NOSECURITY | XATTR_NODEFAULT))
return (EINVAL);
- if ((error = copyinstr(uap->attrname, attrname, sizeof(attrname), &namelen) != 0)) {
+ error = copyinstr(uap->attrname, attrname, sizeof(attrname), &namelen);
+ if (error != 0) {
if (error == EPERM) {
/* if the string won't fit in attrname, copyinstr emits EPERM */
return (ENAMETOOLONG);
if (uap->options & (XATTR_NOFOLLOW | XATTR_NOSECURITY | XATTR_NODEFAULT))
return (EINVAL);
- if ((error = copyinstr(uap->attrname, attrname, sizeof(attrname), &namelen) != 0)) {
+ error = copyinstr(uap->attrname, attrname, sizeof(attrname), &namelen);
+ if (error != 0) {
if (error == EPERM) {
/* if the string won't fit in attrname, copyinstr emits EPERM */
return (ENAMETOOLONG);
if (kdebug_enable) {
long dbg_parms[NUMPARMS];
- int dbg_namelen;
+ int dbg_namelen;
- dbg_namelen = (int)sizeof(dbg_parms);
+ dbg_namelen = (int)sizeof(dbg_parms);
if (length < dbg_namelen) {
memcpy((char *)dbg_parms, buf, length);
memcpy((char *)dbg_parms, buf + (length - dbg_namelen), dbg_namelen);
}
- kdebug_lookup_gen_events(dbg_parms, dbg_namelen, (void *)vp, TRUE);
+ kdebug_vfs_lookup(dbg_parms, dbg_namelen, (void *)vp,
+ KDBG_VFS_LOOKUP_FLAG_LOOKUP);
}
*pathlen = (user_ssize_t)length; /* may be superseded by error */
if (uap->bufsize > PAGE_SIZE) {
return (EINVAL);
}
- MALLOC(realpath, char *, uap->bufsize, M_TEMP, M_WAITOK);
+ MALLOC(realpath, char *, uap->bufsize, M_TEMP, M_WAITOK | M_ZERO);
if (realpath == NULL) {
return (ENOMEM);
}
}
-#ifndef APFSIOC_REVERT_TO_SNAPSHOT
-#define APFSIOC_REVERT_TO_SNAPSHOT _IOW('J', 1, u_int64_t)
-#endif
-
error = VNOP_IOCTL(namend.ni_vp, APFSIOC_REVERT_TO_SNAPSHOT, (caddr_t) NULL,
0, ctx);
case SNAPSHOT_OP_REVERT:
error = snapshot_revert(uap->dirfd, uap->name1, uap->flags, ctx);
break;
+#if CONFIG_MNT_ROOTSNAP
case SNAPSHOT_OP_ROOT:
error = snapshot_root(uap->dirfd, uap->name1, uap->flags, ctx);
break;
+#endif /* CONFIG_MNT_ROOTSNAP */
default:
error = ENOSYS;
}