Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
30bdbedc
Commit
30bdbedc
authored
Feb 02, 2011
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cabarc: Initial version of the cabarc.exe tool, with support for creating a cabinet.
parent
5ae2b0f2
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
494 additions
and
0 deletions
+494
-0
configure
configure
+1
-0
configure.ac
configure.ac
+1
-0
Makefile.in
programs/cabarc/Makefile.in
+8
-0
cabarc.c
programs/cabarc/cabarc.c
+484
-0
No files found.
configure
View file @
30bdbedc
...
...
@@ -15370,6 +15370,7 @@ wine_fn_config_makefile libs/wpp enable_libs_wpp
wine_fn_config_makefile loader enable_loader
wine_fn_config_program aspnet_regiis enable_aspnet_regiis
install
wine_fn_config_program attrib enable_attrib
install
wine_fn_config_program cabarc enable_cabarc
install
wine_fn_config_program cacls enable_cacls
install
wine_fn_config_program clock enable_clock po,install
wine_fn_config_program cmd enable_cmd po,install
...
...
configure.ac
View file @
30bdbedc
...
...
@@ -2871,6 +2871,7 @@ WINE_CONFIG_MAKEFILE([libs/wpp])
WINE_CONFIG_MAKEFILE([loader])
WINE_CONFIG_PROGRAM(aspnet_regiis,,[install])
WINE_CONFIG_PROGRAM(attrib,,[install])
WINE_CONFIG_PROGRAM(cabarc,,[install])
WINE_CONFIG_PROGRAM(cacls,,[install])
WINE_CONFIG_PROGRAM(clock,,[po,install])
WINE_CONFIG_PROGRAM(cmd,,[po,install])
...
...
programs/cabarc/Makefile.in
0 → 100644
View file @
30bdbedc
MODULE
=
cabarc.exe
APPMODE
=
-mconsole
-municode
IMPORTS
=
cabinet
EXTRADEFS
=
-DWINE_NO_UNICODE_MACROS
C_SRCS
=
cabarc.c
@MAKE_PROG_RULES@
programs/cabarc/cabarc.c
0 → 100644
View file @
30bdbedc
/*
* Tool to manipulate cabinet files
*
* Copyright 2011 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdio.h>
#include <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include "fci.h"
#include "fdi.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
cabarc
);
/* from msvcrt */
#define _O_RDONLY 0
#define _O_WRONLY 1
#define _O_RDWR 2
#define _O_ACCMODE (_O_RDONLY|_O_WRONLY|_O_RDWR)
#define _O_APPEND 0x0008
#define _O_RANDOM 0x0010
#define _O_SEQUENTIAL 0x0020
#define _O_TEMPORARY 0x0040
#define _O_NOINHERIT 0x0080
#define _O_CREAT 0x0100
#define _O_TRUNC 0x0200
#define _O_EXCL 0x0400
#define _O_SHORT_LIVED 0x1000
#define _O_TEXT 0x4000
#define _O_BINARY 0x8000
#define _SH_COMPAT 0x00
#define _SH_DENYRW 0x10
#define _SH_DENYWR 0x20
#define _SH_DENYRD 0x30
#define _SH_DENYNO 0x40
#define _A_RDONLY 0x01
#define _A_HIDDEN 0x02
#define _A_SYSTEM 0x04
#define _A_ARCH 0x20
/* command-line options */
static
int
opt_cabinet_id
;
static
int
opt_compression
=
tcompTYPE_MSZIP
;
static
int
opt_recurse
;
static
int
opt_preserve_paths
;
static
int
opt_reserve_space
;
static
int
opt_verbose
;
static
WCHAR
**
opt_files
;
static
void
*
CDECL
cab_alloc
(
ULONG
size
)
{
return
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
}
static
void
CDECL
cab_free
(
void
*
ptr
)
{
HeapFree
(
GetProcessHeap
(),
0
,
ptr
);
}
static
WCHAR
*
strdupAtoW
(
UINT
cp
,
const
char
*
str
)
{
WCHAR
*
ret
=
NULL
;
if
(
str
)
{
DWORD
len
=
MultiByteToWideChar
(
cp
,
0
,
str
,
-
1
,
NULL
,
0
);
if
((
ret
=
cab_alloc
(
len
*
sizeof
(
WCHAR
)
)))
MultiByteToWideChar
(
cp
,
0
,
str
,
-
1
,
ret
,
len
);
}
return
ret
;
}
static
char
*
strdupWtoA
(
UINT
cp
,
const
WCHAR
*
str
)
{
char
*
ret
=
NULL
;
if
(
str
)
{
DWORD
len
=
WideCharToMultiByte
(
cp
,
0
,
str
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
((
ret
=
cab_alloc
(
len
)))
WideCharToMultiByte
(
cp
,
0
,
str
,
-
1
,
ret
,
len
,
NULL
,
NULL
);
}
return
ret
;
}
static
int
CDECL
fci_file_placed
(
CCAB
*
cab
,
char
*
file
,
LONG
size
,
BOOL
continuation
,
void
*
ptr
)
{
if
(
!
continuation
&&
opt_verbose
)
printf
(
"adding %s
\n
"
,
file
);
return
0
;
}
static
INT_PTR
CDECL
fci_open
(
char
*
file
,
int
oflag
,
int
pmode
,
int
*
err
,
void
*
ptr
)
{
DWORD
creation
=
0
,
sharing
=
0
;
int
ioflag
=
0
;
HANDLE
handle
;
switch
(
oflag
&
_O_ACCMODE
)
{
case
_O_RDONLY
:
ioflag
|=
GENERIC_READ
;
break
;
case
_O_WRONLY
:
ioflag
|=
GENERIC_WRITE
;
break
;
case
_O_RDWR
:
ioflag
|=
GENERIC_READ
|
GENERIC_WRITE
;
break
;
}
if
(
oflag
&
_O_CREAT
)
{
if
(
oflag
&
_O_EXCL
)
creation
=
CREATE_NEW
;
else
if
(
oflag
&
_O_TRUNC
)
creation
=
CREATE_ALWAYS
;
else
creation
=
OPEN_ALWAYS
;
}
else
{
if
(
oflag
&
_O_TRUNC
)
creation
=
TRUNCATE_EXISTING
;
else
creation
=
OPEN_EXISTING
;
}
switch
(
pmode
&
0x70
)
{
case
_SH_DENYRW
:
sharing
=
0
;
break
;
case
_SH_DENYWR
:
sharing
=
FILE_SHARE_READ
;
break
;
case
_SH_DENYRD
:
sharing
=
FILE_SHARE_WRITE
;
break
;
default:
sharing
=
FILE_SHARE_READ
|
FILE_SHARE_WRITE
;
break
;
}
handle
=
CreateFileA
(
file
,
ioflag
,
sharing
,
NULL
,
creation
,
FILE_ATTRIBUTE_NORMAL
,
NULL
);
if
(
handle
==
INVALID_HANDLE_VALUE
)
*
err
=
GetLastError
();
return
(
INT_PTR
)
handle
;
}
static
UINT
CDECL
fci_read
(
INT_PTR
hf
,
void
*
pv
,
UINT
cb
,
int
*
err
,
void
*
ptr
)
{
DWORD
num_read
;
if
(
!
ReadFile
(
(
HANDLE
)
hf
,
pv
,
cb
,
&
num_read
,
NULL
))
{
*
err
=
GetLastError
();
return
-
1
;
}
return
num_read
;
}
static
UINT
CDECL
fci_write
(
INT_PTR
hf
,
void
*
pv
,
UINT
cb
,
int
*
err
,
void
*
ptr
)
{
DWORD
written
;
if
(
!
WriteFile
(
(
HANDLE
)
hf
,
pv
,
cb
,
&
written
,
NULL
))
{
*
err
=
GetLastError
();
return
-
1
;
}
return
written
;
}
static
int
CDECL
fci_close
(
INT_PTR
hf
,
int
*
err
,
void
*
ptr
)
{
if
(
!
CloseHandle
(
(
HANDLE
)
hf
))
{
*
err
=
GetLastError
();
return
-
1
;
}
return
0
;
}
static
LONG
CDECL
fci_lseek
(
INT_PTR
hf
,
LONG
dist
,
int
seektype
,
int
*
err
,
void
*
ptr
)
{
DWORD
ret
;
ret
=
SetFilePointer
(
(
HANDLE
)
hf
,
dist
,
NULL
,
seektype
);
if
(
ret
==
INVALID_SET_FILE_POINTER
&&
GetLastError
())
{
*
err
=
GetLastError
();
return
-
1
;
}
return
ret
;
}
static
int
CDECL
fci_delete
(
char
*
file
,
int
*
err
,
void
*
ptr
)
{
if
(
!
DeleteFileA
(
file
))
{
*
err
=
GetLastError
();
return
-
1
;
}
return
0
;
}
static
BOOL
CDECL
fci_get_temp
(
char
*
name
,
int
size
,
void
*
ptr
)
{
char
path
[
MAX_PATH
];
if
(
!
GetTempPathA
(
MAX_PATH
,
path
))
return
FALSE
;
if
(
!
GetTempFileNameA
(
path
,
"cab"
,
0
,
name
))
return
FALSE
;
DeleteFileA
(
name
);
return
TRUE
;
}
static
BOOL
CDECL
fci_get_next_cab
(
CCAB
*
cab
,
ULONG
prev_size
,
void
*
ptr
)
{
WINE_ERR
(
"shouldn't happen
\n
"
);
return
FALSE
;
}
static
LONG
CDECL
fci_status
(
UINT
type
,
ULONG
cb1
,
ULONG
cb2
,
void
*
ptr
)
{
return
0
;
}
static
INT_PTR
CDECL
fci_get_open_info
(
char
*
name
,
USHORT
*
date
,
USHORT
*
time
,
USHORT
*
attribs
,
int
*
err
,
void
*
ptr
)
{
HANDLE
handle
;
BY_HANDLE_FILE_INFORMATION
info
;
WCHAR
*
p
,
*
nameW
=
strdupAtoW
(
CP_UTF8
,
name
);
handle
=
CreateFileW
(
nameW
,
GENERIC_READ
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
0
,
NULL
);
if
(
handle
==
INVALID_HANDLE_VALUE
)
{
*
err
=
GetLastError
();
WINE_ERR
(
"failed to open %s: error %u
\n
"
,
wine_dbgstr_w
(
nameW
),
*
err
);
cab_free
(
nameW
);
return
-
1
;
}
if
(
!
GetFileInformationByHandle
(
handle
,
&
info
))
{
*
err
=
GetLastError
();
CloseHandle
(
handle
);
cab_free
(
nameW
);
return
-
1
;
}
FileTimeToDosDateTime
(
&
info
.
ftLastWriteTime
,
date
,
time
);
*
attribs
=
info
.
dwFileAttributes
&
(
_A_RDONLY
|
_A_HIDDEN
|
_A_SYSTEM
|
_A_ARCH
);
for
(
p
=
nameW
;
*
p
;
p
++
)
if
(
*
p
>=
0x80
)
break
;
if
(
*
p
)
*
attribs
|=
_A_NAME_IS_UTF
;
cab_free
(
nameW
);
return
(
INT_PTR
)
handle
;
}
static
BOOL
add_file
(
HFCI
fci
,
WCHAR
*
name
)
{
BOOL
ret
;
char
*
filename
,
*
path
=
strdupWtoA
(
CP_UTF8
,
name
);
if
(
!
opt_preserve_paths
)
{
if
((
filename
=
strrchr
(
path
,
'\\'
)))
filename
++
;
else
filename
=
path
;
}
else
{
filename
=
path
;
while
(
*
filename
==
'\\'
)
filename
++
;
/* remove leading backslashes */
}
ret
=
FCIAddFile
(
fci
,
path
,
filename
,
FALSE
,
fci_get_next_cab
,
fci_status
,
fci_get_open_info
,
opt_compression
);
cab_free
(
path
);
return
ret
;
}
static
BOOL
add_directory
(
HFCI
fci
,
WCHAR
*
dir
)
{
static
const
WCHAR
wildcardW
[]
=
{
'*'
,
0
};
WCHAR
*
p
,
*
buffer
;
HANDLE
handle
;
WIN32_FIND_DATAW
data
;
BOOL
ret
=
TRUE
;
if
(
!
(
buffer
=
cab_alloc
(
(
strlenW
(
dir
)
+
MAX_PATH
+
2
)
*
sizeof
(
WCHAR
)
)))
return
FALSE
;
strcpyW
(
buffer
,
dir
);
p
=
buffer
+
strlenW
(
buffer
);
if
(
p
>
buffer
&&
p
[
-
1
]
!=
'\\'
)
*
p
++
=
'\\'
;
strcpyW
(
p
,
wildcardW
);
if
((
handle
=
FindFirstFileW
(
buffer
,
&
data
))
!=
INVALID_HANDLE_VALUE
)
{
do
{
if
(
data
.
cFileName
[
0
]
==
'.'
&&
!
data
.
cFileName
[
1
])
continue
;
if
(
data
.
cFileName
[
0
]
==
'.'
&&
data
.
cFileName
[
1
]
==
'.'
&&
!
data
.
cFileName
[
2
])
continue
;
if
(
data
.
dwFileAttributes
&
FILE_ATTRIBUTE_REPARSE_POINT
)
continue
;
strcpyW
(
p
,
data
.
cFileName
);
if
(
data
.
dwFileAttributes
&
FILE_ATTRIBUTE_DIRECTORY
)
ret
=
add_directory
(
fci
,
buffer
);
else
ret
=
add_file
(
fci
,
buffer
);
if
(
!
ret
)
break
;
}
while
(
FindNextFileW
(
handle
,
&
data
));
FindClose
(
handle
);
}
cab_free
(
buffer
);
return
TRUE
;
}
static
BOOL
add_file_or_directory
(
HFCI
fci
,
WCHAR
*
name
)
{
DWORD
attr
=
GetFileAttributesW
(
name
);
if
(
attr
==
INVALID_FILE_ATTRIBUTES
)
{
WINE_MESSAGE
(
"cannot open %s
\n
"
,
wine_dbgstr_w
(
name
)
);
return
FALSE
;
}
if
(
attr
&
FILE_ATTRIBUTE_DIRECTORY
)
{
if
(
opt_recurse
)
return
add_directory
(
fci
,
name
);
WINE_MESSAGE
(
"cabarc: Cannot add %s, it's a directory (use -r for recursive add)
\n
"
,
wine_dbgstr_w
(
name
)
);
return
FALSE
;
}
return
add_file
(
fci
,
name
);
}
static
int
new_cabinet
(
char
*
cab_dir
,
char
*
cab_file
)
{
WCHAR
**
file
;
ERF
erf
;
BOOL
ret
=
FALSE
;
HFCI
fci
;
CCAB
cab
;
cab
.
cb
=
CB_MAX_DISK
;
cab
.
cbFolderThresh
=
CB_MAX_DISK
;
cab
.
cbReserveCFHeader
=
opt_reserve_space
;
cab
.
cbReserveCFFolder
=
0
;
cab
.
cbReserveCFData
=
0
;
cab
.
iCab
=
1
;
cab
.
iDisk
=
0
;
cab
.
setID
=
opt_cabinet_id
;
cab
.
szDisk
[
0
]
=
0
;
strcpy
(
cab
.
szCabPath
,
cab_dir
);
strcat
(
cab
.
szCabPath
,
"
\\
"
);
strcpy
(
cab
.
szCab
,
cab_file
);
fci
=
FCICreate
(
&
erf
,
fci_file_placed
,
cab_alloc
,
cab_free
,
fci_open
,
fci_read
,
fci_write
,
fci_close
,
fci_lseek
,
fci_delete
,
fci_get_temp
,
&
cab
,
NULL
);
for
(
file
=
opt_files
;
*
file
;
file
++
)
if
(
!
(
ret
=
add_file_or_directory
(
fci
,
*
file
)))
break
;
if
(
ret
)
{
if
(
!
(
ret
=
FCIFlushCabinet
(
fci
,
FALSE
,
fci_get_next_cab
,
fci_status
)))
WINE_MESSAGE
(
"cabarc: Failed to create cabinet %s
\n
"
,
wine_dbgstr_a
(
cab_file
)
);
}
FCIDestroy
(
fci
);
return
!
ret
;
}
static
void
usage
(
void
)
{
WINE_MESSAGE
(
"Usage: cabarc [options] command file.cab [files...] [dest_dir
\\
]
\n
"
"
\n
Commands:
\n
"
" L List the contents of the cabinet
\n
"
" N Create a new cabinet
\n
"
" X Extract files from the cabinet into dest_dir
\n
"
"
\n
Options:
\n
"
" -h Display this help
\n
"
" -i id Set cabinet id
\n
"
" -m type Set compression type (mszip|none)
\n
"
" -p Preserve directory names
\n
"
" -r Recurse into directories
\n
"
" -s size Reserve space in the cabinet header
\n
"
" -v More verbose output
\n
"
);
}
int
wmain
(
int
argc
,
WCHAR
*
argv
[]
)
{
static
const
WCHAR
noneW
[]
=
{
'n'
,
'o'
,
'n'
,
'e'
,
0
};
static
const
WCHAR
mszipW
[]
=
{
'm'
,
's'
,
'z'
,
'i'
,
'p'
,
0
};
WCHAR
*
p
,
*
command
;
char
buffer
[
MAX_PATH
];
char
*
cab_file
,
*
file_part
;
int
i
;
while
(
argv
[
1
]
&&
argv
[
1
][
0
]
==
'-'
)
{
switch
(
argv
[
1
][
1
])
{
case
'h'
:
usage
();
return
0
;
case
'i'
:
argv
++
;
argc
--
;
opt_cabinet_id
=
atoiW
(
argv
[
1
]
);
break
;
case
'm'
:
argv
++
;
argc
--
;
if
(
!
strcmpiW
(
argv
[
1
],
noneW
))
opt_compression
=
tcompTYPE_NONE
;
else
if
(
!
strcmpiW
(
argv
[
1
],
mszipW
))
opt_compression
=
tcompTYPE_MSZIP
;
else
{
WINE_MESSAGE
(
"cabarc: Unknown compression type '%s'
\n
"
,
optarg
);
return
1
;
}
break
;
case
'p'
:
opt_preserve_paths
=
1
;
break
;
case
'r'
:
opt_recurse
=
1
;
break
;
case
's'
:
argv
++
;
argc
--
;
opt_reserve_space
=
atoiW
(
argv
[
1
]
);
break
;
case
'v'
:
opt_verbose
++
;
break
;
default:
usage
();
return
1
;
}
argv
++
;
argc
--
;
}
command
=
argv
[
1
];
if
(
argc
<
3
||
!
command
[
0
]
||
command
[
1
])
{
usage
();
return
1
;
}
cab_file
=
strdupWtoA
(
CP_ACP
,
argv
[
2
]
);
argv
+=
2
;
argc
-=
2
;
if
(
!
GetFullPathNameA
(
cab_file
,
MAX_PATH
,
buffer
,
&
file_part
)
||
!
file_part
)
{
WINE_ERR
(
"cannot get full name for %s
\n
"
,
wine_dbgstr_a
(
cab_file
));
return
1
;
}
file_part
[
-
1
]
=
0
;
cab_free
(
cab_file
);
/* map slash to backslash in all file arguments */
for
(
i
=
1
;
i
<
argc
;
i
++
)
for
(
p
=
argv
[
i
];
*
p
;
p
++
)
if
(
*
p
==
'/'
)
*
p
=
'\\'
;
opt_files
=
argv
+
1
;
switch
(
*
command
)
{
case
'l'
:
case
'L'
:
WINE_FIXME
(
"list not implemented
\n
"
);
return
1
;
case
'n'
:
case
'N'
:
return
new_cabinet
(
buffer
,
file_part
);
case
'x'
:
case
'X'
:
WINE_FIXME
(
"extraction not implemented
\n
"
);
return
1
;
default:
usage
();
return
1
;
}
}
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