Annotation of src/usr.bin/ssh/sftp-common.c, Revision 1.8
1.1 djm 1: /*
2: * Copyright (c) 2001 Markus Friedl. All rights reserved.
3: * Copyright (c) 2001 Damien Miller. All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24: */
25:
26: #include "includes.h"
1.8 ! itojun 27: RCSID("$OpenBSD: sftp-common.c,v 1.7 2002/09/11 22:41:50 djm Exp $");
1.1 djm 28:
29: #include "buffer.h"
30: #include "bufaux.h"
31: #include "log.h"
32: #include "xmalloc.h"
33:
34: #include "sftp.h"
35: #include "sftp-common.h"
36:
1.3 markus 37: /* Clear contents of attributes structure */
1.1 djm 38: void
39: attrib_clear(Attrib *a)
40: {
41: a->flags = 0;
42: a->size = 0;
43: a->uid = 0;
44: a->gid = 0;
45: a->perm = 0;
46: a->atime = 0;
47: a->mtime = 0;
48: }
49:
1.3 markus 50: /* Convert from struct stat to filexfer attribs */
1.1 djm 51: void
52: stat_to_attrib(struct stat *st, Attrib *a)
53: {
54: attrib_clear(a);
55: a->flags = 0;
56: a->flags |= SSH2_FILEXFER_ATTR_SIZE;
57: a->size = st->st_size;
58: a->flags |= SSH2_FILEXFER_ATTR_UIDGID;
59: a->uid = st->st_uid;
60: a->gid = st->st_gid;
61: a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
62: a->perm = st->st_mode;
63: a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME;
64: a->atime = st->st_atime;
65: a->mtime = st->st_mtime;
66: }
67:
1.7 djm 68: /* Convert from filexfer attribs to struct stat */
69: void
70: attrib_to_stat(Attrib *a, struct stat *st)
71: {
72: memset(st, 0, sizeof(*st));
73:
74: if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
75: st->st_size = a->size;
76: if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
77: st->st_uid = a->uid;
78: st->st_gid = a->gid;
79: }
80: if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
81: st->st_mode = a->perm;
82: if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
83: st->st_atime = a->atime;
84: st->st_mtime = a->mtime;
85: }
86: }
87:
1.3 markus 88: /* Decode attributes in buffer */
1.1 djm 89: Attrib *
90: decode_attrib(Buffer *b)
91: {
92: static Attrib a;
1.6 deraadt 93:
1.1 djm 94: attrib_clear(&a);
95: a.flags = buffer_get_int(b);
96: if (a.flags & SSH2_FILEXFER_ATTR_SIZE)
97: a.size = buffer_get_int64(b);
98: if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
99: a.uid = buffer_get_int(b);
100: a.gid = buffer_get_int(b);
101: }
102: if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
103: a.perm = buffer_get_int(b);
104: if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
105: a.atime = buffer_get_int(b);
106: a.mtime = buffer_get_int(b);
107: }
108: /* vendor-specific extensions */
109: if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) {
110: char *type, *data;
111: int i, count;
1.6 deraadt 112:
1.1 djm 113: count = buffer_get_int(b);
114: for (i = 0; i < count; i++) {
115: type = buffer_get_string(b, NULL);
116: data = buffer_get_string(b, NULL);
117: debug3("Got file attribute \"%s\"", type);
118: xfree(type);
119: xfree(data);
120: }
121: }
122: return &a;
123: }
124:
1.3 markus 125: /* Encode attributes to buffer */
1.1 djm 126: void
127: encode_attrib(Buffer *b, Attrib *a)
128: {
129: buffer_put_int(b, a->flags);
130: if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
131: buffer_put_int64(b, a->size);
132: if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
133: buffer_put_int(b, a->uid);
134: buffer_put_int(b, a->gid);
135: }
136: if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
137: buffer_put_int(b, a->perm);
138: if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
139: buffer_put_int(b, a->atime);
140: buffer_put_int(b, a->mtime);
141: }
142: }
143:
1.3 markus 144: /* Convert from SSH2_FX_ status to text error message */
1.1 djm 145: const char *
146: fx2txt(int status)
147: {
148: switch (status) {
149: case SSH2_FX_OK:
1.2 markus 150: return("No error");
1.1 djm 151: case SSH2_FX_EOF:
1.2 markus 152: return("End of file");
1.1 djm 153: case SSH2_FX_NO_SUCH_FILE:
1.2 markus 154: return("No such file or directory");
1.1 djm 155: case SSH2_FX_PERMISSION_DENIED:
1.2 markus 156: return("Permission denied");
1.1 djm 157: case SSH2_FX_FAILURE:
158: return("Failure");
159: case SSH2_FX_BAD_MESSAGE:
160: return("Bad message");
161: case SSH2_FX_NO_CONNECTION:
162: return("No connection");
163: case SSH2_FX_CONNECTION_LOST:
164: return("Connection lost");
165: case SSH2_FX_OP_UNSUPPORTED:
166: return("Operation unsupported");
167: default:
168: return("Unknown status");
1.5 deraadt 169: }
1.1 djm 170: /* NOTREACHED */
1.7 djm 171: }
172:
173: /*
174: * drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh
175: */
176: char *
177: ls_file(char *name, struct stat *st, int remote)
178: {
179: int ulen, glen, sz = 0;
180: struct passwd *pw;
181: struct group *gr;
182: struct tm *ltime = localtime(&st->st_mtime);
183: char *user, *group;
184: char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
185:
186: strmode(st->st_mode, mode);
187: if (!remote && (pw = getpwuid(st->st_uid)) != NULL) {
188: user = pw->pw_name;
189: } else {
190: snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
191: user = ubuf;
192: }
193: if (!remote && (gr = getgrgid(st->st_gid)) != NULL) {
194: group = gr->gr_name;
195: } else {
196: snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
197: group = gbuf;
198: }
199: if (ltime != NULL) {
200: if (time(NULL) - st->st_mtime < (365*24*60*60)/2)
201: sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime);
202: else
203: sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime);
204: }
205: if (sz == 0)
206: tbuf[0] = '\0';
207: ulen = MAX(strlen(user), 8);
208: glen = MAX(strlen(group), 8);
209: snprintf(buf, sizeof buf, "%s %3d %-*s %-*s %8llu %s %s", mode,
210: st->st_nlink, ulen, user, glen, group,
1.8 ! itojun 211: (unsigned long long)st->st_size, tbuf, name);
1.7 djm 212: return xstrdup(buf);
1.1 djm 213: }