rem: * Set the last modified header and, if not modified since * last request, return now.
add: * Set the last modified header if not set yet and, if not * modified since last request, return now.
context: FastReturn(NsServer *servPtr, Ns_Conn *conn, int status,    char *type, char *file, struct stat *stPtr){    int         result = NS_ERROR, fd, new, nread;    File	   *filePtr;    char	   *key, *map;    Ns_Entry	   *entPtr;#ifndef _WIN32    FileKey	    ukey;#endif    /*     * Determine the mime type if not given.     */         if (type == NULL) {    	type = Ns_GetMimeType(file);    }        /*     * Set the last modified header and, if not modified since     * last request, return now.     */         Ns_ConnSetLastModifiedHeader(conn, &stPtr->st_mtime);    if (Ns_ConnModifiedSince(conn, stPtr->st_mtime) == NS_FALSE) {	return Ns_ConnReturnNotModified(conn);    }        /*     * For no output (i.e., HEAD request), just send required     * headers.     */         if (conn->flags & NS_CONN_SKIPBODY) {	Ns_ConnSetRequiredHeaders(conn, type, (int) stPtr->st_size);	return Ns_ConnFlushHeaders(conn, status);    }    if (servPtr->fastpath.cache == NULL    	    || stPtr->st_size > servPtr->fastpath.cachemaxentry) {	/*	 * Caching is disabled or the entry is too large for the cache	 * so just open, mmap, and send the content directly.	 */    	fd = open(file, O_RDONLY|O_BINARY);    	if (fd < 0) {	    Ns_Log(Warning, "fastpath: open(%s) failed: %s",		   file, strerror(errno));	    goto notfound;	}#ifndef _WIN32	if (servPtr->fastpath.mmap) {	    map = mmap(0, (size_t) stPtr->st_size, PROT_READ, MAP_SHARED, fd, 0);	    if (map != MAP_FAILED) {	    	close(fd);	    	fd = -1;            	result = Ns_ConnReturnData(conn, status, map, (int) stPtr->st_size, type);	    	munmap(map, (size_t) stPtr->st_size);	    }	}#endif	if (fd != -1) {            result = Ns_ConnReturnOpenFd(conn, status, type, fd, stPtr->st_size);	    close(fd);	}    } else {	/*	 * Search for an existing cache entry for this file, validating 	 * the contents against the current file mtime and size.	 */#ifdef _WIN32	key = file;#else	ukey.dev = stPtr->st_dev;	ukey.ino = stPtr->st_ino;	key = (char *) &ukey;#endif	filePtr = NULL;	Ns_CacheLock(servPtr->fastpath.cache);	entPtr = Ns_CacheCreateEntry(servPtr->fastpath.cache, key, &new);	if (!new) {	    while (entPtr != NULL &&		   (filePtr = Ns_CacheGetValue(entPtr)) == NULL) {		Ns_CacheWait(servPtr->fastpath.cache);		entPtr = Ns_CacheFindEntry(servPtr->fastpath.cache, key);	    }	    if (filePtr != NULL &&		    (filePtr->mtime != stPtr->st_mtime ||		     filePtr->size != stPtr->st_size)) {		Ns_CacheUnsetValue(entPtr);		new = 1;	    }	}	if (new) {	    /*	     * Read and cache new or invalidated entries in one big chunk.	     */	    Ns_CacheUnlock(servPtr->fastpath.cache);	    fd = open(file, O_RDONLY|O_BINARY);	    if (fd < 0) {	    	filePtr = NULL;	        Ns_Log(Warning, "fastpath: failed to open '%s': '%s'",		       file, strerror(errno));	    } else {		filePtr = ns_malloc(sizeof(File) + stPtr->st_size);		filePtr->refcnt = 1;		filePtr->size = stPtr->st_size;		filePtr->mtime = stPtr->st_mtime;		nread = read(fd, filePtr->bytes, (size_t)filePtr->size);		close(fd);		if (nread != filePtr->size) {	    	    Ns_Log(Warning, "fastpath: failed to read '%s': '%s'",			   file, strerror(errno));		    ns_free(filePtr);		    filePtr = NULL;		}	    }	    Ns_CacheLock(servPtr->fastpath.cache);	    entPtr = Ns_CacheCreateEntry(servPtr->fastpath.cache, key, &new);	    if (filePtr != NULL) {		Ns_CacheSetValueSz(entPtr, filePtr, (size_t)filePtr->size);	    } else {		Ns_CacheFlushEntry(entPtr);	    }	    Ns_CacheBroadcast(servPtr->fastpath.cache);	}	if (filePtr != NULL) {	    ++filePtr->refcnt;	    Ns_CacheUnlock(servPtr->fastpath.cache);            result = Ns_ConnReturnData(conn, status, filePtr->bytes,			    filePtr->size, type);	    Ns_CacheLock(servPtr->fastpath.cache);	    DecrEntry(filePtr);	}	Ns_CacheUnlock(servPtr->fastpath.cache);	if (filePtr == NULL) {	    goto notfound;	}    }    return result;notfound:    return Ns_ConnReturnNotFound(conn);}