shm.c 2.0 KB

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