Пример #1
0
int bbcp_FS_Unix::Stat(const char *path, const char *dent, int fd,
                       int chklnks, bbcp_FileInfo *sbuff)
{
   struct stat xbuff;
   char lbuff[2048];
   int n;

// Perform the stat function
//
#ifdef AT_SYMLINK_NOFOLLOW
   if (fstatat(fd, dent, &xbuff, AT_SYMLINK_NOFOLLOW)) return -errno;
   if ((xbuff.st_mode & S_IFMT) != S_IFLNK)
      return (sbuff ? Stat(xbuff, sbuff) : 0);
   if (chklnks > 0) return -ENOENT;
   if (!sbuff) return 0;
   if ((n = READLINK(fd,dent,path,lbuff,sizeof(lbuff)-1)) < 0) return -errno;
// if ((n = readlinkat(fd, dent, lbuff, sizeof(lbuff)-1)) < 0) return -errno;
   lbuff[n] = 0;
   if(sbuff->SLink) free(sbuff->SLink);
   sbuff->SLink = strdup(lbuff);
   if (!chklnks && fstatat(fd, dent, &xbuff, 0)) return -errno;
   return Stat(xbuff, sbuff);
#else
   if (lstat(path, &xbuff)) return -errno;
   if ((xbuff.st_mode & S_IFMT) != S_IFLNK)
      return (sbuff ? Stat(xbuff, sbuff) : 0);
   if (chklnks > 0) return -ENOENT;
   if (!sbuff) return 0;
   if ((n = readlink(path, lbuff, sizeof(lbuff)-1)) < 0) return -errno;
   lbuff[n] = 0;
   if(sbuff->SLink) free(sbuff->SLink);
   sbuff->SLink = strdup(lbuff);
   if (!chklnks && stat(path, &xbuff)) return -errno;
   return Stat(xbuff, sbuff);
#endif
}
Пример #2
0
int
checklink(const char* asp, struct stat* st, int type)
{
	register char*	sp = (char*)asp;
	register char*	ip;
	register int	len;
	register int	n;
	register char*	bp;

	char		buf[PATH_MAX + 1];

	if (sp < state.path.name || sp >= state.path.name + sizeof(state.path.name))
	{
		message((-1, "AHA#%d checklink bounds sp=%p state.path.name=%p sp=%s", __LINE__, sp, state.path.name, sp));
		sp = strncpy(state.path.name, sp, sizeof(state.path.name) - 1);
	}
	while (S_ISLNK(st->st_mode))
	{
		/*
		 * go to the last component
		 */

		if (ip = strrchr(sp, '/'))
			ip++;
		else
			ip = sp;
		strcpy(buf, ip);
		len = (state.path.name + sizeof(state.path.name) - 1) - ip;
		if ((len = READLINK(sp, ip, len)) < 0)
		{
			message((-1, "%s: cannot readlink", sp));
			return 0;
		}
		state.path.linkname = ip;
		state.path.linksize = len;

		/*
		 * check for relative link
		 */

		if (*ip != '/')
		{
			ip[len] = 0;
			if (*ip == *state.opaque && !memcmp(ip, state.opaque, 4) && !memcmp(ip + 4, buf, n = strlen(buf)))
			{
				/*
				 * version object
				 */

				ip += n + 4;
				if (instance(state.path.name, ip, st, 0))
				{
					state.path.linksize = strlen(state.path.linkname);
					if (type & P_LSTAT)
					{
						st->st_size = state.path.linksize;
						st->st_mode &= S_IPERM;
#ifdef S_IFLNK
						st->st_mode |= S_IFLNK;
#endif
						return 0;
					}
					continue;
				}
				errno = ENOENT;
				return -1;
			}
			else if (!(type & (P_LSTAT|P_PATHONLY|P_READLINK)) && *ip == '.' && *(ip + 1) == '.' && (*(ip + 2) == '/' || *(ip + 2) == 0))
			{
				memcpy(buf, ip, len + 1);
				bp = state.path.name;
				while (ip > bp && *(ip - 1) == '/')
					ip--;
				for (;;)
				{
					*(sp = ip) = 0;
					while (ip > bp && *--ip != '/');
					while (ip > bp && *(ip - 1) == '/')
						ip--;
					if (*ip == '/')
						ip++;
					if ((n = READLINK(state.path.name, ip, PATH_MAX - (ip - state.path.name))) <= 0)
					{
						*sp++ = '/';
						state.path.linkname = (char*)memcpy(sp, buf, len + 1);
						return sp + len - state.path.name;
					}
					if (*ip == '/')
						ip = (char*)memcpy(bp = state.path.name, ip, n);
					else if (ip > bp)
						*(ip - 1) = '/';
					ip += n;
				}
			}
		}

		/*
		 * restore last component
		 */

		if (!(type & P_READLINK))
			strcpy(ip, buf);
		break;
	}
	return 0;
}