* BuildPlatformMain supports overriding HOST_LIBROOT on the target now,
so one can set it to the static libroot, if desired.
* Generic attribute emulation:
- Added build tool rm_attrs, a simple "rm" replacement, which also
removes the attributes directory for a given file.
- Added build/scripts/rm_attrs shell script, which wraps the
invocation of the rm_attrs tool. If it doesn't exist yet, the
ordinary rm is used.
- The RM jam variable refers to the rm_attrs script now, i.e. whenever
something is removed by the build system, the attributes are removed
too (if the build tool has already been built, that is).
- Removed the shell function attrrmrf() in build_haiku_image. We use
the rm_attrs tool instead, if necessary.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24528 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+1
-1
@@ -262,7 +262,7 @@ actions ResAttr1
|
|||||||
{
|
{
|
||||||
$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
|
$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
|
||||||
if [ \\"$(deleteAttributeFile1)\\" = "true" ]; then
|
if [ \\"$(deleteAttributeFile1)\\" = "true" ]; then
|
||||||
rm -f $(1)
|
$(RM) $(1)
|
||||||
fi
|
fi
|
||||||
$(2[1]) -O -o "$(1)" "$(2[2-])"
|
$(2[1]) -O -o "$(1)" "$(2[2-])"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -527,15 +527,21 @@ if $(HOST_PLATFORM_BEOS_COMPATIBLE) {
|
|||||||
# for builds of tools in the current environment
|
# for builds of tools in the current environment
|
||||||
HOST_BUILD_COMPATIBILITY_LIB_DIR = [ FDirName $(HOST_OBJECT_BASE_DIR) lib ] ;
|
HOST_BUILD_COMPATIBILITY_LIB_DIR = [ FDirName $(HOST_OBJECT_BASE_DIR) lib ] ;
|
||||||
|
|
||||||
|
# For the generic attributes emulation: Target rm_attrs -- rm replacement that
|
||||||
|
# also removes the attributes.
|
||||||
|
HOST_RM_ATTRS_TARGET = ;
|
||||||
|
|
||||||
if $(HOST_PLATFORM_BEOS_COMPATIBLE) {
|
if $(HOST_PLATFORM_BEOS_COMPATIBLE) {
|
||||||
HOST_LIBSTDC++ = stdc++.r4 ;
|
HOST_LIBSTDC++ = stdc++.r4 ;
|
||||||
HOST_LIBROOT = root ;
|
HOST_LIBROOT = root ;
|
||||||
|
HOST_STATIC_LIBROOT = $(HOST_LIBROOT) ;
|
||||||
HOST_LIBBE = be ;
|
HOST_LIBBE = be ;
|
||||||
HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR = ;
|
HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR = ;
|
||||||
HOST_LIBRARY_NAME_MAP_input_server = /system/servers/input_server ;
|
HOST_LIBRARY_NAME_MAP_input_server = /system/servers/input_server ;
|
||||||
} else {
|
} else {
|
||||||
HOST_LIBSTDC++ = stdc++ ;
|
HOST_LIBSTDC++ = stdc++ ;
|
||||||
HOST_LIBROOT = libroot_build.so ;
|
HOST_LIBROOT = libroot_build.so ;
|
||||||
|
HOST_STATIC_LIBROOT = libroot_build.a ;
|
||||||
HOST_LIBBE = libbe_build.so ;
|
HOST_LIBBE = libbe_build.so ;
|
||||||
HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR
|
HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR
|
||||||
= "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(HOST_BUILD_COMPATIBILITY_LIB_DIR)" ;
|
= "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(HOST_BUILD_COMPATIBILITY_LIB_DIR)" ;
|
||||||
@@ -556,8 +562,10 @@ if $(HOST_PLATFORM_BEOS_COMPATIBLE) {
|
|||||||
# Unlike glibc FreeBSD's libc doesn't have built-in regex support.
|
# Unlike glibc FreeBSD's libc doesn't have built-in regex support.
|
||||||
if $(HOST_PLATFORM) = freebsd {
|
if $(HOST_PLATFORM) = freebsd {
|
||||||
HOST_LIBROOT += /usr/lib/libgnuregex.so ;
|
HOST_LIBROOT += /usr/lib/libgnuregex.so ;
|
||||||
|
HOST_STATIC_LIBROOT += /usr/lib/libgnuregex.so ;
|
||||||
} else if $(HOST_PLATFORM) = darwin {
|
} else if $(HOST_PLATFORM) = darwin {
|
||||||
HOST_LIBROOT += /opt/local/lib/libgnuregex.dylib ;
|
HOST_LIBROOT += /opt/local/lib/libgnuregex.dylib ;
|
||||||
|
HOST_STATIC_LIBROOT += /opt/local/lib/libgnuregex.dylib ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -580,6 +588,19 @@ if $(HOST_PLATFORM_BEOS_COMPATIBLE) {
|
|||||||
# which is somewhat more robust.
|
# which is somewhat more robust.
|
||||||
if $(HAIKU_HOST_USE_XATTR) = 1 {
|
if $(HAIKU_HOST_USE_XATTR) = 1 {
|
||||||
HOST_DEFINES += HAIKU_HOST_USE_XATTR ;
|
HOST_DEFINES += HAIKU_HOST_USE_XATTR ;
|
||||||
|
} else {
|
||||||
|
# Otherwise the generic attribute emulation is used, which uses a
|
||||||
|
# directory per file to store its attribute. We need to redefine RM so
|
||||||
|
# that the attributes are removed as well. We use a wrapper script, which
|
||||||
|
# invokes a build tool. If the build tool hasn't been built yet, the
|
||||||
|
# normal "rm" is used and the attributes are leaked (likely there aren't
|
||||||
|
# any yet).
|
||||||
|
RM = $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) ";"
|
||||||
|
[ FDirName $(HAIKU_TOP) build scripts rm_attrs ]
|
||||||
|
[ FDirName $(HAIKU_OBJECT_DIR) $(HOST_PLATFORM) $(HOST_ARCH) release
|
||||||
|
tools rm_attrs ] -f ;
|
||||||
|
# assumes that rm_attrs is built with debugging disabled
|
||||||
|
HOST_RM_ATTRS_TARGET = <build>rm_attrs ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -664,6 +664,12 @@ AddVariableToScript $(script) : sourceDirsToCopy
|
|||||||
: $(HAIKU_INSTALL_SOURCE_DIRS) ;
|
: $(HAIKU_INSTALL_SOURCE_DIRS) ;
|
||||||
AddVariableToScript $(script) : headerDirsToCopy
|
AddVariableToScript $(script) : headerDirsToCopy
|
||||||
: $(HAIKU_INSTALL_HEADER_DIRS) ;
|
: $(HAIKU_INSTALL_HEADER_DIRS) ;
|
||||||
|
if $(HOST_RM_ATTRS_TARGET) {
|
||||||
|
AddTargetVariableToScript $(script) : $(HOST_RM_ATTRS_TARGET) : rmAttrs ;
|
||||||
|
} else {
|
||||||
|
AddVariableToScript $(script) : rmAttrs : rm ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# create the other scripts
|
# create the other scripts
|
||||||
HAIKU_IMAGE_MAKE_DIRS_SCRIPT = <HaikuImage>haiku.image-make-dirs ;
|
HAIKU_IMAGE_MAKE_DIRS_SCRIPT = <HaikuImage>haiku.image-make-dirs ;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ rule InitScript
|
|||||||
|
|
||||||
actions InitScript1
|
actions InitScript1
|
||||||
{
|
{
|
||||||
rm -f $(1)
|
$(RM) $(1)
|
||||||
echo -n > $(1)
|
echo -n > $(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,7 +678,7 @@ rule BuildVMWareImage vmwareImage : plainImage : imageSize
|
|||||||
|
|
||||||
actions BuildVMWareImage1
|
actions BuildVMWareImage1
|
||||||
{
|
{
|
||||||
rm -f $(1)
|
$(RM) $(1)
|
||||||
$(2[1]) -h 64k -i$(IMAGE_SIZE)M $(1) &&
|
$(2[1]) -h 64k -i$(IMAGE_SIZE)M $(1) &&
|
||||||
cat $(2[2]) >> $(1)
|
cat $(2[2]) >> $(1)
|
||||||
}
|
}
|
||||||
@@ -857,7 +857,7 @@ rule BuildFloppyBootImage image : zbeos : archive
|
|||||||
|
|
||||||
actions BuildFloppyBootImage1
|
actions BuildFloppyBootImage1
|
||||||
{
|
{
|
||||||
rm -f $(<)
|
$(RM) $(<)
|
||||||
# make an empty image
|
# make an empty image
|
||||||
dd if=/dev/zero of=$(<) bs=1k count=1440
|
dd if=/dev/zero of=$(<) bs=1k count=1440
|
||||||
# add zbeos
|
# add zbeos
|
||||||
@@ -882,7 +882,7 @@ rule BuildCDBootImage image : bootfloppy : extrafiles
|
|||||||
|
|
||||||
actions BuildCDBootImage1
|
actions BuildCDBootImage1
|
||||||
{
|
{
|
||||||
rm -f $(<)
|
$(RM) $(<)
|
||||||
mkisofs -b $(BOOTIMG) -r -J -V bootimg -o $(<) $(>[1]) $(>[2-])
|
mkisofs -b $(BOOTIMG) -r -J -V bootimg -o $(<) $(>[1]) $(>[2-])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -557,8 +557,9 @@ rule BuildPlatformMain
|
|||||||
|
|
||||||
# add the build libroot
|
# add the build libroot
|
||||||
if ! $(HOST_PLATFORM_BEOS_COMPATIBLE) {
|
if ! $(HOST_PLATFORM_BEOS_COMPATIBLE) {
|
||||||
Depends $(target) : $(HOST_LIBROOT) ;
|
local libroot = [ on $(target) return $(HOST_LIBROOT) ] ;
|
||||||
NEEDLIBS on $(target) += $(HOST_LIBROOT) ;
|
Depends $(target) : $(libroot) ;
|
||||||
|
NEEDLIBS on $(target) += $(libroot) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,15 +636,15 @@ rule BuildPlatformMergeObjectPIC target : sources : otherObjects
|
|||||||
BuildPlatformMergeObject $(target) : $(sources) : $(otherObjects) ;
|
BuildPlatformMergeObject $(target) : $(sources) : $(otherObjects) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
rule BuildPlatformStaticLibrary
|
rule BuildPlatformStaticLibrary lib : sources : otherObjects
|
||||||
{
|
{
|
||||||
# BuildPlatformStaticLibrary <lib> : <sources> ;
|
# BuildPlatformStaticLibrary <lib> : <sources> ;
|
||||||
# Creates a static library from sources.
|
# Creates a static library from sources.
|
||||||
# <lib>: The library.
|
# <lib>: The static library to be built.
|
||||||
# <sources>: List of source files.
|
# <sources>: List of source files.
|
||||||
|
# <otherObjects>: List of additional object files.
|
||||||
|
#
|
||||||
|
|
||||||
local lib = $(1) ;
|
|
||||||
local sources = $(2) ;
|
|
||||||
local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
|
local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
|
||||||
|
|
||||||
PLATFORM on $(lib) = host ;
|
PLATFORM on $(lib) = host ;
|
||||||
@@ -655,6 +656,6 @@ rule BuildPlatformStaticLibrary
|
|||||||
USES_BE_API on $(objects) = $(usesBeAPI) ;
|
USES_BE_API on $(objects) = $(usesBeAPI) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticLibrary $(lib) : $(sources) ;
|
StaticLibrary $(lib) : $(sources) : $(otherObjects) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ rule Link
|
|||||||
SetType $(1) ;
|
SetType $(1) ;
|
||||||
MimeSet $(1) ;
|
MimeSet $(1) ;
|
||||||
SetVersion $(1) ;
|
SetVersion $(1) ;
|
||||||
|
|
||||||
|
# If the generic attribute emulation is enabled, make sure the tool to
|
||||||
|
# remove the attributes is built first.
|
||||||
|
if $(HOST_RM_ATTRS_TARGET) {
|
||||||
|
Depends $(1) : $(HOST_RM_ATTRS_TARGET) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
# makebootable
|
# makebootable
|
||||||
# resattr
|
# resattr
|
||||||
# rc
|
# rc
|
||||||
|
# rmAttrs
|
||||||
# unzip
|
# unzip
|
||||||
# vmdkheader
|
# vmdkheader
|
||||||
#
|
#
|
||||||
@@ -59,20 +60,6 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# attribute-safe rm -rf
|
|
||||||
# This makes sure there are no leftover attribute file before removing each file
|
|
||||||
attrrmrf()
|
|
||||||
{
|
|
||||||
test -e "$1" || return
|
|
||||||
if [ -d "$outputDir/attributes" ]; then
|
|
||||||
# test for gnu stat, else fallback to the bsd one.
|
|
||||||
statFormatOpt="-c"
|
|
||||||
stat -c '%i' . >/dev/null 2>&1 || statFormatOpt="-f"
|
|
||||||
find "$1" -print0 | xargs -0 stat $statFormatOpt %i | awk "{ print \"$outputDir/attributes/\" \$1 }" | xargs rm -rf
|
|
||||||
fi
|
|
||||||
rm -rf "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
unzipFile()
|
unzipFile()
|
||||||
{
|
{
|
||||||
# unzipFile <archive> <directory>
|
# unzipFile <archive> <directory>
|
||||||
@@ -83,13 +70,13 @@ unzipFile()
|
|||||||
|
|
||||||
if [ $isImage ]; then
|
if [ $isImage ]; then
|
||||||
unzipDir=$tmpDir/unzip
|
unzipDir=$tmpDir/unzip
|
||||||
attrrmrf "$unzipDir"
|
$rmAttrs -rf "$unzipDir"
|
||||||
mkdir -p "$unzipDir"
|
mkdir -p "$unzipDir"
|
||||||
|
|
||||||
$unzip -q -d "$unzipDir" "$zipFile"
|
$unzip -q -d "$unzipDir" "$zipFile"
|
||||||
$cp -r "${sPrefix}$unzipDir/." "${tPrefix}$targetUnzipDir"
|
$cp -r "${sPrefix}$unzipDir/." "${tPrefix}$targetUnzipDir"
|
||||||
|
|
||||||
attrrmrf "$unzipDir"
|
$rmAttrs -rf "$unzipDir"
|
||||||
else
|
else
|
||||||
$unzip -q -o -d "${tPrefix}$targetUnzipDir" "${sPrefix}$zipFile"
|
$unzip -q -o -d "${tPrefix}$targetUnzipDir" "${sPrefix}$zipFile"
|
||||||
fi
|
fi
|
||||||
@@ -192,7 +179,7 @@ if [ ! $updateOnly ]; then
|
|||||||
done
|
done
|
||||||
|
|
||||||
# cleanup tmp dir
|
# cleanup tmp dir
|
||||||
attrrmrf $mimeTmpDir
|
$rmAttrs -rf $mimeTmpDir
|
||||||
fi # ! updateOnly
|
fi # ! updateOnly
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ $# -lt 2 ]; then
|
||||||
|
echo "$0: Usage:..."
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
rmAttrs=$1
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ -f $rmAttrs ]; then
|
||||||
|
$rmAttrs $@
|
||||||
|
else
|
||||||
|
rm $@
|
||||||
|
fi
|
||||||
@@ -11,6 +11,7 @@ local tools =
|
|||||||
<build>listattr
|
<build>listattr
|
||||||
<build>mimeset
|
<build>mimeset
|
||||||
<build>mkindex
|
<build>mkindex
|
||||||
|
<build>rm_attrs_tmp
|
||||||
<build>rmattr
|
<build>rmattr
|
||||||
<build>settype
|
<build>settype
|
||||||
<build>setversion
|
<build>setversion
|
||||||
@@ -56,6 +57,14 @@ BuildPlatformMain <build>mimeset :
|
|||||||
|
|
||||||
BuildPlatformMain <build>mkindex : mkindex.cpp : $(HOST_LIBBE) ;
|
BuildPlatformMain <build>mkindex : mkindex.cpp : $(HOST_LIBBE) ;
|
||||||
|
|
||||||
|
# We want rm_attrs to be self-contained, so we link against the static libroot.
|
||||||
|
HOST_LIBROOT on <build>rm_attrs_tmp = $(HOST_STATIC_LIBROOT) ;
|
||||||
|
BuildPlatformMain <build>rm_attrs_tmp : rm_attrs.cpp
|
||||||
|
: $(HOST_LIBSUPC++) $(HOST_LIBSTDC++) ;
|
||||||
|
MakeLocateDebug <build>rm_attrs ;
|
||||||
|
File <build>rm_attrs : <build>rm_attrs_tmp ;
|
||||||
|
MODE on <build>rm_attrs = 755 ;
|
||||||
|
|
||||||
BuildPlatformMain <build>rmattr : rmattr.cpp : $(HOST_LIBBE) ;
|
BuildPlatformMain <build>rmattr : rmattr.cpp : $(HOST_LIBBE) ;
|
||||||
|
|
||||||
BuildPlatformMain <build>set_haiku_revision : set_haiku_revision.cpp
|
BuildPlatformMain <build>set_haiku_revision : set_haiku_revision.cpp
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
// exported by the generic attribute support in libroot_build.so
|
||||||
|
extern "C" bool __get_attribute_dir_path(const struct stat* st, char* buffer);
|
||||||
|
|
||||||
|
|
||||||
|
class Path {
|
||||||
|
public:
|
||||||
|
bool Init(const char* path)
|
||||||
|
{
|
||||||
|
size_t len = strlen(path);
|
||||||
|
if (len == 0 || len >= PATH_MAX)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
strcpy(fPath, path);
|
||||||
|
fPathLen = len;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetPath() const
|
||||||
|
{
|
||||||
|
return fPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* Buffer()
|
||||||
|
{
|
||||||
|
return fPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferChanged()
|
||||||
|
{
|
||||||
|
fPathLen = strlen(fPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PushLeaf(const char* leaf)
|
||||||
|
{
|
||||||
|
size_t leafLen = strlen(leaf);
|
||||||
|
|
||||||
|
int separatorLen = (fPath[fPathLen - 1] == '/' ? 0 : 1);
|
||||||
|
if (fPathLen + separatorLen + leafLen >= PATH_MAX)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (separatorLen > 0)
|
||||||
|
fPath[fPathLen++] = '/';
|
||||||
|
|
||||||
|
strcpy(fPath + fPathLen, leaf);
|
||||||
|
fPathLen += leafLen;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopLeaf()
|
||||||
|
{
|
||||||
|
char* lastSlash = strrchr(fPath, '/');
|
||||||
|
if (lastSlash == NULL || lastSlash == fPath)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*lastSlash = '\0';
|
||||||
|
fPathLen = lastSlash - fPath;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char fPath[PATH_MAX];
|
||||||
|
size_t fPathLen;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static bool remove_entry(Path& entry, bool recursive, bool force,
|
||||||
|
bool removeAttributes);
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_dir_contents(Path& path, bool force, bool removeAttributes)
|
||||||
|
{
|
||||||
|
// open the dir
|
||||||
|
DIR* dir = opendir(path.GetPath());
|
||||||
|
if (dir < 0) {
|
||||||
|
fprintf(stderr, "Error: Failed to open dir \"%s\": %s\n",
|
||||||
|
path.GetPath(), strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate through the entries
|
||||||
|
errno = 0;
|
||||||
|
while (dirent* entry = readdir(dir)) {
|
||||||
|
// skip "." and ".."
|
||||||
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!path.PushLeaf(entry->d_name)) {
|
||||||
|
fprintf(stderr, "Error: Path name of entry too long: dir: \"%s\", "
|
||||||
|
"entry: \"%s\"\n", path.GetPath(), entry->d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_entry(path, true, force, removeAttributes);
|
||||||
|
|
||||||
|
path.PopLeaf();
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno != 0) {
|
||||||
|
fprintf(stderr, "Error: Failed to read directory \"%s\": %s\n",
|
||||||
|
path.GetPath(), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
// close
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
remove_entry(Path& path, bool recursive, bool force, bool removeAttributes)
|
||||||
|
{
|
||||||
|
// stat the file
|
||||||
|
struct stat st;
|
||||||
|
if (lstat(path.GetPath(), &st) < 0) {
|
||||||
|
// errno == 0 shouldn't happen, but found on OpenSUSE Linux 10.3
|
||||||
|
if (force && (errno == ENOENT || errno == 0))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fprintf(stderr, "Error: Failed to remove \"%s\": %s\n", path.GetPath(),
|
||||||
|
strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the file's attributes
|
||||||
|
if (removeAttributes) {
|
||||||
|
Path attrDirPath;
|
||||||
|
if (__get_attribute_dir_path(&st, attrDirPath.Buffer())) {
|
||||||
|
attrDirPath.BufferChanged();
|
||||||
|
remove_entry(attrDirPath, true, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISDIR(st.st_mode)) {
|
||||||
|
if (!recursive) {
|
||||||
|
fprintf(stderr, "Error: \"%s\" is a directory.\n", path.GetPath());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the contents
|
||||||
|
remove_dir_contents(path, force, removeAttributes);
|
||||||
|
|
||||||
|
// remove the directory
|
||||||
|
if (rmdir(path.GetPath()) < 0) {
|
||||||
|
fprintf(stderr, "Error: Failed to remove directory \"%s\": %s\n",
|
||||||
|
path.GetPath(), strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// remove the entry
|
||||||
|
if (unlink(path.GetPath()) < 0) {
|
||||||
|
fprintf(stderr, "Error: Failed to remove entry \"%s\": %s\n",
|
||||||
|
path.GetPath(), strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, const char* const* argv)
|
||||||
|
{
|
||||||
|
bool recursive = false;
|
||||||
|
bool force = false;
|
||||||
|
|
||||||
|
// parse parameters
|
||||||
|
int argi = 1;
|
||||||
|
for (argi = 1; argi < argc; argi++) {
|
||||||
|
const char *arg = argv[argi];
|
||||||
|
if (arg[0] != '-')
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (arg[1] == '\0') {
|
||||||
|
fprintf(stderr, "Error: Invalid option \"-\"\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; arg[i]; i++) {
|
||||||
|
switch (arg[i]) {
|
||||||
|
case 'f':
|
||||||
|
force = true;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
recursive = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Error: Unknown option \"-%c\"\n", arg[i]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check params
|
||||||
|
if (argi >= argc) {
|
||||||
|
fprintf(stderr, "Usage: %s [ -rf ] <file>...\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove loop
|
||||||
|
for (; argi < argc; argi++) {
|
||||||
|
Path path;
|
||||||
|
if (!path.Init(argv[argi])) {
|
||||||
|
fprintf(stderr, "Error: Invalid path: \"%s\".\n", argv[argi]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_entry(path, recursive, force, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user