1 /*
2  * h_size.c
3  * (C)1998-2011 by Marc Huber <Marc.Huber@web.de>
4  * All rights reserved.
5  *
6  * $Id: h_size.c,v 1.12 2015/03/14 06:11:26 marc Exp marc $
7  *
8  */
9 
10 #include "headers.h"
11 
12 static const char rcsid[] __attribute__ ((used)) = "$Id: h_size.c,v 1.12 2015/03/14 06:11:26 marc Exp marc $";
13 
getasciisize(struct context * ctx,int cur)14 static void getasciisize(struct context *ctx, int cur __attribute__ ((unused)))
15 {
16     DebugIn(DEBUG_BUFFER);
17 
18     sigbus_cur = ctx->cfn;
19     if (chunk_get(ctx, NULL)) {
20 	reply(ctx, MSG_451_Internal_error);
21 	goto bye;
22     } else {
23 	if (chunk_remaining(ctx)) {
24 	    char lastchar = ctx->lastchar;
25 	    char *u = ctx->chunk_start;
26 	    size_t len = MIN(ctx->chunk_length, (size_t) bufsize);
27 	    char *ul = u + len;
28 
29 	    for (; u < ul; lastchar = *u++)
30 		if (*u == '\n' && lastchar != '\r')
31 		    ctx->bytecount++;
32 
33 	    ctx->lastchar = lastchar;
34 	    ctx->bytecount += len;
35 	    chunk_release(ctx, len);
36 	}
37 
38 	if (chunk_remaining(ctx))
39 	    io_sched_renew_proc(ctx->io, ctx, (void *) getasciisize);
40 	else {
41 	    replyf(ctx, "213 %llu\r\n", (unsigned long long) ctx->bytecount);
42 	  bye:
43 	    ctx->lastchar = 0, ctx->bytecount = 0;
44 	    io_sched_pop(ctx->io, ctx);
45 	    cleanup_file(ctx, ctx->ffn);
46 	    ctx->dbufi = buffer_free_all(ctx->dbufi);
47 	}
48     }
49 
50     DebugOut(DEBUG_BUFFER);
51 }
52 
h_size(struct context * ctx,char * arg)53 void h_size(struct context *ctx, char *arg)
54 {
55     char *t;
56     struct stat st;
57 
58     DebugIn(DEBUG_COMMAND);
59 
60     if (ctx->use_ascii && ctx->ffn > -1)
61 	reply(ctx, MSG_452_Command_not_during_transfers);
62     else if (!((t = buildpath(ctx, arg)) && !pickystat(ctx, &st, t)))
63 	reply(ctx, MSG_550_No_such_file_or_directory);
64     else if (!S_ISREG(st.st_mode))
65 	reply(ctx, MSG_550_Not_plain_file);
66     else if (ctx->use_ascii && acl_binary_only(ctx, arg, t))
67 	reply(ctx, MSG_504_size_no_ascii);
68     else if (ctx->use_ascii && ctx->ascii_size_limit > -1 && ctx->ascii_size_limit < st.st_size)
69 	reply(ctx, MSG_504_size_ascii_exceeded);
70     else if (ctx->use_ascii && ((ctx->ffn = open(t, O_RDONLY | O_LARGEFILE)) > -1)) {
71 	fcntl(ctx->ffn, F_SETFD, FD_CLOEXEC);
72 	ctx->iomode_fixed = 0;
73 	io_sched_add(ctx->io, ctx, (void *) getasciisize, 0, 0);
74 #ifdef WITH_MMAP
75 	if (use_mmap)
76 	    ctx->iomode = IOMODE_mmap;
77 	else
78 #endif
79 	    ctx->iomode = IOMODE_read, ctx->iomode_fixed = 1;
80 	ctx->offset = 0;
81 	ctx->remaining = st.st_size;
82 	ctx->bytecount = 0;
83 	ctx->quota_update_on_close = 0;
84     } else if (!ctx->use_ascii)
85 	replyf(ctx, "213 %llu\r\n", (unsigned long long) st.st_size);
86     else
87 	reply(ctx, MSG_550_No_such_file_or_directory);
88 
89     DebugOut(DEBUG_COMMAND);
90 }
91