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

📄 ls.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ls.c
 *
 * Copyright (c) 1992-2001 by Mike Gleason.
 * All rights reserved.
 *
 */

#include "syshdrs.h"
#include "util.h"
#include "ls.h"
#include "trace.h"

/* The program keeps a timestamp of 6 months ago and an hour from now, because
 * the standard /bin/ls command will print the time (i.e. "Nov  8 09:20")
 * instead of the year (i.e. "Oct 27  1996") if a file's timestamp is within
 * this period.
 */
time_t gNowMinus6Mon, gNowPlus1Hr;

/* An array of month name abbreviations.  This may not be in English. */
char gLsMon[13][4];

/* The program keeps its own cache of directory listings, so it doesn't
 * need to re-request them from the server.
 */
LsCacheItem gLsCache[kLsCacheSize];
int gOldestLsCacheItem;
int gLsCacheItemLifetime = kLsCacheItemLifetime;

extern FTPConnectionInfo gConn;
extern char gRemoteCWD[512];
extern int gScreenColumns, gDebug;


void
InitLsCache(void)
{
	(void) memset(gLsCache, 0, sizeof(gLsCache));
	gOldestLsCacheItem = 0;
}	/* InitLsCache */



/* Creates the ls monthname abbreviation array, so we don't have to
 * re-calculate them each time.
 */
void InitLsMonths(void)
{
	time_t now;
	struct tm *ltp;
	int i;

	(void) time(&now);
	ltp = localtime(&now);	/* Fill up the structure. */
	ltp->tm_mday = 15;
	ltp->tm_hour = 12;
	for (i=0; i<12; i++) {
		ltp->tm_mon = i;
		(void) strftime(gLsMon[i], sizeof(gLsMon[i]), "%b", ltp);
		gLsMon[i][sizeof(gLsMon[i]) - 1] = '\0';
	}
	(void) strcpy(gLsMon[i], "BUG");
}	/* InitLsMonths */




void InitLs(void)
{
	InitLsCache();
	InitLsMonths();
}	/* InitLs */




/* Deletes an item from the ls cache. */
static void
FlushLsCacheItem(int i)
{
	Trace(1, "flush ls cache item: %s\n", gLsCache[i].itempath);
	if (gLsCache[i].itempath != NULL)
		free(gLsCache[i].itempath);
	gLsCache[i].itempath = NULL;
	gLsCache[i].expiration = (time_t) 0;
	DisposeFileInfoListContents(&gLsCache[i].fil);
}	/* FlushLsCacheItem */




/* Clears all items from the ls cache. */
void
FlushLsCache(void)
{
	int i;

	for (i=0; i<kLsCacheSize; i++) {
		if (gLsCache[i].expiration != (time_t) 0) {
			FlushLsCacheItem(i);
		}
	}
}	/* FlushLsCache */




/* Checks the cache for a directory listing for the given path. */
int
LsCacheLookup(const char *const itempath)
{
	int i, j;
	time_t now;

	(void) time(&now);
	for (i=0, j=gOldestLsCacheItem; i<kLsCacheSize; i++) {
		if (--j < 0)
			j = kLsCacheSize - 1;
		if ((gLsCache[j].expiration != (time_t) 0) && (gLsCache[j].itempath != NULL)) {
			if (strcmp(itempath, gLsCache[j].itempath) == 0) {
				if (now > gLsCache[j].expiration) {
					/* Found it, but it was expired. */
					FlushLsCacheItem(j);
					return (-1);
				}
				gLsCache[j].hits++;
				return (j);
			}
		}
	}
	return (-1);
}	/* LsCacheLookup */




/* Saves a directory listing from the given path into the cache. */
static void
LsCacheAdd(const char *const itempath, FileInfoListPtr files)
{
	char *cp;
	int j;

	/* Never cache empty listings in case of errors */
	if (files->nFileInfos == 0)
		return;

	j = LsCacheLookup(itempath);
	if (j >= 0) {
		/* Directory was already in there;
		 * Replace it with the new
		 * contents.
		 */
		FlushLsCacheItem(j);
	}

	cp = StrDup(itempath);
	if (cp == NULL)
		return;

	j = gOldestLsCacheItem;
	(void) memcpy(&gLsCache[j].fil, files, sizeof(FileInfoList));
	(void) time(&gLsCache[j].expiration);
	gLsCache[j].expiration += gLsCacheItemLifetime;
	gLsCache[j].hits = 0;
	gLsCache[j].itempath = cp;
	Trace(1, "ls cache add: %s\n", itempath);

	/* Increment the pointer.  This is a circular array, so if it
	 * hits the end it wraps over to the other side.
	 */
	gOldestLsCacheItem++;
	if (gOldestLsCacheItem >= kLsCacheSize)
		gOldestLsCacheItem = 0;
}	/* LsCacheAdd */




/* Does "ls -C", or the nice columnized /bin/ls-style format. */
static void
LsC(FileInfoListPtr dirp, int endChars, FILE *stream)
{
	char buf[400];
	char buf2[400];
	int ncol, nrow;
	int i, j, k, l;
	int colw;
	int n;
	FileInfoVec itemv;
	FileInfoPtr itemp;
	char *cp1, *cp2, *lim;
	int screenColumns;

	screenColumns = gScreenColumns;
	if (screenColumns > 400)
		screenColumns = 400;
	ncol = (screenColumns - 1) / ((int) dirp->maxFileLen + 2 + /*1or0*/ endChars);
	if (ncol < 1)
		ncol = 1;
	colw = (screenColumns - 1) / ncol;
	n = dirp->nFileInfos;
	nrow = n / ncol;
	if ((n % ncol) != 0)
		nrow++;

	for (i=0; i<(int) sizeof(buf2); i++)
		buf2[i] = ' ';

	itemv = dirp->vec;

	for (j=0; j<nrow; j++) {
		(void) memcpy(buf, buf2, sizeof(buf));
		for (i=0, k=j, l=0; i<ncol; i++, k += nrow, l += colw) {
			if (k >= n)
				continue;
			itemp = itemv[k];
			cp1 = buf + l;
			lim = cp1 + (int) (itemp->relnameLen);
			cp2 = itemp->relname;
			while (cp1 < lim)
				*cp1++ = *cp2++;
			if (endChars != 0) {
				if (itemp->type == 'l') {
					/* Regular ls always uses @
					 * for a symlink tail, even if
					 * the linked item is a directory.
					 */
					*cp1++ = '@';
				} else if (itemp->type == 'd') {
					*cp1++ = '/';
				}
			}
		}
		for (cp1 = buf + sizeof(buf); *--cp1 == ' '; ) {}
		++cp1;
		*cp1++ = '\n';
		*cp1 = '\0';
		(void) fprintf(stream, "%s", buf);
		Trace(0, "%s", buf);
	}
}	/* LsC */



/* Converts a timestamp into a recent date string ("May 27 06:33"), or an
 * old (or future) date string (i.e. "Oct 27  1996").
 */
void
LsDate(char *dstr, time_t ts)
{
	struct tm *gtp;

	if (ts == kModTimeUnknown) {
		(void) strcpy(dstr, "            ");
		return;
	}
	gtp = localtime(&ts);
	if (gtp == NULL) {
		(void) strcpy(dstr, "Jan  0  1900");
		return;
	}
	if ((ts > gNowPlus1Hr) || (ts < gNowMinus6Mon)) {
		(void) sprintf(dstr, "%s %2d  %4d",
			gLsMon[gtp->tm_mon],
			gtp->tm_mday,
			gtp->tm_year + 1900
		);
	} else {
		(void) sprintf(dstr, "%s %2d %02d:%02d",
			gLsMon[gtp->tm_mon],
			gtp->tm_mday,
			gtp->tm_hour,
			gtp->tm_min
		);
	}
}	/* LsDate */




/* Does "ls -l", or the detailed /bin/ls-style, one file per line . */
void
LsL(FileInfoListPtr dirp, int endChars, int linkedTo, FILE *stream)
{
	FileInfoPtr diritemp;
	FileInfoVec diritemv;
	int i;
	char fTail[2];
	int fType;
	const char *l1, *l2;
	char datestr[16];
	char sizestr[32];
	char plugspec[16];
	char plugstr[64];
	const char *expad;

	fTail[0] = '\0';
	fTail[1] = '\0';

	(void) time(&gNowPlus1Hr);
	gNowMinus6Mon = gNowPlus1Hr - 15552000;
	gNowPlus1Hr += 3600;

	diritemv = dirp->vec;
#ifdef HAVE_SNPRINTF
	(void) snprintf(
		plugspec,
		sizeof(plugspec) - 1,
#else
	(void) sprintf(
		plugspec,
#endif
		"%%-%ds",
		(int) dirp->maxPlugLen
	);

	if (dirp->maxPlugLen < 29) {
		/* We have some extra space to work with,
		 * so we can space out the columns a little.
		 */
		expad = "  ";
	} else {
		expad = "";
	}

	for (i=0; ; i++) {
		diritemp = diritemv[i];
		if (diritemp == NULL)
			break;

		fType = (int) diritemp->type;
		if (endChars != 0) {
			if (fType == 'd')
				fTail[0] = '/';
			else
				fTail[0] = '\0';
		}

		if (diritemp->rlinkto != NULL) {
			if (linkedTo != 0) {
				l1 = "";
				l2 = "";
			} else {
				l1 = " -> ";
				l2 = diritemp->rlinkto;
			}
		} else {
			l1 = "";
			l2 = "";
		}

		LsDate(datestr, diritemp->mdtm);

		if (diritemp->size == kSizeUnknown) {
			*sizestr = '\0';
		} else {
#ifdef HAVE_SNPRINTF
			(void) snprintf(
				sizestr,
				sizeof(sizestr) - 1,
#else
			(void) sprintf(
				sizestr,
#endif
#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG)
				PRINTF_LONG_LONG,
#else
				"%ld",
#endif
				(longest_int) diritemp->size
			);
		}

#ifdef HAVE_SNPRINTF
		(void) snprintf(
			plugstr,
			sizeof(plugstr) - 1,
#else
		(void) sprintf(
			plugstr,
#endif
			plugspec,
			diritemp->plug
		);

		(void) fprintf(stream, "%s %12s %s%s %s%s%s%s%s\n",
			plugstr,
			sizestr,
			expad,

⌨️ 快捷键说明

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