Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
e26c2a56
Commit
e26c2a56
authored
Oct 26, 2012
by
Jason Edmeades
Committed by
Alexandre Julliard
Nov 06, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
attrib: Add support for attrib /s.
parent
8e575940
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
136 additions
and
59 deletions
+136
-59
attrib.c
programs/attrib/attrib.c
+134
-57
test_builtins.cmd.exp
programs/cmd/tests/test_builtins.cmd.exp
+2
-2
No files found.
programs/attrib/attrib.c
View file @
e26c2a56
...
@@ -25,6 +25,8 @@
...
@@ -25,6 +25,8 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
attrib
);
WINE_DEFAULT_DEBUG_CHANNEL
(
attrib
);
static
const
WCHAR
starW
[]
=
{
'*'
,
'\0'
};
/* =========================================================================
/* =========================================================================
* Load a string from the resource file, handling any error
* Load a string from the resource file, handling any error
* Returns string retrieved from resource file
* Returns string retrieved from resource file
...
@@ -122,20 +124,133 @@ static int __cdecl ATTRIB_wprintf(const WCHAR *format, ...)
...
@@ -122,20 +124,133 @@ static int __cdecl ATTRIB_wprintf(const WCHAR *format, ...)
return
nOut
;
return
nOut
;
}
}
int
wmain
(
int
argc
,
WCHAR
*
argv
[])
/* =========================================================================
* Handle the processing for a single directory, optionally recursing into
* subdirectories if needed.
* Parameters:
* rootdir [I] The directory to search in
* filespec [I] The filespec to search for
* recurse [I] Whether to recurse (search subdirectories before
* current directory)
* attrib_set [I] Attributes to set
* attrib_clear [I] Attributes to clear
*
* Returns TRUE if at least one file displayed / modified
* ========================================================================= */
static
BOOL
ATTRIB_processdirectory
(
const
WCHAR
*
rootdir
,
const
WCHAR
*
filespec
,
BOOL
recurse
,
DWORD
attrib_set
,
DWORD
attrib_clear
)
{
{
DWORD
count
;
BOOL
found
=
FALSE
;
WCHAR
buffer
[
MAX_PATH
];
HANDLE
hff
;
HANDLE
hff
;
WIN32_FIND_DATAW
fd
;
WIN32_FIND_DATAW
fd
;
WCHAR
flags
[]
=
{
' '
,
' '
,
' '
,
' '
,
' '
,
' '
,
' '
,
' '
,
'\0'
};
WCHAR
flags
[]
=
{
' '
,
' '
,
' '
,
' '
,
' '
,
' '
,
' '
,
' '
,
'\0'
};
static
const
WCHAR
slashW
[]
=
{
'\\'
,
'\0'
};
WINE_TRACE
(
"Processing dir '%s', spec '%s', %d,%x,%x
\n
"
,
wine_dbgstr_w
(
rootdir
),
wine_dbgstr_w
(
filespec
),
recurse
,
attrib_set
,
attrib_clear
);
if
(
recurse
)
{
/* Build spec to search for */
strcpyW
(
buffer
,
rootdir
);
strcatW
(
buffer
,
starW
);
/* Search for directories in the location and recurse if necessary */
WINE_TRACE
(
"Searching for directories with '%s'
\n
"
,
wine_dbgstr_w
(
buffer
));
hff
=
FindFirstFileW
(
buffer
,
&
fd
);
if
(
hff
!=
INVALID_HANDLE_VALUE
)
{
do
{
const
WCHAR
dot
[]
=
{
'.'
,
0
};
const
WCHAR
dotdot
[]
=
{
'.'
,
'.'
,
0
};
/* Only interested in directories, and not . nor .. */
if
(
!
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_DIRECTORY
)
||
!
strcmpW
(
fd
.
cFileName
,
dot
)
||
!
strcmpW
(
fd
.
cFileName
,
dotdot
))
continue
;
/* Build new root dir to go searching in */
strcpyW
(
buffer
,
rootdir
);
strcatW
(
buffer
,
fd
.
cFileName
);
strcatW
(
buffer
,
slashW
);
ATTRIB_processdirectory
(
buffer
,
filespec
,
recurse
,
attrib_set
,
attrib_clear
);
}
while
(
FindNextFileW
(
hff
,
&
fd
)
!=
0
);
}
FindClose
(
hff
);
}
/* Build spec to search for */
strcpyW
(
buffer
,
rootdir
);
strcatW
(
buffer
,
filespec
);
WINE_TRACE
(
"Searching for files as '%s'
\n
"
,
wine_dbgstr_w
(
buffer
));
/* Search for files in the location with the filespec supplied */
hff
=
FindFirstFileW
(
buffer
,
&
fd
);
if
(
hff
!=
INVALID_HANDLE_VALUE
)
{
do
{
const
WCHAR
dot
[]
=
{
'.'
,
0
};
const
WCHAR
dotdot
[]
=
{
'.'
,
'.'
,
0
};
DWORD
count
;
WINE_TRACE
(
"Found '%s'
\n
"
,
wine_dbgstr_w
(
fd
.
cFileName
));
if
(
!
strcmpW
(
fd
.
cFileName
,
dot
)
||
!
strcmpW
(
fd
.
cFileName
,
dotdot
))
continue
;
if
(
attrib_set
||
attrib_clear
)
{
fd
.
dwFileAttributes
&=
~
attrib_clear
;
fd
.
dwFileAttributes
|=
attrib_set
;
if
(
!
fd
.
dwFileAttributes
)
fd
.
dwFileAttributes
|=
FILE_ATTRIBUTE_NORMAL
;
strcpyW
(
buffer
,
rootdir
);
strcatW
(
buffer
,
fd
.
cFileName
);
SetFileAttributesW
(
buffer
,
fd
.
dwFileAttributes
);
found
=
TRUE
;
}
else
{
static
const
WCHAR
fmt
[]
=
{
'%'
,
'1'
,
' '
,
' '
,
' '
,
' '
,
' '
,
'%'
,
'2'
,
'\n'
,
'\0'
};
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_HIDDEN
)
{
flags
[
4
]
=
'H'
;
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_SYSTEM
)
{
flags
[
1
]
=
'S'
;
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_ARCHIVE
)
{
flags
[
0
]
=
'A'
;
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_READONLY
)
{
flags
[
5
]
=
'R'
;
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_TEMPORARY
)
{
flags
[
6
]
=
'T'
;
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_COMPRESSED
)
{
flags
[
7
]
=
'C'
;
}
strcpyW
(
buffer
,
rootdir
);
strcatW
(
buffer
,
fd
.
cFileName
);
ATTRIB_wprintf
(
fmt
,
flags
,
buffer
);
for
(
count
=
0
;
count
<
(
sizeof
(
flags
)
/
sizeof
(
WCHAR
)
-
1
);
count
++
)
flags
[
count
]
=
' '
;
found
=
TRUE
;
}
}
while
(
FindNextFileW
(
hff
,
&
fd
)
!=
0
);
}
FindClose
(
hff
);
return
found
;
}
int
wmain
(
int
argc
,
WCHAR
*
argv
[])
{
WCHAR
name
[
MAX_PATH
];
WCHAR
name
[
MAX_PATH
];
WCHAR
*
namepart
;
WCHAR
*
namepart
;
WCHAR
curdir
[
MAX_PATH
];
WCHAR
curdir
[
MAX_PATH
];
WCHAR
originalname
[
MAX_PATH
];
DWORD
attrib_set
=
0
;
DWORD
attrib_set
=
0
;
DWORD
attrib_clear
=
0
;
DWORD
attrib_clear
=
0
;
BOOL
attrib_recurse
=
0
;
const
WCHAR
help_option
[]
=
{
'/'
,
'?'
,
'\0'
};
const
WCHAR
help_option
[]
=
{
'/'
,
'?'
,
'\0'
};
const
WCHAR
start
[]
=
{
'*'
,
'\0'
};
int
i
=
1
;
int
i
=
1
;
BOOL
found
=
FALSE
;
if
((
argc
>=
2
)
&&
!
strcmpW
(
argv
[
1
],
help_option
))
{
if
((
argc
>=
2
)
&&
!
strcmpW
(
argv
[
1
],
help_option
))
{
ATTRIB_wprintf
(
ATTRIB_LoadMessage
(
STRING_HELP
));
ATTRIB_wprintf
(
ATTRIB_LoadMessage
(
STRING_HELP
));
...
@@ -143,7 +258,7 @@ int wmain(int argc, WCHAR *argv[])
...
@@ -143,7 +258,7 @@ int wmain(int argc, WCHAR *argv[])
}
}
/* By default all files from current directory are taken into account */
/* By default all files from current directory are taken into account */
strcpyW
(
name
,
star
t
);
strcpyW
(
name
,
star
W
);
while
(
i
<
argc
)
{
while
(
i
<
argc
)
{
WCHAR
*
param
=
argv
[
i
++
];
WCHAR
*
param
=
argv
[
i
++
];
...
@@ -168,71 +283,33 @@ int wmain(int argc, WCHAR *argv[])
...
@@ -168,71 +283,33 @@ int wmain(int argc, WCHAR *argv[])
WINE_FIXME
(
"Option /D not yet supported
\n
"
);
WINE_FIXME
(
"Option /D not yet supported
\n
"
);
}
else
if
(((
param
[
1
]
==
'R'
)
||
(
param
[
1
]
==
'r'
))
&&
!
param
[
2
])
{
}
else
if
(((
param
[
1
]
==
'R'
)
||
(
param
[
1
]
==
'r'
))
&&
!
param
[
2
])
{
WINE_FIXME
(
"Option /R not yet supported
\n
"
);
WINE_FIXME
(
"Option /R not yet supported
\n
"
);
}
else
if
(((
param
[
1
]
==
'S'
)
||
(
param
[
1
]
==
's'
))
&&
!
param
[
2
])
{
attrib_recurse
=
TRUE
;
}
else
{
}
else
{
WINE_FIXME
(
"Unknown option %s
\n
"
,
debugstr_w
(
param
));
WINE_FIXME
(
"Unknown option %s
\n
"
,
debugstr_w
(
param
));
}
}
}
else
if
(
param
[
0
])
{
}
else
if
(
param
[
0
])
{
strcpyW
(
name
,
param
);
strcpyW
(
original
name
,
param
);
}
}
}
}
/* Name may be a relative or explicit path, so calculate curdir based on
/* Name may be a relative or explicit path, so calculate curdir based on
current locations, stripping off the filename */
current locations, stripping off the filename */
WINE_TRACE
(
"Supplied name: '%s'
\n
"
,
wine_dbgstr_w
(
name
));
WINE_TRACE
(
"Supplied name: '%s'
\n
"
,
wine_dbgstr_w
(
original
name
));
GetFullPathNameW
(
name
,
sizeof
(
curdir
)
/
sizeof
(
WCHAR
),
curdir
,
&
namepart
);
GetFullPathNameW
(
original
name
,
sizeof
(
curdir
)
/
sizeof
(
WCHAR
),
curdir
,
&
namepart
);
WINE_TRACE
(
"Result: '%s'
\n
"
,
wine_dbgstr_w
(
curdir
));
WINE_TRACE
(
"Result: '%s'
\n
"
,
wine_dbgstr_w
(
curdir
));
strcpyW
(
name
,
curdir
);
if
(
namepart
)
{
if
(
namepart
)
*
namepart
=
0x00
;
strcpyW
(
name
,
namepart
);
*
namepart
=
0
;
/* Search for files based on the location and filespec supplied */
hff
=
FindFirstFileW
(
name
,
&
fd
);
if
(
hff
==
INVALID_HANDLE_VALUE
)
{
ATTRIB_wprintf
(
ATTRIB_LoadMessage
(
STRING_FILENOTFOUND
),
name
);
}
else
{
do
{
const
WCHAR
dot
[]
=
{
'.'
,
0
};
const
WCHAR
dotdot
[]
=
{
'.'
,
'.'
,
0
};
if
(
!
strcmpW
(
fd
.
cFileName
,
dot
)
||
!
strcmpW
(
fd
.
cFileName
,
dotdot
))
continue
;
if
(
attrib_set
||
attrib_clear
)
{
fd
.
dwFileAttributes
&=
~
attrib_clear
;
fd
.
dwFileAttributes
|=
attrib_set
;
if
(
!
fd
.
dwFileAttributes
)
fd
.
dwFileAttributes
|=
FILE_ATTRIBUTE_NORMAL
;
strcpyW
(
name
,
curdir
);
strcatW
(
name
,
fd
.
cFileName
);
SetFileAttributesW
(
name
,
fd
.
dwFileAttributes
);
}
else
{
}
else
{
static
const
WCHAR
fmt
[]
=
{
'%'
,
'1'
,
' '
,
' '
,
' '
,
' '
,
' '
,
'%'
,
'2'
,
'\n'
,
'\0'
};
name
[
0
]
=
0
;
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_HIDDEN
)
{
flags
[
4
]
=
'H'
;
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_SYSTEM
)
{
flags
[
1
]
=
'S'
;
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_ARCHIVE
)
{
flags
[
0
]
=
'A'
;
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_READONLY
)
{
flags
[
5
]
=
'R'
;
}
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_TEMPORARY
)
{
flags
[
6
]
=
'T'
;
}
if
(
fd
.
dwFileAttributes
&
FILE_ATTRIBUTE_COMPRESSED
)
{
flags
[
7
]
=
'C'
;
}
strcpyW
(
name
,
curdir
);
strcatW
(
name
,
fd
.
cFileName
);
ATTRIB_wprintf
(
fmt
,
flags
,
name
);
for
(
count
=
0
;
count
<
(
sizeof
(
flags
)
/
sizeof
(
WCHAR
)
-
1
);
count
++
)
flags
[
count
]
=
' '
;
}
}
while
(
FindNextFileW
(
hff
,
&
fd
)
!=
0
);
}
FindClose
(
hff
);
/* Do all the processing based on the filename arg */
found
=
ATTRIB_processdirectory
(
curdir
,
name
,
attrib_recurse
,
attrib_set
,
attrib_clear
);
if
(
!
found
)
{
ATTRIB_wprintf
(
ATTRIB_LoadMessage
(
STRING_FILENOTFOUND
),
originalname
);
}
return
0
;
return
0
;
}
}
programs/cmd/tests/test_builtins.cmd.exp
View file @
e26c2a56
...
@@ -960,8 +960,8 @@ Read-only file not deleted
...
@@ -960,8 +960,8 @@ Read-only file not deleted
Read-only file forcibly deleted
Read-only file forcibly deleted
--- recursive behaviour
--- recursive behaviour
A @pwd@\foobar\baz\level2@or_broken@A @pwd@\foobar\baz\level2@or_broken@A I @pwd@\foobar\baz\level2
A @pwd@\foobar\baz\level2@or_broken@A @pwd@\foobar\baz\level2@or_broken@A I @pwd@\foobar\baz\level2
@todo_wine@
A R @pwd@\foobar\level1@or_broken@A R @pwd@\foobar\level1@or_broken@A R I @pwd@\foobar\level1
A R @pwd@\foobar\level1@or_broken@A R @pwd@\foobar\level1@or_broken@A R I @pwd@\foobar\level1
@todo_wine@
A R @pwd@\foobar\baz\level2@or_broken@A R @pwd@\foobar\baz\level2@or_broken@A R I @pwd@\foobar\baz\level2
A R @pwd@\foobar\baz\level2@or_broken@A R @pwd@\foobar\baz\level2@or_broken@A R I @pwd@\foobar\baz\level2
A @pwd@\foobar\bar@or_broken@A @pwd@\foobar\bar@or_broken@A I @pwd@\foobar\bar
A @pwd@\foobar\bar@or_broken@A @pwd@\foobar\bar@or_broken@A I @pwd@\foobar\bar
--- folders processing
--- folders processing
@pwd@\foobar@or_broken@ @pwd@\foobar@or_broken@ I @pwd@\foobar
@pwd@\foobar@or_broken@ @pwd@\foobar@or_broken@ I @pwd@\foobar
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment