sftp-glob.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /* $OpenBSD: sftp-glob.c,v 1.29 2019/11/13 04:47:52 deraadt Exp $ */
  2. /*
  3. * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include "includes.h"
  18. #include <sys/types.h>
  19. #ifdef HAVE_SYS_STAT_H
  20. # include <sys/stat.h>
  21. #endif
  22. #include <dirent.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <stdarg.h>
  26. #include "xmalloc.h"
  27. #include "sftp.h"
  28. #include "sftp-common.h"
  29. #include "sftp-client.h"
  30. int remote_glob(struct sftp_conn *, const char *, int,
  31. int (*)(const char *, int), glob_t *);
  32. struct SFTP_OPENDIR {
  33. SFTP_DIRENT **dir;
  34. int offset;
  35. };
  36. static struct {
  37. struct sftp_conn *conn;
  38. } cur;
  39. static void *
  40. fudge_opendir(const char *path)
  41. {
  42. struct SFTP_OPENDIR *r;
  43. r = xcalloc(1, sizeof(*r));
  44. if (do_readdir(cur.conn, (char *)path, &r->dir)) {
  45. free(r);
  46. return(NULL);
  47. }
  48. r->offset = 0;
  49. return((void *)r);
  50. }
  51. static struct dirent *
  52. fudge_readdir(struct SFTP_OPENDIR *od)
  53. {
  54. /* Solaris needs sizeof(dirent) + path length (see below) */
  55. static char buf[sizeof(struct dirent) + MAXPATHLEN];
  56. struct dirent *ret = (struct dirent *)buf;
  57. #ifdef __GNU_LIBRARY__
  58. static int inum = 1;
  59. #endif /* __GNU_LIBRARY__ */
  60. if (od->dir[od->offset] == NULL)
  61. return(NULL);
  62. memset(buf, 0, sizeof(buf));
  63. /*
  64. * Solaris defines dirent->d_name as a one byte array and expects
  65. * you to hack around it.
  66. */
  67. #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME
  68. strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN);
  69. #else
  70. strlcpy(ret->d_name, od->dir[od->offset++]->filename,
  71. sizeof(ret->d_name));
  72. #endif
  73. #ifdef __GNU_LIBRARY__
  74. /*
  75. * Idiot glibc uses extensions to struct dirent for readdir with
  76. * ALTDIRFUNCs. Not that this is documented anywhere but the
  77. * source... Fake an inode number to appease it.
  78. */
  79. ret->d_ino = inum++;
  80. if (!inum)
  81. inum = 1;
  82. #endif /* __GNU_LIBRARY__ */
  83. return(ret);
  84. }
  85. static void
  86. fudge_closedir(struct SFTP_OPENDIR *od)
  87. {
  88. free_sftp_dirents(od->dir);
  89. free(od);
  90. }
  91. static int
  92. fudge_lstat(const char *path, struct stat *st)
  93. {
  94. Attrib *a;
  95. if (!(a = do_lstat(cur.conn, (char *)path, 1)))
  96. return(-1);
  97. attrib_to_stat(a, st);
  98. return(0);
  99. }
  100. static int
  101. fudge_stat(const char *path, struct stat *st)
  102. {
  103. Attrib *a;
  104. if (!(a = do_stat(cur.conn, (char *)path, 1)))
  105. return(-1);
  106. attrib_to_stat(a, st);
  107. return(0);
  108. }
  109. int
  110. remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
  111. int (*errfunc)(const char *, int), glob_t *pglob)
  112. {
  113. pglob->gl_opendir = fudge_opendir;
  114. pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
  115. pglob->gl_closedir = (void (*)(void *))fudge_closedir;
  116. pglob->gl_lstat = fudge_lstat;
  117. pglob->gl_stat = fudge_stat;
  118. memset(&cur, 0, sizeof(cur));
  119. cur.conn = conn;
  120. return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
  121. }