... |
... |
@@ -727,66 +727,42 @@ os_lstat(const char* path, u_int64_t *dev, u_int64_t *ino, unsigned int *mode, u |
727
|
727
|
char *
|
728
|
728
|
os_file_author(const char *path)
|
729
|
729
|
{
|
730
|
|
- int status;
|
731
|
|
- struct stat statbuf;
|
732
|
|
- char* author = NULL;
|
733
|
|
- bool nomem = false;
|
734
|
|
- size_t bufsize;
|
735
|
|
- char* buf = NULL;
|
736
|
|
- char* buf2 = NULL;
|
|
730
|
+ struct stat sb;
|
|
731
|
+ char initial[1024];
|
|
732
|
+ char *buffer, *obuffer;
|
|
733
|
+ size_t size;
|
737
|
734
|
struct passwd pwd;
|
738
|
|
- struct passwd *result = NULL;
|
739
|
|
-
|
740
|
|
- status = stat(path, &statbuf);
|
|
735
|
+ struct passwd *ppwd;
|
|
736
|
+ char *result;
|
741
|
737
|
|
742
|
|
- if (status != 0) {
|
|
738
|
+ if (stat(path, &sb) != 0) {
|
743
|
739
|
return NULL;
|
744
|
740
|
}
|
745
|
|
-
|
746
|
|
- bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
|
747
|
|
-
|
748
|
|
- /*
|
749
|
|
- * If sysconf fails, just use a small initial buffer size that we
|
750
|
|
- * will keep growing up to some maximum size.
|
751
|
|
- */
|
752
|
|
- if (bufsize == -1) {
|
753
|
|
- bufsize = 1024;
|
754
|
|
- }
|
755
|
|
-
|
756
|
|
- while (1) {
|
757
|
|
- buf2 = realloc(buf, bufsize);
|
758
|
|
-
|
759
|
|
- if (buf2 == NULL) {
|
760
|
|
- result = NULL;
|
761
|
|
- nomem = true;
|
762
|
|
- break;
|
763
|
|
- }
|
764
|
|
-
|
765
|
|
- buf = buf2;
|
766
|
|
- status = getpwuid_r(statbuf.st_uid, &pwd, buf, bufsize, &result);
|
767
|
|
-
|
768
|
|
- if (status != 0) {
|
769
|
|
- result = NULL;
|
770
|
|
- }
|
771
|
|
- if ((result != NULL) || (status != ERANGE)) {
|
772
|
|
- break;
|
773
|
|
- }
|
774
|
|
- /* If bufsize exceeds some large size, give up. */
|
775
|
|
- if (bufsize > 16384) {
|
776
|
|
- nomem = true;
|
777
|
|
- break;
|
|
741
|
+ result = NULL;
|
|
742
|
+ buffer = initial;
|
|
743
|
+ size = ARRAYSIZE(initial);
|
|
744
|
+ assert(sysconf(_SC_GETPW_R_SIZE_MAX) <= 16384));
|
|
745
|
+ while (size <= 16384) {
|
|
746
|
+ switch (getpwuid_r(sb.st_uid, &pwd, buffer, size, &ppwd)) {
|
|
747
|
+ case 0:
|
|
748
|
+ /* Success, though we might not have a matching entry */
|
|
749
|
+ result = (ppwd == NULL) ? NULL : strdup(pwd.pw_name);
|
|
750
|
+ goto exit;
|
|
751
|
+ case ERANGE:
|
|
752
|
+ /* Buffer is too small, double its size and try again */
|
|
753
|
+ size *= 2;
|
|
754
|
+ obuffer = (buffer == initial) ? NULL : buffer;
|
|
755
|
+ if ((buffer = realloc(obuffer, size)) == NULL) {
|
|
756
|
+ free(obuffer);
|
|
757
|
+ goto exit;
|
|
758
|
+ }
|
|
759
|
+ continue;
|
|
760
|
+ default:
|
|
761
|
+ /* All other errors */
|
|
762
|
+ goto exit;
|
778
|
763
|
}
|
779
|
|
-
|
780
|
|
- bufsize <<= 1;
|
781
|
764
|
}
|
782
|
|
-
|
783
|
|
- if (result) {
|
784
|
|
- author = strdup(result->pw_name);
|
785
|
|
- }
|
786
|
|
-
|
787
|
|
- if (buf) {
|
788
|
|
- free(buf);
|
789
|
|
- }
|
790
|
|
-
|
791
|
|
- return author;
|
|
765
|
+exit:
|
|
766
|
+ free(buffer);
|
|
767
|
+ return result;
|
792
|
768
|
} |