Skip to content

Commit b6377c0

Browse files
committed
use utf8 encoding for file names
1 parent 044e568 commit b6377c0

File tree

6 files changed

+184
-38
lines changed

6 files changed

+184
-38
lines changed

encfs/encfs/compatwin.cpp

+131-26
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//#include <fcntl.h>
77
//#include <fuse.h>
88

9+
#include "encfs.h"
910
#include "pthread.h"
1011

1112
#include <errno.h>
@@ -15,6 +16,7 @@
1516
#include <fcntl.h>
1617
#include <fuse.h>
1718
#include <winioctl.h>
19+
#include <boost/scoped_array.hpp>
1820

1921
void pthread_mutex_init(pthread_mutex_t *mtx, int )
2022
{
@@ -106,7 +108,7 @@ ssize_t pwrite(int fd, const void *buf, size_t count, __int64 offset)
106108

107109
int truncate(const char *path, __int64 length)
108110
{
109-
int fd = open(path, O_RDWR);
111+
int fd = _wopen(utf8_to_wfn(path).c_str(), O_RDWR);
110112

111113
if (fd < 0) return -1;
112114

@@ -283,25 +285,7 @@ utimes(const char *filename, const struct timeval times[2])
283285
struct _utimbuf tm;
284286
tm.actime = times[0].tv_sec;
285287
tm.modtime = times[1].tv_sec;
286-
return _utime(filename, &tm);
287-
}
288-
289-
int
290-
my_stat (const char* fn, struct FUSE_STAT* st)
291-
{
292-
char buf[512];
293-
_snprintf(buf, 512, "%s", fn);
294-
buf[511] = 0;
295-
296-
for (char *p = buf; *p; ++p)
297-
if (*p == '/')
298-
*p = '\\';
299-
300-
size_t l = strlen(buf);
301-
if (buf[l-1] == '\\')
302-
buf[l-1] = 0;
303-
304-
return ::_stati64(buf, st);
288+
return _wutime(utf8_to_wfn(filename).c_str(), &tm);
305289
}
306290

307291
int
@@ -338,12 +322,13 @@ set_sparse(HANDLE fd)
338322
}
339323

340324
int
341-
my_open(const char *fn, int flags)
325+
my_open(const char *fn_utf8, int flags)
342326
{
343-
HANDLE f = CreateFile(fn, flags == O_RDONLY ? GENERIC_WRITE : GENERIC_WRITE|GENERIC_READ, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
327+
std::wstring fn = utf8_to_wfn(fn_utf8);
328+
HANDLE f = CreateFileW(fn.c_str(), flags == O_RDONLY ? GENERIC_WRITE : GENERIC_WRITE|GENERIC_READ, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
344329
if (f == INVALID_HANDLE_VALUE) {
345330
int save_errno = win32_error_to_errno(GetLastError());
346-
f = CreateFile(fn, flags == O_RDONLY ? GENERIC_WRITE : GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
331+
f = CreateFileW(fn.c_str(), flags == O_RDONLY ? GENERIC_WRITE : GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
347332
if (f == INVALID_HANDLE_VALUE) {
348333
errno = save_errno;
349334
return -1;
@@ -360,12 +345,132 @@ my_open(const char *fn, int flags)
360345
return fd;
361346
}
362347

363-
namespace pthread {
348+
int
349+
open(const char *fn, int flags, ...)
350+
{
351+
int mode = 0;
352+
va_list ap;
353+
va_start(ap, flags);
354+
if (flags & O_CREAT)
355+
mode = va_arg(ap, int);
356+
va_end(ap);
357+
return _wopen(utf8_to_wfn(fn).c_str(), flags, mode);
358+
}
359+
360+
int
361+
utime(const char *filename, struct utimbuf *times)
362+
{
363+
return _wutime(utf8_to_wfn(filename).c_str(), (struct _utimbuf*) times);
364+
}
365+
366+
int
367+
mkdir(const char *fn, int mode)
368+
{
369+
return _wmkdir(utf8_to_wfn(fn).c_str());
370+
}
371+
372+
int
373+
rename(const char *oldpath, const char *newpath)
374+
{
375+
return _wrename(utf8_to_wfn(oldpath).c_str(), utf8_to_wfn(newpath).c_str());
376+
}
377+
378+
int
379+
unlink(const char *path)
380+
{
381+
return _wunlink(utf8_to_wfn(path).c_str());
382+
}
364383

365-
int mkdir(const char *fn, int mode)
384+
int
385+
rmdir(const char *path)
366386
{
367-
return ::mkdir(fn);
387+
return _wrmdir(utf8_to_wfn(path).c_str());
368388
}
369389

390+
int
391+
_stati64(const char *path, struct _stati64 *buffer)
392+
{
393+
std::wstring fn = utf8_to_wfn(path).c_str();
394+
if (fn.length() && fn[fn.length()-1] == L'\\')
395+
fn.resize(fn.length()-1);
396+
return _wstati64(fn.c_str(), buffer);
397+
}
398+
399+
int
400+
chmod(const char* path, int mode)
401+
{
402+
return _wchmod(utf8_to_wfn(path).c_str(), mode);
403+
}
404+
405+
struct MY_DIR
406+
{
407+
HANDLE hff;
408+
struct dirent ent;
409+
WIN32_FIND_DATAW wfd;
410+
int pos;
411+
};
412+
413+
MY_DIR*
414+
my_opendir(const char *name)
415+
{
416+
MY_DIR *dir = (MY_DIR*) malloc(sizeof(MY_DIR));
417+
if (!dir) {
418+
errno = ENOMEM;
419+
return NULL;
420+
}
421+
memset(dir, 0, sizeof(*dir));
422+
std::wstring path = utf8_to_wfn(name) + L"\\*";
423+
dir->hff = FindFirstFileW(path.c_str(), &dir->wfd);
424+
if (dir->hff == INVALID_HANDLE_VALUE) {
425+
errno = win32_error_to_errno(GetLastError());
426+
free(dir);
427+
return NULL;
428+
}
429+
return dir;
430+
}
431+
432+
int
433+
my_closedir(MY_DIR* dir)
434+
{
435+
errno = 0;
436+
if (dir && dir->hff != INVALID_HANDLE_VALUE)
437+
FindClose(dir->hff);
438+
free(dir);
439+
return 0;
440+
}
441+
442+
void utf8_to_wchar_buf(const char *src, wchar_t *res, int maxlen);
443+
std::string wchar_to_utf8_cstr(const wchar_t *str);
444+
445+
struct dirent*
446+
my_readdir(MY_DIR* dir)
447+
{
448+
errno = EBADF;
449+
if (!dir) return NULL;
450+
errno = 0;
451+
if (dir->pos < 0) return NULL;
452+
if (dir->pos == 0) {
453+
++dir->pos;
454+
} else if (!FindNextFileW(dir->hff, &dir->wfd)) {
455+
errno = GetLastError() == ERROR_NO_MORE_FILES ? 0 : win32_error_to_errno(GetLastError());
456+
return NULL;
457+
}
458+
std::string path = wchar_to_utf8_cstr(dir->wfd.cFileName);
459+
strncpy(dir->ent.d_name, path.c_str(), sizeof(dir->ent.d_name));
460+
dir->ent.d_name[sizeof(dir->ent.d_name)-1] = 0;
461+
dir->ent.d_namlen = strlen(dir->ent.d_name);
462+
return &dir->ent;
463+
}
464+
465+
std::wstring
466+
utf8_to_wfn(const std::string& src)
467+
{
468+
int len = src.length()+1;
469+
boost::scoped_array<wchar_t> buf(new wchar_t[len]);
470+
utf8_to_wchar_buf(src.c_str(), buf.get(), len);
471+
for (wchar_t *p = buf.get(); *p; ++p)
472+
if (*p == L'/')
473+
*p = L'\\';
474+
return buf.get();
370475
}
371476

encfs/encfs/dangerous

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
while read FN; do
4+
FN=($FN)
5+
FN=${FN%%@*}
6+
echo $FN
7+
i586-mingw32msvc-objdump -tC .libs/*.o|grep -w $FN| grep -v ::
8+
done < ../../files_functions.txt

encfs/encfs/encfs.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -822,9 +822,9 @@ static uint32_t encfs_win_get_attributes(const char *fn)
822822
if(!FSRoot)
823823
return res;
824824

825-
std::string path = FSRoot->cipherPath(fn);
825+
std::wstring path = utf8_to_wfn(FSRoot->cipherPath(fn));
826826
// TODO error
827-
return GetFileAttributes(path.c_str());
827+
return GetFileAttributesW(path.c_str());
828828
}
829829

830830
static int encfs_win_set_attributes(const char *fn, uint32_t attr)
@@ -836,8 +836,8 @@ static int encfs_win_set_attributes(const char *fn, uint32_t attr)
836836
if(!FSRoot)
837837
return res;
838838

839-
std::string path = FSRoot->cipherPath(fn);
840-
if (SetFileAttributes(path.c_str(), attr))
839+
std::wstring path = utf8_to_wfn(FSRoot->cipherPath(fn));
840+
if (SetFileAttributesW(path.c_str(), attr))
841841
return 0;
842842
return -win32_error_to_errno(GetLastError());
843843
}
@@ -868,9 +868,9 @@ static int encfs_win_set_times(const char *path, struct fuse_file_info *fi, cons
868868
if(!FSRoot)
869869
return res;
870870

871-
std::string fn = FSRoot->cipherPath(path);
871+
std::wstring fn = utf8_to_wfn(FSRoot->cipherPath(path));
872872

873-
HANDLE f = CreateFile(fn.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
873+
HANDLE f = CreateFileW(fn.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
874874
if (f == INVALID_HANDLE_VALUE)
875875
return -win32_error_to_errno(GetLastError());
876876

encfs/encfs/pthread.h

+20-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include <windows.h>
55
#include <stdio.h>
6+
#include <dirent.h>
7+
#include <string>
68

79
typedef HANDLE pthread_t;
810
typedef CRITICAL_SECTION pthread_mutex_t;
@@ -24,13 +26,26 @@ ssize_t pwrite(int fd, const void *buf, size_t count, __int64 offset);
2426
int truncate(const char *path, __int64 length);
2527
int statvfs(const char *path, struct statvfs *buf);
2628
int utimes(const char *filename, const struct timeval times[2]);
27-
int my_stat (const char* fn, struct FUSE_STAT* st);
28-
#define lstat my_stat
29+
int utime(const char *filename, struct utimbuf *times);
30+
#define lstat stat
2931
int my_open(const char *fn, int flags);
30-
namespace pthread {
3132
int mkdir(const char *fn, int mode);
32-
}
33-
using pthread::mkdir;
33+
int rename(const char *oldpath, const char *newpath);
34+
int unlink(const char *path);
35+
int rmdir(const char *path);
36+
int __MINGW_NOTHROW _stati64(const char *path, struct _stati64 *buffer);
37+
int chmod (const char*, int);
38+
39+
typedef struct MY_DIR MY_DIR;
40+
MY_DIR *my_opendir(const char *name);
41+
int my_closedir(MY_DIR* dir);
42+
struct dirent* my_readdir(MY_DIR* dir);
43+
#define DIR MY_DIR
44+
#define opendir my_opendir
45+
#define closedir my_closedir
46+
#define readdir my_readdir
47+
48+
std::wstring utf8_to_wfn(const std::string& src);
3449

3550
#define mlock(a,b) do { } while(0)
3651
#define munlock(a,b) do { } while(0)

files_functions.txt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
chmod
2+
CreateFileA@28
3+
GetFileAttributesA@4
4+
GetModuleFileNameA@12 (maingui.cpp)
5+
mkdir
6+
open
7+
opendir
8+
closedir
9+
readdir
10+
rename
11+
rmdir
12+
SearchPathA@24 (drives.cpp)
13+
SetCurrentDirectoryA@4 (maingui.cpp)
14+
SetFileAttributesA@8
15+
_stati64
16+
unlink
17+
utime
18+
_utime

web/encfs.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ <h2>Use</h2>
6262

6363
<h2>News</h2>
6464
<ul>
65+
<li>2011-07-01 Fix encoding problem with no-encrypted filenames</li>
6566
<li>2011-05-26 Fix a possible buffer overflow</li>
6667
<li>2011-05-18 Fix problem renaming to already present files/directories</li>
6768
<li>2011-05-13 Fix encoding if wrong renaming file</li>
@@ -94,7 +95,6 @@ <h2>Limits and TODO</h2>
9495
<li>installer</li>
9596
<li>option to not open explorer window</li>
9697
<li>BUG: encrypted files name can be very long causing problems and paths greater than 256 characters (mostly C functions and also API have this limit)</li>
97-
<li>BUG: not using encrypted names cause encoding problem and unaccessible files as encfs expect utf8 encoding</li>
9898
<li>BUG: using remove drive as crypted folder excel seems to have problem saving</li>
9999
</ul>
100100

0 commit comments

Comments
 (0)