db.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /* It must be here to include config.h before another headers */
  2. #include "lub/db.h"
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <errno.h>
  6. #include <sys/types.h>
  7. #include <pwd.h>
  8. #include <grp.h>
  9. #include <unistd.h>
  10. #include <assert.h>
  11. #include <string.h>
  12. #include <lub/conv.h>
  13. #define DEFAULT_GETPW_R_SIZE_MAX 1024
  14. // Workaround to implement fully statical build. The libc uses dlopen() to
  15. // implement NSS functions. So getpwnam() etc. need shared objects support.
  16. // Exclude them on static build. Application will support UIDs and GIDs in
  17. // digital format only.
  18. #ifndef DISABLE_NSS
  19. struct passwd *lub_db_getpwnam(const char *name)
  20. {
  21. long int size;
  22. char *buf;
  23. struct passwd *pwbuf;
  24. struct passwd *pw = NULL;
  25. int res = 0;
  26. #ifdef _SC_GETPW_R_SIZE_MAX
  27. if ((size = sysconf(_SC_GETPW_R_SIZE_MAX)) < 0)
  28. size = DEFAULT_GETPW_R_SIZE_MAX;
  29. #else
  30. size = DEFAULT_GETPW_R_SIZE_MAX;
  31. #endif
  32. pwbuf = malloc(sizeof(*pwbuf) + size);
  33. if (!pwbuf)
  34. return NULL;
  35. buf = (char *)pwbuf + sizeof(*pwbuf);
  36. res = getpwnam_r(name, pwbuf, buf, size, &pw);
  37. if (res || !pw) {
  38. free(pwbuf);
  39. if (res != 0)
  40. errno = res;
  41. else
  42. errno = ENOENT;
  43. return NULL;
  44. }
  45. return pwbuf;
  46. }
  47. struct passwd *lub_db_getpwuid(uid_t uid)
  48. {
  49. long int size;
  50. char *buf;
  51. struct passwd *pwbuf;
  52. struct passwd *pw = NULL;
  53. int res = 0;
  54. #ifdef _SC_GETPW_R_SIZE_MAX
  55. if ((size = sysconf(_SC_GETPW_R_SIZE_MAX)) < 0)
  56. size = DEFAULT_GETPW_R_SIZE_MAX;
  57. #else
  58. size = DEFAULT_GETPW_R_SIZE_MAX;
  59. #endif
  60. pwbuf = malloc(sizeof(*pwbuf) + size);
  61. if (!pwbuf)
  62. return NULL;
  63. buf = (char *)pwbuf + sizeof(*pwbuf);
  64. res = getpwuid_r(uid, pwbuf, buf, size, &pw);
  65. if (NULL == pw) {
  66. free(pwbuf);
  67. if (res != 0)
  68. errno = res;
  69. else
  70. errno = ENOENT;
  71. return NULL;
  72. }
  73. return pwbuf;
  74. }
  75. struct group *lub_db_getgrnam(const char *name)
  76. {
  77. long int size;
  78. char *buf;
  79. struct group *grbuf;
  80. struct group *gr = NULL;
  81. int res = 0;
  82. #ifdef _SC_GETGR_R_SIZE_MAX
  83. if ((size = sysconf(_SC_GETGR_R_SIZE_MAX)) < 0)
  84. size = DEFAULT_GETPW_R_SIZE_MAX;
  85. #else
  86. size = DEFAULT_GETPW_R_SIZE_MAX;
  87. #endif
  88. grbuf = malloc(sizeof(*grbuf) + size);
  89. if (!grbuf)
  90. return NULL;
  91. buf = (char *)grbuf + sizeof(*grbuf);
  92. res = getgrnam_r(name, grbuf, buf, size, &gr);
  93. if (!gr) {
  94. free(grbuf);
  95. if (res != 0)
  96. errno = res;
  97. else
  98. errno = ENOENT;
  99. return NULL;
  100. }
  101. return grbuf;
  102. }
  103. struct group *lub_db_getgrgid(gid_t gid)
  104. {
  105. long int size;
  106. char *buf;
  107. struct group *grbuf;
  108. struct group *gr = NULL;
  109. int res = 0;
  110. #ifdef _SC_GETGR_R_SIZE_MAX
  111. if ((size = sysconf(_SC_GETGR_R_SIZE_MAX)) < 0)
  112. size = DEFAULT_GETPW_R_SIZE_MAX;
  113. #else
  114. size = DEFAULT_GETPW_R_SIZE_MAX;
  115. #endif
  116. grbuf = malloc(sizeof(struct group) + size);
  117. if (!grbuf)
  118. return NULL;
  119. buf = (char *)grbuf + sizeof(struct group);
  120. res = getgrgid_r(gid, grbuf, buf, size, &gr);
  121. if (!gr) {
  122. free(grbuf);
  123. if (res != 0)
  124. errno = res;
  125. else
  126. errno = ENOENT;
  127. return NULL;
  128. }
  129. return grbuf;
  130. }
  131. // -----------------------------------------------------------------------------
  132. #else // DISABLE_NSS
  133. // All UIDs and GIDs must be in digital format. Functions only converts digits
  134. // to text or text to digits. Text names are not supported. So functions
  135. // simulate the real functions.
  136. struct passwd *lub_db_getpwnam(const char *name)
  137. {
  138. long int size = 0;
  139. struct passwd *buf = NULL;
  140. long int val = 0;
  141. assert(name);
  142. if (!name)
  143. return NULL;
  144. size = strlen(name) + 1;
  145. // Try to convert
  146. if (lub_conv_atol(name, &val, 0) < 0)
  147. return NULL;
  148. buf = calloc(1, sizeof(*buf) + size);
  149. if (!buf)
  150. return NULL;
  151. buf->pw_name = (char *)buf + sizeof(*buf);
  152. memcpy(buf->pw_name, name, size);
  153. buf->pw_uid = (uid_t)val;
  154. buf->pw_gid = (gid_t)val; // Let's primary GID be the same as UID
  155. return buf;
  156. }
  157. struct passwd *lub_db_getpwuid(uid_t uid)
  158. {
  159. char str[20];
  160. long int size = 0;
  161. struct passwd *buf = NULL;
  162. snprintf(str, sizeof(str), "%u", uid);
  163. str[sizeof(str) - 1] = '\0';
  164. size = strlen(str) + 1;
  165. buf = calloc(1, sizeof(*buf) + size);
  166. if (!buf)
  167. return NULL;
  168. buf->pw_name = (char *)buf + sizeof(*buf);
  169. memcpy(buf->pw_name, str, size);
  170. buf->pw_uid = uid;
  171. buf->pw_gid = uid; // Let's primary GID be the same as UID
  172. return buf;
  173. }
  174. struct group *lub_db_getgrnam(const char *name)
  175. {
  176. long int size = 0;
  177. struct group *buf = NULL;
  178. long int val = 0;
  179. assert(name);
  180. if (!name)
  181. return NULL;
  182. size = strlen(name) + 1;
  183. // Try to convert
  184. if (lub_conv_atol(name, &val, 0) < 0)
  185. return NULL;
  186. buf = calloc(1, sizeof(*buf) + size);
  187. if (!buf)
  188. return NULL;
  189. buf->gr_name = (char *)buf + sizeof(*buf);
  190. memcpy(buf->gr_name, name, size);
  191. buf->gr_gid = (gid_t)val;
  192. return buf;
  193. }
  194. struct group *lub_db_getgrgid(gid_t gid)
  195. {
  196. char str[20];
  197. long int size = 0;
  198. struct group *buf = NULL;
  199. snprintf(str, sizeof(str), "%u", gid);
  200. str[sizeof(str) - 1] = '\0';
  201. size = strlen(str) + 1;
  202. buf = calloc(1, sizeof(*buf) + size);
  203. if (!buf)
  204. return NULL;
  205. buf->gr_name = (char *)buf + sizeof(*buf);
  206. memcpy(buf->gr_name, str, size);
  207. buf->gr_gid = gid;
  208. return buf;
  209. }
  210. #endif // DISABLE_NSS