/contrib/cvs/lib/savecwd.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 142 lines · 110 code · 19 blank · 13 comment · 16 complexity · e49beb123c7e63f582443ff38281c028 MD5 · raw file

  1. #ifdef HAVE_CONFIG_H
  2. # include "config.h"
  3. #endif
  4. #include <stdio.h>
  5. #ifdef STDC_HEADERS
  6. # include <stdlib.h>
  7. #endif
  8. #ifdef HAVE_UNISTD_H
  9. # include <unistd.h>
  10. #endif
  11. #ifdef HAVE_FCNTL_H
  12. # include <sys/types.h>
  13. # include <fcntl.h>
  14. #else
  15. # include <sys/file.h>
  16. #endif
  17. #ifdef HAVE_DIRECT_H
  18. # include <direct.h>
  19. #endif
  20. #ifdef HAVE_IO_H
  21. # include <io.h>
  22. #endif
  23. #include <errno.h>
  24. # ifndef errno
  25. extern int errno;
  26. #endif
  27. #include "savecwd.h"
  28. #include "error.h"
  29. char *xgetwd __PROTO((void));
  30. /* Record the location of the current working directory in CWD so that
  31. the program may change to other directories and later use restore_cwd
  32. to return to the recorded location. This function may allocate
  33. space using malloc (via xgetwd) or leave a file descriptor open;
  34. use free_cwd to perform the necessary free or close. Upon failure,
  35. no memory is allocated, any locally opened file descriptors are
  36. closed; return non-zero -- in that case, free_cwd need not be
  37. called, but doing so is ok. Otherwise, return zero. */
  38. int
  39. save_cwd (cwd)
  40. struct saved_cwd *cwd;
  41. {
  42. static int have_working_fchdir = 1;
  43. cwd->desc = -1;
  44. cwd->name = NULL;
  45. if (have_working_fchdir)
  46. {
  47. #ifdef HAVE_FCHDIR
  48. cwd->desc = open (".", O_RDONLY);
  49. if (cwd->desc < 0)
  50. {
  51. error (0, errno, "cannot open current directory");
  52. return 1;
  53. }
  54. # if __sun__ || sun
  55. /* On SunOS 4, fchdir returns EINVAL if accounting is enabled,
  56. so we have to fall back to chdir. */
  57. if (fchdir (cwd->desc))
  58. {
  59. if (errno == EINVAL)
  60. {
  61. close (cwd->desc);
  62. cwd->desc = -1;
  63. have_working_fchdir = 0;
  64. }
  65. else
  66. {
  67. error (0, errno, "current directory");
  68. close (cwd->desc);
  69. cwd->desc = -1;
  70. return 1;
  71. }
  72. }
  73. # endif /* __sun__ || sun */
  74. #else
  75. #define fchdir(x) (abort (), 0)
  76. have_working_fchdir = 0;
  77. #endif
  78. }
  79. if (!have_working_fchdir)
  80. {
  81. cwd->name = xgetwd ();
  82. if (cwd->name == NULL)
  83. {
  84. error (0, errno, "cannot get current directory");
  85. return 1;
  86. }
  87. }
  88. return 0;
  89. }
  90. /* Change to recorded location, CWD, in directory hierarchy.
  91. If "saved working directory", NULL))
  92. */
  93. int
  94. restore_cwd (cwd, dest)
  95. const struct saved_cwd *cwd;
  96. const char *dest;
  97. {
  98. int fail = 0;
  99. if (cwd->desc >= 0)
  100. {
  101. if (fchdir (cwd->desc))
  102. {
  103. error (0, errno, "cannot return to %s",
  104. (dest ? dest : "saved working directory"));
  105. fail = 1;
  106. }
  107. }
  108. else if (chdir (cwd->name) < 0)
  109. {
  110. error (0, errno, "%s", cwd->name);
  111. fail = 1;
  112. }
  113. return fail;
  114. }
  115. void
  116. free_cwd (cwd)
  117. struct saved_cwd *cwd;
  118. {
  119. if (cwd->desc >= 0)
  120. close (cwd->desc);
  121. if (cwd->name)
  122. free (cwd->name);
  123. }