shm.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* Copyright (C) 2009 Bernhard Reutner-Fischer <uclibc@uclibc.org>
  2. *
  3. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  4. */
  5. #include <features.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <sys/mman.h>
  9. #include <fcntl.h>
  10. #include <unistd.h>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <errno.h>
  14. #ifndef _PATH_SHM
  15. #define _PATH_SHM "/dev/shm/"
  16. #endif
  17. #ifndef NAME_MAX
  18. #define NAME_MAX 255
  19. #endif
  20. /* Get name of dummy shm operation handle.
  21. * Returns a malloc'ed buffer containing the OS specific path
  22. * to the shm filename or NULL upon failure.
  23. */
  24. static __attribute_noinline__ char* get_shm_name(const char*name) __nonnull((1));
  25. static char* get_shm_name(const char*name)
  26. {
  27. char *path;
  28. int i;
  29. /* Skip leading slashes */
  30. while (*name == '/')
  31. ++name;
  32. #ifdef __USE_GNU
  33. i = asprintf(&path, _PATH_SHM "%s", name);
  34. if (i < 0)
  35. return NULL;
  36. #else
  37. path = malloc(NAME_MAX);
  38. if (path == NULL)
  39. return NULL;
  40. i = snprintf(path, NAME_MAX, _PATH_SHM "%s", name);
  41. if (i < 0) {
  42. free(path);
  43. return NULL;
  44. } else if (i >= NAME_MAX) {
  45. free(path);
  46. __set_errno(ENAMETOOLONG);
  47. return NULL;
  48. }
  49. #endif
  50. return path;
  51. }
  52. int shm_open(const char *name, int oflag, mode_t mode)
  53. {
  54. int fd, old_errno;
  55. char *shm_name = get_shm_name(name);
  56. /* Stripped multiple '/' from start; may have set errno properly */
  57. if (shm_name == NULL)
  58. return -1;
  59. /* The FD_CLOEXEC file descriptor flag associated with the new
  60. * file descriptor is set. */
  61. #ifdef O_CLOEXEC
  62. /* Just open it with CLOEXEC set, for brevity */
  63. fd = open(shm_name, oflag | O_CLOEXEC, mode);
  64. #else
  65. fd = open(shm_name, oflag, mode);
  66. if (fd >= 0) {
  67. int fdflags = fcntl(fd, F_GETFD, 0);
  68. if (fdflags >= 0)
  69. fdflags = fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
  70. if (fdflags < 0) {
  71. close(fd);
  72. fd = -1;
  73. }
  74. }
  75. #endif
  76. old_errno = errno;
  77. free(shm_name);
  78. errno = old_errno;
  79. return fd;
  80. }
  81. int shm_unlink(const char *name)
  82. {
  83. char *shm_name = get_shm_name(name);
  84. int ret, old_errno;
  85. /* Stripped multiple '/' from start; may have set errno properly */
  86. if (shm_name == NULL)
  87. return -1;
  88. ret = unlink(shm_name);
  89. old_errno = errno;
  90. free(shm_name);
  91. errno = old_errno;
  92. return ret;
  93. }