lha_arch_win32.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. Copyright (c) 2012, Simon Howard
  3. Permission to use, copy, modify, and/or distribute this software
  4. for any purpose with or without fee is hereby granted, provided
  5. that the above copyright notice and this permission notice appear
  6. in all copies.
  7. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  8. WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  9. WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  10. AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
  11. CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  13. NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. //
  17. // Architecture-specific files for compilation on Windows.
  18. // A work in progress.
  19. //
  20. #include "lha_arch.h"
  21. #if LHA_ARCH == LHA_ARCH_WINDOWS
  22. #define WIN32_LEAN_AND_MEAN
  23. #include <windows.h>
  24. #include <fcntl.h>
  25. #include <io.h>
  26. #include <stdlib.h>
  27. #include <stdint.h>
  28. static uint64_t unix_epoch_offset = 0;
  29. int lha_arch_vasprintf(char **result, char *fmt, va_list args)
  30. {
  31. int len;
  32. len = vsnprintf(NULL, 0, fmt, args);
  33. if (len >= 0) {
  34. *result = malloc(len + 1);
  35. if (*result != NULL) {
  36. return vsprintf(*result, fmt, args);
  37. }
  38. }
  39. *result = NULL;
  40. return -1;
  41. }
  42. void lha_arch_set_binary(FILE *handle)
  43. {
  44. _setmode(_fileno(handle), _O_BINARY);
  45. }
  46. int lha_arch_mkdir(char *path, unsigned int unix_mode)
  47. {
  48. return CreateDirectoryA(path, NULL) != 0;
  49. }
  50. int lha_arch_chown(char *filename, int unix_uid, int unix_gid)
  51. {
  52. return 1;
  53. }
  54. int lha_arch_chmod(char *filename, int unix_perms)
  55. {
  56. return 1;
  57. }
  58. static int set_timestamps(char *filename,
  59. FILETIME *creation_time,
  60. FILETIME *modification_time,
  61. FILETIME *access_time)
  62. {
  63. HANDLE file;
  64. int result;
  65. // Open file handle to the file to change.
  66. // The FILE_FLAG_BACKUP_SEMANTICS flag is needed so that we
  67. // can obtain handles to directories as well as files.
  68. file = CreateFileA(filename,
  69. FILE_WRITE_ATTRIBUTES,
  70. FILE_SHARE_READ | FILE_SHARE_WRITE,
  71. NULL,
  72. OPEN_EXISTING,
  73. FILE_FLAG_BACKUP_SEMANTICS,
  74. NULL);
  75. if (file == INVALID_HANDLE_VALUE) {
  76. return 0;
  77. }
  78. // Set the timestamp and close the file handle.
  79. result = SetFileTime(file, creation_time,
  80. access_time, modification_time);
  81. CloseHandle(file);
  82. return result != 0;
  83. }
  84. int lha_arch_set_windows_timestamps(char *filename,
  85. uint64_t creation_time,
  86. uint64_t modification_time,
  87. uint64_t access_time)
  88. {
  89. FILETIME _creation_time;
  90. FILETIME _modification_time;
  91. FILETIME _access_time;
  92. _creation_time.dwHighDateTime
  93. = (uint32_t) ((creation_time >> 32) & 0xffffffff);
  94. _creation_time.dwLowDateTime
  95. = (uint32_t) (creation_time & 0xffffffff);
  96. _modification_time.dwHighDateTime
  97. = (uint32_t) ((modification_time >> 32) & 0xffffffff);
  98. _modification_time.dwLowDateTime
  99. = (uint32_t) (modification_time & 0xffffffff);
  100. _access_time.dwHighDateTime
  101. = (uint32_t) ((access_time >> 32) & 0xffffffff);
  102. _access_time.dwLowDateTime
  103. = (uint32_t) (access_time & 0xffffffff);
  104. return set_timestamps(filename, &_creation_time,
  105. &_modification_time, &_access_time);
  106. }
  107. int lha_arch_utime(char *filename, unsigned int timestamp)
  108. {
  109. SYSTEMTIME unix_epoch;
  110. FILETIME filetime;
  111. uint64_t ts_scaled;
  112. // Calculate offset between Windows FILETIME Jan 1, 1601 epoch
  113. // and Unix Jan 1, 1970 offset.
  114. if (unix_epoch_offset == 0) {
  115. unix_epoch.wYear = 1970;
  116. unix_epoch.wMonth = 1;
  117. unix_epoch.wDayOfWeek = 4; // Thursday
  118. unix_epoch.wDay = 1;
  119. unix_epoch.wHour = 0; // 00:00:00.0
  120. unix_epoch.wMinute = 0;
  121. unix_epoch.wSecond = 0;
  122. unix_epoch.wMilliseconds = 0;
  123. SystemTimeToFileTime(&unix_epoch, &filetime);
  124. unix_epoch_offset = ((uint64_t) filetime.dwHighDateTime << 32)
  125. + filetime.dwLowDateTime;
  126. }
  127. // Convert to Unix FILETIME.
  128. ts_scaled = (uint64_t) timestamp * 10000000 + unix_epoch_offset;
  129. filetime.dwHighDateTime = (uint32_t) ((ts_scaled >> 32) & 0xffffffff);
  130. filetime.dwLowDateTime = (uint32_t) (ts_scaled & 0xffffffff);
  131. // Set all timestamps to the same value:
  132. return set_timestamps(filename, &filetime, &filetime, &filetime);
  133. }
  134. FILE *lha_arch_fopen(char *filename, int unix_uid, int unix_gid, int unix_perms)
  135. {
  136. return fopen(filename, "wb");
  137. }
  138. LHAFileType lha_arch_exists(char *filename)
  139. {
  140. WIN32_FILE_ATTRIBUTE_DATA file_attr;
  141. // Read file attributes to determine the type of the file.
  142. // If this fails, assume the file does not exist.
  143. if (GetFileAttributesExA(filename, GetFileExInfoStandard,
  144. &file_attr)) {
  145. if ((file_attr.dwFileAttributes
  146. & FILE_ATTRIBUTE_DIRECTORY) != 0) {
  147. return LHA_FILE_DIRECTORY;
  148. } else {
  149. return LHA_FILE_FILE;
  150. }
  151. }
  152. return LHA_FILE_NONE;
  153. }
  154. int lha_arch_symlink(char *path, char *target)
  155. {
  156. // No-op.
  157. return 1;
  158. }
  159. #endif /* LHA_ARCH_WINDOWS */