logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git/

sync.c (2376B)


  1. // utils-std: Collection of commonly available Unix tools
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #define _GNU_SOURCE // syncfs
  6. #define _XOPEN_SOURCE 700 // sync
  7. #include "../config.h" // HAS_*
  8. #include "../libutils/getopt_nolong.h"
  9. #include <errno.h>
  10. #include <fcntl.h> // open, O_*
  11. #include <stdbool.h>
  12. #include <stdio.h> // fprintf
  13. #include <stdlib.h> // abort
  14. #include <string.h> // strerror
  15. #include <unistd.h> // fsync, sync, getopt, syncfs
  16. #ifdef HAS_GETOPT_LONG
  17. #include <getopt.h>
  18. #endif
  19. const char *argv0 = "sync";
  20. int
  21. main(int argc, char *argv[])
  22. {
  23. int err = 0;
  24. int (*sync_func)(int) = fsync;
  25. #ifdef HAS_GETOPT_LONG
  26. // Strictly for GNUisms compatibility so no long-only options
  27. // clang-format off
  28. static struct option opts[] = {
  29. {"data", no_argument, NULL, 'd'},
  30. {"file-system", no_argument, NULL, 'f'},
  31. {0, 0, 0, 0},
  32. };
  33. // clang-format on
  34. // Need + as first character to get POSIX-style option parsing
  35. for(int c = -1; (c = getopt_long(argc, argv, "+:df", opts, NULL)) != -1;)
  36. #else
  37. for(int c = -1; (c = getopt_nolong(argc, argv, ":df")) != -1;)
  38. #endif
  39. {
  40. switch(c)
  41. {
  42. case 'd':
  43. sync_func = fdatasync;
  44. break;
  45. case 'f':
  46. #ifdef HAS_SYNCFS
  47. sync_func = syncfs;
  48. break;
  49. #else
  50. fprintf(stderr,
  51. "sync: error: System doesn't supports syncfs(3), continuing with error status set\n");
  52. err = 1;
  53. break;
  54. #endif
  55. case '?':
  56. GETOPT_UNKNOWN_OPT
  57. return 1;
  58. default:
  59. abort();
  60. }
  61. }
  62. argc -= optind;
  63. argv += optind;
  64. if(argc == 0)
  65. {
  66. #ifdef HAS_SYNCFS
  67. if(sync_func == syncfs) fprintf(stderr, "sync: warning: Option -f passed without arguments\n");
  68. #endif
  69. sync();
  70. return err;
  71. }
  72. for(int i = 0; i < argc; i++)
  73. {
  74. int fd = open(argv[i], O_RDONLY);
  75. if(fd < 0)
  76. {
  77. fprintf(stderr, "sync: error: Failed opening file '%s': %s\n", argv[i], strerror(errno));
  78. return 1;
  79. }
  80. if(sync_func(fd) < 0)
  81. {
  82. fprintf(stderr,
  83. "sync: error: Failed synchronizing changes related to file '%s': %s\n",
  84. argv[i],
  85. strerror(errno));
  86. return 1;
  87. }
  88. if(close(fd) < 0)
  89. {
  90. fprintf(stderr,
  91. "sync: error: Failed closing file-descriptor of file '%s': %s\n",
  92. argv[i],
  93. strerror(errno));
  94. return 1;
  95. }
  96. }
  97. return err;
  98. }