⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arch.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
    /*     * We don't have this archive on the list yet, so we want to find out     * everything that's in it and cache it so we can get at it quickly.     */    arch = fopen (archive, "r");    if (arch == (FILE *) NULL) {	return ((struct ar_hdr *) NULL);    }        /*     * We use the ARMAG string to make sure this is an archive we     * can handle...     */    if ((fread (magic, SARMAG, 1, arch) != 1) ||    	(strncmp (magic, ARMAG, SARMAG) != 0)) {	    fclose (arch);	    return ((struct ar_hdr *) NULL);    }    ar = (Arch *)emalloc (sizeof (Arch));    ar->name = strdup (archive);    Hash_InitTable (&ar->members, -1);    memName[AR_MAX_NAME_LEN] = '\0';        while (fread ((char *)&arh, sizeof (struct ar_hdr), 1, arch) == 1) {	if (strncmp ( arh.ar_fmag, ARFMAG, sizeof (arh.ar_fmag)) != 0) {				 /*				  * The header is bogus, so the archive is bad				  * and there's no way we can recover...				  */				 fclose (arch);				 Hash_DeleteTable (&ar->members);				 free ((Address)ar);				 return ((struct ar_hdr *) NULL);	} else {	    (void) strncpy (memName, arh.ar_name, sizeof(arh.ar_name));	    for (cp = &memName[AR_MAX_NAME_LEN]; *cp == ' '; cp--) {		continue;	    }	    cp[1] = '\0';	    he = Hash_CreateEntry (&ar->members, strdup (memName),				   (Boolean *)NULL);	    Hash_SetValue (he, (ClientData)emalloc (sizeof (struct ar_hdr)));	    memcpy ((Address)Hash_GetValue (he), (Address)&arh, 		sizeof (struct ar_hdr));	}	/*	 * We need to advance the stream's pointer to the start of the	 * next header. Files are padded with newlines to an even-byte	 * boundary, so we need to extract the size of the file from the	 * 'size' field of the header and round it up during the seek.	 */	arh.ar_size[sizeof(arh.ar_size)-1] = '\0';	(void) sscanf (arh.ar_size, "%10d", &size);	fseek (arch, (size + 1) & ~1, 1);    }    fclose (arch);    (void) Lst_AtEnd (archives, (ClientData) ar);    /*     * Now that the archive has been read and cached, we can look into     * the hash table to find the desired member's header.     */    he = Hash_FindEntry (&ar->members, member);    if (he != (Hash_Entry *) NULL) {	return ((struct ar_hdr *) Hash_GetValue (he));    } else {	return ((struct ar_hdr *) NULL);    }}/*- *----------------------------------------------------------------------- * ArchFindMember -- *	Locate a member of an archive, given the path of the archive and *	the path of the desired member. If the archive is to be modified, *	the mode should be "r+", if not, it should be "r". * * Results: *	An FILE *, opened for reading and writing, positioned at the *	start of the member's struct ar_hdr, or NULL if the member was *	nonexistent. The current struct ar_hdr for member. * * Side Effects: *	The passed struct ar_hdr structure is filled in. * *----------------------------------------------------------------------- */static FILE *ArchFindMember (archive, member, arhPtr, mode)    char	  *archive;   /* Path to the archive */    char	  *member;    /* Name of member. If it is a path, only the			       * last component is used. */    struct ar_hdr *arhPtr;    /* Pointer to header structure to be filled in */    char	  *mode;      /* The mode for opening the stream */{    FILE *	  arch;	      /* Stream to archive */    int		  size;       /* Size of archive member */    char	  *cp;	      /* Useful character pointer */    char	  magic[SARMAG];    int		  len;    arch = fopen (archive, mode);    if (arch == (FILE *) NULL) {	return ((FILE *) NULL);    }        /*     * We use the ARMAG string to make sure this is an archive we     * can handle...     */    if ((fread (magic, SARMAG, 1, arch) != 1) ||    	(strncmp (magic, ARMAG, SARMAG) != 0)) {	    fclose (arch);	    return ((FILE *) NULL);    }    /*     * Because of space constraints and similar things, files are archived     * using their final path components, not the entire thing, so we need     * to point 'member' to the final component, if there is one, to make     * the comparisons easier...     */    cp = strrchr (member, '/');    if (cp != (char *) NULL) {	member = cp + 1;    }    len = strlen (member);    if (len > sizeof (arhPtr->ar_name)) {	len = sizeof (arhPtr->ar_name);    }        while (fread ((char *)arhPtr, sizeof (struct ar_hdr), 1, arch) == 1) {	if (strncmp(arhPtr->ar_fmag, ARFMAG, sizeof (arhPtr->ar_fmag) ) != 0) {	     /*	      * The header is bogus, so the archive is bad	      * and there's no way we can recover...	      */	     fclose (arch);	     return ((FILE *) NULL);	} else if (strncmp (member, arhPtr->ar_name, len) == 0) {	    /*	     * If the member's name doesn't take up the entire 'name' field,	     * we have to be careful of matching prefixes. Names are space-	     * padded to the right, so if the character in 'name' at the end	     * of the matched string is anything but a space, this isn't the	     * member we sought.	     */	    if (len != sizeof(arhPtr->ar_name) && arhPtr->ar_name[len] != ' '){		continue;	    } else {		/*		 * To make life easier, we reposition the file at the start		 * of the header we just read before we return the stream.		 * In a more general situation, it might be better to leave		 * the file at the actual member, rather than its header, but		 * not here...		 */		fseek (arch, -sizeof(struct ar_hdr), 1);		return (arch);	    }	} else {	    /*	     * This isn't the member we're after, so we need to advance the	     * stream's pointer to the start of the next header. Files are	     * padded with newlines to an even-byte boundary, so we need to	     * extract the size of the file from the 'size' field of the	     * header and round it up during the seek.	     */	    arhPtr->ar_size[sizeof(arhPtr->ar_size)-1] = '\0';	    (void)sscanf (arhPtr->ar_size, "%10d", &size);	    fseek (arch, (size + 1) & ~1, 1);	}    }    /*     * We've looked everywhere, but the member is not to be found. Close the     * archive and return NULL -- an error.     */    fclose (arch);    return ((FILE *) NULL);}/*- *----------------------------------------------------------------------- * Arch_Touch -- *	Touch a member of an archive. * * Results: *	The 'time' field of the member's header is updated. * * Side Effects: *	The modification time of the entire archive is also changed. *	For a library, this could necessitate the re-ranlib'ing of the *	whole thing. * *----------------------------------------------------------------------- */voidArch_Touch (gn)    GNode	  *gn;	  /* Node of member to touch */{    FILE *	  arch;	  /* Stream open to archive, positioned properly */    struct ar_hdr arh;	  /* Current header describing member */    arch = ArchFindMember(Var_Value (ARCHIVE, gn),			  Var_Value (TARGET, gn),			  &arh, "r+");    sprintf(arh.ar_date, "%-12ld", (long) now);    if (arch != (FILE *) NULL) {	(void)fwrite ((char *)&arh, sizeof (struct ar_hdr), 1, arch);	fclose (arch);    }}/*- *----------------------------------------------------------------------- * Arch_TouchLib -- *	Given a node which represents a library, touch the thing, making *	sure that the table of contents also is touched. * * Results: *	None. * * Side Effects: *	Both the modification time of the library and of the RANLIBMAG *	member are set to 'now'. * *----------------------------------------------------------------------- */voidArch_TouchLib (gn)    GNode	    *gn;      	/* The node of the library to touch */{    FILE *	    arch;	/* Stream open to archive */    struct ar_hdr   arh;      	/* Header describing table of contents */    struct timeval  times[2];	/* Times for utimes() call */    arch = ArchFindMember (gn->path, RANLIBMAG, &arh, "r+");    sprintf(arh.ar_date, "%-12ld", (long) now);    if (arch != (FILE *) NULL) {	(void)fwrite ((char *)&arh, sizeof (struct ar_hdr), 1, arch);	fclose (arch);	times[0].tv_sec = times[1].tv_sec = now;	times[0].tv_usec = times[1].tv_usec = 0;	utimes(gn->path, times);    }}/*- *----------------------------------------------------------------------- * Arch_MTime -- *	Return the modification time of a member of an archive. * * Results: *	The modification time (seconds). * * Side Effects: *	The mtime field of the given node is filled in with the value *	returned by the function. * *----------------------------------------------------------------------- */intArch_MTime (gn)    GNode	  *gn;	      /* Node describing archive member */{    struct ar_hdr *arhPtr;    /* Header of desired member */    int		  modTime;    /* Modification time as an integer */    arhPtr = ArchStatMember (Var_Value (ARCHIVE, gn),			     Var_Value (TARGET, gn),			     TRUE);    if (arhPtr != (struct ar_hdr *) NULL) {	(void)sscanf (arhPtr->ar_date, "%12d", &modTime);    } else {	modTime = 0;    }    gn->mtime = modTime;    return (modTime);}/*- *----------------------------------------------------------------------- * Arch_MemMTime -- *	Given a non-existent archive member's node, get its modification *	time from its archived form, if it exists. * * Results: *	The modification time. * * Side Effects: *	The mtime field is filled in. * *----------------------------------------------------------------------- */intArch_MemMTime (gn)    GNode   	  *gn;{    LstNode 	  ln;    GNode   	  *pgn;    char    	  *nameStart,		  *nameEnd;    if (Lst_Open (gn->parents) != SUCCESS) {	gn->mtime = 0;	return (0);    }    while ((ln = Lst_Next (gn->parents)) != NILLNODE) {	pgn = (GNode *) Lst_Datum (ln);	if (pgn->type & OP_ARCHV) {	    /*	     * If the parent is an archive specification and is being made	     * and its member's name matches the name of the node we were	     * given, record the modification time of the parent in the	     * child. We keep searching its parents in case some other	     * parent requires this child to exist...	     */	    nameStart = strchr (pgn->name, '(') + 1;	    nameEnd = strchr (nameStart, ')');	    if (pgn->make &&		strncmp(nameStart, gn->name, nameEnd - nameStart) == 0) {				     gn->mtime = Arch_MTime(pgn);	    }	} else if (pgn->make) {	    /*	     * Something which isn't a library depends on the existence of	     * this target, so it needs to exist.	     */	    gn->mtime = 0;	    break;	}    }    Lst_Close (gn->parents);    return (gn->mtime);}/*- *----------------------------------------------------------------------- * Arch_FindLib -- *	Search for a library along the given search path.  * * Results: *	None. * * Side Effects: *	The node's 'path' field is set to the found path (including the *	actual file name, not -l...). If the system can handle the -L *	flag when linking (or we cannot find the library), we assume that *	the user has placed the .LIBRARIES variable in the final linking *	command (or the linker will know where to find it) and set the *	TARGET variable for this node to be the node's name. Otherwise, *	we set the TARGET variable to be the full path of the library, *	as returned by Dir_FindFile. * *----------------------------------------------------------------------- */voidArch_FindLib (gn, path)    GNode	    *gn;	      /* Node of library to find */    Lst	    	    path;	      /* Search path */{    char	    *libName;   /* file name for archive */    libName = (char *)emalloc (strlen (gn->name) + 6 - 2);    sprintf(libName, "lib%s.a", &gn->name[2]);    gn->path = Dir_FindFile (libName, path);    free (libName);#ifdef LIBRARIES    Var_Set (TARGET, gn->name, gn);#else    Var_Set (TARGET, gn->path == (char *) NULL ? gn->name : gn->path, gn);#endif LIBRARIES}/*- *----------------------------------------------------------------------- * Arch_LibOODate -- *	Decide if a node with the OP_LIB attribute is out-of-date. Called *	from Make_OODate to make its life easier. * *	There are several ways for a library to be out-of-date that are *	not available to ordinary files. In addition, there are ways *	that are open to regular files that are not available to *	libraries. A library that is only used as a source is never *	considered out-of-date by itself. This does not preclude the *	library's modification time from making its parent be out-of-date. *	A library will be considered out-of-date for any of these reasons, *	given that it is a target on a dependency line somewhere: *	    Its modification time is less than that of one of its *	    	  sources (gn->mtime < gn->cmtime). *	    Its modification time is greater than the time at which the *	    	  make began (i.e. it's been modified in the course *	    	  of the make, probably by archiving). *	    Its modification time doesn't agree with the modification *	    	  time of its RANLIBMAG member (i.e. its table of contents *	    	  is out-of-date). * * * Results: *	TRUE if the library is out-of-date. FALSE otherwise. * * Side Effects: *	The library will be hashed if it hasn't been already. * *----------------------------------------------------------------------- */BooleanArch_LibOODate (gn)    GNode   	  *gn;  	/* The library's graph node */{    Boolean 	  oodate;        if (OP_NOP(gn->type) && Lst_IsEmpty(gn->children)) {	oodate = FALSE;    } else if ((gn->mtime > now) || (gn->mtime < gn->cmtime)) {	oodate = TRUE;    } else {	struct ar_hdr  	*arhPtr;    /* Header for __.SYMDEF */	int 	  	modTimeTOC; /* The table-of-contents's mod time */	arhPtr = ArchStatMember (gn->path, RANLIBMAG, FALSE);	if (arhPtr != (struct ar_hdr *)NULL) {	    (void)sscanf (arhPtr->ar_date, "%12d", &modTimeTOC);	    if (DEBUG(ARCH) || DEBUG(MAKE)) {		printf("%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC));	    }	    oodate = (gn->mtime > modTimeTOC);	} else {	    /*	     * A library w/o a table of contents is out-of-date	     */	    if (DEBUG(ARCH) || DEBUG(MAKE)) {		printf("No t.o.c....");	    }	    oodate = TRUE;	}    }    return (oodate);}/*- *----------------------------------------------------------------------- * Arch_Init -- *	Initialize things for this module. * * Results: *	None. * * Side Effects: *	The 'archives' list is initialized. * *----------------------------------------------------------------------- */voidArch_Init (){    archives = Lst_Init (FALSE);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -