1 #include <string.h>
2 #include <stdio.h>
3 #include "afpfs-ng/map_def.h"
4 #include "afpfs-ng/dsi.h"
5 #include "afpfs-ng/afp.h"
6 
afp_status_header(char * text,int * len)7 int afp_status_header(char * text, int * len)
8 {
9 	int pos;
10 	memset(text,0,*len);
11 
12 	pos=snprintf(text,*len,"AFPFS Version: %s\n"
13 		"UAMs compiled in: %s\n",
14 		AFPFS_VERSION,
15 		get_uam_names_list());
16 	*len-=pos;
17 	if (*len==0) return -1;
18 	return pos;
19 }
20 
print_volume_status(struct afp_volume * v,char * text,int * pos_p,int * len)21 static void print_volume_status(struct afp_volume * v,
22 	char * text,int * pos_p, int * len)
23 {
24 	struct afp_server * s = v->server;
25 	int pos = *pos_p;
26 	unsigned int fl = v->extra_flags;
27 
28 	pos+=snprintf(text+pos,*len-pos,
29 		"    Volume %s, id %d, attribs 0x%x mounted: %s%s\n",
30 		v->volume_name_printable,v->volid,
31 		v->attributes,
32 		(v->mounted==AFP_VOLUME_MOUNTED) ? v->mountpoint:"No",
33 		((v->mounted==AFP_VOLUME_MOUNTED) && (volume_is_readonly(v))) ?
34 			" (read only)":"");
35 
36 	if (v->mounted==AFP_VOLUME_MOUNTED) {
37 		pos+=snprintf(text+pos,*len-pos,
38 		"        did cache stats: %llu miss, %llu hit, %llu expired, %llu force removal\n        uid/gid mapping: %s (%d/%d)\n",
39 		v->did_cache_stats.misses, v->did_cache_stats.hits,
40 		v->did_cache_stats.expired,
41 		v->did_cache_stats.force_removed,
42 		get_mapping_name(v),
43 		s->server_uid,s->server_gid);
44 		pos+=snprintf(text+pos,*len-pos,
45 		"        Unix permissions: %s",
46 			(v->extra_flags&VOLUME_EXTRA_FLAGS_VOL_SUPPORTS_UNIX)?
47 				"Yes":"No");
48 
49 		if (s->server_type==AFPFS_SERVER_TYPE_NETATALK) {
50 			pos+=snprintf(text+pos,*len-pos,
51 			", Netatalk permissions broken: ");
52 
53 			if (fl&VOLUME_EXTRA_FLAGS_VOL_CHMOD_KNOWN)
54 				if (fl&VOLUME_EXTRA_FLAGS_VOL_CHMOD_BROKEN)
55 					pos+=snprintf(text+pos,*len-pos,
56 						"Yes\n");
57 				else
58 					pos+=snprintf(text+pos,*len-pos,
59 						"No\n");
60 			else
61 				pos+=snprintf(text+pos,*len-pos,
62 					"Unknown\n");
63 		}
64 	}
65 	*pos_p=pos;
66 }
67 
afp_status_server(struct afp_server * s,char * text,int * len)68 int afp_status_server(struct afp_server * s, char * text, int * len)
69 {
70 	int j;
71 	struct afp_volume *v;
72 	char signature_string[AFP_SIGNATURE_LEN*2+1];
73 	int pos=0;
74 	int firsttime=0;
75 	struct dsi_request * request;
76 
77 	memset(text,0,*len);
78 
79 	if (s==NULL) {
80 		pos+=snprintf(text+pos,*len-pos,
81 			"Not connected to any servers\n");
82 		goto out;
83 	}
84 
85 	for (j=0;j<AFP_SIGNATURE_LEN;j++)
86 		sprintf(signature_string+(j*2),"%02x",
87 			(unsigned int) ((char) s->signature[j]));
88 
89 	pos+=snprintf(text+pos,*len-pos,
90 		"Server %s\n"
91 		"    connection: %s:%d %s\n"
92 		"    using AFP version: %s\n",
93 		s->server_name_printable,
94 		inet_ntoa(s->address.sin_addr),ntohs(s->address.sin_port),
95 			(s->connect_state==SERVER_STATE_DISCONNECTED ?
96 			"Disconnected" : "(active)"),
97 		s->using_version->av_name
98 	);
99 
100 	pos+=snprintf(text+pos,*len-pos,
101 		"    server UAMs: ");
102 
103 	for (j=1;j<0x100;j<<=1) {
104 		if (j & s->supported_uams) {
105 			if (firsttime!=0)
106 				pos+=snprintf(text+pos,*len-pos,
107 					", ");
108 			if (j==s->using_uam)
109 				pos+=snprintf(text+pos,*len-pos,
110 					"%s (used)",
111 					uam_bitmap_to_string(j));
112 			else
113 				pos+=snprintf(text+pos,*len-pos,
114 					"%s",
115 					uam_bitmap_to_string(j));
116 			firsttime=1;
117 		}
118 	};
119 
120 	pos+=snprintf(text+pos,*len-pos,
121 		"\n    login message: %s\n"
122 		"    type: %s",
123 		s->loginmesg, s->machine_type);
124 
125 
126 	pos+=snprintf(text+pos,*len-pos,
127 		"\n"
128 		"    signature: %s\n"
129 		"    transmit delay: %ums\n"
130 		"    quantums: %u(tx) %u(rx)\n"
131 		"    last request id: %d in queue: %llu\n",
132 	signature_string,
133 	s->tx_delay,
134 	s->tx_quantum, s->rx_quantum,
135 	s->lastrequestid,s->stats.requests_pending);
136 
137 	for (request=s->command_requests;request;request=request->next) {
138 		pos+=snprintf(text+pos,*len-pos,
139 			"         request %d, %s\n",
140 			request->requestid, afp_get_command_name(request->subcommand));
141 	}
142 
143 	pos+=snprintf(text+pos,*len-pos,
144 		"    transfer: %llu(rx) %llu(tx)\n"
145 		"    runt packets: %llu\n",
146 	s->stats.rx_bytes,s->stats.tx_bytes,
147 	s->stats.runt_packets);
148 
149 	if (*len==0) goto out;
150 
151 	for (j=0;j<s->num_volumes;j++) {
152 		v=&s->volumes[j];
153 		print_volume_status(v,text,&pos,len);
154 		pos+=snprintf(text+pos,*len-pos,"\n");
155 	}
156 
157 out:
158 	*len-=pos;
159 	return pos;
160 
161 }
162