1 /*
2 * h_cwd.c
3 * (C)1998-2011 by Marc Huber <Marc.Huber@web.de>
4 *
5 * $Id: h_cwd.c,v 1.14 2015/03/14 06:11:25 marc Exp marc $
6 *
7 */
8
9 #include "headers.h"
10
11 static const char rcsid[] __attribute__ ((used)) = "$Id: h_cwd.c,v 1.14 2015/03/14 06:11:25 marc Exp marc $";
12
h_cwd(struct context * ctx,char * arg)13 void h_cwd(struct context *ctx, char *arg)
14 {
15 char *t = NULL, *u = NULL;
16 struct stat st;
17 int r = -1;
18
19 Debug((DEBUG_COMMAND, "+ %s %s\n", __func__, arg));
20
21 if (arg[0] == '.' && arg[1] == '.' && !arg[2]) {
22 for (u = ctx->cwd + ctx->cwdlen; u > ctx->cwd + ctx->rootlen && *u != '/'; u--);
23 if (*u != '/')
24 u = NULL;
25 }
26
27 again:
28
29 if (u) {
30 *u = 0;
31 ctx->cwdlen = (u_int) (u - ctx->cwd);
32 acl_conf_readme(ctx);
33 file2control(ctx, "250", ctx->readme);
34 replyf(ctx, MSG_250_Dir_changed, ctx->cwdlen == ctx->rootlen ? "/" : ctx->cwd + ctx->rootlen);
35 } else if ((t = buildpath(ctx, arg)) && !(r = pickystat(ctx, &st, t)) && S_ISDIR(st.st_mode)) {
36 if ((st.st_mode & S_IXOTH) || ((st.st_mode & S_IXUSR) && (st.st_uid == ctx->uid)) || ((st.st_mode & S_IXGRP) && check_gids(ctx, st.st_gid))) {
37 u_int l = (u_int) strlen(t);
38
39 if (ctx->cwdlen >= sizeof(ctx->cwd)) {
40 logerr("buffer too small in %s:%d (%s/%s)", __FILE__, __LINE__, ctx->user, t);
41 reply(ctx, MSG_551_Internal_error);
42 DebugOut(DEBUG_COMMAND);
43 return;
44 }
45 strcpy(ctx->cwd, t);
46 ctx->cwdlen = l;
47 acl_conf_readme(ctx);
48 file2control(ctx, "250", ctx->readme);
49 replyf(ctx, MSG_250_Dir_changed, ctx->cwdlen == ctx->rootlen ? "/" : ctx->cwd + ctx->rootlen);
50 } else
51 reply(ctx, MSG_550_Permission_denied);
52 } else {
53 if (r && (arg[0] == '~') && (arg[1] == '/' || !arg[1])) {
54 char *c = alloca(ctx->homelen - ctx->rootlen + strlen(arg) + 3);
55
56 strcpy(c, "/");
57 strcat(c, ctx->home + ctx->rootlen);
58 strcat(c, "/");
59 strcat(c, arg + 1);
60 arg = c;
61 goto again;
62 }
63
64 reply(ctx, MSG_501_No_such_dir);
65 }
66
67 DebugOut(DEBUG_COMMAND);
68 }
69
h_cdup(struct context * ctx,char * arg)70 void h_cdup(struct context *ctx, char *arg __attribute__ ((unused)))
71 {
72 h_cwd(ctx, "..");
73 }
74