Beispiel #1
0
static int
touch_file (struct file *file)
{
  if (!silent_flag)
    message (0, "touch %s", file->name);

  /* Print-only (-n) takes precedence over touch (-t).  */
  if (just_print_flag)
    return 0;

#ifndef	NO_ARCHIVES
  if (ar_name (file->name))
    return ar_touch (file->name);
  else
#endif
    {
      int fd = open (file->name, O_RDWR | O_CREAT, 0666);

      if (fd < 0)
	TOUCH_ERROR ("touch: open: ");
      else
	{
	  struct stat statbuf;
	  char buf = 'x';
          int e;

          EINTRLOOP (e, fstat (fd, &statbuf));
	  if (e < 0)
	    TOUCH_ERROR ("touch: fstat: ");
	  /* Rewrite character 0 same as it already is.  */
	  if (read (fd, &buf, 1) < 0)
	    TOUCH_ERROR ("touch: read: ");
	  if (lseek (fd, 0L, 0) < 0L)
	    TOUCH_ERROR ("touch: lseek: ");
	  if (write (fd, &buf, 1) < 0)
	    TOUCH_ERROR ("touch: write: ");
	  /* If file length was 0, we just
	     changed it, so change it back.  */
	  if (statbuf.st_size == 0)
	    {
	      (void) close (fd);
	      fd = open (file->name, O_RDWR | O_TRUNC, 0666);
	      if (fd < 0)
		TOUCH_ERROR ("touch: open: ");
	    }
	  (void) close (fd);
	}
    }

  return 0;
}
Beispiel #2
0
static void
delete_target (struct file *file, const char *on_behalf_of)
{
  struct stat st;
  int e;

	if (file->precious || file->phony) {
		return;
	}

#ifndef NO_ARCHIVES
  if (ar_name (file->name))
    {
      time_t file_date = (file->last_mtime == NONEXISTENT_MTIME
			  ? (time_t) -1
			  : (time_t) FILE_TIMESTAMP_S (file->last_mtime));
      if (ar_member_date (file->name) != file_date)
	{
		if (on_behalf_of) {
	    error (NILF, _("*** [%s] Archive member `%s' may be bogus; not deleted"),
		   on_behalf_of, file->name);
		} else {
	    error (NILF, _("*** Archive member `%s' may be bogus; not deleted"),
		   file->name);
		}
	}
      return;
    }
#endif	/* !NO_ARCHIVES.  */

  EINTRLOOP (e, stat (file->name, &st));
  if (e == 0
      && S_ISREG (st.st_mode)
#ifdef ST_MTIM_NSEC
      && FILE_TIMESTAMP_STAT_MODTIME (file->name, st) != file->last_mtime
#endif /* ST_MTIM_NSEC */
	  && e != 1)
    {
		if (on_behalf_of) {
	error (NILF, _("*** [%s] Deleting file `%s'"), on_behalf_of, file->name);
		} else
	error (NILF, _("*** Deleting file `%s'"), file->name);
      if (unlink (file->name) < 0
	  && errno != ENOENT)	/* It disappeared; so what.  */
	perror_with_name ("unlink: ", file->name);
    }
}
Beispiel #3
0
unsigned long AddModule(unsigned long mod_start, unsigned long mod_end, unsigned long end)
{
    char *p = (char *)mod_start;

    if (p[0] == 0x7f && p[1] == 'E' && p[2] == 'L' && p[3] == 'F')
    {
        /* 
         * The loaded file is an ELF object. It may be put directly into our list of modules.
         * Unfortunately GRUB doesn't give us names of loaded modules
         */
        struct ELFNode *mo = module_prepare(NULL);

        mo->Name = "Kickstart ELF";
        mo->eh = (void*)mod_start;

        D(kprintf("[BOOT] * ELF module %s @ %p\n", mo->Name, mo->eh));

	if (mod_end > end)
	    end = mod_end;
    }
    else if (p[0] == 'P' && p[1] == 'K' && p[2] == 'G' && p[3] == 0x01)
    {
        /* 
         * The loaded file is an PKG\0 archive. Scan it to find all modules which are 
         * stored here.
         */
        void *file = p + 8;

        D(kprintf("[BOOT] * package @ %p:\n", mod_start));

        while (file < (void*)mod_end)
        {
            int len = LONG2BE(*(int *)file);
            char *s = __bs_remove_path(file+4);
            struct ELFNode *mo = module_prepare(s);

            file += 5+len;
            len = LONG2BE(*(int *)file);
            file += 4;

            mo->Name = s;
            mo->eh = file;
            D(kprintf("[BOOT]   * PKG module %s @ %p\n", mo->Name, mo->eh));

            file += len;
        }

	if (mod_end > end)
	    end = mod_end;
    }
    else if (memcmp(p,"!<arch>\n",8) == 0) {
        const struct ar_header *file;
        char *name;
        const struct ar_header *longnames = NULL;

        /* ar(1) archive */
        D(kprintf("[BOOT] * archive @ %p:\n", mod_start));

        /* Look for the GNU extended name section */
        for (file = (void *)(p + 8); (void *)file < (void*)mod_end; file = ar_next(file))
        {
            name = ar_name(file, NULL);
            if (strcmp(name, "//") == 0)
            {
                longnames = file;
                break;
            }
        }
        D(kprintf("[BOOT] *   longnames @ %p\n", longnames));

        for (file = (void *)(p + 8); (void *)file < (void*)mod_end; file = ar_next(file))
        {
            const char *data = ar_data(file);
            char *s = ar_name(file, longnames);

            if (memcmp(data,"\177ELF",4) == 0) {
                struct ELFNode *mo = module_prepare(s);

                mo->Name = s;
                mo->eh = (void *)data;
                D(kprintf("[BOOT] *   ar module %s @ %p\n", mo->Name, mo->eh));
            } else {
                D(kprintf("[BOOT] *   Ignored @ %p (%s)\n", file, s));
            }
        }

	if (mod_end > end)
	    end = mod_end;

    }
    else
       	kprintf("[BOOT] Unknown module 0x%p\n", p);

    return end;
}
Beispiel #4
0
FILE_TIMESTAMP
f_mtime (struct file *file, int search)
{
  FILE_TIMESTAMP mtime;

  /* File's mtime is not known; must get it from the system.  */

#ifndef	NO_ARCHIVES
  if (ar_name (file->name))
    {
      /* This file is an archive-member reference.  */

      char *arname, *memname;
      struct file *arfile;
      time_t member_date;

      /* Find the archive's name.  */
      ar_parse_name (file->name, &arname, &memname);

      /* Find the modification time of the archive itself.
	 Also allow for its name to be changed via VPATH search.  */
      arfile = lookup_file (arname);
      if (arfile == 0)
        arfile = enter_file (strcache_add (arname));
      mtime = f_mtime (arfile, search);
      check_renamed (arfile);
      if (search && strcmp (arfile->hname, arname))
	{
	  /* The archive's name has changed.
	     Change the archive-member reference accordingly.  */

          char *name;
	  unsigned int arlen, memlen;

	  arlen = strlen (arfile->hname);
	  memlen = strlen (memname);

	  name = xmalloc (arlen + 1 + memlen + 2);
	  memcpy (name, arfile->hname, arlen);
	  name[arlen] = '(';
	  memcpy (name + arlen + 1, memname, memlen);
	  name[arlen + 1 + memlen] = ')';
	  name[arlen + 1 + memlen + 1] = '\0';

          /* If the archive was found with GPATH, make the change permanent;
             otherwise defer it until later.  */
          if (arfile->name == arfile->hname)
            rename_file (file, name);
          else
            rehash_file (file, name);
          check_renamed (file);
	}

      free (arname);

      file->low_resolution_time = 1;

      if (mtime == NONEXISTENT_MTIME)
	/* The archive doesn't exist, so its members don't exist either.  */
	return NONEXISTENT_MTIME;

      member_date = ar_member_date (file->hname);
      mtime = (member_date == (time_t) -1
               ? NONEXISTENT_MTIME
               : file_timestamp_cons (file->hname, member_date, 0));
    }
  else
#endif
    {
      mtime = name_mtime (file->name);

      if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath)
	{
	  /* If name_mtime failed, search VPATH.  */
	  const char *name = vpath_search (file->name, &mtime, NULL, NULL);
	  if (name
	      /* Last resort, is it a library (-lxxx)?  */
	      || (file->name[0] == '-' && file->name[1] == 'l'
		  && (name = library_search (file->name, &mtime)) != 0))
	    {
	      if (mtime != UNKNOWN_MTIME)
		/* vpath_search and library_search store UNKNOWN_MTIME
		   if they didn't need to do a stat call for their work.  */
		file->last_mtime = mtime;

              /* If we found it in VPATH, see if it's in GPATH too; if so,
                 change the name right now; if not, defer until after the
                 dependencies are updated. */
              if (gpath_search (name, strlen(name) - strlen(file->name) - 1))
                {
                  rename_file (file, name);
                  check_renamed (file);
                  return file_mtime (file);
                }

	      rehash_file (file, name);
	      check_renamed (file);
              /* If the result of a vpath search is -o or -W, preserve it.
                 Otherwise, find the mtime of the resulting file.  */
              if (mtime != OLD_MTIME && mtime != NEW_MTIME)
                mtime = name_mtime (name);
	    }
	}
    }

  /* Files can have bogus timestamps that nothing newly made will be
     "newer" than.  Updating their dependents could just result in loops.
     So notify the user of the anomaly with a warning.

     We only need to do this once, for now. */

  if (!clock_skew_detected
      && mtime != NONEXISTENT_MTIME && mtime != NEW_MTIME
      && !file->updated)
    {
      static FILE_TIMESTAMP adjusted_now;

      FILE_TIMESTAMP adjusted_mtime = mtime;

#if defined(WINDOWS32) || defined(__MSDOS__)
      /* Experimentation has shown that FAT filesystems can set file times
         up to 3 seconds into the future!  Play it safe.  */

#define FAT_ADJ_OFFSET  (FILE_TIMESTAMP) 3

      FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS;
      if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime)
        adjusted_mtime -= adjustment;
#elif defined(__EMX__)
      /* FAT filesystems round time to the nearest even second!
         Allow for any file (NTFS or FAT) to perhaps suffer from this
         brain damage.  */
      FILE_TIMESTAMP adjustment = (((FILE_TIMESTAMP_S (adjusted_mtime) & 1) == 0
                     && FILE_TIMESTAMP_NS (adjusted_mtime) == 0)
                    ? (FILE_TIMESTAMP) 1 << FILE_TIMESTAMP_LO_BITS
                    : 0);
#endif

      /* If the file's time appears to be in the future, update our
         concept of the present and try once more.  */
      if (adjusted_now < adjusted_mtime)
        {
          int resolution;
          FILE_TIMESTAMP now = file_timestamp_now (&resolution);
          adjusted_now = now + (resolution - 1);
          if (adjusted_now < adjusted_mtime)
            {
#ifdef NO_FLOAT
              error (NILF, _("Warning: File '%s' has modification time in the future"),
                     file->name);
#else
              double from_now =
                (FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now)
                 + ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now))
                    / 1e9));
              char from_now_string[100];

              if (from_now >= 99 && from_now <= ULONG_MAX)
                sprintf (from_now_string, "%lu", (unsigned long) from_now);
              else
                sprintf (from_now_string, "%.2g", from_now);
              error (NILF, _("Warning: File '%s' has modification time %s s in the future"),
                     file->name, from_now_string);
#endif
              clock_skew_detected = 1;
            }
        }
    }

  /* Store the mtime into all the entries for this file.  */
  if (file->double_colon)
    file = file->double_colon;

  do
    {
      /* If this file is not implicit but it is intermediate then it was
	 made so by the .INTERMEDIATE target.  If this file has never
	 been built by us but was found now, it existed before make
	 started.  So, turn off the intermediate bit so make doesn't
	 delete it, since it didn't create it.  */
      if (mtime != NONEXISTENT_MTIME && file->command_state == cs_not_started
	  && file->command_state == cs_not_started
	  && !file->tried_implicit && file->intermediate)
	file->intermediate = 0;

      file->last_mtime = mtime;
      file = file->prev;
    }
  while (file != 0);

  return mtime;
}
Beispiel #5
0
void
set_file_variables (struct file *file)
{
    struct dep *d;
    const char *at, *percent, *star, *less;

#ifndef	NO_ARCHIVES
    /* If the target is an archive member `lib(member)',
       then $@ is `lib' and $% is `member'.  */

    if (ar_name (file->name))
    {
        unsigned int len;
        const char *cp;
        char *p;

        cp = strchr (file->name, '(');
        p = alloca (cp - file->name + 1);
        memcpy (p, file->name, cp - file->name);
        p[cp - file->name] = '\0';
        at = p;
        len = strlen (cp + 1);
        p = alloca (len);
        memcpy (p, cp + 1, len - 1);
        p[len - 1] = '\0';
        percent = p;
    }
    else
#endif	/* NO_ARCHIVES.  */
    {
        at = file->name;
        percent = "";
    }

    /* $* is the stem from an implicit or static pattern rule.  */
    if (file->stem == 0)
    {
        /* In Unix make, $* is set to the target name with
        any suffix in the .SUFFIXES list stripped off for
         explicit rules.  We store this in the `stem' member.  */
        const char *name;
        unsigned int len;

#ifndef	NO_ARCHIVES
        if (ar_name (file->name))
        {
            name = strchr (file->name, '(') + 1;
            len = strlen (name) - 1;
        }
        else
#endif
        {
            name = file->name;
            len = strlen (name);
        }

        for (d = enter_file (strcache_add (".SUFFIXES"))->deps; d ; d = d->next)
        {
            unsigned int slen = strlen (dep_name (d));
            if (len > slen && strneq (dep_name (d), name + (len - slen), slen))
            {
                file->stem = strcache_add_len (name, len - slen);
                break;
            }
        }
        if (d == 0)
            file->stem = "";
    }
    star = file->stem;

    /* $< is the first not order-only dependency.  */
    less = "";
    for (d = file->deps; d != 0; d = d->next)
        if (!d->ignore_mtime)
        {
            if (!d->need_2nd_expansion)
                less = dep_name (d);
            break;
        }

    if (file->cmds == default_file->cmds)
        /* This file got its commands from .DEFAULT.
           In this case $< is the same as $@.  */
        less = at;

#define	DEFINE_VARIABLE(name, len, value) \
  (void) define_variable_for_file (name,len,value,o_automatic,0,file)

    /* Define the variables.  */

    DEFINE_VARIABLE ("<", 1, less);
    DEFINE_VARIABLE ("*", 1, star);
    DEFINE_VARIABLE ("@", 1, at);
    DEFINE_VARIABLE ("%", 1, percent);

    /* Compute the values for $^, $+, $?, and $|.  */

    {
        static char *plus_value=0, *bar_value=0, *qmark_value=0;
        static unsigned int plus_max=0, bar_max=0, qmark_max=0;

        unsigned int qmark_len, plus_len, bar_len;
        char *cp;
        char *caret_value;
        char *qp;
        char *bp;
        unsigned int len;

        struct hash_table dep_hash;
        void **slot;

        /* Compute first the value for $+, which is supposed to contain
           duplicate dependencies as they were listed in the makefile.  */

        plus_len = 0;
        bar_len = 0;
        for (d = file->deps; d != 0; d = d->next)
        {
            if (!d->need_2nd_expansion)
            {
                if (d->ignore_mtime)
                    bar_len += strlen (dep_name (d)) + 1;
                else
                    plus_len += strlen (dep_name (d)) + 1;
            }
        }

        if (bar_len == 0)
            bar_len++;

        if (plus_len == 0)
            plus_len++;

        if (plus_len > plus_max)
            plus_value = xrealloc (plus_value, plus_max = plus_len);

        cp = plus_value;

        qmark_len = plus_len + 1;	/* Will be this or less.  */
        for (d = file->deps; d != 0; d = d->next)
            if (! d->ignore_mtime && ! d->need_2nd_expansion)
            {
                const char *c = dep_name (d);

#ifndef	NO_ARCHIVES
                if (ar_name (c))
                {
                    c = strchr (c, '(') + 1;
                    len = strlen (c) - 1;
                }
                else
#endif
                    len = strlen (c);

                memcpy (cp, c, len);
                cp += len;
                *cp++ = FILE_LIST_SEPARATOR;
                if (! (d->changed || always_make_flag))
                    qmark_len -= len + 1;	/* Don't space in $? for this one.  */
            }

        /* Kill the last space and define the variable.  */

        cp[cp > plus_value ? -1 : 0] = '\0';
        DEFINE_VARIABLE ("+", 1, plus_value);

        /* Compute the values for $^, $?, and $|.  */

        cp = caret_value = plus_value; /* Reuse the buffer; it's big enough.  */

        if (qmark_len > qmark_max)
            qmark_value = xrealloc (qmark_value, qmark_max = qmark_len);
        qp = qmark_value;

        if (bar_len > bar_max)
            bar_value = xrealloc (bar_value, bar_max = bar_len);
        bp = bar_value;

        /* Make sure that no dependencies are repeated in $^, $?, and $|.  It
           would be natural to combine the next two loops but we can't do it
           because of a situation where we have two dep entries, the first
           is order-only and the second is normal (see below).  */

        hash_init (&dep_hash, 500, dep_hash_1, dep_hash_2, dep_hash_cmp);

        for (d = file->deps; d != 0; d = d->next)
        {
            if (d->need_2nd_expansion)
                continue;

            slot = hash_find_slot (&dep_hash, d);
            if (HASH_VACANT (*slot))
                hash_insert_at (&dep_hash, d, slot);
            else
            {
                /* Check if the two prerequisites have different ignore_mtime.
                   If so then we need to "upgrade" one that is order-only.  */

                struct dep* hd = (struct dep*) *slot;

                if (d->ignore_mtime != hd->ignore_mtime)
                    d->ignore_mtime = hd->ignore_mtime = 0;
            }
        }

        for (d = file->deps; d != 0; d = d->next)
        {
            const char *c;

            if (d->need_2nd_expansion || hash_find_item (&dep_hash, d) != d)
                continue;

            c = dep_name (d);
#ifndef	NO_ARCHIVES
            if (ar_name (c))
            {
                c = strchr (c, '(') + 1;
                len = strlen (c) - 1;
            }
            else
#endif
                len = strlen (c);

            if (d->ignore_mtime)
            {
                memcpy (bp, c, len);
                bp += len;
                *bp++ = FILE_LIST_SEPARATOR;
            }
            else
            {
                memcpy (cp, c, len);
                cp += len;
                *cp++ = FILE_LIST_SEPARATOR;
                if (d->changed || always_make_flag)
                {
                    memcpy (qp, c, len);
                    qp += len;
                    *qp++ = FILE_LIST_SEPARATOR;
                }
            }
        }

        hash_free (&dep_hash, 0);

        /* Kill the last spaces and define the variables.  */

        cp[cp > caret_value ? -1 : 0] = '\0';
        DEFINE_VARIABLE ("^", 1, caret_value);

        qp[qp > qmark_value ? -1 : 0] = '\0';
        DEFINE_VARIABLE ("?", 1, qmark_value);

        bp[bp > bar_value ? -1 : 0] = '\0';
        DEFINE_VARIABLE ("|", 1, bar_value);
    }

#undef	DEFINE_VARIABLE
}