Beispiel #1
0
static int mod_remove ( char *mod )
{
	int rc;
	static struct mod_list_t rm_a_dummy = { "-a", NULL, NULL, NULL, NULL };

	struct mod_list_t *head = 0;
	struct mod_list_t *tail = 0;

	if ( mod )
		check_dep ( mod, &head, &tail );
	else  // autoclean
		head = tail = &rm_a_dummy;

	if ( head && tail )
		rc = mod_process ( head, 0 );  // process head ---> tail
	else
		rc = 1;
	return rc;

}
Beispiel #2
0
extern int modprobe_main(int argc, char** argv)
{
	int	ch, rc = 0;
	int	loadall = 0, showconfig = 0, debug = 0, autoclean = 0, list = 0;
	int	show_only = 0, quiet = 0, remove_opt = 0, do_syslog = 0, verbose = 0;
	char	*load_type = NULL, *config = NULL;
	char cmd[256];

	while ((ch = getopt(argc, argv, "acdklnqrst:vVC:")) != -1)
		switch(ch) {
		case 'a':
			loadall++;
			break;
		case 'c':
			showconfig++;
			break;
		case 'd':
			debug++;
			break;
		case 'k':
			autoclean++;
			break;
		case 'l':
			list++;
			break;
		case 'n':
			show_only++;
			break;
		case 'q':
			quiet++;
			break;
		case 'r':
			remove_opt++;
			break;
		case 's':
			do_syslog++;
			break;
		case 't':
			load_type = optarg;
			break;
		case 'v':
			verbose++;
			break;
		case 'C':
			config = optarg;
			break;
		case 'V':
		default:
			show_usage();
			break;
		}

	if (load_type || config) {
		fprintf(stderr, "-t and -C not supported\n");
		exit(EXIT_FAILURE);
	}

	if (showconfig)
		exit(EXIT_SUCCESS);
	
	if (list)
		exit(EXIT_SUCCESS);
	
	if (remove_opt) {
		do {
			snprintf(cmd, sizeof(cmd)-1, "rmmod %s %s %s",
					optind >= argc ? "-a" : "",
					do_syslog ? "-s" : "",
					optind < argc ? argv[optind] : "");
			if (do_syslog)
				syslog(LOG_INFO, "%s", cmd);
			if (verbose)
				printf("%s\n", cmd);
			if (!show_only)
				rc = system(cmd);
				
#ifdef BB_FEATURE_MODPROBE_DEPEND
			if ( optind < argc )
				check_dep ( argv [optind], do_syslog, show_only, verbose, MODPROBE_REMOVE);
#endif				
		} while (++optind < argc);
		exit(EXIT_SUCCESS);
	}

	if (optind >= argc) {
		fprintf(stderr, "No module or pattern provided\n");
		exit(EXIT_FAILURE);
	}

	snprintf(cmd, sizeof(cmd)-1, "insmod %s %s %s",
			do_syslog ? "-s" : "",
			quiet ? "-q" : "",
			autoclean ? "-k" : "");

#ifdef BB_FEATURE_MODPROBE_DEPEND
	check_dep ( argv [optind], do_syslog, show_only, verbose, MODPROBE_INSERT);
#endif

	while (optind < argc) {
		if (strlen(cmd) + 1 + strlen(argv[optind]) >= sizeof(cmd))
		{
			error_msg_and_die("Too many module parameters!\n");
		}
		strcat(cmd, " ");
		strcat(cmd, argv[optind]);
		optind++;
	}
	if (do_syslog)
		syslog(LOG_INFO, "%s", cmd);
	if (verbose)
		printf("%s\n", cmd);
	if (!show_only)
		rc = system(cmd);
	else
		rc = 0;

	exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
}
Beispiel #3
0
static int
check_dep (struct file *file, unsigned int depth,
           FILE_TIMESTAMP this_mtime, int *must_make_ptr)
{
  struct file *ofile;
  struct dep *d;
  int dep_status = 0;

  ++depth;
  start_updating (file);

  /* We might change file if we find a different one via vpath;
     remember this one to turn off updating.  */
  ofile = file;

  if (file->phony || !file->intermediate)
    {
      /* If this is a non-intermediate file, update it and record whether it
         is newer than THIS_MTIME.  */
      FILE_TIMESTAMP mtime;
      dep_status = update_file (file, depth);
      check_renamed (file);
      mtime = file_mtime (file);
      check_renamed (file);
      if (mtime == NONEXISTENT_MTIME || mtime > this_mtime)
	*must_make_ptr = 1;
    }
  else
    {
      /* FILE is an intermediate file.  */
      FILE_TIMESTAMP mtime;

      if (!file->phony && file->cmds == 0 && !file->tried_implicit)
	{
	  if (try_implicit_rule (file, depth))
	    DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n"));
	  else
	    DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n"));
	  file->tried_implicit = 1;
	}
      if (file->cmds == 0 && !file->is_target
	  && default_file != 0 && default_file->cmds != 0)
	{
	  DBF (DB_IMPLICIT, _("Using default commands for '%s'.\n"));
	  file->cmds = default_file->cmds;
	}

      check_renamed (file);
      mtime = file_mtime (file);
      check_renamed (file);
      if (mtime != NONEXISTENT_MTIME && mtime > this_mtime)
        /* If the intermediate file actually exists and is newer, then we
           should remake from it.  */
	*must_make_ptr = 1;
      else
	{
          /* Otherwise, update all non-intermediate files we depend on, if
             necessary, and see whether any of them is more recent than the
             file on whose behalf we are checking.  */
	  struct dep *ld;
          int deps_running = 0;

          /* If this target is not running, set it's state so that we check it
             fresh.  It could be it was checked as part of an order-only
             prerequisite and so wasn't rebuilt then, but should be now.  */
          if (file->command_state != cs_running)
            set_command_state (file, cs_not_started);

	  ld = 0;
	  d = file->deps;
	  while (d != 0)
	    {
              int maybe_make;

	      if (is_updating (d->file))
		{
		  error (NILF, _("Circular %s <- %s dependency dropped."),
			 file->name, d->file->name);
		  if (ld == 0)
		    {
		      file->deps = d->next;
                      free_dep (d);
		      d = file->deps;
		    }
		  else
		    {
		      ld->next = d->next;
                      free_dep (d);
		      d = ld->next;
		    }
		  continue;
		}

	      d->file->parent = file;
              maybe_make = *must_make_ptr;
	      dep_status |= check_dep (d->file, depth, this_mtime,
                                       &maybe_make);
              if (! d->ignore_mtime)
                *must_make_ptr = maybe_make;
	      check_renamed (d->file);
	      if (dep_status != 0 && !keep_going_flag)
		break;

	      if (d->file->command_state == cs_running
		  || d->file->command_state == cs_deps_running)
		deps_running = 1;

	      ld = d;
	      d = d->next;
	    }

          if (deps_running)
            /* Record that some of FILE's deps are still being made.
               This tells the upper levels to wait on processing it until the
               commands are finished.  */
            set_command_state (file, cs_deps_running);
	}
    }

  finish_updating (file);
  finish_updating (ofile);

  return dep_status;
}
Beispiel #4
0
static int
update_file_1 (struct file *file, unsigned int depth)
{
  FILE_TIMESTAMP this_mtime;
  int noexist, must_make, deps_changed;
  int dep_status = 0;
  struct file *ofile;
  struct dep *d, *ad;
  struct dep amake;
  int running = 0;

  DBF (DB_VERBOSE, _("Considering target file '%s'.\n"));

  if (file->updated)
    {
      if (file->update_status > 0)
	{
	  DBF (DB_VERBOSE,
               _("Recently tried and failed to update file '%s'.\n"));

          /* If the file we tried to make is marked no_diag then no message
             was printed about it when it failed during the makefile rebuild.
             If we're trying to build it again in the normal rebuild, print a
             message now.  */
          if (file->no_diag && !file->dontcare)
              complain (file);

	  return file->update_status;
	}

      DBF (DB_VERBOSE, _("File '%s' was considered already.\n"));
      return 0;
    }

  switch (file->command_state)
    {
    case cs_not_started:
    case cs_deps_running:
      break;
    case cs_running:
      DBF (DB_VERBOSE, _("Still updating file '%s'.\n"));
      return 0;
    case cs_finished:
      DBF (DB_VERBOSE, _("Finished updating file '%s'.\n"));
      return file->update_status;
    default:
      abort ();
    }

  /* Determine whether the diagnostics will be issued should this update
     fail. */
  file->no_diag = file->dontcare;

  ++depth;

  /* Notice recursive update of the same file.  */
  start_updating (file);

  /* We might change file if we find a different one via vpath;
     remember this one to turn off updating.  */
  ofile = file;

  /* Looking at the file's modtime beforehand allows the possibility
     that its name may be changed by a VPATH search, and thus it may
     not need an implicit rule.  If this were not done, the file
     might get implicit commands that apply to its initial name, only
     to have that name replaced with another found by VPATH search.  */

  this_mtime = file_mtime (file);
  check_renamed (file);
  noexist = this_mtime == NONEXISTENT_MTIME;
  if (noexist)
    DBF (DB_BASIC, _("File '%s' does not exist.\n"));
  else if (ORDINARY_MTIME_MIN <= this_mtime && this_mtime <= ORDINARY_MTIME_MAX
	   && file->low_resolution_time)
    {
      /* Avoid spurious rebuilds due to low resolution time stamps.  */
      int ns = FILE_TIMESTAMP_NS (this_mtime);
      if (ns != 0)
	error (NILF, _("*** Warning: .LOW_RESOLUTION_TIME file '%s' has a high resolution time stamp"),
	       file->name);
      this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns;
    }

  must_make = noexist;

  /* If file was specified as a target with no commands,
     come up with some default commands.  */

  if (!file->phony && file->cmds == 0 && !file->tried_implicit)
    {
      if (try_implicit_rule (file, depth))
	DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n"));
      else
	DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n"));
      file->tried_implicit = 1;
    }
  if (file->cmds == 0 && !file->is_target
      && default_file != 0 && default_file->cmds != 0)
    {
      DBF (DB_IMPLICIT, _("Using default recipe for '%s'.\n"));
      file->cmds = default_file->cmds;
    }

  /* Update all non-intermediate files we depend on, if necessary, and see
     whether any of them is more recent than this file.  We need to walk our
     deps, AND the deps of any also_make targets to ensure everything happens
     in the correct order.  */

  amake.file = file;
  amake.next = file->also_make;
  ad = &amake;
  while (ad)
    {
      struct dep *lastd = 0;

      /* Find the deps we're scanning */
      d = ad->file->deps;
      ad = ad->next;

      while (d)
        {
          FILE_TIMESTAMP mtime;
          int maybe_make;
          int dontcare = 0;

          check_renamed (d->file);

          mtime = file_mtime (d->file);
          check_renamed (d->file);

          if (is_updating (d->file))
            {
              error (NILF, _("Circular %s <- %s dependency dropped."),
                     file->name, d->file->name);
              /* We cannot free D here because our the caller will still have
                 a reference to it when we were called recursively via
                 check_dep below.  */
              if (lastd == 0)
                file->deps = d->next;
              else
                lastd->next = d->next;
              d = d->next;
              continue;
            }

          d->file->parent = file;
          maybe_make = must_make;

          /* Inherit dontcare flag from our parent. */
          if (rebuilding_makefiles)
            {
              dontcare = d->file->dontcare;
              d->file->dontcare = file->dontcare;
            }

          dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make);

          /* Restore original dontcare flag. */
          if (rebuilding_makefiles)
            d->file->dontcare = dontcare;

          if (! d->ignore_mtime)
            must_make = maybe_make;

          check_renamed (d->file);

          {
            register struct file *f = d->file;
            if (f->double_colon)
              f = f->double_colon;
            do
              {
                running |= (f->command_state == cs_running
                            || f->command_state == cs_deps_running);
                f = f->prev;
              }
            while (f != 0);
          }

          if (dep_status != 0 && !keep_going_flag)
            break;

          if (!running)
            /* The prereq is considered changed if the timestamp has changed while
               it was built, OR it doesn't exist.  */
            d->changed = ((file_mtime (d->file) != mtime)
                          || (mtime == NONEXISTENT_MTIME));

          lastd = d;
          d = d->next;
        }
    }

  /* Now we know whether this target needs updating.
     If it does, update all the intermediate files we depend on.  */

  if (must_make || always_make_flag)
    {
      for (d = file->deps; d != 0; d = d->next)
	if (d->file->intermediate)
	  {
            int dontcare = 0;

	    FILE_TIMESTAMP mtime = file_mtime (d->file);
	    check_renamed (d->file);
	    d->file->parent = file;

            /* Inherit dontcare flag from our parent. */
            if (rebuilding_makefiles)
              {
                dontcare = d->file->dontcare;
                d->file->dontcare = file->dontcare;
              }


	    dep_status |= update_file (d->file, depth);

            /* Restore original dontcare flag. */
            if (rebuilding_makefiles)
              d->file->dontcare = dontcare;

	    check_renamed (d->file);

	    {
	      register struct file *f = d->file;
	      if (f->double_colon)
		f = f->double_colon;
	      do
		{
		  running |= (f->command_state == cs_running
			      || f->command_state == cs_deps_running);
		  f = f->prev;
		}
	      while (f != 0);
	    }

	    if (dep_status != 0 && !keep_going_flag)
	      break;

	    if (!running)
	      d->changed = ((file->phony && file->cmds != 0)
			    || file_mtime (d->file) != mtime);
	  }
    }

  finish_updating (file);
  finish_updating (ofile);

  DBF (DB_VERBOSE, _("Finished prerequisites of target file '%s'.\n"));

  if (running)
    {
      set_command_state (file, cs_deps_running);
      --depth;
      DBF (DB_VERBOSE, _("The prerequisites of '%s' are being made.\n"));
      return 0;
    }

  /* If any dependency failed, give up now.  */

  if (dep_status != 0)
    {
      file->update_status = dep_status;
      notice_finished_file (file);

      --depth;

      DBF (DB_VERBOSE, _("Giving up on target file '%s'.\n"));

      if (depth == 0 && keep_going_flag
	  && !just_print_flag && !question_flag)
	error (NILF,
               _("Target '%s' not remade because of errors."), file->name);

      return dep_status;
    }

  if (file->command_state == cs_deps_running)
    /* The commands for some deps were running on the last iteration, but
       they have finished now.  Reset the command_state to not_started to
       simplify later bookkeeping.  It is important that we do this only
       when the prior state was cs_deps_running, because that prior state
       was definitely propagated to FILE's also_make's by set_command_state
       (called above), but in another state an also_make may have
       independently changed to finished state, and we would confuse that
       file's bookkeeping (updated, but not_started is bogus state).  */
    set_command_state (file, cs_not_started);

  /* Now record which prerequisites are more
     recent than this file, so we can define $?.  */

  deps_changed = 0;
  for (d = file->deps; d != 0; d = d->next)
    {
      FILE_TIMESTAMP d_mtime = file_mtime (d->file);
      check_renamed (d->file);

      if (! d->ignore_mtime)
        {
#if 1
          /* %%% In version 4, remove this code completely to
	   implement not remaking deps if their deps are newer
	   than their parents.  */
          if (d_mtime == NONEXISTENT_MTIME && !d->file->intermediate)
            /* We must remake if this dep does not
               exist and is not intermediate.  */
            must_make = 1;
#endif

          /* Set DEPS_CHANGED if this dep actually changed.  */
          deps_changed |= d->changed;
        }

      /* Set D->changed if either this dep actually changed,
	 or its dependent, FILE, is older or does not exist.  */
      d->changed |= noexist || d_mtime > this_mtime;

      if (!noexist && ISDB (DB_BASIC|DB_VERBOSE))
	{
          const char *fmt = 0;

          if (d->ignore_mtime)
            {
              if (ISDB (DB_VERBOSE))
                fmt = _("Prerequisite '%s' is order-only for target '%s'.\n");
            }
          else if (d_mtime == NONEXISTENT_MTIME)
            {
              if (ISDB (DB_BASIC))
                fmt = _("Prerequisite '%s' of target '%s' does not exist.\n");
            }
	  else if (d->changed)
            {
              if (ISDB (DB_BASIC))
                fmt = _("Prerequisite '%s' is newer than target '%s'.\n");
            }
          else if (ISDB (DB_VERBOSE))
            fmt = _("Prerequisite '%s' is older than target '%s'.\n");

          if (fmt)
            {
              print_spaces (depth);
              printf (fmt, dep_name (d), file->name);
              fflush (stdout);
            }
	}
    }

  /* Here depth returns to the value it had when we were called.  */
  depth--;

  if (file->double_colon && file->deps == 0)
    {
      must_make = 1;
      DBF (DB_BASIC,
           _("Target '%s' is double-colon and has no prerequisites.\n"));
    }
  else if (!noexist && file->is_target && !deps_changed && file->cmds == 0
           && !always_make_flag)
    {
      must_make = 0;
      DBF (DB_VERBOSE,
           _("No recipe for '%s' and no prerequisites actually changed.\n"));
    }
  else if (!must_make && file->cmds != 0 && always_make_flag)
    {
      must_make = 1;
      DBF (DB_VERBOSE, _("Making '%s' due to always-make flag.\n"));
    }

  if (!must_make)
    {
      if (ISDB (DB_VERBOSE))
        {
          print_spaces (depth);
          printf (_("No need to remake target '%s'"), file->name);
          if (!streq (file->name, file->hname))
              printf (_("; using VPATH name '%s'"), file->hname);
          puts (".");
          fflush (stdout);
        }

      notice_finished_file (file);

      /* Since we don't need to remake the file, convert it to use the
         VPATH filename if we found one.  hfile will be either the
         local name if no VPATH or the VPATH name if one was found.  */

      while (file)
        {
          file->name = file->hname;
          file = file->prev;
        }

      return 0;
    }

  DBF (DB_BASIC, _("Must remake target '%s'.\n"));

  /* It needs to be remade.  If it's VPATH and not reset via GPATH, toss the
     VPATH.  */
  if (!streq(file->name, file->hname))
    {
      DB (DB_BASIC, (_("  Ignoring VPATH name '%s'.\n"), file->hname));
      file->ignore_vpath = 1;
    }

  /* Now, take appropriate actions to remake the file.  */
  remake_file (file);

  if (file->command_state != cs_finished)
    {
      DBF (DB_VERBOSE, _("Recipe of '%s' is being run.\n"));
      return 0;
    }

  switch (file->update_status)
    {
    case 2:
      DBF (DB_BASIC, _("Failed to remake target file '%s'.\n"));
      break;
    case 0:
      DBF (DB_BASIC, _("Successfully remade target file '%s'.\n"));
      break;
    case 1:
      DBF (DB_BASIC, _("Target file '%s' needs remade under -q.\n"));
      break;
    default:
      assert (file->update_status >= 0 && file->update_status <= 2);
      break;
    }

  file->updated = 1;
  return file->update_status;
}
static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t **tail )
{
	struct mod_list_t *find;
	struct dep_t *dt;

	int lm;

	// remove .o extension
	lm = xstrlen ( mod );
	if (( mod [lm-2] == '.' ) && ( mod [lm-1] == 'o' ))
		mod [lm-2] = 0;

	// check dependencies
	for ( dt = depend; dt; dt = dt-> m_next ) {
		if ( strcmp ( dt-> m_module, mod ) == 0 ) 
			break;
	}
	// resolve alias names
	if ( dt && dt-> m_isalias ) {
		if ( dt-> m_depcnt == 1 )
			check_dep ( dt-> m_deparr [0], head, tail );
		printf ( "Got alias: %s -> %s\n", mod, dt-> m_deparr [0] );
			
		return;
	}
	
	// search for duplicates
	for ( find = *head; find; find = find-> m_next ) {
		if ( !strcmp ( mod, find-> m_module )) {
			// found -> dequeue it

			if ( find-> m_prev )
				find-> m_prev-> m_next = find-> m_next;
			else
				*head = find-> m_next;
					
			if ( find-> m_next )
				find-> m_next-> m_prev = find-> m_prev;
			else
				*tail = find-> m_prev;
					
			break; // there can be only one duplicate
		}				
	}

	if ( !find ) { // did not find a duplicate
		find = (struct mod_list_t *) xmalloc ( sizeof(struct mod_list_t));		
		find-> m_module = mod;
	}

	// enqueue at tail	
	if ( *tail )
		(*tail)-> m_next = find;
	find-> m_prev   = *tail;
	find-> m_next   = 0;

	if ( !*head )
		*head = find;
	*tail = find;
		
	if ( dt ) {	
		int i;
		
		for ( i = 0; i < dt-> m_depcnt; i++ )
			check_dep ( dt-> m_deparr [i], head, tail );
	}
}
Beispiel #6
0
/*
 * Builds the dependency list (aka stack) of a module.
 * head: the highest module in the stack (last to insmod, first to rmmod)
 * tail: the lowest module in the stack (first to insmod, last to rmmod)
 */
static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t **tail )
{
	struct mod_list_t *find;
	struct dep_t *dt;
	struct mod_opt_t *opt = 0;
	char *path = 0;

	/* Search for the given module name amongst all dependency rules.
	 * The module name in a dependency rule can be a shell pattern,
	 * so try to match the given module name against such a pattern.
	 * Of course if the name in the dependency rule is a plain string,
	 * then we consider it a pattern, and matching will still work. */
	for ( dt = depend; dt; dt = dt-> m_next ) {
		if ( fnmatch ( dt-> m_name, mod, 0 ) == 0) {
			break;
		}
	}

	if( !dt ) {
		bb_error_msg ("module %s not found.", mod);
		return;
	}

	// resolve alias names
	while ( dt-> m_isalias ) {
		if ( dt-> m_depcnt == 1 ) {
			struct dep_t *adt;

			for ( adt = depend; adt; adt = adt-> m_next ) {
				if ( strcmp ( adt-> m_name, dt-> m_deparr [0] ) == 0 )
					break;
			}
			if ( adt ) {
				/* This is the module we are aliased to */
				struct mod_opt_t *opts = dt-> m_options;
				/* Option of the alias are appended to the options of the module */
				while( opts ) {
					adt-> m_options = append_option( adt-> m_options, opts-> m_opt_val );
					opts = opts-> m_next;
				}
				dt = adt;
			}
			else {
				bb_error_msg ("module %s not found.", mod);
				return;
			}
		}
		else {
			bb_error_msg ("Bad alias %s", dt-> m_name);
			return;
		}
	}

	mod = dt-> m_name;
	path = dt-> m_path;
	opt = dt-> m_options;

	// search for duplicates
	for ( find = *head; find; find = find-> m_next ) {
		if ( !strcmp ( mod, find-> m_name )) {
			// found -> dequeue it

			if ( find-> m_prev )
				find-> m_prev-> m_next = find-> m_next;
			else
				*head = find-> m_next;

			if ( find-> m_next )
				find-> m_next-> m_prev = find-> m_prev;
			else
				*tail = find-> m_prev;

			break; // there can be only one duplicate
		}
	}

	if ( !find ) { // did not find a duplicate
		find = (struct mod_list_t *) xmalloc ( sizeof(struct mod_list_t));
		find-> m_name = mod;
		find-> m_path = path;
		find-> m_options = opt;
	}

	// enqueue at tail
	if ( *tail )
		(*tail)-> m_next = find;
	find-> m_prev   = *tail;
	find-> m_next   = 0;

	if ( !*head )
		*head = find;
	*tail = find;

	if ( dt ) {
		int i;

		/* Add all dependable module for that new module */
		for ( i = 0; i < dt-> m_depcnt; i++ )
			check_dep ( dt-> m_deparr [i], head, tail );
	}
}