2
$Id: ad_ls.c,v 1.4 2009-10-14 01:38:28 didg Exp $
4
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
19
#endif /* HAVE_CONFIG_H */
22
#include <sys/types.h>
36
#include <atalk/adouble.h>
37
#include <atalk/cnid.h>
38
#include <atalk/volinfo.h>
41
#define ADv2_DIRNAME ".AppleDouble"
43
#define DIR_DOT_OR_DOTDOT(a) \
44
((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
53
/* Used for pretty printing */
57
static char *netatalk_dirs[] = {
64
static char *labels[] = {
76
Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
77
Returns pointer to name or NULL.
79
static const char *check_netatalk_dirs(const char *name)
83
for (c=0; netatalk_dirs[c]; c++) {
84
if ((strcmp(name, netatalk_dirs[c])) == 0)
85
return netatalk_dirs[c];
91
static void usage_ls(void)
94
"Usage: ad ls [-dRl[u]] [file|dir, ...]\n\n"
95
" -l Long Output [-u: unix info]:\n"
96
" <unixinfo ...> <FinderFlags> <AFPAttributes> <Color> <Type> <Creator> <CNID from AppleDouble> <name>\n\n"
97
" FinderFlags (valid for (f)ile and/or (d)irectory):\n"
98
" d = On Desktop (f/d)\n"
99
" e = Hidden extension (f/d)\n"
100
" m = Shared (can run multiple times) (f)\n"
101
" n = No INIT resources (f)\n"
102
" i = Inited (f/d)\n"
103
" c = Custom icon (f/d)\n"
104
" t = Stationery (f)\n"
105
" s = Name locked (f/d)\n"
106
" b = Bundle (f/d)\n"
107
" v = Invisible (f/d)\n"
108
" a = Alias file (f/d)\n\n"
110
" y = System (f/d)\n"
111
" w = No write (f)\n"
112
" p = Needs backup (f/d)\n"
113
" r = No rename (f/d)\n"
114
" l = No delete (f/d)\n"
115
" o = No copy (f)\n\n"
116
" Note: any letter appearing in uppercase means the flag is set\n"
117
" but it's a directory for which the flag is not allowed.\n"
121
static void print_numlinks(const struct stat *statp)
123
printf("%5ld", (long)statp->st_nlink);
126
static void print_owner(const struct stat *statp)
128
struct passwd *pwd = getpwuid(statp->st_uid);
131
printf(" %-8ld", (long)statp->st_uid);
133
printf(" %-8s", pwd->pw_name);
136
static void print_group(const struct stat *statp)
138
struct group *grp = getgrgid(statp->st_gid);
141
printf(" %-8ld", (long)statp->st_gid);
143
printf(" %-8s", grp->gr_name);
146
static void print_size(const struct stat *statp)
148
switch (statp->st_mode & S_IFMT) {
151
printf("%4u,%4u", (unsigned)(statp->st_rdev >> 8),
152
(unsigned)(statp->st_rdev & 0xFF));
155
printf("%9lu", (unsigned long)statp->st_size);
159
static void print_date(const struct stat *statp)
165
if (time(&now) == -1) {
166
printf(" ????????????");
169
diff = difftime(now, statp->st_mtime);
170
if (diff < 0 || diff > 60 * 60 * 24 * 182.5)
174
strftime(buf, sizeof(buf), fmt, localtime(&statp->st_mtime));
178
static void print_flags(char *path, afpvol_t *vol, const struct stat *st)
183
uint16_t FinderFlags;
184
uint16_t AFPattributes;
185
char type[5] = "----";
186
char creator[5] = "----";
190
if (S_ISDIR(st->st_mode))
191
adflags = ADFLAGS_DIR;
193
if (vol->volinfo.v_path == NULL)
196
ad_init(&ad, vol->volinfo.v_adouble, vol->volinfo.v_ad_options);
198
if ( ad_metadata(path, adflags, &ad) < 0 )
201
FinderInfo = ad_entry(&ad, ADEID_FINDERI);
203
memcpy(&FinderFlags, FinderInfo + 8, 2);
204
FinderFlags = ntohs(FinderFlags);
206
memcpy(type, FinderInfo, 4);
207
memcpy(creator, FinderInfo + 4, 4);
209
ad_getattr(&ad, &AFPattributes);
210
AFPattributes = ntohs(AFPattributes);
213
Finder flags. Lowercase means valid, uppercase means invalid because
214
object is a dir and flag is only valid for files.
217
if (FinderFlags & FINDERINFO_ISONDESK)
222
if (FinderFlags & FINDERINFO_HIDEEXT)
227
if (FinderFlags & FINDERINFO_ISHARED) {
228
if (adflags & ADFLAGS_DIR)
235
if (FinderFlags & FINDERINFO_HASNOINITS) {
236
if (adflags & ADFLAGS_DIR)
243
if (FinderFlags & FINDERINFO_HASBEENINITED)
248
if (FinderFlags & FINDERINFO_HASCUSTOMICON)
253
if (FinderFlags & FINDERINFO_ISSTATIONNERY) {
254
if (adflags & ADFLAGS_DIR)
261
if (FinderFlags & FINDERINFO_NAMELOCKED)
266
if (FinderFlags & FINDERINFO_HASBUNDLE)
271
if (FinderFlags & FINDERINFO_INVISIBLE)
276
if (FinderFlags & FINDERINFO_ISALIAS)
284
if (AFPattributes & ATTRBIT_SYSTEM)
289
if (AFPattributes & ATTRBIT_NOWRITE) {
290
if (adflags & ADFLAGS_DIR)
297
if (AFPattributes & ATTRBIT_BACKUP)
302
if (AFPattributes & ATTRBIT_NORENAME)
307
if (AFPattributes & ATTRBIT_NODELETE)
312
if (AFPattributes & ATTRBIT_NOCOPY) {
313
if (adflags & ADFLAGS_DIR)
321
printf(" %s ", labels[(FinderFlags & FINDERINFO_COLOR) >> 1]);
325
if (isalnum(type[i]))
332
if (isalnum(creator[i]))
340
cnid = ad_forcegetid(&ad);
342
printf(" %10u ", ntohl(cnid));
344
printf(" !ADVOL_CACHE ");
346
ad_close_metadata(&ad);
349
#define TYPE(b) ((st->st_mode & (S_IFMT)) == (b))
350
#define MODE(b) ((st->st_mode & (b)) == (b))
352
static void print_mode(const struct stat *st)
356
else if (TYPE(S_IFCHR))
358
else if (TYPE(S_IFDIR))
360
else if (TYPE(S_IFIFO))
362
else if (TYPE(S_IFREG))
364
else if (TYPE(S_IFLNK))
366
else if (TYPE(S_IFSOCK))
370
putchar(MODE(S_IRUSR) ? 'r' : '-');
371
putchar(MODE(S_IWUSR) ? 'w' : '-');
378
else if (MODE(S_IXUSR))
382
putchar(MODE(S_IRGRP) ? 'r' : '-');
383
putchar(MODE(S_IWGRP) ? 'w' : '-');
390
else if (MODE(S_IXGRP))
394
putchar(MODE(S_IROTH) ? 'r' : '-');
395
putchar(MODE(S_IWOTH) ? 'w' : '-');
396
if (MODE(S_IFDIR) && MODE(S_ISVTX)) {
402
else if (MODE(S_IXOTH))
410
static int ad_print(char *path, const struct stat *st, afpvol_t *vol)
428
print_flags(path, vol, st);
429
printf(" %s\n", path);
435
static int ad_ls_r(char *path, afpvol_t *vol)
437
int ret = 0, cwd, dirprinted = 0, dirempty;
440
static char cwdpath[MAXPATHLEN+1];
443
static struct stat st; /* Save some stack space */
448
strcat(cwdpath, "/");
450
strcat(cwdpath, path);
453
if (lstat(path, &st) < 0) {
454
perror("Can't stat");
457
/* If its a file or a dir with -d option call ad_print and return */
458
if (S_ISREG(st.st_mode) || ls_d)
459
return ad_print(path, &st, vol);
461
/* Its a dir: chdir to it remembering where we started */
462
if ((cwd = open(".", O_RDONLY)) == -1) {
463
perror("Cant open .");
466
if (chdir(path) != 0) {
467
perror("Cant chdir");
472
if ((dp = opendir (".")) == NULL) {
473
perror("Couldn't opendir .");
477
/* First run: print everything */
479
while ((ep = readdir (dp))) {
480
/* Check if its "." or ".." */
481
if (DIR_DOT_OR_DOTDOT(ep->d_name))
484
/* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
485
if ((name = check_netatalk_dirs(ep->d_name)) != NULL)
488
if ((ep->d_name[0] == '.') && ! ls_a)
493
if (recursion && ! dirprinted) {
494
printf("\n%s:\n", cwdpath);
498
if (lstat(ep->d_name, &st) < 0) {
499
perror("Can't stat");
503
ret = ad_print(ep->d_name, &st, vol);
508
if (! ls_l && ! dirempty)
511
/* Second run: recurse to dirs */
514
while ((ep = readdir (dp))) {
515
/* Check if its "." or ".." */
516
if (DIR_DOT_OR_DOTDOT(ep->d_name))
519
/* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
520
if ((name = check_netatalk_dirs(ep->d_name)) != NULL)
523
if ((ret = lstat(ep->d_name, &st)) < 0) {
524
perror("Can't stat");
529
if (S_ISDIR(st.st_mode)) {
531
ret = ad_ls_r(ep->d_name, vol);
543
tmp = strrchr(cwdpath, '/');
550
int ad_ls(int argc, char **argv)
556
while ((c = getopt(argc, argv, ":adlRu")) != -1) {
582
if ((argc - optind) == 0) {
592
/* First run: only print files from argv paths */
593
while(optind < argc) {
594
if (stat(argv[optind], &st) != 0)
596
if (S_ISDIR(st.st_mode))
603
newvol(argv[optind], &vol);
604
ad_ls_r(argv[optind], &vol);
609
if (havefile && (! ls_l))
612
/* Second run: print dirs */
614
while(optind < argc) {
615
if (stat(argv[optind], &st) != 0)
617
if ( ! S_ISDIR(st.st_mode))
619
if ((optind > firstarg) || havefile)
620
printf("\n%s:\n", argv[optind]);
625
newvol(argv[optind], &vol);
626
ad_ls_r(argv[optind], &vol);