Exemple #1
0
static void
check_modes(char *fname, int mode)
	{
	struct stat		st;
	struct group	*grp;
	struct passwd	*pwd;
	char			ch_cmd[200];

	if (stat(fname, &st) == 0)
		{
		grp = getgrgid(st.st_gid);
		pwd = getpwuid(st.st_uid);

		if (   strcmp(pwd->pw_name, pikrellcam.effective_user)
		    || strcmp(grp->gr_name, "www-data")
		   )
			{
			snprintf(ch_cmd, sizeof(ch_cmd), "sudo chown %s.www-data %s",
					pikrellcam.effective_user, fname);
			exec_wait(ch_cmd, NULL);
			}
		if ((st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != mode)
			{
			snprintf(ch_cmd, sizeof(ch_cmd), "sudo chmod %o %s", mode, fname);
			exec_wait(ch_cmd, NULL);
			}
		}
	}
Exemple #2
0
void
event_still_capture_cmd(char *cmd)
	{
	if (!cmd || !*cmd)
		return;

	exec_wait(cmd, NULL);
	}
Exemple #3
0
bool promote_dependencies(const std::string& snapshot, std::vector<std::string>& dependencies)
{
	zfs_elevate();
	
	std::cout << "Searching for origin " << snapshot << std::endl;
	
	std::string snap_data;
	int rc = exec_wait(find_zfs_cmd(), snap_data, "list", "-H", "-o", "name", NULL);
	if(rc!=0)
		return false;
	
	std::vector<std::string> snaps;
	Tokenize(snap_data, snaps, "\n");
		
	std::string snap_folder = ExtractFilePath(snapshot);
	for(size_t i=0;i<snaps.size();++i)
	{	
		if( !next(trim(snaps[i]), 0, snap_folder)
			|| trim(snaps[i]).size()<=snap_folder.size() )
			continue;
		
		std::string stdout;
		std::string subvolume_folder = snaps[i];
		int rc=exec_wait(find_zfs_cmd(), stdout, "get", "-H", "-o", "value", "origin", subvolume_folder.c_str(), NULL);
		if(rc==0)
		{
			stdout=trim(stdout);
			
			if(stdout==snapshot)
			{	
				std::cout << "Origin is " << subvolume_folder << std::endl;
				
				if(exec_wait(find_zfs_cmd(), true, "promote", subvolume_folder.c_str(), NULL)!=0)
				{
					return false;
				}
				
				dependencies.push_back(subvolume_folder);
			}
		}
	}
	
	return true;
}
Exemple #4
0
bool make_readonly(int mode, std::string subvolume_folder)
{
#ifdef _WIN32
	return false;
#else
	if(mode==mode_btrfs)
	{
		int rc=exec_wait(find_btrfs_cmd(), true, "property", "set", "-ts", subvolume_folder.c_str(), "ro", "true", NULL);
		return rc==0;
	}
	else if(mode==mode_zfs)
	{
		zfs_elevate();
		int rc=exec_wait(find_zfs_cmd(), true, "snapshot", (subvolume_folder+"@ro").c_str(), NULL);
		return rc==0;
	}
	return false;
#endif
}
Exemple #5
0
bool is_subvolume(int mode, std::string subvolume_folder)
{
#ifdef _WIN32
	return true;
#else
	if(mode==mode_btrfs)
	{
		int rc=exec_wait(find_btrfs_cmd(), false, "subvolume", "list", subvolume_folder.c_str(), NULL);
		return rc==0;
	}
	else if(mode==mode_zfs)
	{
		zfs_elevate();
		int rc=exec_wait(find_zfs_cmd(), false, "list", subvolume_folder.c_str(), NULL);
		return rc==0;
	}
	return false;
#endif
}
Exemple #6
0
  /* Useful for emailing a motion event preview jpeg.
  */
void
event_preview_save_cmd(char *cmd)
	{
	if (!cmd || !*cmd)
		return;

//	log_printf("event_preview_save_cmd(); running %s %s\n", cmd,
//					pikrellcam.preview_filename);
	exec_wait(cmd, pikrellcam.preview_filename);
	}
Exemple #7
0
  /* Generate a motion area thumb.
  */
void
event_motion_area_thumb(void)
	{
	char	*cmd = NULL;

	asprintf(&cmd, "%s/scripts-dist/_thumb $F $m $P $G $i $J $K $Y",
			pikrellcam.install_dir);
	exec_wait(cmd, pikrellcam.preview_filename);
	if (cmd)
		free(cmd);
	}
Exemple #8
0
void
log_lines(void)
	{
	char	buf[128];

	if (pikrellcam.log_lines > 0)
		{
		snprintf(buf, sizeof(buf), "%s/scripts-dist/_log-lines %d $G",
					pikrellcam.install_dir, pikrellcam.log_lines);
		exec_wait(buf, NULL); 
		}
	}
Exemple #9
0
bool create_snapshot(int mode, std::string snapshot_src, std::string snapshot_dst)
{
#ifdef _WIN32
	return CopyFolder(widen(snapshot_src), widen(snapshot_dst));
#else
	if(mode==mode_btrfs)
	{
		int rc=exec_wait(find_btrfs_cmd(), true, "subvolume", "snapshot", snapshot_src.c_str(), snapshot_dst.c_str(), NULL);
		chown_dir(snapshot_dst);
		return rc==0;
	}
	else if(mode==mode_zfs)
	{
		zfs_elevate();
		int rc=exec_wait(find_zfs_cmd(), true, "clone", (snapshot_src+"@ro").c_str(), snapshot_dst.c_str(), NULL);
		chown_dir(snapshot_dst);
		return rc==0;
	}
	return false;
#endif
}
Exemple #10
0
bool create_subvolume(int mode, std::string subvolume_folder)
{
#ifdef _WIN32
	return os_create_dir(subvolume_folder);
#else
	if(mode==mode_btrfs)
	{
		int rc=exec_wait(find_btrfs_cmd(), true, "subvolume", "create", subvolume_folder.c_str(), NULL);
		chown_dir(subvolume_folder);
		return rc==0;
	}
	else if(mode==mode_zfs)
	{
		zfs_elevate();
		int rc=exec_wait(find_zfs_cmd(), true, "create", "-p", subvolume_folder.c_str(), NULL);
		chown_dir(subvolume_folder);
		return rc==0;
	}
	return false;
#endif
}
Exemple #11
0
std::string find_zfs_cmd()
{
	static std::string zfs_cmd;
	
	if(!zfs_cmd.empty())
	{
		return zfs_cmd;
	}
	
	if(exec_wait("zfs", false, "--version", NULL)==2)
	{
		zfs_cmd="zfs";
		return zfs_cmd;
	}
	else if(exec_wait("/sbin/zfs", false, "--version", NULL)==2)
	{
		zfs_cmd="/sbin/zfs";
		return zfs_cmd;
	}
	else if(exec_wait("/bin/zfs", false, "--version", NULL)==2)
	{
		zfs_cmd="/bin/zfs";
		return zfs_cmd;
	}
	else if(exec_wait("/usr/sbin/zfs", false, "--version", NULL)==2)
	{
		zfs_cmd="/usr/sbin/zfs";
		return zfs_cmd;
	}
	else if(exec_wait("/usr/bin/zfs", false, "--version", NULL)==2)
	{
		zfs_cmd="/usr/bin/zfs";
		return zfs_cmd;
	}
	else
	{
		zfs_cmd="zfs";
		return zfs_cmd;
	}
}
Exemple #12
0
std::string find_btrfs_cmd()
{
	static std::string btrfs_cmd;
	
	if(!btrfs_cmd.empty())
	{
		return btrfs_cmd;
	}
	
	if(exec_wait("btrfs", false, "--version", NULL)==0)
	{
		btrfs_cmd="btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/sbin/btrfs", false, "--version", NULL)==0)
	{
		btrfs_cmd="/sbin/btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/bin/btrfs", false, "--version", NULL)==0)
	{
		btrfs_cmd="/bin/btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/usr/sbin/btrfs", false, "--version", NULL)==0)
	{
		btrfs_cmd="/usr/sbin/btrfs";
		return btrfs_cmd;
	}
	else if(exec_wait("/usr/bin/btrfs", false, "--version", NULL)==0)
	{
		btrfs_cmd="/usr/bin/btrfs";
		return btrfs_cmd;
	}
	else
	{
		btrfs_cmd="btrfs";
		return btrfs_cmd;
	}
}
Exemple #13
0
static boolean
make_dir(char *dir)
	{
	boolean 		dir_exists;

	if ((dir_exists = isdir(dir)) == FALSE)
		{
		exec_wait("sudo mkdir -p $F", dir);
		if ((dir_exists = isdir(dir)) == FALSE)
			log_printf("Make directory failed: %s\n", dir);
		else
			dir_exists = TRUE;
		}
	if (dir_exists)
		check_modes(dir, 0775);
	return dir_exists;
	}
Exemple #14
0
int make1( TARGET * const t )
{
    state * pState;

    memset( (char *)counts, 0, sizeof( *counts ) );

    /* Recursively make the target and its dependencies. */
    push_state( &state_stack, t, NULL, T_STATE_MAKE1A );

    while ( 1 )
    {
        while ( ( pState = current_state( &state_stack ) ) )
        {
            if ( intr )
                pop_state( &state_stack );

            switch ( pState->curstate )
            {
                case T_STATE_MAKE1A: make1a( pState ); break;
                case T_STATE_MAKE1B: make1b( pState ); break;
                case T_STATE_MAKE1C: make1c( pState ); break;
                default:
                    assert( !"make1(): Invalid state detected." );
            }
        }
        if ( !cmdsrunning )
            break;
        /* Wait for outstanding commands to finish running. */
        exec_wait();
    }

    clear_state_freelist();

    /* Talk about it. */
    if ( counts->failed )
        printf( "...failed updating %d target%s...\n", counts->failed,
            counts->failed > 1 ? "s" : "" );
    if ( DEBUG_MAKE && counts->skipped )
        printf( "...skipped %d target%s...\n", counts->skipped,
            counts->skipped > 1 ? "s" : "" );
    if ( DEBUG_MAKE && counts->made )
        printf( "...updated %d target%s...\n", counts->made,
            counts->made > 1 ? "s" : "" );

    return counts->total != counts->made;
}
Exemple #15
0
bool get_mountpoint(int mode, std::string subvolume_folder)
{
#ifdef _WIN32
	std::cout << subvolume_folder << std::endl;
	return true;
#else
	if(mode==mode_btrfs)
	{
		std::cout << subvolume_folder << std::endl;
		return true;
	}
	else if(mode==mode_zfs)
	{
		zfs_elevate();
		int rc=exec_wait(find_zfs_cmd(), true, "get", "-H", "-o", "value", "mountpoint", subvolume_folder.c_str(), NULL);
		return rc==0;
	}
	return false;
#endif
}
Exemple #16
0
int built_cmd (CMD *cmd)
{
	int status = SUCCESS;

	if (!cmd) return status;

	if(cmd->fromType != NONE)
	{
		//setup input redirection
		int red_err = set_red_in(cmd);
		if(red_err != SUCCESS)
		{
			perror("RED_IN: ");
			exit(red_err);
		}
	}

	if(cmd->toType != NONE) 
	{
		//setup output redirection
		int red_err = set_red_out(cmd);
		if (red_err != SUCCESS)
		{
			perror("RED_OUT: ");
			exit(red_err);
		} 
	}

	if (strcmp(cmd->argv[0], "dirs") == 0)
		status = exec_dirs();
	else if (strcmp(cmd->argv[0], "cd") == 0)
		status = exec_cd(cmd);
	else if (strcmp(cmd->argv[0], "wait") == 0)
		status = exec_wait();

	return status;
}
Exemple #17
0
int make1( LIST * targets )
{
    state * pState;
    int status = 0;

    memset( (char *)counts, 0, sizeof( *counts ) );
    
    {
        LISTITER iter, end;
        stack temp_stack = { NULL };
        for ( iter = list_begin( targets ), end = list_end( targets );
              iter != end; iter = list_next( iter ) )
            push_state( &temp_stack, bindtarget( list_item( iter ) ), NULL, T_STATE_MAKE1A );
        push_stack_on_stack( &state_stack, &temp_stack );
    }

    /* Clear any state left over from the past */
    quit = 0;

    /* Recursively make the target and its dependencies. */

    while ( 1 )
    {
        while ( ( pState = current_state( &state_stack ) ) )
        {
            if ( quit )
                pop_state( &state_stack );

            switch ( pState->curstate )
            {
                case T_STATE_MAKE1A: make1a( pState ); break;
                case T_STATE_MAKE1B: make1b( pState ); break;
                case T_STATE_MAKE1C: make1c( pState ); break;
                default:
                    assert( !"make1(): Invalid state detected." );
            }
        }
        if ( !cmdsrunning )
            break;
        /* Wait for outstanding commands to finish running. */
        exec_wait();
    }

    clear_state_freelist();

    /* Talk about it. */
    if ( counts->failed )
        printf( "...failed updating %d target%s...\n", counts->failed,
            counts->failed > 1 ? "s" : "" );
    if ( DEBUG_MAKE && counts->skipped )
        printf( "...skipped %d target%s...\n", counts->skipped,
            counts->skipped > 1 ? "s" : "" );
    if ( DEBUG_MAKE && counts->made )
        printf( "...updated %d target%s...\n", counts->made,
            counts->made > 1 ? "s" : "" );

    /* If we were interrupted, exit now that all child processes
       have finished. */
    if ( intr )
        exit( 1 );

    {
        LISTITER iter, end;
        for ( iter = list_begin( targets ), end = list_end( targets );
              iter != end; iter = list_next( iter ) )
        {
            /* Check that the target was updated and that the
               update succeeded. */
            TARGET * t = bindtarget( list_item( iter ) );
            if (t->progress == T_MAKE_DONE)
            {
                if (t->status != EXEC_CMD_OK)
                    status = 1;
            }
            else if ( ! ( t->progress == T_MAKE_NOEXEC_DONE && globs.noexec ) )
            {
                status = 1;
            }
        }
    }
    return status;
}
Exemple #18
0
bool remove_subvolume(int mode, std::string subvolume_folder, bool quiet=false)
{
#ifdef _WIN32
	return os_remove_nonempty_dir(widen(subvolume_folder));
#else
	if(mode==mode_btrfs)
	{
		int compat_rc = exec_wait(find_btrfs_cmd(), false, "subvolume", "delete", "-c", NULL);
		
		if(compat_rc==1)
		{
			compat_rc = exec_wait("/bin/sh", false, "-c", (find_btrfs_cmd() +
				" subvolume delete -c 2>&1 | grep \"ERROR: error accessing '-c'\"").c_str(), NULL);
			if(compat_rc==0)
			{
				compat_rc=12;
			}
		}
		
		int rc;
		if(compat_rc==12)
		{
			rc=exec_wait(find_btrfs_cmd(), !quiet, "subvolume", "delete", subvolume_folder.c_str(), NULL);
		}
		else
		{
			rc=exec_wait(find_btrfs_cmd(), !quiet, "subvolume", "delete", "-c", subvolume_folder.c_str(), NULL);
		}
		return rc==0;
	}
	else if(mode==mode_zfs)
	{
		zfs_elevate();
		
		exec_wait(find_zfs_cmd(), false, "destroy", (subvolume_folder+"@ro").c_str(), NULL);
		int rc = exec_wait(find_zfs_cmd(), false, "destroy", subvolume_folder.c_str(), NULL);
		if(rc!=0)
		{
			std::cout << "Destroying subvol " << subvolume_folder << " failed. Promoting dependencies..." << std::endl;
			std::string rename_name = ExtractFileName(subvolume_folder);
			if(exec_wait(find_zfs_cmd(), true, "rename", (subvolume_folder+"@ro").c_str(), (subvolume_folder+"@"+rename_name).c_str(), NULL)!=0
				&& is_subvolume(mode, subvolume_folder+"@ro") )
			{
				return false;
			}
			
			std::vector<std::string> dependencies;
			if(!promote_dependencies(subvolume_folder+"@"+rename_name, dependencies))
			{
				return false;
			}

			rc = exec_wait(find_zfs_cmd(), true, "destroy", subvolume_folder.c_str(), NULL);
			
			if(rc==0)
			{
				for(size_t i=0;i<dependencies.size();++i)
				{
					if(is_subvolume(mode, dependencies[i]+"@"+rename_name))
					{
						rc = exec_wait(find_zfs_cmd(), true, "destroy", (dependencies[i]+"@"+rename_name).c_str(), NULL);
						if(rc!=0)
						{
							break;
						}
					}
				}
			}
		}
		
		return rc==0;
	}
	return false;
#endif
}
Exemple #19
0
int
main(int argc, char *argv[])
	{
	int		fifo;
	int	 	i, n;
	char	*opt, *arg, *equal_arg, *homedir, *user;
	char	*line, *eol, buf[4096];

	pgm_name = argv[0];
	bcm_host_init();
	time(&pikrellcam.t_now);

	config_set_defaults();

	for (i = 1; i < argc; i++)
		get_arg_pass1(argv[i]);

	if (!config_load(pikrellcam.config_file))
		config_save(pikrellcam.config_file);
	if (!motion_regions_config_load(pikrellcam.motion_regions_config_file))
		motion_regions_config_save(pikrellcam.motion_regions_config_file);
	if (!at_commands_config_load(pikrellcam.at_commands_config_file))
		at_commands_config_save(pikrellcam.at_commands_config_file);

	for (i = 1; i < argc; i++)
		{
		if (get_arg_pass1(argv[i]))
			continue;
		opt = argv[i];

		/* Just for initial install-pikrellcam.sh run to create config files.
		*/
		if (!strcmp(opt, "-quit"))
			exit(0);

		/* Accept: --opt arg   -opt arg    opt=arg    --opt=arg    -opt=arg
		*/
		for (i = 0; i < 2; ++i)
			if (*opt == '-')
				++opt;
		if ((equal_arg = strchr(opt, '=')) != NULL)
			{
			*equal_arg++ = '\0';
			arg = equal_arg;
			++i;
			}
		else
			arg = argv[i + 1];

		/* For camera parameters, do not set the camera, only replace
		|  values in the parameter table.
		*/
		if (   !config_set_option(opt, arg, TRUE)
		    && !mmalcam_config_parameter_set(opt, arg, FALSE)
		   )
			{
			log_printf("Bad arg: %s\n", opt);
			exit(1);
			}
		}

	homedir = getpwuid(geteuid())->pw_dir;
	user = strrchr(homedir, '/');
	pikrellcam.effective_user = strdup(user ? user + 1 : "pi");

	if (*pikrellcam.log_file != '/')
		{
		snprintf(buf, sizeof(buf), "%s/%s", pikrellcam.install_dir, pikrellcam.log_file);
		dup_string(&pikrellcam.log_file, buf);
		}
	if (*pikrellcam.media_dir != '/')
		{
		snprintf(buf, sizeof(buf), "%s/%s", pikrellcam.install_dir, pikrellcam.media_dir);
		dup_string(&pikrellcam.media_dir, buf);
		}
	strftime(buf, sizeof(buf), "%F %T", localtime(&pikrellcam.t_now));
	log_printf("\n%s ==== PiKrellCam started ====\n", buf);

	snprintf(buf, sizeof(buf), "%s/%s", pikrellcam.install_dir, "www");
	check_modes(buf, 0775);

	asprintf(&pikrellcam.command_fifo, "%s/www/FIFO", pikrellcam.install_dir);
	asprintf(&pikrellcam.script_dir, "%s/scripts", pikrellcam.install_dir);
	asprintf(&pikrellcam.mjpeg_filename, "%s/mjpeg.jpg", pikrellcam.mjpeg_dir);

	log_printf("using FIFO: %s\n", pikrellcam.command_fifo);
	log_printf("using mjpeg: %s\n", pikrellcam.mjpeg_filename);


	/* Subdirs must match www/config.php and the init script is supposed
	|  to take care of that.
	*/
	asprintf(&pikrellcam.video_dir, "%s/%s", pikrellcam.media_dir, PIKRELLCAM_VIDEO_SUBDIR);
	asprintf(&pikrellcam.still_dir, "%s/%s", pikrellcam.media_dir, PIKRELLCAM_STILL_SUBDIR);
	asprintf(&pikrellcam.timelapse_dir, "%s/%s", pikrellcam.media_dir, PIKRELLCAM_TIMELAPSE_SUBDIR);

	if (!make_dir(pikrellcam.media_dir))
		exit(1);

	snprintf(buf, sizeof(buf), "%s/scripts-dist/init $I $m $M $P $G",
								pikrellcam.install_dir);
	exec_wait(buf, NULL);

	/* User may have enabled a mount disk on media_dir
	*/
	exec_wait(pikrellcam.on_startup_cmd, NULL);
	check_modes(pikrellcam.media_dir, 0775);

	if (   !make_dir(pikrellcam.mjpeg_dir)
	    || !make_dir(pikrellcam.video_dir)
	    || !make_dir(pikrellcam.still_dir)
	    || !make_dir(pikrellcam.timelapse_dir)
	    || !make_fifo(pikrellcam.command_fifo)
	   )
		exit(1);

	if ((fifo = open(pikrellcam.command_fifo, O_RDONLY | O_NONBLOCK)) < 0)
		{
		log_printf("Failed to open FIFO: %s.  %m\n", pikrellcam.command_fifo);
		exit(1);
		}

	fcntl(fifo, F_SETFL, 0);
	read(fifo, buf, sizeof(buf));
	
	sun_times_init();
	camera_start();
	config_timelapse_load_status();

	signal(SIGINT, signal_quit);
	signal(SIGTERM, signal_quit);
	signal(SIGCHLD, event_child_signal);

	while (1)
		{
		usleep(1000000 / EVENT_LOOP_FREQUENCY);
		event_process();

		/* Process lines in the FIFO.  Single lines via an echo "xxx" > FIFO
		|  or from a web page may not have a terminating \n.
		|  Local scripts may dump multiple \n terminated lines into the FIFO.
		*/
		if ((n = read(fifo, buf, sizeof(buf) - 2)) > 0)
			{
			if (buf[n - 1] != '\n')
				buf[n++] = '\n';	/* ensures all lines in buf end in \n */
			buf[n] = '\0';
			line = buf;
			eol = strchr(line, '\n');

			while (eol > line)
				{
				*eol++ = '\0';
				command_process(line);
				while (*eol == '\n')
					++eol;
				line = eol;
				eol = strchr(line, '\n');
				}
			}
		}
	return 0;
	}
Exemple #20
0
void exec_cmd
(
    char * command,
    void (* func)( void * closure, int status, timing_info *, char * invoked_command, char * command_output ),
    void * closure,
    LIST * shell,
    char * action,
    char * target
)
{
    int      slot;
    int      raw_cmd = 0 ;
    char   * argv_static[ MAXARGC + 1 ];  /* +1 for NULL */
    char * * argv = argv_static;
    char   * p;
    char   * command_orig = command;

    /* Check to see if we need to hack around the line-length limitation. Look
     * for a JAMSHELL setting of "%", indicating that the command should be
     * invoked directly.
     */
    if ( shell && !strcmp( shell->string, "%" ) && !list_next( shell ) )
    {
        raw_cmd = 1;
        shell = 0;
    }

    /* Find a slot in the running commands table for this one. */
    for ( slot = 0; slot < MAXJOBS; ++slot )
        if ( !cmdtab[ slot ].pi.hProcess )
            break;
    if ( slot == MAXJOBS )
    {
        printf( "no slots for child!\n" );
        exit( EXITBAD );
    }

    /* Compute the name of a temp batch file, for possible use. */
    if ( !cmdtab[ slot ].tempfile_bat )
    {
        char const * tempdir = path_tmpdir();
        DWORD procID = GetCurrentProcessId();

        /* SVA - allocate 64 bytes extra just to be safe. */
        cmdtab[ slot ].tempfile_bat = BJAM_MALLOC_ATOMIC( strlen( tempdir ) + 64 );

        sprintf( cmdtab[ slot ].tempfile_bat, "%s\\jam%d-%02d.bat",
            tempdir, procID, slot );
    }

    /* Trim leading, -ending- white space */
    while ( *( command + 1 ) && isspace( *command ) )
        ++command;

    /* Write to .BAT file unless the line would be too long and it meets the
     * other spawnability criteria.
     */
    if ( raw_cmd && ( can_spawn( command ) >= MAXLINE ) )
    {
        if ( DEBUG_EXECCMD )
            printf("Executing raw command directly\n");
    }
    else
    {
        FILE * f = 0;
        int tries = 0;
        raw_cmd = 0;

        /* Write command to bat file. For some reason this open can fail
         * intermitently. But doing some retries works. Most likely this is due
         * to a previously existing file of the same name that happens to be
         * opened by an active virus scanner. Pointed out and fixed by Bronek
         * Kozicki.
         */
        for ( ; !f && ( tries < 4 ); ++tries )
        {
            f = fopen( cmdtab[ slot ].tempfile_bat, "w" );
            if ( !f && ( tries < 4 ) ) Sleep( 250 );
        }
        if ( !f )
        {
            printf( "failed to write command file!\n" );
            exit( EXITBAD );
        }
        fputs( command, f );
        fclose( f );

        command = cmdtab[ slot ].tempfile_bat;

        if ( DEBUG_EXECCMD )
        {
            if ( shell )
                printf( "using user-specified shell: %s", shell->string );
            else
                printf( "Executing through .bat file\n" );
        }
    }

    /* Formulate argv; If shell was defined, be prepared for % and ! subs.
     * Otherwise, use stock cmd.exe.
     */
    if ( shell )
    {
        int i;
        char jobno[ 4 ];
        int gotpercent = 0;

        sprintf( jobno, "%d", slot + 1 );

        for ( i = 0; shell && ( i < MAXARGC ); ++i, shell = list_next( shell ) )
        {
            switch ( shell->string[ 0 ] )
            {
                case '%': argv[ i ] = command; ++gotpercent; break;
                case '!': argv[ i ] = jobno; break;
                default : argv[ i ] = shell->string;
            }
            if ( DEBUG_EXECCMD )
                printf( "argv[%d] = '%s'\n", i, argv[ i ] );
        }

        if ( !gotpercent )
            argv[ i++ ] = command;

        argv[ i ] = 0;
    }
    else if ( raw_cmd )
    {
        argv = string_to_args( command );
    }
    else
    {
        argv[ 0 ] = "cmd.exe";
        argv[ 1 ] = "/Q/C";  /* anything more is non-portable */
        argv[ 2 ] = command;
        argv[ 3 ] = 0;
    }

    /* Catch interrupts whenever commands are running. */
    if ( !cmdsrunning++ )
        istat = signal( SIGINT, onintr );

    /* Start the command. */
    {
        SECURITY_ATTRIBUTES sa
            = { sizeof( SECURITY_ATTRIBUTES ), 0, 0 };
        SECURITY_DESCRIPTOR sd;
        STARTUPINFO si
            = { sizeof( STARTUPINFO ), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        string cmd;

        /* Init the security data. */
        InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
        SetSecurityDescriptorDacl( &sd, TRUE, NULL, FALSE );
        sa.lpSecurityDescriptor = &sd;
        sa.bInheritHandle = TRUE;

        /* Create the stdout, which is also the merged out + err, pipe. */
        if ( !CreatePipe( &cmdtab[ slot ].pipe_out[ 0 ],
            &cmdtab[ slot ].pipe_out[ 1 ], &sa, 0 ) )
        {
            perror( "CreatePipe" );
            exit( EXITBAD );
        }

        /* Create the stdout, which is also the merged out+err, pipe. */
        if ( globs.pipe_action == 2 )
        {
            if ( !CreatePipe( &cmdtab[ slot ].pipe_err[ 0 ],
                &cmdtab[ slot ].pipe_err[ 1 ], &sa, 0 ) )
            {
                perror( "CreatePipe" );
                exit( EXITBAD );
            }
        }

        /* Set handle inheritance off for the pipe ends the parent reads from. */
        SetHandleInformation( cmdtab[ slot ].pipe_out[ 0 ], HANDLE_FLAG_INHERIT, 0 );
        if ( globs.pipe_action == 2 )
            SetHandleInformation( cmdtab[ slot ].pipe_err[ 0 ], HANDLE_FLAG_INHERIT, 0 );

        /* Hide the child window, if any. */
        si.dwFlags |= STARTF_USESHOWWINDOW;
        si.wShowWindow = SW_HIDE;

        /* Set the child outputs to the pipes. */
        si.dwFlags |= STARTF_USESTDHANDLES;
        si.hStdOutput = cmdtab[ slot ].pipe_out[ 1 ];
        if ( globs.pipe_action == 2 )
        {
            /* Pipe stderr to the action error output. */
            si.hStdError = cmdtab[ slot ].pipe_err[ 1 ];
        }
        else if ( globs.pipe_action == 1 )
        {
            /* Pipe stderr to the console error output. */
            si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
        }
        else
        {
            /* Pipe stderr to the action merged output. */
            si.hStdError = cmdtab[ slot ].pipe_out[ 1 ];
        }

        /* Let the child inherit stdin, as some commands assume it's available. */
        si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);

        /* Save the operation for exec_wait() to find. */
        cmdtab[ slot ].func = func;
        cmdtab[ slot ].closure = closure;
        if ( action && target )
        {
            string_copy( &cmdtab[ slot ].action, action );
            string_copy( &cmdtab[ slot ].target, target );
        }
        else
        {
            string_free( &cmdtab[ slot ].action );
            string_new ( &cmdtab[ slot ].action );
            string_free( &cmdtab[ slot ].target );
            string_new ( &cmdtab[ slot ].target );
        }
        string_copy( &cmdtab[ slot ].command, command_orig );

        /* Put together the command we run. */
        {
            char * * argp = argv;
            string_new( &cmd );
            string_copy( &cmd, *(argp++) );
            while ( *argp )
            {
                string_push_back( &cmd, ' ' );
                string_append( &cmd, *(argp++) );
            }
        }

        /* Create output buffers. */
        string_new( &cmdtab[ slot ].buffer_out );
        string_new( &cmdtab[ slot ].buffer_err );

        /* Run the command by creating a sub-process for it. */
        if (
            ! CreateProcess(
                NULL                    ,  /* application name               */
                cmd.value               ,  /* command line                   */
                NULL                    ,  /* process attributes             */
                NULL                    ,  /* thread attributes              */
                TRUE                    ,  /* inherit handles                */
                CREATE_NEW_PROCESS_GROUP,  /* create flags                   */
                NULL                    ,  /* env vars, null inherits env    */
                NULL                    ,  /* current dir, null is our       */
                                           /* current dir                    */
                &si                     ,  /* startup info                   */
                &cmdtab[ slot ].pi         /* child process info, if created */
                )
            )
        {
            perror( "CreateProcess" );
            exit( EXITBAD );
        }

        /* Clean up temporary stuff. */
        string_free( &cmd );
    }

    /* Wait until we are under the limit of concurrent commands. Do not trust
     * globs.jobs alone.
     */
    while ( ( cmdsrunning >= MAXJOBS ) || ( cmdsrunning >= globs.jobs ) )
        if ( !exec_wait() )
            break;

    if ( argv != argv_static )
        free_argv( argv );
}
Exemple #21
0
static void make1c( state const * const pState )
{
    TARGET * const t = pState->t;
    CMD * const cmd = (CMD *)t->cmds;

    if ( cmd && t->status == EXEC_CMD_OK )
    {
        /* Pop state first in case something below (e.g. exec_cmd(), exec_wait()
         * or make1c_closure()) pushes a new state. Note that we must not access
         * the popped state data after this as the same stack node might have
         * been reused internally for some newly pushed state.
         */
        pop_state( &state_stack );

        /* Increment the jobs running counter. */
        ++cmdsrunning;

        /* Execute the actual build command or fake it if no-op. */
        if ( globs.noexec || cmd->noop )
        {
            timing_info time_info = { 0 };
            timestamp_current( &time_info.start );
            timestamp_copy( &time_info.end, &time_info.start );
            make1c_closure( t, EXEC_CMD_OK, &time_info, "", "", EXIT_OK );
        }
        else
        {
            exec_cmd( cmd->buf, make1c_closure, t, cmd->shell );

            /* Wait until under the concurrent command count limit. */
            /* FIXME: This wait could be skipped here and moved to just before
             * trying to execute a command that would cross the command count
             * limit. Note though that this might affect the order in which
             * unrelated targets get built and would thus require that all
             * affected Boost Build tests be updated.
             */
            assert( 0 < globs.jobs );
            assert( globs.jobs <= MAXJOBS );
            while ( cmdsrunning >= globs.jobs )
                exec_wait();
        }
    }
    else
    {
        ACTIONS * actions;

        /* Collect status from actions, and distribute it as well. */
        for ( actions = t->actions; actions; actions = actions->next )
            if ( actions->action->status > t->status )
                t->status = actions->action->status;
        for ( actions = t->actions; actions; actions = actions->next )
            if ( t->status > actions->action->status )
                actions->action->status = t->status;

        /* Tally success/failure for those we tried to update. */
        if ( t->progress == T_MAKE_RUNNING )
            switch ( t->status )
            {
                case EXEC_CMD_OK: ++counts->made; break;
                case EXEC_CMD_FAIL: ++counts->failed; break;
            }

        /* Tell parents their dependency has been built. */
        {
            TARGETS * c;
            stack temp_stack = { NULL };
            TARGET * additional_includes = NULL;

            t->progress = globs.noexec ? T_MAKE_NOEXEC_DONE : T_MAKE_DONE;

            /* Target has been updated so rescan it for dependencies. */
            if ( t->fate >= T_FATE_MISSING && t->status == EXEC_CMD_OK &&
                !( t->flags & T_FLAG_INTERNAL ) )
            {
                TARGET * saved_includes;
                SETTINGS * s;

                t->rescanned = 1;

                /* Clean current includes. */
                saved_includes = t->includes;
                t->includes = 0;

                s = copysettings( t->settings );
                pushsettings( root_module(), s );
                headers( t );
                popsettings( root_module(), s );
                freesettings( s );

                if ( t->includes )
                {
                    /* Tricky. The parents have already been processed, but they
                     * have not seen the internal node, because it was just
                     * created. We need to:
                     *  - push MAKE1A states that would have been pushed by the
                     *    parents here
                     *  - make sure all unprocessed parents will pick up the
                     *    new includes
                     *  - make sure processing the additional MAKE1A states is
                     *    done before processing the MAKE1B state for our
                     *    current target (which would mean this target has
                     *    already been built), otherwise the parent would be
                     *    considered built before the additional MAKE1A state
                     *    processing even got a chance to start.
                     */
                    make0( t->includes, t->parents->target, 0, 0, 0, t->includes
                        );
                    /* Link the old includes on to make sure that it gets
                     * cleaned up correctly.
                     */
                    t->includes->includes = saved_includes;
                    for ( c = t->dependants; c; c = c->next )
                        c->target->depends = targetentry( c->target->depends,
                            t->includes );
                    /* Will be processed below. */
                    additional_includes = t->includes;
                }
                else
                {
                    t->includes = saved_includes;
                }
            }

            if ( additional_includes )
                for ( c = t->parents; c; c = c->next )
                    push_state( &temp_stack, additional_includes, c->target,
                        T_STATE_MAKE1A );

            if ( t->scc_root )
            {
                TARGET * const scc_root = target_scc( t );
                assert( scc_root->progress < T_MAKE_DONE );
                for ( c = t->parents; c; c = c->next )
                {
                    if ( target_scc( c->target ) == scc_root )
                        push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B
                            );
                    else
                        scc_root->parents = targetentry( scc_root->parents,
                            c->target );
                }
            }
            else
            {
                for ( c = t->parents; c; c = c->next )
                    push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B );
            }

#ifdef OPT_SEMAPHORE
            /* If there is a semaphore, it is now free. */
            if ( t->semaphore )
            {
                assert( t->semaphore->asynccnt == 1 );
                --t->semaphore->asynccnt;

                if ( DEBUG_EXECCMD )
                    printf( "SEM: %s is now free\n", object_str(
                        t->semaphore->name ) );

                /* If anything is waiting, notify the next target. There is no
                 * point in notifying all waiting targets, since they will be
                 * notified again.
                 */
                if ( t->semaphore->parents )
                {
                    TARGETS * first = t->semaphore->parents;
                    t->semaphore->parents = first->next;
                    if ( first->next )
                        first->next->tail = first->tail;

                    if ( DEBUG_EXECCMD )
                        printf( "SEM: placing %s on stack\n", object_str(
                            first->target->name ) );
                    push_state( &temp_stack, first->target, NULL, T_STATE_MAKE1B
                        );
                    BJAM_FREE( first );
                }
            }
#endif

            /* Must pop state before pushing any more. */
            pop_state( &state_stack );

            /* Using stacks reverses the order of execution. Reverse it back. */
            push_stack_on_stack( &state_stack, &temp_stack );
        }
    }
}
Exemple #22
0
void exec_cmd
(
    char * string,
    void (*func)( void *closure, int status, timing_info*, char *, char * ),
    void * closure,
    LIST * shell,
    char * action,
    char * target
)
{
    static int initialized = 0;
    int    out[2];
    int    err[2];
    int    slot;
    int    len;
    char * argv[ MAXARGC + 1 ];  /* +1 for NULL */

    /* Find a slot in the running commands table for this one. */
    for ( slot = 0; slot < MAXJOBS; ++slot )
        if ( !cmdtab[ slot ].pid )
            break;

    if ( slot == MAXJOBS )
    {
        printf( "no slots for child!\n" );
        exit( EXITBAD );
    }

    /* Forumulate argv. If shell was defined, be prepared for % and ! subs.
     * Otherwise, use stock /bin/sh on unix or cmd.exe on NT.
     */
    if ( shell )
    {
        int  i;
        char jobno[4];
        int  gotpercent = 0;

        sprintf( jobno, "%d", slot + 1 );

        for ( i = 0; shell && i < MAXARGC; ++i, shell = list_next( shell ) )
        {
            switch ( shell->string[0] )
            {
                case '%': argv[ i ] = string; ++gotpercent; break;
                case '!': argv[ i ] = jobno;                break;
                default : argv[ i ] = shell->string;
            }
            if ( DEBUG_EXECCMD )
                printf( "argv[%d] = '%s'\n", i, argv[ i ] );
        }

        if ( !gotpercent )
        argv[ i++ ] = string;

        argv[ i ] = 0;
    }
    else
    {
        argv[ 0 ] = "/bin/sh";
        argv[ 1 ] = "-c";
        argv[ 2 ] = string;
        argv[ 3 ] = 0;
    }

    /* Increment jobs running. */
    ++cmdsrunning;

    /* Save off actual command string. */
    cmdtab[ slot ].command = BJAM_MALLOC_ATOMIC( strlen( string ) + 1 );
    strcpy( cmdtab[ slot ].command, string );

    /* Initialize only once. */
    if ( !initialized )
    {
        times( &old_time );
        initialized = 1;
    }

    /* Create pipes from child to parent. */
    {
        if ( pipe( out ) < 0 )
            exit( EXITBAD );
        fcntl( out[0], F_SETFL, O_NONBLOCK );
        fcntl( out[1], F_SETFL, O_NONBLOCK );

        if ( pipe( err ) < 0 )
            exit( EXITBAD );
        fcntl( err[0], F_SETFL, O_NONBLOCK );
        fcntl( err[1], F_SETFL, O_NONBLOCK );
    }

    /* Start the command */

    cmdtab[ slot ].start_dt = time(0);

    if ( 0 < globs.timeout )
    {
        /*
         * Handle hung processes by manually tracking elapsed time and signal
         * process when time limit expires.
         */
        struct tms buf;
        cmdtab[ slot ].start_time = times( &buf );

        /* Make a global, only do this once. */
        if ( tps == 0 ) tps = sysconf( _SC_CLK_TCK );
    }

    if ( ( cmdtab[ slot ].pid = vfork() ) == 0 )
    {
        int pid = getpid();

        close( out[0] );
        close( err[0] );

        dup2( out[1], STDOUT_FILENO );

        if ( globs.pipe_action == 0 )
        {
            dup2( out[1], STDERR_FILENO );
            close( err[1] );
        }
        else
            dup2( err[1], STDERR_FILENO );

        /* Make this process a process group leader so that when we kill it, all
         * child processes of this process are terminated as well. We use
         * killpg(pid, SIGKILL) to kill the process group leader and all its
         * children.
         */
        if ( 0 < globs.timeout )
        {
            struct rlimit r_limit;
            r_limit.rlim_cur = globs.timeout;
            r_limit.rlim_max = globs.timeout;
            setrlimit( RLIMIT_CPU, &r_limit );
        }
        setpgid( pid,pid );
        execvp( argv[0], argv );
        perror( "execvp" );
        _exit( 127 );
    }
    else if ( cmdtab[ slot ].pid == -1 )
    {
        perror( "vfork" );
        exit( EXITBAD );
    }

    setpgid( cmdtab[ slot ].pid, cmdtab[ slot ].pid );

    /* close write end of pipes */
    close( out[1] );
    close( err[1] );

    /* child writes stdout to out[1], parent reads from out[0] */
    cmdtab[ slot ].fd[ OUT ] = out[0];
    cmdtab[ slot ].stream[ OUT ] = fdopen( cmdtab[ slot ].fd[ OUT ], "rb" );
    if ( cmdtab[ slot ].stream[ OUT ] == NULL )
    {
        perror( "fdopen" );
        exit( EXITBAD );
    }

    /* child writes stderr to err[1], parent reads from err[0] */
    if (globs.pipe_action == 0)
    {
      close(err[0]);
    }
    else
    {
        cmdtab[ slot ].fd[ ERR ] = err[0];
        cmdtab[ slot ].stream[ ERR ] = fdopen( cmdtab[ slot ].fd[ ERR ], "rb" );
        if ( cmdtab[ slot ].stream[ ERR ] == NULL )
        {
            perror( "fdopen" );
            exit( EXITBAD );
        }
    }

    /* Ensure enough room for rule and target name. */
    if ( action && target )
    {
        len = strlen( action ) + 1;
        if ( cmdtab[ slot ].action_length < len )
        {
            BJAM_FREE( cmdtab[ slot ].action );
            cmdtab[ slot ].action = BJAM_MALLOC_ATOMIC( len );
            cmdtab[ slot ].action_length = len;
        }
        strcpy( cmdtab[ slot ].action, action );
        len = strlen( target ) + 1;
        if ( cmdtab[ slot ].target_length < len )
        {
            BJAM_FREE( cmdtab[ slot ].target );
            cmdtab[ slot ].target = BJAM_MALLOC_ATOMIC( len );
            cmdtab[ slot ].target_length = len;
        }
        strcpy( cmdtab[ slot ].target, target );
    }
    else
    {
        BJAM_FREE( cmdtab[ slot ].action );
        BJAM_FREE( cmdtab[ slot ].target );
        cmdtab[ slot ].action = 0;
        cmdtab[ slot ].target = 0;
        cmdtab[ slot ].action_length = 0;
        cmdtab[ slot ].target_length = 0;
    }

    /* Save the operation for exec_wait() to find. */
    cmdtab[ slot ].func = func;
    cmdtab[ slot ].closure = closure;

    /* Wait until we are under the limit of concurrent commands. Do not trust
     * globs.jobs alone.
     */
    while ( ( cmdsrunning >= MAXJOBS ) || ( cmdsrunning >= globs.jobs ) )
        if ( !exec_wait() )
            break;
}
Exemple #23
0
bool torture_gpo_system_access_policies(struct torture_context *tctx)
{
	TALLOC_CTX *ctx = talloc_new(tctx);
	int ret, vers = 0, i;
	const char *sysvol_path = NULL, *gpo_dir = NULL;
	const char *gpo_file = NULL, *gpt_file = NULL;
	struct ldb_context *samdb = NULL;
	struct ldb_result *result;
	const char *attrs[] = {
		"minPwdAge",
		"maxPwdAge",
		"minPwdLength",
		"pwdProperties",
		NULL
	};
	FILE *fp = NULL;
	const char **gpo_update_cmd;
	char **gpo_unapply_cmd;
	int minpwdcases[] = { 0, 1, 998 };
	int maxpwdcases[] = { 0, 1, 999 };
	int pwdlencases[] = { 0, 1, 14 };
	int pwdpropcases[] = { 0, 1, 1 };
	struct ldb_message *old_message = NULL;
	const char **itr;
	int gpo_update_len = 0;

	sysvol_path = lpcfg_path(lpcfg_service(tctx->lp_ctx, "sysvol"),
				 lpcfg_default_service(tctx->lp_ctx), tctx);
	torture_assert(tctx, sysvol_path, "Failed to fetch the sysvol path");

	/* Ensure the sysvol path exists */
	gpo_dir = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPODIR);
	mkdir_p(gpo_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
	gpo_file = talloc_asprintf(ctx, "%s/%s", gpo_dir, GPOFILE);

	/* Get the gpo update command */
	gpo_update_cmd = lpcfg_gpo_update_command(tctx->lp_ctx);
	torture_assert(tctx, gpo_update_cmd && gpo_update_cmd[0],
		       "Failed to fetch the gpo update command");

	/* Open and read the samba db and store the initial password settings */
	samdb = samdb_connect(ctx,
			      tctx->ev,
			      tctx->lp_ctx,
			      system_session(tctx->lp_ctx),
			      NULL,
			      0);
	torture_assert(tctx, samdb, "Failed to connect to the samdb");

	ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
			 LDB_SCOPE_BASE, attrs, NULL);
	torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
		       "Searching the samdb failed");

	old_message = result->msgs[0];

	for (i = 0; i < 3; i++) {
		/* Write out the sysvol */
		if ( (fp = fopen(gpo_file, "w")) ) {
			fputs(talloc_asprintf(ctx, GPTTMPL, minpwdcases[i],
					      maxpwdcases[i], pwdlencases[i],
					      pwdpropcases[i]), fp);
			fclose(fp);
		}

		/* Update the version in the GPT.INI */
		gpt_file = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPTINI);
		if ( (fp = fopen(gpt_file, "r")) ) {
			char line[256];
			while (fgets(line, 256, fp)) {
				if (strncasecmp(line, "Version=", 8) == 0) {
					vers = atoi(line+8);
					break;
				}
			}
			fclose(fp);
		}
		if ( (fp = fopen(gpt_file, "w")) ) {
			char *data = talloc_asprintf(ctx,
						     "[General]\nVersion=%d\n",
						     ++vers);
			fputs(data, fp);
			fclose(fp);
		}

		/* Run the gpo update command */
		ret = exec_wait(discard_const_p(char *, gpo_update_cmd));
		torture_assert(tctx, ret == 0,
			       "Failed to execute the gpo update command");

		ret = ldb_search(samdb, ctx, &result,
				 ldb_get_default_basedn(samdb),
				 LDB_SCOPE_BASE, attrs, NULL);
		torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
			       "Searching the samdb failed");

		/* minPwdAge */
		torture_assert_int_equal(tctx, unix2nttime(
						ldb_msg_find_attr_as_string(
							result->msgs[0],
							attrs[0],
							"")), minpwdcases[i],
			       "The minPwdAge was not applied");

		/* maxPwdAge */
		torture_assert_int_equal(tctx, unix2nttime(
						ldb_msg_find_attr_as_string(
							result->msgs[0],
							attrs[1],
							"")), maxpwdcases[i],
			       "The maxPwdAge was not applied");

		/* minPwdLength */
		torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
							result->msgs[0],
							attrs[2],
							-1),
					       pwdlencases[i],
				"The minPwdLength was not applied");

		/* pwdProperties */
		torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
							result->msgs[0],
							attrs[3],
							-1),
					       pwdpropcases[i],
			       "The pwdProperties were not applied");
	}

	/* Unapply the settings and verify they are removed */
	for (itr = gpo_update_cmd; *itr != NULL; itr++) {
		gpo_update_len++;
	}
	gpo_unapply_cmd = talloc_array(ctx, char*, gpo_update_len+2);
	for (i = 0; i < gpo_update_len; i++) {
		gpo_unapply_cmd[i] = talloc_strdup(gpo_unapply_cmd,
						   gpo_update_cmd[i]);
	}
	gpo_unapply_cmd[i] = talloc_asprintf(gpo_unapply_cmd, "--unapply");
	gpo_unapply_cmd[i+1] = NULL;
	ret = exec_wait(gpo_unapply_cmd);
	torture_assert(tctx, ret == 0,
		       "Failed to execute the gpo unapply command");
	ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
			 LDB_SCOPE_BASE, attrs, NULL);
	torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
		       "Searching the samdb failed");
	/* minPwdAge */
	torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
						result->msgs[0],
						attrs[0],
						"")),
		       unix2nttime(ldb_msg_find_attr_as_string(old_message,
							       attrs[0],
							       "")
				  ),
		       "The minPwdAge was not unapplied");
	/* maxPwdAge */
	torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
						result->msgs[0],
						attrs[1],
						"")),
		       unix2nttime(ldb_msg_find_attr_as_string(old_message,
							       attrs[1],
							       "")
				  ),
		       "The maxPwdAge was not unapplied");
	/* minPwdLength */
	torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
						result->msgs[0],
						attrs[2],
						-1),
				       ldb_msg_find_attr_as_int(
						old_message,
						attrs[2],
						-2),
			"The minPwdLength was not unapplied");
	/* pwdProperties */
	torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
						result->msgs[0],
						attrs[3],
						-1),
					ldb_msg_find_attr_as_int(
						old_message,
						attrs[3],
						-2),
			"The pwdProperties were not unapplied");

	talloc_free(ctx);
	return true;
}