Skip to content

Commit

Permalink
attrib: add tool to set or modify file attributes.
Browse files Browse the repository at this point in the history
exFAT files may be marked as hidden, read-only, or system. While these
flags may be ignored on Unix platforms, it may be useful to mark a file
as hidden when building a file system image destined for use on Windows.

This new tool allows these three flags to be set or cleared on a single
file on a file system. If run with no flags, it displays the file's
current attributes, including "dir" and "arch" (whatever that is).
  • Loading branch information
wjt authored and relan committed Feb 27, 2023
1 parent 91fba49 commit 41fd196
Show file tree
Hide file tree
Showing 6 changed files with 305 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Makefile

# make
*.o
/attrib/exfatattrib
/dump/dumpexfat
/fsck/exfatfsck
/fuse/mount.exfat-fuse
Expand Down
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

SUBDIRS = libexfat dump fsck fuse label mkfs
SUBDIRS = libexfat attrib dump fsck fuse label mkfs
27 changes: 27 additions & 0 deletions attrib/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# Makefile.am (08.11.20)
# Automake source.
#
# Free exFAT implementation.
# Copyright (C) 2020 Endless OS Foundation LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

sbin_PROGRAMS = exfatattrib
dist_man8_MANS = exfatattrib.8
exfatattrib_SOURCES = main.c
exfatattrib_CPPFLAGS = -I$(top_srcdir)/libexfat
exfatattrib_LDADD = ../libexfat/libexfat.a
85 changes: 85 additions & 0 deletions attrib/exfatattrib.8
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
.\" Copyright (C) 2020 Endless OS Foundation
.\"
.TH EXFATATTRIB 8 "November 2020"
.SH NAME
.B exfatattrib
\- Set or display exFAT file attributes
.SH SYNOPSIS
.B exfatattrib
[
.B \-r
|
.B \-R
|
.B \-i
|
.B \-I
|
.B \-s
|
.B \-S
|
.B \-a
|
.B \-A
]
.I device
.I file
.SH DESCRIPTION
.B exfatattrib
sets or displays attributes of a file on an exFAT file system.

.I device
is the path to an unmounted disk partition or disk image file containing an
exFAT file system.

.I file
is the path of a file within that file system.

If run with no command line options, the current attributes of
.I file
are displayed; otherwise, the specified attributes are set or cleared. It is an
error to set and clear the same flag.

.SH COMMAND LINE OPTIONS
Command line options available:

.TP
.BI -r
Set read\-only flag
.TP
.BI \-R
Clear read\-only flag
.TP
.BI \-i
Set hidden flag (mnemonic: \fBi\fRnvisible)
.TP
.BI \-I
Clear hidden flag
.TP
.BI \-s
Set system flag
.TP
.BI \-S
Clear system flag
.TP
.BI \-a
Set archive flag
.TP
.BI \-A
Clear archive flag
.TP
.BI \-h
Display this help message
.TP
.BI \-V
Print version and copyright.

.SH EXIT CODES
Zero is returned if errors were not found. Any other code means an error.

.SH AUTHOR
Will Thompson

.SH SEE ALSO
.BR chmod(1)
190 changes: 190 additions & 0 deletions attrib/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
main.c (08.11.20)
Prints or changes exFAT file attributes
Free exFAT implementation.
Copyright (C) 2020 Endless OS Foundation LLC
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <exfat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

static void usage(const char* prog)
{
fprintf(stderr,
"Display current attributes:\n"
" %1$s <device> <file>\n"
"\n"
"Set attributes:\n"
" %1$s [FLAGS] <device> <file>\n"
"\n"
"Flags:\n"
" -r Set read-only flag\n"
" -R Clear read-only flag\n"
" -i Set hidden flag\n"
" -I Clear hidden flag\n"
" -s Set system flag\n"
" -S Clear system flag\n"
" -a Set archive flag\n"
" -A Clear archive flag\n"
"\n"
" -h Display this help message\n"
" -V Display version information\n",
prog);
exit(1);
}

static void print_attribute(uint16_t attribs, uint16_t attrib,
const char* label)
{
printf("%9s: %s\n", label, (attribs & attrib) ? "yes" : "no");
}

static int attribute(struct exfat* ef, struct exfat_node* node,
uint16_t add_flags, uint16_t clear_flags)
{
if ((add_flags | clear_flags) != 0)
{
uint16_t attrib = node->attrib;

attrib |= add_flags;
attrib &= ~clear_flags;

if (node->attrib != attrib)
{
int ret;

node->attrib = attrib;
node->is_dirty = true;

ret = exfat_flush_node(ef, node);
if (ret != 0)
{
char buffer[EXFAT_UTF8_NAME_BUFFER_MAX];

exfat_get_name(node, buffer);
exfat_error("failed to flush changes to '%s': %s", buffer,
strerror(-ret));
return 1;
}
}
}
else
{
print_attribute(node->attrib, EXFAT_ATTRIB_RO, "Read-only");
print_attribute(node->attrib, EXFAT_ATTRIB_HIDDEN, "Hidden");
print_attribute(node->attrib, EXFAT_ATTRIB_SYSTEM, "System");
print_attribute(node->attrib, EXFAT_ATTRIB_ARCH, "Archive");
/* read-only attributes */
print_attribute(node->attrib, EXFAT_ATTRIB_VOLUME, "Volume");
print_attribute(node->attrib, EXFAT_ATTRIB_DIR, "Directory");
}

return 0;
}

int main(int argc, char* argv[])
{
int opt;
int ret;
const char* spec = NULL;
const char* options = "";
const char* file_path = NULL;
struct exfat ef;
struct exfat_node* node;
uint16_t add_flags = 0;
uint16_t clear_flags = 0;

while ((opt = getopt(argc, argv, "rRiIsSaAhV")) != -1)
{
switch (opt)
{
case 'V':
printf("exfatattrib %s\n", VERSION);
puts("Copyright (C) 2011-2018 Andrew Nayenko");
puts("Copyright (C) 2020 Endless OS Foundation LLC");
return 0;
case 'r':
add_flags |= EXFAT_ATTRIB_RO;
break;
case 'R':
clear_flags |= EXFAT_ATTRIB_RO;
break;
/* "-h[elp]" is taken; i is the second letter of "hidden" and
its synonym "invisible" */
case 'i':
add_flags |= EXFAT_ATTRIB_HIDDEN;
break;
case 'I':
clear_flags |= EXFAT_ATTRIB_HIDDEN;
break;
case 's':
add_flags |= EXFAT_ATTRIB_SYSTEM;
break;
case 'S':
clear_flags |= EXFAT_ATTRIB_SYSTEM;
break;
case 'a':
add_flags |= EXFAT_ATTRIB_ARCH;
break;
case 'A':
clear_flags |= EXFAT_ATTRIB_ARCH;
break;
default:
usage(argv[0]);
}
}

if ((add_flags & clear_flags) != 0)
{
exfat_error("can't set and clear the same flag");
return 1;
}

if (argc - optind != 2)
usage(argv[0]);

spec = argv[optind];
file_path = argv[optind + 1];

if ((add_flags | clear_flags) == 0)
options = "ro";

ret = exfat_mount(&ef, spec, options);
if (ret != 0)
{
exfat_error("failed to mount %s: %s", spec, strerror(-ret));
return 1;
}

ret = exfat_lookup(&ef, &node, file_path);
if (ret != 0)
{
exfat_error("failed to look up '%s': %s", file_path, strerror(-ret));
exfat_unmount(&ef);
return 1;
}

ret = attribute(&ef, node, add_flags, clear_flags);

exfat_put_node(&ef, node);
exfat_unmount(&ef);

return ret;
}
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ esac
AC_CONFIG_HEADERS([libexfat/config.h])
AC_CONFIG_FILES([
libexfat/Makefile
attrib/Makefile
dump/Makefile
fsck/Makefile
fuse/Makefile
Expand Down

0 comments on commit 41fd196

Please sign in to comment.