50#include "acfutils/stat.h"
51#include "acfutils/time.h"
57static const char *
const icao_country_codes[] = {
61 "DA",
"DB",
"DF",
"DG",
"DI",
"DN",
"DR",
"DT",
"DX",
62 "EB",
"ED",
"EE",
"EF",
"EG",
"EH",
"EI",
"EK",
"EL",
63 "EN",
"EP",
"ES",
"ET",
"EV",
"EY",
64 "FA",
"FB",
"FC",
"FD",
"FE",
"FG",
"FH",
"FI",
"FJ",
65 "FK",
"FL",
"FM",
"FN",
"FO",
"FP",
"FQ",
"FS",
"FT",
66 "FV",
"FW",
"FX",
"FY",
"FZ",
67 "GA",
"GB",
"GC",
"GE",
"GF",
"GG",
"GL",
"GM",
"GO",
68 "GQ",
"GS",
"GU",
"GV",
69 "HA",
"HB",
"HC",
"HD",
"HE",
"HH",
"HK",
"HL",
"HR",
72 "LA",
"LB",
"LC",
"LD",
"LE",
"LF",
"LG",
"LH",
"LI",
73 "LJ",
"LK",
"LL",
"LM",
"LN",
"LO",
"LP",
"LQ",
"LR",
74 "LS",
"LT",
"LU",
"LV",
"LW",
"LX",
"LY",
"LZ",
75 "MB",
"MD",
"MG",
"MH",
"MK",
"MM",
"MN",
"MP",
"MR",
76 "MS",
"MT",
"MU",
"MW",
"MY",
"MZ",
77 "NC",
"NF",
"NG",
"NI",
"NL",
"NS",
"NT",
"NV",
"NW",
79 "OA",
"OB",
"OE",
"OI",
"OJ",
"OK",
"OL",
"OM",
"OO",
80 "OP",
"OR",
"OS",
"OT",
"OY",
81 "PA",
"PB",
"PC",
"PF",
"PG",
"PH",
"PJ",
"PK",
"PL",
82 "PM",
"PO",
"PP",
"PT",
"PW",
83 "RC",
"RJ",
"RK",
"RO",
"RP",
84 "SA",
"SB",
"SC",
"SD",
"SE",
"SF",
"SG",
"SH",
"SI",
85 "SJ",
"SK",
"SL",
"SM",
"SN",
"SO",
"SP",
"SS",
"SU",
87 "TA",
"TB",
"TD",
"TF",
"TG",
"TI",
"TJ",
"TK",
"TL",
88 "TN",
"TQ",
"TR",
"TT",
"TU",
"TV",
"TX",
89 "UA",
"UB",
"UC",
"UD",
"UG",
"UK",
"UM",
"UT",
91 "VA",
"VC",
"VD",
"VE",
"VG",
"VH",
"VI",
"VL",
"VM",
92 "VN",
"VO",
"VQ",
"VR",
"VT",
"VV",
"VY",
93 "WA",
"WB",
"WI",
"WM",
"WP",
"WQ",
"WR",
"WS",
100static const char *months[12] = {
101 "JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
102 "JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC"
108} airac_eff_dates[] = {
110 {1501,
"08-JAN"}, {1502,
"05-FEB"}, {1503,
"05-MAR"}, {1504,
"02-APR"},
111 {1505,
"30-APR"}, {1506,
"28-MAY"}, {1507,
"25-JUN"}, {1508,
"23-JUL"},
112 {1509,
"20-AUG"}, {1510,
"17-SEP"}, {1511,
"15-OCT"}, {1512,
"12-NOV"},
115 {1601,
"07-JAN"}, {1602,
"04-FEB"}, {1603,
"03-MAR"}, {1604,
"31-MAR"},
116 {1605,
"28-APR"}, {1606,
"26-MAY"}, {1607,
"23-JUN"}, {1608,
"21-JUL"},
117 {1609,
"18-AUG"}, {1610,
"15-SEP"}, {1611,
"13-OCT"}, {1612,
"10-NOV"},
120 {1701,
"05-JAN"}, {1702,
"02-FEB"}, {1703,
"02-MAR"}, {1704,
"30-MAR"},
121 {1705,
"27-APR"}, {1706,
"25-MAY"}, {1707,
"22-JUN"}, {1708,
"20-JUL"},
122 {1709,
"17-AUG"}, {1710,
"14-SEP"}, {1711,
"12-OCT"}, {1712,
"09-NOV"},
125 {1801,
"04-JAN"}, {1802,
"01-FEB"}, {1803,
"01-MAR"}, {1804,
"29-MAR"},
126 {1805,
"26-APR"}, {1806,
"24-MAY"}, {1807,
"21-JUN"}, {1808,
"19-JUL"},
127 {1809,
"16-AUG"}, {1810,
"13-SEP"}, {1811,
"11-OCT"}, {1812,
"08-NOV"},
130 {1901,
"03-JAN"}, {1902,
"31-JAN"}, {1903,
"28-FEB"}, {1904,
"28-MAR"},
131 {1905,
"25-APR"}, {1906,
"23-MAY"}, {1907,
"20-JUN"}, {1908,
"18-JUL"},
132 {1909,
"15-AUG"}, {1910,
"12-SEP"}, {1911,
"10-OCT"}, {1912,
"07-NOV"},
135 {2001,
"02-JAN"}, {2002,
"30-JAN"}, {2003,
"27-FEB"}, {2004,
"26-MAR"},
136 {2005,
"23-APR"}, {2006,
"21-MAY"}, {2007,
"18-JUN"}, {2008,
"16-JUL"},
137 {2009,
"13-AUG"}, {2010,
"10-SEP"}, {2011,
"08-OCT"}, {2012,
"05-NOV"},
138 {2013,
"03-DEC"}, {2014,
"31-DEC"},
140 {2101,
"28-JAN"}, {2102,
"25-FEB"}, {2103,
"25-MAR"}, {2104,
"22-APR"},
141 {2105,
"20-MAY"}, {2106,
"17-JUN"}, {2107,
"15-JUL"}, {2108,
"12-AUG"},
142 {2109,
"09-SEP"}, {2110,
"07-OCT"}, {2111,
"04-NOV"}, {2112,
"02-DEC"},
145 {2201,
"27-JAN"}, {2202,
"24-FEB"}, {2203,
"24-MAR"}, {2204,
"21-APR"},
146 {2205,
"19-MAY"}, {2206,
"16-JUN"}, {2207,
"14-JUL"}, {2208,
"11-AUG"},
147 {2209,
"08-SEP"}, {2210,
"06-OCT"}, {2211,
"03-NOV"}, {2212,
"01-DEC"},
150 {2301,
"26-JAN"}, {2302,
"23-FEB"}, {2303,
"23-MAR"}, {2304,
"20-APR"},
151 {2305,
"18-MAY"}, {2306,
"15-JUN"}, {2307,
"13-JUL"}, {2308,
"10-AUG"},
152 {2309,
"07-SEP"}, {2310,
"05-OCT"}, {2311,
"02-NOV"}, {2312,
"30-NOV"},
155 {2401,
"25-JAN"}, {2402,
"22-FEB"}, {2403,
"21-MAR"}, {2404,
"18-APR"},
156 {2405,
"16-MAY"}, {2406,
"13-JUN"}, {2407,
"11-JUL"}, {2408,
"08-AUG"},
157 {2409,
"05-SEP"}, {2410,
"03-OCT"}, {2411,
"31-OCT"}, {2412,
"28-NOV"},
160 {2501,
"23-JAN"}, {2502,
"20-FEB"}, {2503,
"20-MAR"}, {2504,
"17-APR"},
161 {2505,
"15-MAY"}, {2506,
"12-JUN"}, {2507,
"10-JUL"}, {2508,
"07-AUG"},
162 {2509,
"04-SEP"}, {2510,
"02-OCT"}, {2511,
"30-OCT"}, {2512,
"27-NOV"},
165 {2601,
"22-JAN"}, {2602,
"19-FEB"}, {2603,
"19-MAR"}, {2604,
"16-APR"},
166 {2605,
"14-MAY"}, {2606,
"11-JUN"}, {2607,
"09-JUL"}, {2608,
"06-AUG"},
167 {2609,
"03-SEP"}, {2610,
"01-OCT"}, {2611,
"29-OCT"}, {2612,
"26-NOV"},
170 {2701,
"21-JAN"}, {2702,
"18-FEB"}, {2703,
"18-MAR"}, {2704,
"15-APR"},
171 {2705,
"13-MAY"}, {2706,
"10-JUN"}, {2707,
"08-JUL"}, {2708,
"05-AUG"},
172 {2709,
"02-SEP"}, {2710,
"30-SEP"}, {2711,
"28-OCT"}, {2712,
"25-NOV"},
175 {2801,
"20-JAN"}, {2802,
"17-FEB"}, {2803,
"16-MAR"}, {2804,
"13-APR"},
176 {2805,
"11-MAY"}, {2806,
"08-JUN"}, {2807,
"06-JUL"}, {2808,
"03-AUG"},
177 {2809,
"31-AUG"}, {2810,
"28-SEP"}, {2811,
"26-OCT"}, {2812,
"23-NOV"},
180 {2901,
"18-JAN"}, {2902,
"15-FEB"}, {2903,
"15-MAR"}, {2904,
"12-APR"},
181 {2905,
"10-MAY"}, {2906,
"07-JUN"}, {2907,
"05-JUL"}, {2908,
"02-AUG"},
182 {2909,
"30-AUG"}, {2910,
"27-SEP"}, {2911,
"25-OCT"}, {2912,
"22-NOV"},
197 "from: %s:%d %f -> %f", file, line, hdg1, hdg2);
199 if (hdg1 > hdg2 + 180)
200 return (360 - hdg1 + hdg2);
202 return (-(hdg1 - hdg2));
204 if (hdg2 > hdg1 + 180)
205 return (-(360 - hdg2 + hdg1));
207 return (hdg2 - hdg1);
219 return (code >= 0 && code <= 7777 &&
221 ((code / 10) % 10) <= 7 &&
222 ((code / 100) % 10) <= 7 &&
223 ((code / 1000) % 10) <= 7);
235 unsigned freq_khz = freq_mhz * 1000;
238 if (freq_khz < 108000 || freq_khz > 117950)
244 if (freq_khz >= 108000 && freq_khz <= 112000 &&
245 freq_khz % 200 != 0 && freq_khz % 200 != 50)
248 if (freq_khz % 50 != 0)
263 unsigned freq_khz = freq_mhz * 1000;
266 if (freq_khz < 108100 || freq_khz > 111950)
269 if (freq_khz % 200 != 100 && freq_khz % 200 != 150)
282 unsigned freq_khz = freq_mhz * 1000;
285 if (freq_khz < 133000 || freq_khz > 136000 ||
299 unsigned freq_hz = freq_khz * 1000;
301 return (freq_hz >= 177000 && freq_hz <= 1750000);
314 if (strlen(icao) != 4)
316 for (
int i = 0; i < 4; i++) {
317 if ((icao[i] <
'A' || icao[i] >
'Z') &&
318 (icao[i] <
'0' || icao[i] >
'9')) {
322 if (icao[0] ==
'I' || icao[0] ==
'J' || icao[0] ==
'Q' ||
338 if (strlen(iata) != 3)
340 for (
int i = 0; i < 3; i++) {
341 if (iata[i] <
'A' || iata[i] >
'Z')
363 for (
int i = 0; icao_country_codes[i] != NULL; i++) {
364 if (strncmp(icao, icao_country_codes[i],
365 strlen(icao_country_codes[i])) == 0)
366 return (icao_country_codes[i]);
382 int len = strlen(rwy_ID);
384 if (len < 2 || len > 3 || !isdigit(rwy_ID[0]) || !isdigit(rwy_ID[1]))
387 if (hdg == 0 || hdg > 36)
390 if (rwy_ID[2] !=
'R' && rwy_ID[2] !=
'L' && rwy_ID[2] !=
'C' &&
425 if (len > 0 && dst[len - 1] ==
'T') {
431 if (dst[0] >=
'1' && dst[0] <=
'9' &&
432 (len == 1 || (len == 2 && !isdigit(dst[1])))) {
433 memmove(dst + 1, dst, len + 1);
439month2nr(
const char *month)
441 for (
int i = 0; i < 12; i++) {
442 if (strcmp(month, months[i]) == 0)
445 VERIFY_MSG(0,
"Invalid month specified: \"%s\"", month);
449nr2month(
unsigned tm_mon)
452 return (months[tm_mon]);
458 struct tm cyc_tm = { .tm_year = 0 };
459 char day[4], month[4];
460 int year = (airac_eff_dates[i].cycle / 100) + 100;
461 const char *start = airac_eff_dates[i].start;
463 snprintf(day,
sizeof (day),
"%c%c", start[0], start[1]);
464 snprintf(month,
sizeof (month),
"%c%c%c", start[3], start[4], start[5]);
466 cyc_tm.tm_year = year;
467 cyc_tm.tm_mday = atoi(day);
468 cyc_tm.tm_mon = month2nr(month);
471 cyc_tm.tm_isdst = -1;
473 return (lacf_timegm(&cyc_tm));
487 for (
int i = 0; airac_eff_dates[i].cycle != -1; i++) {
488 if (airac_eff_dates[i].cycle == cycle)
489 return (airac_eff_dates[i].start);
500 for (
int i = 0; airac_eff_dates[i].cycle != -1; i++) {
501 if (airac_eff_dates[i].cycle == cycle)
502 return (cycle2start(i));
528 for (
int i = 0; airac_eff_dates[i].cycle != -1; i++) {
529 if (airac_eff_dates[i].cycle == cycle) {
535 time_t cycle_end_t = cycle2start(i) + 28 * 86400;
540 snprintf(buf, 16,
"%02d-%s", end_tm.tm_mday,
541 nr2month(end_tm.tm_mon));
543 if (cycle_end_p != NULL)
544 *cycle_end_p = cycle_end_t;
559 for (
int i = 0; airac_eff_dates[i].cycle != -1; i++) {
560 if (cycle2start(i) > t && i > 0)
561 return (airac_eff_dates[i - 1].cycle);
591 bool_t toomany = B_FALSE;
595 for (
char *p = line; *p != 0; p++) {
598 if (i < (ssize_t)capacity)
606 return (toomany ? -i : i);
650strsplit(
const char *input,
const char *sep, bool_t skip_empty,
size_t *num)
654 size_t seplen = strlen(sep);
656 for (
const char *a = input, *b = strstr(a, sep);
657 a != NULL; a = b + seplen, b = strstr(a, sep)) {
659 b = input + strlen(input);
660 if (a != b || !skip_empty)
664 if (a == b && skip_empty)
671 for (
const char *a = input, *b = strstr(a, sep);
672 a != NULL; a = b + seplen, b = strstr(a, sep)) {
674 b = input + strlen(input);
675 if (a != b || !skip_empty) {
678 memcpy(result[i], a, b - a);
682 if (a == b && skip_empty)
686 memcpy(result[i], a, b - a);
707 for (
size_t i = 0; i < num; i++)
736 va_start(ap, format);
737 needed = vsnprintf(NULL, 0, format, ap);
740 va_start(ap, format);
742 (void) vsnprintf(*str + *sz, needed + 1, format, ap);
755 for (
int i = 0, n = strlen(str); i + 2 < n; i++) {
757 if (str[i] ==
'%' && isxdigit(str[i + 1]) &&
758 isxdigit(str[i + 2])) {
759 char dig[3] = { str[i + 1], str[i + 2], 0 };
761 sscanf(dig,
"%x", &val);
763 memmove(&str[i + 1], &str[i + 3], (n - i) - 2);
775 for (
int i = 0, n = strlen(str); i < n; i++)
776 str[i] = tolower(str[i]);
785 for (
int i = 0, n = strlen(str); i < n; i++)
786 str[i] = toupper(str[i]);
799 if ((str[0] & 0xe0) == 0xc0 && str[1] != 0)
801 if ((str[0] & 0xf0) == 0xe0 && str[1] != 0 && str[2] != 0)
803 if ((str[0] & 0xf8) == 0xf0 && str[1] != 0 && str[2] != 0 &&
818 size_t num_chars = 0;
819 for (
const char *s = str; s[0] != 0; num_chars++)
852 size_t n = 0, len = 0;
860 for (
const char *c = va_arg(ap2,
const char *); c != NULL;
861 c = va_arg(ap2,
const char *)) {
862 len += 1 + strlen(c);
867 n += snprintf(str, len + 1,
"%s", comp);
868 for (
const char *c = va_arg(ap,
const char *); c != NULL;
869 c = va_arg(ap,
const char *)) {
871 n += snprintf(&str[n], len - n + 1,
"%c%s", DIRSEP, c);
873 if (str[n - 1] == DIRSEP) {
894 for (
int i = 0, n = strlen(str); i < n; i++) {
904 for (
char *elem = str; *elem !=
'\0';) {
905 if (elem[0] == DIRSEP && elem[1] == DIRSEP) {
907 memmove(elem, &elem[1], strlen(&elem[1]) + 1);
926 const char *last_sep;
932 last_sep = MAX(strrchr(path,
'/'), strrchr(path,
'\\'));
933 if (last_sep == NULL) {
935 return (strdup(replace));
957 last = MAX(strrchr(path,
'/'), strrchr(path,
'\\'));
981 period = strrchr(path,
'.');
987 strlcpy(str, path, l + 1);
988 strlcpy(&str[l],
".", 2);
989 strlcpy(&str[l + 1], ext, k + 1);
995find_prev_path_sep(
char *path,
char *elem)
999 for (elem--; elem >= path; elem--) {
1000 if (*elem == DIRSEP)
1021 while ((elem = strstr(path, DIRSEP_S
".." DIRSEP_S)) != NULL ||
1022 ((elem = strstr(path, DIRSEP_S
"..")) != NULL && elem[3] ==
'\0')) {
1023 char *prev_comp = find_prev_path_sep(path, elem);
1024 if (prev_comp == NULL) {
1028 memmove(prev_comp, &elem[3], strlen(&elem[3]) + 1);
1039 char *filename, *str;
1058 char *filename, *str;
1089#define MAX_FILESIZE (256 << 20)
1094 fp = fopen(filename,
"rb");
1098 fseek(fp, 0, SEEK_END);
1100 if (len < 0 || len > MAX_FILESIZE) {
1104 fseek(fp, 0, SEEK_SET);
1107 if (fread(contents, 1, len, fp) != (
size_t)len) {
1138 FILE *fp = fopen(filename,
"rb");
1144 fseek(fp, 0, SEEK_END);
1151 fseek(fp, 0, SEEK_SET);
1154 if (fread(buf, 1, s, fp) < (
size_t)s) {
1178 ASSERT(filename != NULL);
1179 if (!
file_exists(filename, NULL) || stat(filename, &st) != 0)
1181 return (st.st_size);
1187win_perror(DWORD err,
const char *fmt, ...)
1190 LPSTR win_msg = NULL;
1195 len = vsnprintf(NULL, 0, fmt, ap);
1199 vsnprintf(caller_msg, len + 1, fmt, ap);
1202 (void) FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1203 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
1204 NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1205 (LPSTR)&win_msg, 0, NULL);
1207 logMsg(
"%s: %s", caller_msg, win_msg);
1225 unsigned len = strlen(filename);
1226 TCHAR *filenameT =
safe_calloc(len + 1,
sizeof (*filenameT));
1229 MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameT, len + 1);
1230 attr = GetFileAttributes(filenameT);
1232 *isdir = !!(attr & FILE_ATTRIBUTE_DIRECTORY);
1233 if (attr == INVALID_FILE_ATTRIBUTES) {
1245 if (stat(filename, &st) < 0) {
1246 if (errno != ENOENT)
1247 logMsg(
"Error checking if file %s exists: %s",
1248 filename, strerror(errno));
1252 *isdir = S_ISDIR(st.st_mode);
1266 unsigned len = strlen(dirname);
1267 WCHAR *dirnameW =
safe_calloc(len + 1,
sizeof (*dirnameW));
1269 MultiByteToWideChar(CP_UTF8, 0, dirname, -1, dirnameW, len + 1);
1270 if (!CreateDirectory(dirnameW, NULL) &&
1271 (err = GetLastError()) != ERROR_ALREADY_EXISTS) {
1272 win_perror(err,
"Error creating directory %s", dirname);
1278 if (mkdir(dirname, 0777) != 0 && errno != EEXIST) {
1279 logMsg(
"Error creating directory %s: %s", dirname,
1294 char *partname =
safe_calloc(1, strlen(dirname) + 1);
1296 for (
const char *start = dirname, *end = strchr(&dirname[1], DIRSEP);
1297 end != NULL; start = end, end = strchr(&start[1], DIRSEP)) {
1298 strncat(partname, start, end - start);
1311win_rmdir(
const LPTSTR dirnameT)
1313 WIN32_FIND_DATA find_data;
1314 HANDLE h_find = INVALID_HANDLE_VALUE;
1315 unsigned dirname_len = wcslen(dirnameT);
1316 TCHAR *srchnameT =
safe_calloc(dirname_len + 4,
sizeof (*srchnameT));
1318 StringCchPrintf(srchnameT, dirname_len + 4, TEXT(
"%s\\*"), dirnameT);
1319 h_find = FindFirstFile(srchnameT, &find_data);
1320 if (h_find == INVALID_HANDLE_VALUE) {
1321 int err = GetLastError();
1322 char dirname[MAX_PATH];
1323 WideCharToMultiByte(CP_UTF8, 0, dirnameT, -1, dirname,
1324 sizeof (dirname), NULL, NULL);
1325 win_perror(err,
"Error listing directory %s", dirname);
1329 TCHAR filepathT[MAX_PATH];
1332 if (wcscmp(find_data.cFileName, TEXT(
".")) == 0 ||
1333 wcscmp(find_data.cFileName, TEXT(
"..")) == 0)
1336 StringCchPrintf(filepathT, MAX_PATH, TEXT(
"%s\\%s"), dirnameT,
1337 find_data.cFileName);
1338 attrs = GetFileAttributes(filepathT);
1340 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
1341 if (!win_rmdir(filepathT))
1344 if (!DeleteFile(filepathT)) {
1345 char filepath[MAX_PATH];
1346 WideCharToMultiByte(CP_UTF8, 0, filepathT, -1,
1347 filepath,
sizeof (filepath), NULL, NULL);
1348 win_perror(GetLastError(),
"Error removing "
1349 "file %s", filepath);
1353 }
while (FindNextFile(h_find, &find_data));
1355 if (!RemoveDirectory(dirnameT)) {
1356 char dirname[MAX_PATH];
1357 WideCharToMultiByte(CP_UTF8, 0, dirnameT, -1,
1358 dirname,
sizeof (dirname), NULL, NULL);
1359 win_perror(GetLastError(),
"Error removing directory %s",
1368 if (h_find != INVALID_HANDLE_VALUE) {
1385 unsigned l = strlen(dirname) + 1;
1386 TCHAR *dirnameT =
safe_calloc(l + 1,
sizeof (*dirnameT));
1388 MultiByteToWideChar(CP_UTF8, 0, dirname, -1, dirnameT, l);
1389 bool_t result = win_rmdir(dirnameT);
1396 if ((dp = opendir(dirname)) == NULL) {
1397 logMsg(
"Error removing directory %s: %s", dirname,
1401 while ((de = readdir(dp)) != NULL) {
1402 char filename[FILENAME_MAX];
1406 if (strcmp(de->d_name,
".") == 0 ||
1407 strcmp(de->d_name,
"..") == 0)
1410 if (snprintf(filename,
sizeof (filename),
"%s/%s", dirname,
1411 de->d_name) >= (ssize_t)sizeof (filename)) {
1412 logMsg(
"Error removing directory %s: path too long",
1416 if (lstat(filename, &st) < 0) {
1417 logMsg(
"Error removing directory %s: cannot stat "
1418 "file %s: %s", dirname, de->d_name,
1422 if (S_ISDIR(st.st_mode)) {
1427 err = unlink(filename);
1430 logMsg(
"Error removing %s: %s", filename,
1436 if (rmdir(dirname) != 0) {
1437 logMsg(
"Error removing %s: %s", dirname, strerror(errno));
1462 unsigned l = strlen(filename) + 1;
1463 TCHAR *filenameT =
safe_calloc(l,
sizeof (*filenameT));
1466 MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameT, l);
1467 if (!DeleteFile(filenameT) && ((error = GetLastError()) !=
1468 ERROR_FILE_NOT_FOUND || !notfound_ok)) {
1469 win_perror(error,
"Cannot remove file %s", filename);
1476 if (unlink(filename) < 0 && (errno != ENOENT || !notfound_ok)) {
1477 logMsg(
"Cannot remove file %s: %s", filename, strerror(errno));
1491 int l = strlen(filename);
1496 return (strdup(
""));
1498 p1 = strrchr(filename,
'/');
1499 p2 = strrchr(filename,
'\\');
1502 return (strdup(
""));
1512opendir(
const char *path)
1515 unsigned l = strlen(path) + 3;
1518 MultiByteToWideChar(CP_UTF8, 0, path, -1, pathT, l);
1519 StringCchCat(pathT, l, TEXT(
"\\*"));
1520 dirp->handle = FindFirstFile(pathT, &dirp->find_data);
1521 if (dirp->handle == INVALID_HANDLE_VALUE) {
1522 win_perror(GetLastError(),
"Cannot open directory %s", path);
1527 dirp->first = B_TRUE;
1537 if (FindNextFile(dirp->handle, &dirp->find_data) == 0)
1540 dirp->first = B_FALSE;
1542 WideCharToMultiByte(CP_UTF8, 0, dirp->find_data.cFileName, -1,
1543 dirp->de.d_name, sizeof (dirp->de.d_name), NULL, NULL);
1550 FindClose(dirp->handle);
1555stat(
const char *pathname,
struct stat *buf)
1557 FILETIME wtime, atime;
1558 HANDLE fh = INVALID_HANDLE_VALUE;
1559 unsigned l = strlen(pathname) + 1;
1560 TCHAR *pathnameT =
safe_calloc(l,
sizeof (*pathnameT));
1562 ULARGE_INTEGER ftime;
1569 MultiByteToWideChar(CP_UTF8, 0, pathname, -1, pathnameT, l);
1570 fh = CreateFile(pathnameT, (!isdir ? FILE_READ_ATTRIBUTES : 0) |
1571 GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
1572 if (fh == INVALID_HANDLE_VALUE ||
1573 !GetFileTime(fh, NULL, &atime, &wtime) ||
1574 (!isdir && !GetFileSizeEx(fh, &sz))) {
1575 win_perror(GetLastError(),
"Cannot stat %s", pathname);
1582 buf->st_size = sz.QuadPart;
1584 ftime.LowPart = atime.dwLowDateTime;
1585 ftime.HighPart = atime.dwHighDateTime;
1586 buf->st_atime = ftime.QuadPart / 10000000ull - 11644473600ull;
1588 ftime.LowPart = wtime.dwLowDateTime;
1589 ftime.HighPart = wtime.dwHighDateTime;
1590 buf->st_mtime = ftime.QuadPart / 10000000ull - 11644473600ull;
1596 if (fh != INVALID_HANDLE_VALUE) {
1606qsort_partition(
void *base,
long lo,
long hi,
size_t size,
1607 int (*compar)(
const void *,
const void *,
void *),
void *arg)
1611 memcpy(tmp, base + size * (i), size); \
1612 memcpy(base + size * (i), base + size * (j), size); \
1613 memcpy(base + size * (j), tmp, size); \
1615 void *pivot = base + hi * size;
1619 for (
long j = lo; j < hi; j++) {
1620 if (compar(base + j * size, pivot, arg) < 0) {
1633qsort_r_impl(
void *base,
long lo,
long hi,
size_t size,
1634 int (*compar)(
const void *,
const void *,
void *),
void *arg)
1637 long p = qsort_partition(base, lo, hi, size, compar, arg);
1639 qsort_r_impl(base, lo, p - 1, size, compar, arg);
1640 qsort_r_impl(base, p + 1, hi, size, compar, arg);
1651 int (*compar)(
const void *,
const void *,
void *),
void *arg)
1656 qsort_r_impl(base, 0, nmemb - 1, size, compar, arg);
1677 for (l = 0; l + 1 < cap && src[l] !=
'\0'; l++)
1684 memcpy(dest, src, MIN(cap - 1, l + 1));
1686 dest[cap - 1] =
'\0';
#define ASSERT_MSG(x, fmt,...)
#define VERIFY3S(x, op, y)
#define VERIFY_MSG(x, fmt,...)
char * file2str_name(long *len_p, const char *filename)
char * lacf_dirname(const char *filename)
char ** strsplit(const char *input, const char *sep, bool_t skip_empty, size_t *num)
ssize_t filesz(const char *filename)
void unescape_percent(char *str)
int airac_time2cycle(time_t t)
void fix_pathsep(char *str)
char * mkpathname(const char *comp,...)
void strtoupper(char *str)
char * path_ext_subst(const char *path, const char *ext)
void copy_rwy_ID(const char *src, char dst[4])
char * file2str(const char *comp,...)
bool_t remove_directory(const char *dirname)
bool_t is_valid_icao_code(const char *icao)
ssize_t explode_line(char *line, char delim, char **comps, size_t capacity)
void path_normalize(char *path)
static bool_t lacf_gmtime_r(const time_t *tim, struct tm *tm)
size_t utf8_get_num_chars(const char *str)
bool_t is_valid_loc_freq(double freq_mhz)
char * file2str_ext(long *len_p, const char *comp,...)
const char * extract_icao_country_code(const char *icao)
bool_t is_valid_vor_freq(double freq_mhz)
bool_t is_valid_ndb_freq(double freq_khz)
static bool_t is_valid_hdg(double hdg)
static char * sprintf_alloc(const char *fmt,...)
const char * airac_cycle2eff_date(int cycle)
bool_t create_directory(const char *dirname)
bool_t is_valid_tacan_freq(double freq_mhz)
void * file2buf(const char *filename, size_t *bufsz)
bool_t airac_cycle2exp_date(int cycle, char buf[16], time_t *cycle_end_p)
void append_format(char **str, size_t *sz, const char *format,...)
void lacf_qsort_r(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *, void *), void *arg)
void lacf_strlcpy(char *dest, const char *src, size_t cap)
void free_strlist(char **comps, size_t num)
double rel_hdg_impl(double hdg1, double hdg2, const char *file, int line)
size_t utf8_char_get_num_bytes(const char *str)
bool_t create_directory_recursive(const char *dirname)
bool_t is_valid_rwy_ID(const char *rwy_ID)
char * path_last_comp(const char *path)
void strtolower(char *str)
bool_t remove_file(const char *filename, bool_t notfound_ok)
time_t airac_cycle2eff_date2(int cycle)
bool_t is_valid_xpdr_code(int code)
char * mkpathname_v(const char *comp, va_list ap)
bool_t file_exists(const char *path, bool_t *isdir)
bool_t is_valid_iata_code(const char *iata)
char * path_last_comp_subst(const char *path, const char *replace)
static void strip_space(char *line)
static void * safe_realloc(void *oldptr, size_t size)
static void * safe_calloc(size_t nmemb, size_t size)
static void * safe_malloc(size_t size)