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 }
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; }