This fixes bug 18059. If this one is not acceptable, feel free to take it and
clean it up, I am abandoning this effort from here forward.
_________________________________________________________________
Windows Live: Keep your friends up to date with what you do online.
http://windowslive.com/Campaign/SocialNetworking?ocid=PID23285::T:WLMTAGL:ON:WL:en-US:SI_SB_online:082009
From 358bc34d6b400eef5200364cb2b6162a656c2c1a Mon Sep 17 00:00:00 2001
From: EA Durbin <ead1...@hotmail.com>
Date: Mon, 17 Aug 2009 18:33:37 -0500
Subject: attrib.exe: add new application attrib.exe
---
programs/attrib/Makefile.in | 13 +++
programs/attrib/attrib.c | 181 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 194 insertions(+), 0 deletions(-)
create mode 100644 programs/attrib/Makefile.in
create mode 100644 programs/attrib/attrib.c
diff --git a/programs/attrib/Makefile.in b/programs/attrib/Makefile.in
new file mode 100644
index 0000000..3be4d21
--- /dev/null
+++ b/programs/attrib/Makefile.in
@@ -0,0 +1,13 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR = @srcdir@
+VPATH = @srcdir@
+MODULE = attrib.exe
+APPMODE = -municode
+IMPORTS = kernel32
+
+C_SRCS = attrib.c
+
+...@make_prog_rules@
+
+...@dependencies@ # everything below this line is overwritten by make depend
diff --git a/programs/attrib/attrib.c b/programs/attrib/attrib.c
new file mode 100644
index 0000000..4fbdeb3
--- /dev/null
+++ b/programs/attrib/attrib.c
@@ -0,0 +1,181 @@
+/*
+ * File Attributes
+ *
+ * Copyright 2009 EA Durbin
+ *
+ * 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/debug.h"
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winnt.h"
+#include "winnls.h"
+#include <stdio.h>
+WINE_DEFAULT_DEBUG_CHANNEL(attrib);
+#define IsAttrib(x, y) ((INVALID_FILE_ATTRIBUTES != (x)) && ((x) & (y)))
+
+static void usage(void)
+{
+ printf("Usage: attrib [+R|-R][+A|-A][+S|-S][+H|-H][+C|-C][[drive:][path]filename] [/S][/D]...\n"
+ " + Sets an attribute\n"
+ " - Clears an attribute\n"
+ " R Read-only file attribute\n"
+ " A Archive file attribute\n"
+ " S System file attribute\n"
+ " H Hidden file attribute\n"
+ " C Compressed file attribute\n"
+ " /S Process files in all directories in the specified path.\n"
+ " /D Process folders as well.\n");
+}
+
+void recurseattr(LPWSTR filename, DWORD clrAttr, DWORD setAttr, BOOL folders)
+{
+ HANDLE hFindFile = INVALID_HANDLE_VALUE;
+ WIN32_FIND_DATAW w32fd;
+ BOOL done = TRUE;
+ int len = lstrlenW(filename);
+ static const WCHAR asterisk[] = {'*',0};
+ static const WCHAR dot[] = {'.',0};
+ static const WCHAR dotdot[] = {'.','.',0};
+ /* add wildcard */
+ if (len && filename[len-1] != '\\') filename[len++] = '\\';
+ lstrcpyW(filename + len, asterisk);
+ if((hFindFile = FindFirstFileW(filename, &w32fd)) != INVALID_HANDLE_VALUE)
+ {
+ for(done = FALSE; !done; done = !FindNextFileW(hFindFile, &w32fd))
+ {
+ WINE_TRACE("Processing: %s\n", wine_dbgstr_w(w32fd.cFileName));
+ if (lstrcmpW(dot, w32fd.cFileName) != 0 &&
+ lstrcmpW(dotdot, w32fd.cFileName) != 0)
+ {
+ lstrcpyW(filename + len, w32fd.cFileName);
+ if(w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if(folders == TRUE)
+ {
+ if(!IsAttrib(w32fd.dwFileAttributes, setAttr))
+ SetFileAttributesW(filename, (w32fd.dwFileAttributes | setAttr));
+ if(IsAttrib(w32fd.dwFileAttributes, clrAttr))
+ SetFileAttributesW(filename, w32fd.dwFileAttributes & ~clrAttr);
+ }
+ recurseattr(filename, clrAttr, setAttr, folders);
+ }
+ if(!IsAttrib(w32fd.dwFileAttributes, setAttr))
+ SetFileAttributesW(filename, (w32fd.dwFileAttributes | setAttr));
+ if(IsAttrib(w32fd.dwFileAttributes, clrAttr))
+ SetFileAttributesW(filename, w32fd.dwFileAttributes & ~clrAttr);
+ }
+ }
+ FindClose(hFindFile);
+ }
+}
+
+int wmain(int argc, WCHAR *argv[])
+{
+ int i = 0;
+ BOOL allfiles = FALSE;
+ BOOL folders = FALSE;
+ DWORD dwAttr = 0;
+ DWORD clrAttr = 0;
+ DWORD setAttr = 0;
+ LPWSTR path = NULL;
+ for(i = 1; i < argc; i++)
+ {
+ WINE_TRACE("Processing argument: %s\n", wine_dbgstr_w(argv[i]));
+ switch(argv[i][0])
+ {
+ case '+':
+ switch(toupper(argv[i][1]))
+ {
+ case 'C':
+ setAttr |= FILE_ATTRIBUTE_COMPRESSED;
+ break;
+ case 'R':
+ setAttr |= FILE_ATTRIBUTE_READONLY;
+ break;
+ case 'A':
+ setAttr |= FILE_ATTRIBUTE_ARCHIVE;
+ break;
+ case 'S':
+ setAttr |= FILE_ATTRIBUTE_SYSTEM;
+ break;
+ case 'H':
+ setAttr |= FILE_ATTRIBUTE_HIDDEN;
+ break;
+ default:
+ fprintf(stderr, "invalid attribute: %s\n", wine_dbgstr_w(argv[i]));
+ usage();
+ }
+ case '-':
+ switch(argv[i][1])
+ {
+ case 'C':
+ clrAttr |= FILE_ATTRIBUTE_COMPRESSED;
+ break;
+ case 'R':
+ clrAttr |= FILE_ATTRIBUTE_READONLY;
+ break;
+ case 'A':
+ clrAttr |= FILE_ATTRIBUTE_ARCHIVE;
+ break;
+ case 'S':
+ clrAttr |= FILE_ATTRIBUTE_SYSTEM;
+ break;
+ case 'H':
+ clrAttr |= FILE_ATTRIBUTE_HIDDEN;
+ break;
+ default:
+ fprintf(stderr, "invalid attribute: %s\n", wine_dbgstr_w(argv[i]));
+ usage();
+ }
+ break;
+ case '/': /* recurse directory or apply attributes to a folder */
+ switch(argv[i][1])
+ {
+ case 'D':
+ folders = TRUE;
+ break;
+ case 'S':
+ allfiles = TRUE;
+ break;
+ }
+ break;
+ default: /* file path */
+ path = argv[i];
+ }
+ }
+ dwAttr = GetFileAttributesW(path);
+ if(dwAttr == INVALID_FILE_ATTRIBUTES) /* file doesn't exist or GetFileAttributes failed */
+ return 1;
+ if(allfiles == TRUE)
+ {
+ if(!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
+ return 1; /* must be a directory */
+ recurseattr(path, clrAttr, setAttr, folders);
+ }
+ else
+ {
+ if((folders != TRUE) && (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
+ return 1;
+ if(!(IsAttrib(dwAttr, setAttr)))
+ SetFileAttributesW(path, dwAttr | setAttr);
+ if(IsAttrib(dwAttr, clrAttr))
+ SetFileAttributesW(path, dwAttr & ~clrAttr);
+ }
+ return 0;
+}
--
1.6.0.4