Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F102960220
ls.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Feb 25, 21:23
Size
8 KB
Mime Type
text/x-c
Expires
Thu, Feb 27, 21:23 (2 d)
Engine
blob
Format
Raw Data
Handle
24425644
Attached To
R3704 elastic-yarn
ls.c
View Options
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
#include "winutils.h"
//----------------------------------------------------------------------------
// Function: GetMaskString
//
// Description:
// Get the mask string that are used for output to the console.
//
// Returns:
// TRUE: on success
//
// Notes:
// The function only sets the existed permission in the mask string. If the
// permission does not exist, the corresponding character in mask string is not
// altered. The caller need to initilize the mask string to be all '-' to get
// the correct mask string.
//
static
BOOL
GetMaskString
(
__in
INT
accessMask
,
__in_ecount
(
10
)
LPWSTR
maskString
)
{
if
(
wcslen
(
maskString
)
!=
10
)
return
FALSE
;
if
((
accessMask
&
UX_DIRECTORY
)
==
UX_DIRECTORY
)
maskString
[
0
]
=
L'd'
;
else
if
((
accessMask
&
UX_SYMLINK
)
==
UX_SYMLINK
)
maskString
[
0
]
=
L'l'
;
if
((
accessMask
&
UX_U_READ
)
==
UX_U_READ
)
maskString
[
1
]
=
L'r'
;
if
((
accessMask
&
UX_U_WRITE
)
==
UX_U_WRITE
)
maskString
[
2
]
=
L'w'
;
if
((
accessMask
&
UX_U_EXECUTE
)
==
UX_U_EXECUTE
)
maskString
[
3
]
=
L'x'
;
if
((
accessMask
&
UX_G_READ
)
==
UX_G_READ
)
maskString
[
4
]
=
L'r'
;
if
((
accessMask
&
UX_G_WRITE
)
==
UX_G_WRITE
)
maskString
[
5
]
=
L'w'
;
if
((
accessMask
&
UX_G_EXECUTE
)
==
UX_G_EXECUTE
)
maskString
[
6
]
=
L'x'
;
if
((
accessMask
&
UX_O_READ
)
==
UX_O_READ
)
maskString
[
7
]
=
L'r'
;
if
((
accessMask
&
UX_O_WRITE
)
==
UX_O_WRITE
)
maskString
[
8
]
=
L'w'
;
if
((
accessMask
&
UX_O_EXECUTE
)
==
UX_O_EXECUTE
)
maskString
[
9
]
=
L'x'
;
return
TRUE
;
}
//----------------------------------------------------------------------------
// Function: LsPrintLine
//
// Description:
// Print one line of 'ls' command given all the information needed
//
// Returns:
// None
//
// Notes:
// if useSeparator is false, separates the output tokens with a space
// character, otherwise, with a pipe character
//
static
BOOL
LsPrintLine
(
const
INT
mask
,
const
DWORD
hardlinkCount
,
LPCWSTR
ownerName
,
LPCWSTR
groupName
,
const
FILETIME
*
lpFileWritetime
,
const
LARGE_INTEGER
fileSize
,
LPCWSTR
path
,
BOOL
useSeparator
)
{
// 'd' + 'rwx' for user, group, other
static
const
size_t
ck_ullMaskLen
=
1
+
3
*
3
;
LPWSTR
maskString
=
NULL
;
SYSTEMTIME
stFileWriteTime
;
BOOL
ret
=
FALSE
;
maskString
=
(
LPWSTR
)
LocalAlloc
(
LPTR
,
(
ck_ullMaskLen
+
1
)
*
sizeof
(
WCHAR
));
if
(
maskString
==
NULL
)
{
ReportErrorCode
(
L"LocalAlloc"
,
GetLastError
());
return
FALSE
;
}
// Build mask string from mask mode
if
(
FAILED
(
StringCchCopyW
(
maskString
,
(
ck_ullMaskLen
+
1
),
L"----------"
)))
{
goto
LsPrintLineEnd
;
}
if
(
!
GetMaskString
(
mask
,
maskString
))
{
goto
LsPrintLineEnd
;
}
// Convert file time to system time
if
(
!
FileTimeToSystemTime
(
lpFileWritetime
,
&
stFileWriteTime
))
{
goto
LsPrintLineEnd
;
}
if
(
useSeparator
)
{
fwprintf
(
stdout
,
L"%10s|%d|%s|%s|%lld|%3s|%2d|%4d|%s
\n
"
,
maskString
,
hardlinkCount
,
ownerName
,
groupName
,
fileSize
.
QuadPart
,
MONTHS
[
stFileWriteTime
.
wMonth
-
1
],
stFileWriteTime
.
wDay
,
stFileWriteTime
.
wYear
,
path
);
}
else
{
fwprintf
(
stdout
,
L"%10s %d %s %s %lld %3s %2d %4d %s
\n
"
,
maskString
,
hardlinkCount
,
ownerName
,
groupName
,
fileSize
.
QuadPart
,
MONTHS
[
stFileWriteTime
.
wMonth
-
1
],
stFileWriteTime
.
wDay
,
stFileWriteTime
.
wYear
,
path
);
}
ret
=
TRUE
;
LsPrintLineEnd:
LocalFree
(
maskString
);
return
ret
;
}
// List of command line options supported by "winutils ls"
enum
CmdLineOption
{
CmdLineOptionFollowSymlink
=
0x1
,
// "-L"
CmdLineOptionSeparator
=
0x2
// "-F"
// options should be powers of 2 (aka next is 0x4)
};
static
wchar_t
*
CurrentDir
=
L"."
;
//----------------------------------------------------------------------------
// Function: ParseCommandLine
//
// Description:
// Parses the command line
//
// Returns:
// TRUE on the valid command line, FALSE otherwise
//
BOOL
ParseCommandLine
(
__in
int
argc
,
__in_ecount
(
argc
)
wchar_t
*
argv
[],
__deref_out
PWSTR
*
path
,
__out
int
*
optionsMask
)
{
int
MaxOptions
=
2
;
// Should be equal to the number of elems in CmdLineOption
int
i
=
0
;
assert
(
optionsMask
!=
NULL
);
assert
(
argv
!=
NULL
);
assert
(
path
!=
NULL
);
*
optionsMask
=
0
;
if
(
argc
==
1
)
{
// no path specified, assume "."
*
path
=
CurrentDir
;
return
TRUE
;
}
if
(
argc
==
2
)
{
// only path specified, no other options
*
path
=
argv
[
1
];
return
TRUE
;
}
if
(
argc
>
2
+
MaxOptions
)
{
// too many parameters
return
FALSE
;
}
for
(
i
=
1
;
i
<
argc
-
1
;
++
i
)
{
if
(
wcscmp
(
argv
[
i
],
L"-L"
)
==
0
)
{
// Check if this option was already specified
BOOL
alreadySet
=
*
optionsMask
&
CmdLineOptionFollowSymlink
;
if
(
alreadySet
)
return
FALSE
;
*
optionsMask
|=
CmdLineOptionFollowSymlink
;
}
else
if
(
wcscmp
(
argv
[
i
],
L"-F"
)
==
0
)
{
// Check if this option was already specified
BOOL
alreadySet
=
*
optionsMask
&
CmdLineOptionSeparator
;
if
(
alreadySet
)
return
FALSE
;
*
optionsMask
|=
CmdLineOptionSeparator
;
}
else
{
return
FALSE
;
}
}
*
path
=
argv
[
argc
-
1
];
return
TRUE
;
}
//----------------------------------------------------------------------------
// Function: Ls
//
// Description:
// The main method for ls command
//
// Returns:
// 0: on success
//
// Notes:
//
int
Ls
(
__in
int
argc
,
__in_ecount
(
argc
)
wchar_t
*
argv
[])
{
LPWSTR
pathName
=
NULL
;
LPWSTR
longPathName
=
NULL
;
BY_HANDLE_FILE_INFORMATION
fileInformation
;
LPWSTR
ownerName
=
NULL
;
LPWSTR
groupName
=
NULL
;
INT
unixAccessMode
=
0
;
DWORD
dwErrorCode
=
ERROR_SUCCESS
;
LARGE_INTEGER
fileSize
;
int
ret
=
EXIT_FAILURE
;
int
optionsMask
=
0
;
if
(
!
ParseCommandLine
(
argc
,
argv
,
&
pathName
,
&
optionsMask
))
{
fwprintf
(
stderr
,
L"Incorrect command line arguments.
\n\n
"
);
LsUsage
(
argv
[
0
]);
return
EXIT_FAILURE
;
}
assert
(
pathName
!=
NULL
);
if
(
wcsspn
(
pathName
,
L"/?|><:*
\"
"
)
!=
0
)
{
fwprintf
(
stderr
,
L"Incorrect file name format: %s
\n
"
,
pathName
);
return
EXIT_FAILURE
;
}
// Convert the path the the long path
//
dwErrorCode
=
ConvertToLongPath
(
pathName
,
&
longPathName
);
if
(
dwErrorCode
!=
ERROR_SUCCESS
)
{
ReportErrorCode
(
L"ConvertToLongPath"
,
dwErrorCode
);
goto
LsEnd
;
}
dwErrorCode
=
GetFileInformationByName
(
longPathName
,
optionsMask
&
CmdLineOptionFollowSymlink
,
&
fileInformation
);
if
(
dwErrorCode
!=
ERROR_SUCCESS
)
{
ReportErrorCode
(
L"GetFileInformationByName"
,
dwErrorCode
);
goto
LsEnd
;
}
dwErrorCode
=
FindFileOwnerAndPermission
(
longPathName
,
optionsMask
&
CmdLineOptionFollowSymlink
,
&
ownerName
,
&
groupName
,
&
unixAccessMode
);
if
(
dwErrorCode
!=
ERROR_SUCCESS
)
{
ReportErrorCode
(
L"FindFileOwnerAndPermission"
,
dwErrorCode
);
goto
LsEnd
;
}
fileSize
.
HighPart
=
fileInformation
.
nFileSizeHigh
;
fileSize
.
LowPart
=
fileInformation
.
nFileSizeLow
;
// Print output using the input path name (not the long one)
//
if
(
!
LsPrintLine
(
unixAccessMode
,
fileInformation
.
nNumberOfLinks
,
ownerName
,
groupName
,
&
fileInformation
.
ftLastWriteTime
,
fileSize
,
pathName
,
optionsMask
&
CmdLineOptionSeparator
))
goto
LsEnd
;
ret
=
EXIT_SUCCESS
;
LsEnd:
LocalFree
(
ownerName
);
LocalFree
(
groupName
);
LocalFree
(
longPathName
);
return
ret
;
}
void
LsUsage
(
LPCWSTR
program
)
{
fwprintf
(
stdout
,
L"\
Usage: %s [OPTIONS] [FILE]
\n
\
List information about the FILE (the current directory by default).
\n
\
Using long listing format and list directory entries instead of contents,
\n
\
and do not dereference symbolic links.
\n
\
Provides equivalent or similar function as 'ls -ld' on GNU/Linux.
\n
\
\n
\
OPTIONS: -L dereference symbolic links
\n
\
-F format the output by separating tokens with a pipe
\n
"
,
program
);
}
Event Timeline
Log In to Comment