Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
wine
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Package registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Zsolt Vadász
wine
Commits
30bdbedc
Commit
30bdbedc
authored
14 years ago
by
Alexandre Julliard
Browse files
Options
Downloads
Patches
Plain Diff
cabarc: Initial version of the cabarc.exe tool, with support for creating a cabinet.
parent
5ae2b0f2
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
configure
+1
-0
1 addition, 0 deletions
configure
configure.ac
+1
-0
1 addition, 0 deletions
configure.ac
programs/cabarc/Makefile.in
+8
-0
8 additions, 0 deletions
programs/cabarc/Makefile.in
programs/cabarc/cabarc.c
+484
-0
484 additions, 0 deletions
programs/cabarc/cabarc.c
with
494 additions
and
0 deletions
configure
+
1
−
0
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
...
...
This diff is collapsed.
Click to expand it.
configure.ac
+
1
−
0
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])
...
...
This diff is collapsed.
Click to expand it.
programs/cabarc/Makefile.in
0 → 100644
+
8
−
0
View file @
30bdbedc
MODULE
=
cabarc.exe
APPMODE
=
-mconsole
-municode
IMPORTS
=
cabinet
EXTRADEFS
=
-DWINE_NO_UNICODE_MACROS
C_SRCS
=
cabarc.c
@MAKE_PROG_RULES@
This diff is collapsed.
Click to expand it.
programs/cabarc/cabarc.c
0 → 100644
+
484
−
0
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
;
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment