+ if ((fd = open(".", O_RDONLY)) < 0)
+ return -1;
+ if (fstat(fd, &dot) < 0) {
+ save = errno;
+ close(fd);
+ errno = save;
+ return -1;
+ }
+ /* check that the device and inode are non-zero, otherwise punt */
+ if (dot.st_dev == 0 || dot.st_ino == 0) {
+ close(fd);
+ errno = EINVAL;
+ return -1;
+ }
+ if (size < MAXPATHLEN) {
+ /* the hard case; allocate a buffer of size MAXPATHLEN to use */
+ b = (char *)alloca(MAXPATHLEN);
+ if (b == NULL) {
+ close(fd);
+ errno = ENOMEM; /* make sure it isn't ERANGE */
+ return -1;
+ }
+ } else
+ b = buf;
+
+ err = fcntl(fd, F_GETPATH, b);
+ if (err) {
+ save = errno;
+ close(fd);
+ errno = save;
+ return err;
+ }
+ close(fd);
+ /*
+ * now double-check that the path returned by fcntl() has the same
+ * device and inode number as '.'.
+ */
+ if (stat(b, &pt) < 0)
+ return -1;
+ /*
+ * Since dot.st_dev and dot.st_ino are non-zero, we don't need to
+ * separately test for pt.st_dev and pt.st_ino being non-zero, because
+ * they have to match
+ */
+ if (dot.st_dev != pt.st_dev || dot.st_ino != pt.st_ino) {
+ errno = EINVAL;
+ return -1;
+ }
+ /*
+ * For the case where we allocated a buffer, check that it can fit
+ * in the real buffer, and copy it over.
+ */
+ if (size < MAXPATHLEN) {
+ if (strlen(b) >= size) {
+ errno = ERANGE;
+ return -1;
+ }
+ strcpy(buf, b);
+ }
+ return 0;
+}
+
+__private_extern__ char *
+__private_getcwd(pt, size, usegetpath)