Ejemplo n.º 1
0
/*
 * Generic synctask interface for channel program syncfuncs.
 *
 * To perform some action in syncing context, we'd generally call
 * dsl_sync_task(), but since the Lua script is already running inside a
 * synctask we need to leave out some actions (such as acquiring the config
 * rwlock and performing space checks).
 *
 * If 'sync' is false, executes a dry run and returns the error code.
 *
 * If we are not running in syncing context and we are not doing a dry run
 * (meaning we are running a zfs.sync function in open-context) then we
 * return a Lua error.
 *
 * This function also handles common fatal error cases for channel program
 * library functions. If a fatal error occurs, err_dsname will be the dataset
 * name reported in error messages, if supplied.
 */
static int
zcp_sync_task(lua_State *state, dsl_checkfunc_t *checkfunc,
    dsl_syncfunc_t *syncfunc, void *arg, boolean_t sync, const char *err_dsname)
{
	int err;
	zcp_run_info_t *ri = zcp_run_info(state);

	err = checkfunc(arg, ri->zri_tx);
	if (!sync)
		return (err);

	if (!ri->zri_sync) {
		return (luaL_error(state, "running functions from the zfs.sync "
		    "submodule requires passing sync=TRUE to "
		    "lzc_channel_program() (i.e. do not specify the \"-n\" "
		    "command line argument)"));
	}

	if (err == 0) {
		syncfunc(arg, ri->zri_tx);
	} else if (err == EIO) {
		if (err_dsname != NULL) {
			return (luaL_error(state,
			    "I/O error while accessing dataset '%s'",
			    err_dsname));
		} else {
			return (luaL_error(state,
			    "I/O error while accessing dataset."));
		}
	}

	return (err);
}
Ejemplo n.º 2
0
/*
 * retrieves "cookie" in "value"
 * returns 0 if OK
 *         1 if no cookie at all
 *         2 if no cookie by the name "cookie" found
 *         3 if cookie value contains unwanted characters
 */
int flateGetCookie(char *value, int valuesz, char *cookie, int (*checkfunc)(int c)) {
    char *ptr;
    char buf[MAXCOOKIESIZE + 1];
    int sz;
    
    
    ptr = getenv("HTTP_COOKIE");
    if (!ptr) {
        value[0] = '\0';
        return(1);
    }
    
    while (*ptr != '\0') {
        while (isspace(*ptr) || *ptr == ';')
            ptr++;
        sz = 0;
        while (sz < MAXCOOKIESIZE && ptr[sz] != '\0' && !isspace(ptr[sz]) && ptr[sz] != ';' && ptr[sz] != '=') {
            buf[sz] = ptr[sz];
            sz++;
        }
        buf[sz] = '\0';
        
        if (stricmp(buf, cookie)) { /* according to RFC 2965, cookie names are case insensitive */
            ptr += sz;
            while (*ptr != '\0' && *ptr != ';')
                ptr++;
            continue;
        }
        
        ptr += sz;
        while (isspace(*ptr))
            ptr++;
        
        if (*ptr != '=') {
            while (*ptr != '\0' && *ptr != ';')
                ptr++;
            continue;
        }
        ptr++;
        while (isspace(*ptr))
            ptr++;
        
        sz = 0;
        while (sz < valuesz && ptr[sz] != '\0' && !isspace(ptr[sz]) && ptr[sz] != ';') {
            if (checkfunc && !checkfunc(ptr[sz])) { /* check for unwanted characaters */
                value[0] = '\0';
                return(3);
            }
            value[sz] = ptr[sz];
            sz++;
        }
        value[sz] = '\0';
        
        return(0);
    }
    return(2);    
}
Ejemplo n.º 3
0
int _waitfor( __const char *path, int delay_ms, int poll_ms, int (*checkfunc)(__const char *, void *), void *handle )
{
	int					notify_id = -1;
    struct sigevent     event;
    int                 chid = -1, coid = -1;
    struct _pulse       pulse;
	int					ret_val = -1;
	uint64_t			polltimeout = 100 * (uint64_t)1000000;
	uint64_t			timeout_nsec;

	timeout_nsec = _syspage_time(CLOCK_MONOTONIC);
	timeout_nsec += delay_ms * (uint64_t)1000000;

    /* Check to make sure we don't wait for something already there... */
    ret_val = checkfunc( path, handle );
	if ( ret_val >= 0 || ret_val == WAITFOR_CHECK_ABORT ) {
		return ret_val;
    }

	if ( poll_ms > 0 ) {
		polltimeout = poll_ms * (uint64_t)1000000;
	}

	/* 
	 * We make the channel fixed since we want to remain at the current
	 * thread's priority
	 */
    chid = ChannelCreate(_NTO_CHF_FIXED_PRIORITY);
	if ( chid == -1 ) {
		goto fail1;
	}
    coid = ConnectAttach( ND_LOCAL_NODE, 0, chid, _NTO_SIDE_CHANNEL, 0 );
	if ( coid == -1 ) {
		goto fail2;
	}

    SIGEV_PULSE_INIT( &event, coid, SIGEV_PULSE_PRIO_INHERIT, PULSE_CODE_PATHSPACE, 0 );
    notify_id = procmgr_event_notify_add( PROCMGR_EVENT_PATHSPACE, &event );
	if ( notify_id == -1 ) {
		goto fail3;
	}

    while(_syspage_time(CLOCK_MONOTONIC) < timeout_nsec) {

		/* we need to poll in case we are checking for a subdirectory/file,
		 * since we won't get a pathmgr event for those.
		 */
		SIGEV_UNBLOCK_INIT(&event);
		if ( TimerTimeout( CLOCK_MONOTONIC, _NTO_TIMEOUT_RECEIVE, &event, &polltimeout, NULL) == -1 ) {
			ret_val = -1;
			break;
		}
	   	if ( MsgReceivePulse( chid, &pulse, sizeof(pulse), NULL ) != -1 || errno == ETIMEDOUT ) {
			ret_val = checkfunc( path, handle );
			if ( ret_val >= 0 || ret_val == WAITFOR_CHECK_ABORT ) {
				break;
            }
		} else {
			break;
		}
    }

	(void)procmgr_event_notify_delete( notify_id );
fail3:
	(void)ConnectDetach(coid);
fail2:
	(void)ChannelDestroy(chid);
fail1:
    return ret_val;
}