Skip to content

Instantly share code, notes, and snippets.

@DeaR
Last active December 14, 2015 05:39
Show Gist options
  • Save DeaR/5036534 to your computer and use it in GitHub Desktop.
Save DeaR/5036534 to your computer and use it in GitHub Desktop.
NYAOSの内蔵lsでリパースポイントを展開してみた(適当)
diff -r c95acae76050 lsf.cpp
--- a/lsf.cpp Sun Feb 24 15:47:59 2013 +0900
+++ b/lsf.cpp Tue Feb 26 19:34:27 2013 +0900
@@ -10,6 +10,8 @@
# include "ntcons.h"
# include <windows.h>
# include <wincon.h>
+# include <locale.h>
+# include <ddk/ntifs.h>
#endif
#include "writer.h" /* for test */
@@ -33,6 +35,7 @@
static NnString ls_executable_file ;
static NnString ls_read_only_file ;
static NnString ls_end_code ;
+static NnString ls_reparse_point ;
#define C2(x,y) (x<<8 | y)
@@ -73,6 +76,7 @@
ls_executable_file = LS_LEFT "1;35" LS_RIGHT ; /* 紫 */
ls_read_only_file = LS_LEFT "1;33" LS_RIGHT ; /* 黄 */
ls_end_code = LS_LEFT "0" LS_RIGHT ; /* 灰色 */
+ ls_reparse_point = LS_LEFT "1;36" LS_RIGHT ; /* 水色 */
NnString env,one;
@@ -103,6 +107,7 @@
case C2('h','i'): ls_hidden_file = value ; break ;
case C2('e','x'): ls_executable_file = value ; break ;
case C2('e','c'): ls_end_code = value ; break ;
+ case C2('l','n'): ls_reparse_point = value ; break ;
default: goto errpt;
}
}
@@ -150,6 +155,8 @@
{
if( stat.isHidden() ){
return ls_hidden_file.chars();
+ }else if ( stat.isReparsePoint() ){
+ return ls_reparse_point.chars() ;
}else if ( stat.isSystem() ){
return ls_system_file.chars() ;
}else if( stat.isDir() ){
@@ -192,6 +199,54 @@
buffer << "0123456789"[ n ];
}
+/* リパースポイント情報の取得
+ * return
+ * 0 : 成功
+ * 1 : エラー
+ */
+static int get_reparse_data( const NnFileStat *st, char *target, size_t len )
+{
+#ifdef NYACUS
+ HANDLE hDir = CreateFile((st->name()).chars(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if( hDir == INVALID_HANDLE_VALUE ) return 1;
+
+ BYTE _buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ REPARSE_DATA_BUFFER *buf = (REPARSE_DATA_BUFFER*)_buf;
+ DWORD dwRet = 0;
+ BOOL br = DeviceIoControl(hDir, FSCTL_GET_REPARSE_POINT, NULL, 0, (PVOID)buf, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRet, NULL);
+
+ CloseHandle(hDir);
+ if( br == 0 ) return 1;
+
+ if( buf->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT ){
+ size_t wlen = buf->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
+ WCHAR wcs[wlen + 1];
+ wcsncpy((wchar_t*)wcs, (const wchar_t*)(&buf->MountPointReparseBuffer.PathBuffer[buf->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)]), wlen + 1);
+ wcs[wlen] = 0;
+ setlocale(LC_CTYPE, "jpn");
+ if( (wcs[0] == '\\') && (wcs[1] == '?') && (wcs[2] == '?') && (wcs[3] == '\\') ){
+ wcstombs(target, &wcs[4], len);
+ } else {
+ wcstombs(target, wcs, len);
+ }
+ return 0;
+ } else if( buf->ReparseTag == IO_REPARSE_TAG_SYMLINK ){
+ size_t wlen = buf->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
+ WCHAR wcs[wlen + 1];
+ wcsncpy((wchar_t*)wcs, (const wchar_t*)(&buf->SymbolicLinkReparseBuffer.PathBuffer[buf->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)]), wlen + 1);
+ wcs[wlen] = 0;
+ setlocale(LC_CTYPE, "jpn");
+ if( (wcs[0] == '\\') && (wcs[1] == '?') && (wcs[2] == '?') && (wcs[3] == '\\') ){
+ wcstombs(target, &wcs[4], len);
+ } else {
+ wcstombs(target, wcs, len);
+ }
+ return 0;
+ }
+#endif
+ return 1;
+}
+
/* ファイルの一覧を格子状に出力する.
* list (i) NnFileStat の配列
* option (i) オプション
@@ -239,7 +294,28 @@
out << ls_end_code ;
}
- if( st->isDir() ){
+ if( st->isReparsePoint() ){
+ out << " -> ";
+ if( get_reparse_data( st, buffer, sizeof(buffer) ) == 0 ){
+ NnDir *dir2 = new NnDir(buffer);
+ NnFileStat *st2 = dir2->stat();
+ if( option & OPT_COLOR ){
+ out << attr2color(*st2);
+ }
+ out << buffer;
+ if( option & OPT_COLOR ){
+ out << ls_end_code ;
+ }
+ if( st2->isDir() ){
+ out << '/';
+ } else if( isExecutable( st2->name() ) || st2->isDir() ){
+ out << '*';
+ }
+ delete dir2;
+ } else {
+ out << '?';
+ }
+ } else if( st->isDir() ){
out << '/';
} else if( canExe ){
out << '*';
@@ -284,7 +360,10 @@
if( option & OPT_COLOR ){
line << ls_end_code ;
}
- if( st->isDir() ){
+ if( st->isReparsePoint() ){
+ line << '@';
+ --left;
+ }else if( st->isDir() ){
line << '/';
--left;
}else if( isExecutable( st->name() ) ){
diff -r c95acae76050 nndir.h
--- a/nndir.h Sun Feb 24 15:47:59 2013 +0900
+++ b/nndir.h Tue Feb 26 19:34:27 2013 +0900
@@ -32,7 +32,8 @@
ATTR_SYSTEM = 0x04 ,
ATTR_LABEL = 0x08 ,
ATTR_DIRECTORY= 0x10 ,
- ATTR_ARCHIVED = 0x20
+ ATTR_ARCHIVED = 0x20 ,
+ ATTR_REPARSE_POINT = 0x400
};
NnFileStat( const NnString &name , unsigned attr , filesize_t size ,
@@ -53,6 +54,7 @@
int isLabel() const { return (attr_ & ATTR_LABEL ) != 0 ; }
int isDir() const { return (attr_ & ATTR_DIRECTORY) != 0 ; }
int isArchived() const { return (attr_ & ATTR_ARCHIVED ) != 0 ; }
+ int isReparsePoint() const { return (attr_ & ATTR_REPARSE_POINT ) != 0 ; }
virtual int compare( const NnSortable &another ) const ;
@@ -93,6 +95,7 @@
int isLabel() const { return (attr_ & NnFileStat::ATTR_LABEL )!=0; }
int isDir() const { return (attr_ & NnFileStat::ATTR_DIRECTORY)!=0; }
int isArchived() const { return (attr_ & NnFileStat::ATTR_ARCHIVED )!=0; }
+ int isReparsePoint() const { return (attr_ & NnFileStat::ATTR_REPARSE_POINT )!=0; }
int attr() const { return attr_ ; }
filesize_t size()const { return size_ ; }
const NnTimeStamp &stamp() const { return stamp_; }
@DeaR
Copy link
Author

DeaR commented Feb 26, 2013

ビルドしてうpった
http://sdrv.ms/ZwXmAj
3.3.6_0に上書きでおk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment