libnfs.c: add nlink to nfsdirent so we can get it for 'free'
[deb_libnfs.git] / utils / nfs-ls.c
CommitLineData
a6bc1707
RS
1/*
2 Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2010
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
16*/
17
18#define _FILE_OFFSET_BITS 64
19#define _GNU_SOURCE
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#ifdef AROS
26#include "aros_compat.h"
27#endif
28
29#ifdef WIN32
30#include "win32_compat.h"
31#pragma comment(lib, "ws2_32.lib")
32WSADATA wsaData;
67a9f57e 33#define PRId64 "ll"
a6bc1707 34#else
67a9f57e 35#include <inttypes.h>
a6bc1707
RS
36#include <string.h>
37#include <sys/stat.h>
1dc9ea0d 38#include <sys/statvfs.h>
a6bc1707
RS
39#ifndef AROS
40#include <sys/statvfs.h>
41#endif
42#endif
43
44#ifdef HAVE_UNISTD_H
45#include <unistd.h>
46#endif
47
48#include <stdio.h>
49#include <stdlib.h>
50#include <stdint.h>
a6bc1707
RS
51#include <sys/types.h>
52#include <sys/stat.h>
53#include <fcntl.h>
54#include "libnfs-zdr.h"
55#include "libnfs.h"
56#include "libnfs-raw.h"
57#include "libnfs-raw-mount.h"
58
59struct client {
60 char *server;
61 char *export;
62 uint32_t mount_port;
63 int is_finished;
64};
65
17d3cbb1 66int recursive = 0, summary = 0, discovery = 0;
1dc9ea0d 67
a6bc1707
RS
68void print_usage(void)
69{
17d3cbb1
PL
70 fprintf(stderr, "Usage: nfs-ls [-?|--help|--usage] [-R|--recursive] [-s|--summary] [-D|--discovery] <url>\n");
71}
72
73int process_server(const char *server) {
74 struct exportnode *exports;
75 struct exportnode *export;
76
77 exports = mount_getexports(server);
78 if (exports == NULL) {
79 fprintf(stderr, "Failed to get exports for server %s.\n", server);
80 return -1;
81 }
82 for (export=exports; export; export = export->ex_next) {
83 printf("nfs://%s%s\n", server, export->ex_dir);
84 }
85 mount_free_export_list(exports);
86 return 0;
1dc9ea0d
PL
87}
88
89void process_dir(struct nfs_context *nfs, char *dir, int level) {
90 int ret;
91 struct nfsdirent *nfsdirent;
92 struct statvfs svfs;
93 struct nfsdir *nfsdir;
1dc9ea0d
PL
94
95 if (!level) {
96 printf("Recursion detected!\n");
97 exit(10);
98 }
99
100 ret = nfs_opendir(nfs, dir, &nfsdir);
101 if (ret != 0) {
dc3ed8c3 102 printf("Failed to opendir(\"%s\") %s\n", dir, nfs_get_error(nfs));
1dc9ea0d
PL
103 exit(10);
104 }
105 while((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) {
106 char path[1024];
107
108 if (!strcmp(nfsdirent->name, ".") || !strcmp(nfsdirent->name, "..")) {
109 continue;
110 }
1dc9ea0d 111 snprintf(path, 1024, "%s/%s", dir, nfsdirent->name);
1dc9ea0d 112
390ff38a 113 switch (nfsdirent->mode & S_IFMT) {
1dc9ea0d
PL
114#ifndef WIN32
115 case S_IFLNK:
116 printf("l");
117 break;
118#endif
119 case S_IFREG:
120 printf("-");
121 break;
122 case S_IFDIR:
123 printf("d");
124 break;
125 case S_IFCHR:
126 printf("c");
127 break;
128 case S_IFBLK:
129 printf("b");
130 break;
131 }
132 printf("%c%c%c",
390ff38a
RS
133 "-r"[!!(nfsdirent->mode & S_IRUSR)],
134 "-w"[!!(nfsdirent->mode & S_IWUSR)],
135 "-x"[!!(nfsdirent->mode & S_IXUSR)]
1dc9ea0d
PL
136 );
137 printf("%c%c%c",
390ff38a
RS
138 "-r"[!!(nfsdirent->mode & S_IRGRP)],
139 "-w"[!!(nfsdirent->mode & S_IWGRP)],
140 "-x"[!!(nfsdirent->mode & S_IXGRP)]
1dc9ea0d
PL
141 );
142 printf("%c%c%c",
390ff38a
RS
143 "-r"[!!(nfsdirent->mode & S_IROTH)],
144 "-w"[!!(nfsdirent->mode & S_IWOTH)],
145 "-x"[!!(nfsdirent->mode & S_IXOTH)]
1dc9ea0d 146 );
390ff38a
RS
147 printf(" %2d", (int)nfsdirent->nlink);
148 printf(" %5d", (int)nfsdirent->uid);
149 printf(" %5d", (int)nfsdirent->gid);
150 printf(" %12" PRId64, nfsdirent->size);
1dc9ea0d
PL
151
152 printf(" %s\n", path + 1);
153
390ff38a 154 if (recursive && (nfsdirent->mode & S_IFMT) == S_IFDIR) {
1dc9ea0d
PL
155 process_dir(nfs, path, level - 1);
156 }
157 }
158 nfs_closedir(nfs, nfsdir);
a6bc1707
RS
159}
160
161int main(int argc, char *argv[])
162{
163 struct nfs_context *nfs = NULL;
d2ec73c7 164 int i, ret = 1, res;
a6bc1707
RS
165 uint64_t offset;
166 struct client client;
1dc9ea0d 167 struct statvfs stvfs;
76ead54b 168 struct nfs_url *url = NULL;
a6bc1707 169 exports export, tmp;
a6bc1707
RS
170
171#ifdef WIN32
172 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
173 printf("Failed to start Winsock2\n");
174 exit(10);
175 }
176#endif
177
178#ifdef AROS
179 aros_init_socket();
180#endif
181
d2ec73c7 182 if (argc < 2) {
a6bc1707 183 fprintf(stderr, "No URL specified.\n");
d2ec73c7 184 goto finished;
1dc9ea0d
PL
185 }
186
187 for (i=1; i < argc -1; i++) {
188 if (!strcmp(argv[i], "-R") || !strcmp(argv[i], "--recursive")) {
189 recursive++;
190 } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--summary")) {
191 summary++;
17d3cbb1
PL
192 } else if (!strcmp(argv[i], "-D") || !strcmp(argv[i], "--discovery")) {
193 discovery++;
194 } else{
d2ec73c7 195 goto finished;
1dc9ea0d 196 }
a6bc1707
RS
197 }
198
a6bc1707
RS
199 nfs = nfs_init_context();
200 if (nfs == NULL) {
201 printf("failed to init context\n");
202 goto finished;
203 }
204
17d3cbb1
PL
205 if (discovery) {
206 url = nfs_parse_url_incomplete(nfs, argv[argc - 1]);
207 if (url == NULL) {
208 fprintf(stderr, "%s\n", nfs_get_error(nfs));
209 goto finished;
210 }
211 if (!url->server) {
212 struct nfs_server_list *srvrs;
213 struct nfs_server_list *srv;
214
215 srvrs = nfs_find_local_servers();
216 if (srvrs == NULL) {
217 fprintf(stderr, "Failed to find local servers.\n");
218 goto finished;
219 }
220 for (srv=srvrs; srv; srv = srv->next) {
221 if (recursive) {
222 process_server(srv->addr);
223 } else {
224 printf("nfs://%s\n", srv->addr);
225 }
226 }
227 free_nfs_srvr_list(srvrs);
228 ret = 0;
229 goto finished;
230 }
231 if (url->server && !url->path) {
232 ret = process_server(url->server);
233 goto finished;
234 }
235 nfs_destroy_url(url);
236 }
237
d2ec73c7
PL
238 url = nfs_parse_url_dir(nfs, argv[argc - 1]);
239 if (url == NULL) {
240 fprintf(stderr, "%s\n", nfs_get_error(nfs));
241 goto finished;
242 }
243
244 client.server = url->server;
245 client.export = url->path;
246 client.is_finished = 0;
247
17d3cbb1 248 if ((ret = nfs_mount(nfs, client.server, client.export)) != 0) {
d2ec73c7 249 fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs));
a6bc1707
RS
250 goto finished;
251 }
252
1dc9ea0d 253 process_dir(nfs, "", 16);
a6bc1707 254
1dc9ea0d 255 if (summary) {
9ecd7868 256 if (nfs_statvfs(nfs, "", &stvfs) != 0) {
1dc9ea0d 257 goto finished;
a6bc1707 258 }
1dc9ea0d
PL
259 printf("\n%12" PRId64 " of %12" PRId64 " bytes free.\n",
260 stvfs.f_frsize * stvfs.f_bfree, stvfs.f_frsize * stvfs.f_blocks);
a6bc1707 261 }
d2ec73c7
PL
262
263 ret = 0;
a6bc1707 264finished:
17d3cbb1 265 if (ret > 0) {
d2ec73c7
PL
266 print_usage();
267 }
d2ec73c7 268 nfs_destroy_url(url);
17d3cbb1 269 if (nfs != NULL) {
a6bc1707
RS
270 nfs_destroy_context(nfs);
271 }
d2ec73c7 272 return ret;
a6bc1707 273}