123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- #include "precompile.h"
- #include <wchar.h>
- #include <errno.h>
- #ifdef _WIN32
- #include <mbstring.h>
- #include <limits.h>
- #include <ShellAPI.h>
- #else
- #include <winpr/wtypes.h>
- #include <winpr/error.h>
- #include <winpr/file.h>
- #endif
- #include "array.h"
- #include "fileutil.h"
- #include "strutil.h"
- TOOLKIT_API BOOL CreateDirA(LPCSTR lpDirPath, BOOL bRecursive)
- {
- size_t len = strlen(lpDirPath);
- if (len <= 2 || len >= MAX_PATH-2) {
- return FALSE;
- } else {
- if (!bRecursive) {
- return CreateDirectoryA(lpDirPath, NULL) || (GetLastError() == ERROR_ALREADY_EXISTS);
- } else {
- CHAR tmp[MAX_PATH], *p;
- p = &tmp[0];
- strncpy(tmp, lpDirPath, MAX_PATH);
- tmp[MAX_PATH-1] = 0;
- if (tmp[len-1] != '\\') {
- tmp[len++] = '\\';
- tmp[len] = 0;
- }
- while ((p = strchr(p, '\\')) != NULL) {
- *p = 0;
- if (!ExistsDirA(tmp)) {
- if (!CreateDirectoryA(tmp, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
- return FALSE;
- }
- *p = '\\';
- p++;
- }
- }
- }
- return TRUE;
- }
- TOOLKIT_API BOOL CreateDirW(LPCWSTR lpDirPath, BOOL bRecursive)
- {
- size_t len = wcslen(lpDirPath);
- if (len <= 2 || len >= MAX_PATH-2) {
- return FALSE;
- } else {
- if (!bRecursive) {
- return CreateDirectoryW(lpDirPath, NULL) || (GetLastError() == ERROR_ALREADY_EXISTS);
- } else {
- WCHAR tmp[MAX_PATH], *p;
- p = &tmp[0];
- wcsncpy(tmp, lpDirPath, MAX_PATH);
- tmp[MAX_PATH-1] = 0;
- if (tmp[len-1] != '\\') {
- tmp[len++] = '\\';
- tmp[len] = 0;
- }
- while ((p = wcschr(p, '\\')) != NULL) {
- *p = 0;
- if (!ExistsDirW(tmp)) {
- if (!CreateDirectoryW(tmp, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
- return FALSE;
- }
- *p = '\\';
- p++;
- }
- }
- }
- return TRUE;
- }
- TOOLKIT_API BOOL CreateParentDirA(LPCSTR lpPath, BOOL bRecursive)
- {
- CHAR pdir[MAX_PATH];
- const CHAR *p;
- p = strrchr(lpPath, '\\');
- if (!p)
- return FALSE;
- strncpy(pdir, lpPath, p-lpPath);
- pdir[p-lpPath] = 0;
- return CreateDirA(pdir, bRecursive);
- }
- TOOLKIT_API BOOL CreateParentDirW(LPCWSTR lpPath, BOOL bRecursive)
- {
- WCHAR pdir[MAX_PATH];
- const WCHAR *p;
- p = wcsrchr(lpPath, '\\');
- if (!p)
- return FALSE;
- wcsncpy(pdir, lpPath, p-lpPath);
- pdir[p-lpPath] = 0;
- return CreateDirW(pdir, bRecursive);
- }
- TOOLKIT_API BOOL ClearDirRecursiveA(LPCSTR lpDirPath)
- {
- array_header_t *arr;
- BOOL bRet = TRUE;
- assert(lpDirPath);
- arr = fileutil_get_sub_files_a(lpDirPath);
- if (arr) {
- int i;
- for (i = 0; i < arr->nelts; ++i) {
- char *tmp = ARRAY_IDX(arr, i, char*);
- bRet &= DeleteFileA(tmp);
- }
- toolkit_array_free2(arr);
- }
- arr = fileutil_get_sub_dirs_a(lpDirPath);
- if (arr) {
- int i;
- for (i = 0; i < arr->nelts; ++i) {
- char *tmp = ARRAY_IDX(arr, i, char*);
- bRet &= ClearDirRecursiveA(tmp);
- }
- toolkit_array_free2(arr);
- }
- return bRet;
- }
- TOOLKIT_API BOOL ClearDirRecursiveW(LPCWSTR lpDirPath)
- {
- array_header_t *arr;
- BOOL bRet = TRUE;
- assert(lpDirPath);
- arr = fileutil_get_sub_files_w(lpDirPath);
- if (arr) {
- int i;
- for (i = 0; i < arr->nelts; ++i) {
- wchar_t *tmp = ARRAY_IDX(arr, i, wchar_t*);
- bRet &= DeleteFileW(tmp);
- }
- toolkit_array_free2(arr);
- }
- arr = fileutil_get_sub_dirs_w(lpDirPath);
- if (arr) {
- int i;
- for (i = 0; i < arr->nelts; ++i) {
- wchar_t *tmp = ARRAY_IDX(arr, i, wchar_t*);
- bRet &= ClearDirRecursiveW(tmp);
- }
- toolkit_array_free2(arr);
- }
- return bRet;
- }
- TOOLKIT_API BOOL RemoveFileA(LPCSTR pszFile)
- {
- if(ExistsFileA(pszFile))
- {
- // remove readonly attribute
- DWORD dwRet = GetFileAttributesA(pszFile);
- if (dwRet & FILE_ATTRIBUTE_READONLY)
- {
- dwRet &= (~FILE_ATTRIBUTE_READONLY);
- SetFileAttributesA(pszFile, dwRet);
- }
- // delete it
- return DeleteFileA(pszFile);
- }
- return FALSE;
- }
- // 移除文件只读属性
- TOOLKIT_API BOOL RemoveFileReadOnlyAttributeA(LPCSTR pszFile)
- {
- if(ExistsFileA(pszFile))
- {
- // remove readonly attribute
- DWORD dwRet = GetFileAttributesA(pszFile);
- if (dwRet & FILE_ATTRIBUTE_READONLY)
- {
- dwRet &= (~FILE_ATTRIBUTE_READONLY);
- SetFileAttributesA(pszFile, dwRet);
- }
- return TRUE;
- }
- return FALSE;
- }
- // 递归拷贝所有文件及子文件夹
- TOOLKIT_API BOOL CopyDirA(LPCSTR pszSourceDir, LPCSTR pszDestDir)
- {
- array_header_t *arr;
- BOOL bRet = TRUE;
- if (!ExistsDirA(pszSourceDir))
- return FALSE;
- if (!ExistsDirA(pszDestDir))
- {
- if (!CreateDirRecursiveA(pszDestDir))
- return FALSE;
- }
- arr = fileutil_get_sub_files_a(pszSourceDir);
- if (arr)
- {
- int i;
- for (i = 0; i < arr->nelts; ++i)
- {
- char szDestFile[256] = {0};
- char *file = ARRAY_IDX(arr, i, char*);
- strcpy(szDestFile, pszDestDir);
- if (szDestFile[strlen(szDestFile)-1] != '\\')
- strcat(szDestFile, "\\");
- strcat(szDestFile, strrchr(file, '\\')+1);
-
- bRet &= CopyFileA(file, szDestFile, FALSE);
- }
- toolkit_array_free2(arr);
- }
- arr = fileutil_get_sub_dirs_a(pszSourceDir);
- if (arr)
- {
- int i;
- for (i = 0; i < arr->nelts; ++i)
- {
- char szDestSubDir[256] = {0};
- char *dir = ARRAY_IDX(arr, i, char*);
- strcpy(szDestSubDir, pszDestDir);
- if (szDestSubDir[strlen(szDestSubDir)-1] != '\\')
- strcat(szDestSubDir, "\\");
- strcat(szDestSubDir, strrchr(dir, '\\')+1);
-
- bRet &= CopyDirA(dir, szDestSubDir);
- }
- toolkit_array_free2(arr);
- }
- return bRet;
- }
- // 只能删除非只读文件或目录
- //TOOLKIT_API BOOL RemoveDirRecursiveA(LPCSTR lpDirPath)
- //{
- // array_header_t *arr;
- // BOOL bRet = TRUE;
- //
- // assert(lpDirPath);
- //
- // arr = fileutil_get_sub_files_a(lpDirPath);
- // if (arr) {
- // int i;
- // for (i = 0; i < arr->nelts; ++i) {
- // char *tmp = ARRAY_IDX(arr, i, char*);
- // bRet &= DeleteFileA(tmp);
- // }
- // toolkit_array_free2(arr);
- // }
- //
- // arr = fileutil_get_sub_dirs_a(lpDirPath);
- // if (arr) {
- // int i;
- // for (i = 0; i < arr->nelts; ++i) {
- // char *tmp = ARRAY_IDX(arr, i, char*);
- // bRet &= RemoveDirRecursiveA(tmp);
- // }
- // toolkit_array_free2(arr);
- // }
- //
- // if (bRet) {
- // bRet = RemoveDirectoryA(lpDirPath);
- // }
- //
- // return bRet;
- //}
- TOOLKIT_API BOOL RemoveDirRecursiveA(LPCSTR lpDirPath)
- {
- #ifdef _WIN32
- int nRet = 0;
- char szDir[256] = {0};
- SHFILEOPSTRUCT fo;
- memset(&fo, 0, sizeof(fo));
- memcpy(szDir, lpDirPath, strlen(lpDirPath));
- fo.wFunc = FO_DELETE;
- fo.pFrom = szDir;
- fo.fFlags = FOF_NO_UI;
- nRet = SHFileOperationA(&fo);
- return nRet ==0 ? TRUE: FALSE;
- #else
- array_header_t* arr;
- BOOL bRet = TRUE;
- assert(lpDirPath);
- arr = fileutil_get_sub_files_a(lpDirPath);
- if (arr) {
- int i;
- for (i = 0; i < arr->nelts; ++i) {
- char* tmp = ARRAY_IDX(arr, i, char*);
- bRet &= DeleteFileA(tmp);
- }
- toolkit_array_free2(arr);
- }
- arr = fileutil_get_sub_dirs_a(lpDirPath);
- if (arr) {
- int i;
- for (i = 0; i < arr->nelts; ++i) {
- char* tmp = ARRAY_IDX(arr, i, char*);
- bRet &= RemoveDirRecursiveA(tmp);
- }
- toolkit_array_free2(arr);
- }
- if (bRet) {
- bRet = RemoveDirectoryA(lpDirPath);
- }
- return bRet;
- #endif
- }
- TOOLKIT_API BOOL RemoveDirRecursiveW(LPCWSTR lpDirPath)
- {
- array_header_t *arr;
- BOOL bRet = TRUE;
- assert(lpDirPath);
- arr = fileutil_get_sub_files_w(lpDirPath);
- if (arr) {
- int i;
- for (i = 0; i < arr->nelts; ++i) {
- wchar_t *tmp = ARRAY_IDX(arr, i, wchar_t*);
- bRet &= DeleteFileW(tmp);
- }
- toolkit_array_free2(arr);
- }
- arr = fileutil_get_sub_dirs_w(lpDirPath);
- if (arr) {
- int i;
- for (i = 0; i < arr->nelts; ++i) {
- wchar_t *tmp = ARRAY_IDX(arr, i, wchar_t*);
- bRet &= RemoveDirRecursiveW(tmp);
- }
- toolkit_array_free2(arr);
- }
- if (bRet) {
- bRet = RemoveDirectoryW(lpDirPath);
- }
- return bRet;
- }
- static array_header_t *fileutil_get_sub_a(const char *path, int isfile, int limitation)
- {
- array_header_t *arr = NULL;
- char tmp[MAX_PATH];
- int npath;
- if (!path)
- return NULL;
- npath = strlen(path);
- if (npath < 2)
- return NULL;
- strcpy(tmp, path);
- if (tmp[npath-1] != '\\') {
- tmp[npath++] = '\\';
- tmp[npath] = 0;
- }
- tmp[npath++] = '*';
- tmp[npath] = 0;
- arr = array_make(3, sizeof(char*));
- {
- WIN32_FIND_DATAA fd;
- HANDLE hFind = FindFirstFileA(tmp, &fd);
- if (hFind != INVALID_HANDLE_VALUE) {
- tmp[--npath] = 0;
- do {
- int isdir = !!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
- if (isdir) {
- if (strcmp(fd.cFileName, ".") == 0 || strcmp(fd.cFileName, "..") == 0) {
- continue;;
- }
- }
- if (isfile ^ isdir) {
- char *v = malloc(sizeof(char)*(npath + strlen(fd.cFileName)+1));
- strcpy(v, tmp);
- strcat(v, fd.cFileName);
- ARRAY_PUSH(arr, char*) = v;
- }
- } while (FindNextFileA(hFind, &fd) && arr->nelts < limitation);
- FindClose(hFind);
- }
- }
- return arr;
- }
- static array_header_t *fileutil_get_sub_w(const wchar_t *path, int isfile, int limitation)
- {
- array_header_t *arr = NULL;
- WCHAR tmp[MAX_PATH];
- int npath;
- if (!path)
- return NULL;
- npath = wcslen(path);
- if (npath < 2)
- return NULL;
- wcscpy(tmp, path);
- if (tmp[npath-1] != '\\') {
- tmp[npath++] = '\\';
- tmp[npath] = 0;
- }
- tmp[npath++] = '*';
- tmp[npath] = 0;
- arr = array_make(3, sizeof(wchar_t*));
- {
- WIN32_FIND_DATAW fd;
- HANDLE hFind = FindFirstFileW(tmp, &fd);
- if (hFind != INVALID_HANDLE_VALUE) {
- tmp[--npath] = 0;
- do {
- int isdir = !!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
- if (isfile ^ isdir) {
- wchar_t *v = malloc(sizeof(wchar_t)*(npath + wcslen(fd.cFileName)+1));
- wcscpy(v, tmp);
- wcscat(v, fd.cFileName);
- ARRAY_PUSH(arr, wchar_t*) = v;
- }
- } while (FindNextFileW(hFind, &fd) && arr->nelts < limitation);
- FindClose(hFind);
- }
- }
- return arr;
- }
- TOOLKIT_API array_header_t *fileutil_get_sub_files_a(const char *path)
- {
- return fileutil_get_sub_a(path, 1, INT_MAX);
- }
- TOOLKIT_API array_header_t *fileutil_get_sub_dirs_a(const char *path)
- {
- return fileutil_get_sub_a(path, 0, INT_MAX);
- }
- TOOLKIT_API array_header_t *fileutil_get_sub_files_w(const wchar_t *path)
- {
- return fileutil_get_sub_w(path, 1, INT_MAX);
- }
- TOOLKIT_API array_header_t *fileutil_get_sub_dirs_w(const wchar_t *path)
- {
- return fileutil_get_sub_w(path, 0, INT_MAX);
- }
- TOOLKIT_API array_header_t *fileutil_get_sub_files2_a(const char *path, int limitation)
- {
- return fileutil_get_sub_a(path, 1, limitation);
- }
- TOOLKIT_API array_header_t *fileutil_get_sub_dirs2_a(const char *path, int limitation)
- {
- return fileutil_get_sub_a(path, 0, limitation);
- }
- TOOLKIT_API array_header_t *fileutil_get_sub_files2_w(const wchar_t *path, int limitation)
- {
- return fileutil_get_sub_w(path, 1, limitation);
- }
- TOOLKIT_API array_header_t *fileutil_get_sub_dirs2_w(const wchar_t *path, int limitation)
- {
- return fileutil_get_sub_w(path, 0, limitation);
- }
- TOOLKIT_API FILE *fileutil_transaction_fopen(const char *filename, const char *mode)
- {
- DWORD dwAttr;
- char t[MAX_PATH];
- int write_flag;
- if (!filename || !mode) {
- errno = EINVAL;
- return NULL;
- }
- write_flag = (int)strchr(mode, 'w');
- strcpy(t, filename);
- strcat(t, ".bak");
- dwAttr = GetFileAttributesA(filename);
- if (dwAttr != INVALID_FILE_ATTRIBUTES && dwAttr & FILE_ATTRIBUTE_DIRECTORY) {
- errno = EIO;
- return NULL;
- }
- if (dwAttr != INVALID_FILE_ATTRIBUTES) {
- if (!(dwAttr & FILE_ATTRIBUTE_READONLY)) {
- BOOL bRet = DeleteFileA(filename);
- if (bRet) {
- if (!write_flag) {
- if (ExistsFileA(t)) {
- bRet = CopyFileA(t, filename, FALSE);
- if (bRet)
- bRet = SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL);
- }
- }
- }
- if (!bRet) {
- errno = EIO;
- return NULL;
- }
- } else {
- if (write_flag) {
- BOOL bRet = TRUE;
- if (ExistsFileA(t)) {
- bRet = SetFileAttributesA(t, dwAttr & ~FILE_ATTRIBUTE_READONLY);
- }
- if (bRet) {
- bRet = CopyFileA(filename, t, FALSE);
- }
- if (!bRet) {
- errno = EIO;
- return NULL;
- }
- }
- }
- } else {
- if (!write_flag) {
- BOOL bRet = TRUE;
- if (ExistsFileA(t)) {
- bRet = CopyFileA(t, filename, FALSE);
- } else {
- bRet = FALSE;
- }
- if (!bRet) {
- errno = EIO;
- return NULL;
- }
- }
- }
- return fopen(filename, mode);
- }
- TOOLKIT_API int fileutil_transaction_fclose(const char *filename, FILE *fp)
- {
- int rc = fclose(fp);
- if (!rc && filename) {
- DWORD dwAttr = GetFileAttributesA(filename);
- if (dwAttr != INVALID_FILE_ATTRIBUTES) {
- if (!(dwAttr & FILE_ATTRIBUTE_READONLY))
- SetFileAttributesA(filename, dwAttr | FILE_ATTRIBUTE_READONLY);
- }
- }
- return rc;
- }
|