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

📄 getcwd.c

📁 标准c库代码,可以应用于各个系统提供了大量的基本函数
💻 C
字号:
/* * Copyright (c) 1989, 1991 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#if defined(LIBC_SCCS) && !defined(lint)static char sccsid[] = "@(#)getcwd.c	5.11 (Berkeley) 2/24/91";#endif /* LIBC_SCCS and not lint */#include <sys/stat.h>#include <errno.h>#include <dirent.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <reent.h>#include <_syslist.h>#define bcopy(a,b,c)	memmove (b,a,c)#define	ISDOT(dp) \	(dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \	    dp->d_name[1] == '.' && dp->d_name[2] == '\0'))#ifndef _REENT_ONLYchar *getcwd (pt, size)     char *pt;     size_t size;{  register struct dirent *dp;  register DIR *dir;  register dev_t dev;  register ino_t ino;  register int first;  register char *bpt, *bup;  struct stat s;  dev_t root_dev;  ino_t root_ino;  size_t ptsize, upsize;  int save_errno;  char *ept, *eup, *up;  /*   * If no buffer specified by the user, allocate one as necessary.   * If a buffer is specified, the size has to be non-zero.  The path   * is built from the end of the buffer backwards.   */  if (pt)    {      ptsize = 0;      if (!size)	{	  errno = EINVAL;	  return (char *) NULL;	}      ept = pt + size;    }  else    {      if (!(pt = (char *) malloc (ptsize = 1024 - 4)))	{	  return (char *) NULL;	}      ept = pt + ptsize;    }  bpt = ept - 1;  *bpt = '\0';  /*   * Allocate bytes (1024 - malloc space) for the string of "../"'s.   * Should always be enough (it's 340 levels).  If it's not, allocate   * as necessary.  Special * case the first stat, it's ".", not "..".   */  if (!(up = (char *) malloc (upsize = 1024 - 4)))    {      goto err;    }  eup = up + MAXPATHLEN;  bup = up;  up[0] = '.';  up[1] = '\0';  /* Save root values, so know when to stop. */  if (stat ("/", &s))    goto err;  root_dev = s.st_dev;  root_ino = s.st_ino;  errno = 0;			/* XXX readdir has no error return. */  for (first = 1;; first = 0)    {      /* Stat the current level. */      if (_stat (up, &s))	goto err;      /* Save current node values. */      ino = s.st_ino;      dev = s.st_dev;      /* Check for reaching root. */      if (root_dev == dev && root_ino == ino)	{	  *--bpt = '/';	  /*	   * It's unclear that it's a requirement to copy the	   * path to the beginning of the buffer, but it's always	   * been that way and stuff would probably break.	   */	  (void) bcopy (bpt, pt, ept - bpt);	  free (up);	  return pt;	}      /*       * Build pointer to the parent directory, allocating memory       * as necessary.  Max length is 3 for "../", the largest       * possible component name, plus a trailing NULL.       */      if (bup + 3 + MAXNAMLEN + 1 >= eup)	{	  if (!(up = (char *) realloc (up, upsize *= 2)))	    {	      goto err;	    }	  bup = up;	  eup = up + upsize;	}      *bup++ = '.';      *bup++ = '.';      *bup = '\0';      /* Open and stat parent directory. */      if (!(dir = _opendir (up)) || _fstat (__dirfd (dir), &s))	goto err;      /* Add trailing slash for next directory. */      *bup++ = '/';      /*       * If it's a mount point, have to stat each element because       * the inode number in the directory is for the entry in the       * parent directory, not the inode number of the mounted file.       */      save_errno = 0;      if (s.st_dev == dev)	{	  for (;;)	    {	      if (!(dp = _readdir (dir)))		goto notfound;	      if (dp->d_ino == ino)		break;	    }	}      else	for (;;)	  {	    if (!(dp = _readdir (dir)))	      goto notfound;	    if (ISDOT (dp))	      continue;	    bcopy (dp->d_name, bup, strlen (dp->d_name) + 1);	    /* Save the first error for later. */	    if (stat (up, &s))	      {		if (!save_errno)		  save_errno = errno;		errno = 0;		continue;	      }	    if (s.st_dev == dev && s.st_ino == ino)	      break;	  }      /*       * Check for length of the current name, preceding slash,       * leading slash.       */      if (bpt - pt <= strlen (dp->d_name) + (first ? 1 : 2))	{	  size_t len, off;	  if (!ptsize)	    {	      errno = ERANGE;	      goto err;	    }	  off = bpt - pt;	  len = ept - bpt;	  if (!(pt = (char *) realloc (pt, ptsize *= 2)))	    {	      goto err;	    }	  bpt = pt + off;	  ept = pt + ptsize;	  (void) bcopy (bpt, ept - len, len);	  bpt = ept - len;	}      if (!first)	*--bpt = '/';      bpt -= strlen (dp->d_name);      bcopy (dp->d_name, bpt, strlen (dp->d_name));      (void) _closedir (dir);      /* Truncate any file name. */      *bup = '\0';    }notfound:  /*   * If readdir set errno, use it, not any saved error; otherwise,   * didn't find the current directory in its parent directory, set   * errno to ENOENT.   */  if (!errno)    errno = save_errno ? save_errno : ENOENT;  /* FALLTHROUGH */err:  if (ptsize)    free (pt);  free (up);  return (char *) NULL;}#endif /* _REENT_ONLY */

⌨️ 快捷键说明

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