Changeset 07fbfced in rtems


Ignore:
Timestamp:
Mar 5, 2001, 11:01:43 PM (20 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
2e549dad
Parents:
1fc16ff
Message:

2001-01-31 Sergei Organov <osv@…>

  • rtems_servers/ftp.d: Following changes:
    • Hacks with current dir and root dir removed in favor of new libio support for task-local current and root directories.
    • Bug in `close_data_socket()' introduced by previous change fixed.
    • `command_pasv()' changed to set timeout on socket we are listening on and code fixed to don't close socket twice on error.
    • serr()' changed to clear errno'.
    • data_socket()' changed to clear errno' before `bind()'.
    • session()' changed to clear errno' before processing session.
    • `close_data_socket()' fixed to close both active and passive sockets
    • Initialize info->data_socket to -1 in `daemon()'
    • Initialize fname' to empty string in exec_command()'
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/libnetworking/ChangeLog

    r1fc16ff r07fbfced  
     12001-01-31        Sergei Organov <osv@javad.ru>
     2
     3        * rtems_servers/ftp.d: Following changes:
     4          - Hacks with current dir and root dir removed in favor of new libio
     5            support for task-local current and root directories.
     6          - Bug in `close_data_socket()' introduced by previous change fixed.
     7          - `command_pasv()' changed to set timeout on socket we are listening
     8            on and code fixed to don't close socket twice on error.
     9          - `serr()' changed to clear `errno'.
     10          - `data_socket()' changed to clear `errno' before `bind()'.
     11          - `session()' changed to clear `errno' before processing session.
     12          - `close_data_socket()' fixed to close both active and passive sockets
     13          - Initialize info->data_socket to -1 in `daemon()'
     14          - Initialize `fname' to empty string  in `exec_command()'
     15
    1162001-02-03      Ralf Corsepius <corsepiu@faw.uni-ulm.de>
    217
  • c/src/libnetworking/ChangeLog

    r1fc16ff r07fbfced  
     12001-01-31        Sergei Organov <osv@javad.ru>
     2
     3        * rtems_servers/ftp.d: Following changes:
     4          - Hacks with current dir and root dir removed in favor of new libio
     5            support for task-local current and root directories.
     6          - Bug in `close_data_socket()' introduced by previous change fixed.
     7          - `command_pasv()' changed to set timeout on socket we are listening
     8            on and code fixed to don't close socket twice on error.
     9          - `serr()' changed to clear `errno'.
     10          - `data_socket()' changed to clear `errno' before `bind()'.
     11          - `session()' changed to clear `errno' before processing session.
     12          - `close_data_socket()' fixed to close both active and passive sockets
     13          - Initialize info->data_socket to -1 in `daemon()'
     14          - Initialize `fname' to empty string  in `exec_command()'
     15
    1162001-02-03      Ralf Corsepius <corsepiu@faw.uni-ulm.de>
    217
  • c/src/libnetworking/rtems_servers/ftpd.c

    r1fc16ff r07fbfced  
    1515 *
    1616 *  Changes:
     17 *
     18 *    2001-01-31        Sergei Organov <osv@javad.ru>
     19 *
     20 *      * Hacks with current dir and root dir removed in favor of new libio
     21 *        support for task-local current and root directories.
     22 *
     23 *    2001-01-30        Sergei Organov <osv@javad.ru>
     24 *
     25 *      * Bug in `close_data_socket()' introduced by previous change fixed.
     26 *      * `command_pasv()' changed to set timeout on socket we are listening on
     27 *        and code fixed to don't close socket twice on error.
     28 *      * `serr()' changed to clear `errno'.
     29 *      * `data_socket()' changed to clear `errno' before `bind()'.
     30 *      * `session()' changed to clear `errno' before processing session.
     31 *
     32 *    2001-01-29        Sergei Organov <osv@javad.ru>
     33 *
     34 *      * `close_data_socket()' fixed to close both active and passive sockets
     35 *      * Initialize info->data_socket to -1 in `daemon()'
     36 *      * Initialize `fname' to empty string  in `exec_command()'
    1737 *
    1838 *    2001-01-22        Sergei Organov <osv@javad.ru>
     
    170190#include <rtems/rtems_bsdnet.h>
    171191#include <rtems/error.h>
     192#include <rtems/libio.h>
    172193#include <syslog.h>
    173194
     
    236257  int                 data_socket; /* Socket for data connection */
    237258  int                 idle;        /* Timeout in seconds */
    238   char                cwd[FTPD_BUFSIZE];  /* Current working directory */
    239259  int                 xfer_mode;   /* Transfer mode (ASCII/binary) */
    240260  rtems_id            tid;         /* Task id */
     
    262282
    263283/*
    264  * Root node for FTPD without trailing slash.  Even '/' node is denoted as
    265  * empty string here.
    266  */
    267 static char ftpd_root[FTPD_BUFSIZE];
     284 * Root directory
     285 */
     286
     287static char const* ftpd_root = "/";
    268288
    269289/*
     
    287307serr(void)
    288308{
    289   return strerror(errno);
     309  int err = errno;
     310  errno = 0;
     311  return strerror(err);
    290312}
    291313
     
    306328{
    307329  return (ftpd_access & FTPD_NO_WRITE) == 0;
    308 }
    309 
    310 /*PAGE
    311  *
    312  *  Utility routines to manage root directory and session local
    313  *  current working directory.
    314  *
    315  */
    316 
    317 
    318 /*PAGE
    319  *
    320  * is_dir
    321  *
    322  * Return 1 if file with given 'name' exists and is directory, 0 otherwise.
    323  *
    324  */
    325 static int
    326 is_dir(char const* name)
    327 {
    328   struct stat s;
    329   int res = stat(name, &s) == 0 && S_ISDIR(s.st_mode);
    330   return res;
    331 }
    332 
    333 /*PAGE
    334  *
    335  * squeeze_path
    336  *
    337  * Squeezes path according to OS rules, i.e., eliminates /./, /../, and //
    338  * from the path.  Does nothing if the path is relative, i.e. doesn't begin
    339  * with '/'.  The trailing slash is always removed, even when alone, i.e. "/"
    340  * will be "" after squeeze.
    341  *
    342  * Input parameters:
    343  *   path - the path to be squeezed
    344  *   full - full file name or NULL (assumed that it points to the beginning of
    345  *          buffer, and 'path' also points somewhere into the same buffer). Is
    346  *          used to check if intermediate names are directories.
    347  *
    348  * Output parameters:
    349  *   path - squeezed path
    350  *   returns 1 on success, 0 on failure (if any name that supposed to denote
    351  *     directory is not a directory).
    352  *
    353  */
    354 static int
    355 squeeze_path(char* path, char* full)
    356 {
    357   if(path[0] == '/')
    358   {
    359     char* e = path + 1;
    360     int rest = strlen(e);
    361     while(rest >= 0)
    362     {
    363       int len;
    364       char* s = e;
    365       e = strchr(s, '/');
    366       if(e)
    367       {
    368         char c = *e;
    369         *e = '\0';
    370         if(full && !is_dir(full))
    371         {
    372           *e = c;
    373           return 0;
    374         }
    375         *e++ = c;
    376       }
    377       else
    378         e = s + rest + 1;
    379       len = e - s;
    380       rest -= len;
    381       if(len == 1 || (len == 2 && s[0] == '.'))
    382       {
    383         if(rest >= 0)
    384           memmove(s, e, rest + 1);
    385         else
    386           *s++ = '\0';
    387         e = s;
    388       }
    389       else if(len == 3 && s[0] == '.' && s[1] == '.')
    390       {
    391         char* ps = s;
    392         if(ps - 1 > path) {
    393           do
    394             --ps;
    395           while(ps[-1] != '/');
    396         }
    397         if(rest >= 0)
    398           memmove(ps, e, rest + 1);
    399         else
    400           *ps++ = '\0';
    401         e = ps;
    402       }
    403     }
    404     if(e[-2] == '/')
    405     {
    406       e[-2] = '\0';
    407       if(full && !is_dir(full))
    408         return 0;
    409     }
    410   }
    411   return 1;
    412 }
    413 
    414 
    415 /*PAGE
    416  *
    417  * make_path
    418  *
    419  * Makes full path given file name, current working directory and root
    420  * directory (file scope variable 'root').
    421  *
    422  * Input parameters:
    423  *   cwd  - current working directory
    424  *   name - file name
    425  *   root (file scope variable) - FTPD root directory
    426  *
    427  * Output parameters:
    428  *   buf - full path
    429  *   returns pointer to non-root part of the 'buf', i.e. to first character
    430  *           different from '/' after root part.
    431  *
    432  */
    433 static char const*
    434 make_path(char* buf, char const* cwd, char const* name)
    435 {
    436   char* res = NULL;
    437 
    438   int rlen = strlen(ftpd_root);
    439   int clen = strlen(cwd);
    440   int nlen = strlen(name);
    441   int len = rlen + nlen;
    442 
    443   if (name[0] != '/')
    444   {
    445     ++len;
    446     if (clen > 0)
    447       len += clen + 1;
    448   }
    449 
    450   if (FTPD_BUFSIZE > len)
    451   {
    452     char* b = buf;
    453     memcpy(b, ftpd_root, rlen); b += rlen;
    454     if (name[0] != '/')
    455     {
    456       *b++ = '/';
    457       if (clen > 0)
    458       {
    459         memcpy(b, cwd, clen); b += clen;
    460         *b++ = '/';
    461       }
    462     }
    463     memcpy(b, name, nlen); b += nlen;
    464     *b = '\0';
    465 
    466     res = buf + rlen;
    467     while(rlen-- > 0 && res[-1] == '/')
    468       --res;
    469     if(!squeeze_path(res, buf))
    470       res = NULL;
    471   }
    472 
    473   return res;
    474330}
    475331
     
    603459    }
    604460    task_pool.queue[i] = task_pool.info + i;
    605     info->ctrl_fp = NULL;
    606     info->ctrl_socket  = -1;
    607461    if (++id > 'z')
    608462      id = 'a';
     
    638492    if(++task_pool.head >= task_pool.count)
    639493      task_pool.head = 0;
    640     info->ctrl_socket = -1;
    641     info->ctrl_fp = NULL;
    642494    rtems_semaphore_release(task_pool.mutex);
    643495  }
     
    801653      for(tries = 1; tries < 10; ++tries)
    802654      {
     655        errno = 0;
    803656        if(bind(s, (struct sockaddr *)&data_source, sizeof(data_source)) >= 0)
    804657          break;
     
    850703close_data_socket(FTPD_SessionInfo_t *info)
    851704{
    852   int s = info->pasv_socket;
     705  /* As at most one data socket could be open simultaneously and in some cases
     706     data_socket == pasv_socket, we select socket to close, then close it. */
     707  int s = info->data_socket;
    853708  if(0 > s)
    854     s = info->data_socket;
     709    s = info->pasv_socket;
    855710  if(!close_socket(s))
    856711    syslog(LOG_ERR, "ftpd: Error closing data socket.");
     
    937792  char                buf[FTPD_DATASIZE];
    938793  int                 res = 0;
    939   char const* r = NULL;
    940794
    941795  if(!can_read())
     
    945799  }
    946800
    947   r = make_path(buf, info->cwd, filename);
    948 
    949   if (NULL == r || 0 > (fd = open(buf, O_RDONLY)))
     801  if (0 > (fd = open(filename, O_RDONLY)))
    950802  {
    951803    send_reply(info, 550, "Error opening file.");
     
    1031883/*PAGE
    1032884 *
     885 * discard
     886 *
     887 * Analog of `write' routine that just discards passed data
     888 *
     889 * Input parameters:
     890 *   fd    - file descriptor (ignored)
     891 *   buf   - data to write (ignored)
     892 *   count - number of bytes in `buf'
     893 *
     894 * Output parameters:
     895 *   returns `count'
     896 *
     897 */
     898static ssize_t
     899discard(int fd, void const* buf, size_t count)
     900{
     901  (void)fd;
     902  (void)buf;
     903  return count;
     904}
     905
     906/*PAGE
     907 *
    1033908 * command_store
    1034909 *
     
    1052927  int                    res = 1;
    1053928  int                    bare_lfs = 0;
    1054 
    1055   int null = !strcmp("/dev/null", filename);
     929  int                    null = 0;
     930  typedef ssize_t (*WriteProc)(int, void const*, size_t);
     931  WriteProc              wrt = &write;
    1056932
    1057933  if(!can_write())
     
    1059935    send_reply(info, 550, "Access denied.");
    1060936    return;
    1061   }
    1062 
    1063   if(!null)
    1064   {
    1065     if (NULL == make_path(buf, info->cwd, filename))
    1066     {
    1067       send_reply(info, 550, "Error creating file.");
    1068       return;
    1069     }
    1070937  }
    1071938
     
    1076943    return;
    1077944
    1078 
     945  null = !strcmp("/dev/null", filename);
    1079946  if (null)
    1080947  {
    1081948    /* File "/dev/null" just throws data away.
    1082      *  FIXME: this is hack.  Using /dev/null filesystem entry would be
    1083      *  better.  However, it's not clear how to handle root directory other
    1084      *  than '/' then.
     949     *  FIXME: this is hack.  Using `/dev/null' filesystem entry would be
     950     *  better.
    1085951     */
    1086     while ((n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
    1087       ;
    1088   }
    1089   else if (rtems_ftpd_configuration.hooks != NULL)
     952    wrt = &discard;
     953  }
     954
     955  if (!null && rtems_ftpd_configuration.hooks != NULL)
    1090956  {
    1091957
     
    11601026  else
    11611027  {
    1162     /* Data transfer to regular file. */
    1163     int fd =
    1164       creat(buf, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
     1028    /* Data transfer to regular file or /dev/null. */
     1029    int fd = 0;
     1030
     1031    if(!null)
     1032      fd = creat(filename,
     1033        S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
    11651034
    11661035    if (0 > fd)
     
    11751044      while ((n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
    11761045      {
    1177         if (write(fd, buf, n) != n)
     1046        if (wrt(fd, buf, n) != n)
    11781047        {
    11791048          res = 0;
     
    11971066          char const lf = '\r';
    11981067          pended_cr = 0;
    1199           if(write(fd, &lf, 1) != 1)
     1068          if(wrt(fd, &lf, 1) != 1)
    12001069          {
    12011070            res = 0;
     
    12321101            break;
    12331102          count = i - sub - pended_cr;
    1234           if(count > 0 && write(fd, b, count) != count)
     1103          if(count > 0 && wrt(fd, b, count) != count)
    12351104          {
    12361105            res = 0;
    12371106            break;
    12381107          }
    1239           if(sub == 2 && write(fd, e - 1, 1) != 1)
     1108          if(sub == 2 && wrt(fd, e - 1, 1) != 1)
    12401109            res = 0;
    12411110        }
     
    13851254  struct stat         stat_buf;
    13861255  char                buf[FTPD_BUFSIZE];
    1387   char                path[FTPD_BUFSIZE];
    13881256  time_t curTime;
    1389   char const* res;
    1390   char const* cwd = info->cwd;
    13911257  int sc = 1;
    13921258
     
    14031269    fname = ".";
    14041270
    1405   res = make_path(path, cwd, fname);
    1406 
    1407   if (NULL == res || 0 > stat(path, &stat_buf))
     1271  if (0 > stat(fname, &stat_buf))
    14081272  {
    14091273    snprintf(buf, FTPD_BUFSIZE,
     
    14111275    send(s, buf, strlen(buf), 0);
    14121276  }
    1413   else if (S_ISDIR(stat_buf.st_mode) && (NULL == (dirp = opendir(path))))
     1277  else if (S_ISDIR(stat_buf.st_mode) && (NULL == (dirp = opendir(fname))))
    14141278  {
    14151279    snprintf(buf, FTPD_BUFSIZE,
     
    14211285    time(&curTime);
    14221286    if(!dirp && *fname)
    1423       sc = sc && send_dirline(s, wide, curTime, path, "", fname, buf);
     1287      sc = sc && send_dirline(s, wide, curTime, fname, "", fname, buf);
    14241288    else {
    14251289      /* FIXME: need "." and ".." only when '-a' option is given */
    1426       sc = sc && send_dirline(s, wide, curTime, path, "", ".", buf);
    1427       sc = sc && send_dirline(s, wide, curTime, path,
    1428         (strcmp(path, ftpd_root) ? ".." : ""), "..", buf);
     1290      sc = sc && send_dirline(s, wide, curTime, fname, "", ".", buf);
     1291      sc = sc && send_dirline(s, wide, curTime, fname,
     1292        (strcmp(fname, ftpd_root) ? ".." : ""), "..", buf);
    14291293      while (sc && (dp = readdir(dirp)) != NULL)
    14301294        sc = sc &&
    1431           send_dirline(s, wide, curTime, path, dp->d_name, dp->d_name, buf);
     1295          send_dirline(s, wide, curTime, fname, dp->d_name, dp->d_name, buf);
    14321296    }
    14331297  }
     
    14461310/*PAGE
    14471311 *
    1448  * rtems_ftpd_cwd
    1449  *
    1450  * Change current working directory.  We use 'chdir' here only to validate the
    1451  * new directory.  We keep track of current working directory ourselves because
    1452  * current working directory in RTEMS isn't thread local, but we need it to be
    1453  * session local.
     1312 * command_cwd
     1313 *
     1314 * Change current working directory.
    14541315 *
    14551316 * Input parameters:
     
    14581319 *
    14591320 * Output parameters:
    1460  *   info->cwd is set to new CWD value.
     1321 *   NONE
    14611322 *
    14621323 */
    14631324static void
    1464 rtems_ftpd_cwd(FTPD_SessionInfo_t  *info, char *dir)
     1325command_cwd(FTPD_SessionInfo_t  *info, char *dir)
     1326{
     1327  if(chdir(dir) == 0)
     1328    send_reply(info, 250, "CWD command successful.");
     1329  else
     1330    send_reply(info, 550, "CWD command failed.");
     1331}
     1332
     1333
     1334/*PAGE
     1335 *
     1336 * command_pwd
     1337 *
     1338 * Send current working directory to client.
     1339 *
     1340 * Input parameters:
     1341 *   info - corresponding SessionInfo structure
     1342 *
     1343 * Output parameters:
     1344 *   NONE
     1345 */
     1346static void
     1347command_pwd(FTPD_SessionInfo_t  *info)
    14651348{
    14661349  char buf[FTPD_BUFSIZE];
    1467   char const* cwd = make_path(buf, info->cwd, dir);
    1468   if(cwd && chdir(buf) == 0)
    1469   {
    1470     send_reply(info, 250, "CWD command successful.");
    1471     strcpy(info->cwd, cwd);
    1472   }
    1473   else
    1474   {
    1475     send_reply(info, 550, "CWD command failed.");
    1476   }
    1477 }
    1478 
    1479 
     1350  char const* cwd;
     1351  errno = 0;
     1352  buf[0] = '"';
     1353  cwd = getcwd(buf + 1, FTPD_BUFSIZE - 4);
     1354  if(cwd)
     1355  {
     1356    int len = strlen(cwd);
     1357    static char const txt[] = "\" is the current directory.";
     1358    int size = sizeof(txt);
     1359    if(len + size + 1 >= FTPD_BUFSIZE)
     1360      size = FTPD_BUFSIZE - len - 2;
     1361    memcpy(buf + len + 1, txt, size);
     1362    buf[len + size] = '\0';
     1363    send_reply(info, 250, buf);
     1364  }
     1365  else {
     1366    snprintf(buf, FTPD_BUFSIZE, "Error: %s.", serr());
     1367    send_reply(info, 452, buf);
     1368  }
     1369}
    14801370
    14811371/*PAGE
     
    14981388  char buf[FTPD_BUFSIZE];
    14991389
    1500   if (NULL == make_path(buf, info->cwd, fname) || 0 > stat(buf, &stbuf))
     1390  if (0 > stat(fname, &stbuf))
    15011391  {
    15021392    snprintf(buf, FTPD_BUFSIZE, "%s: %s.", fname, serr());
     
    16151505    else if (0 > listen(s, 1))
    16161506      syslog(LOG_ERR, "ftpd: Error listening on PASV socket: %s", serr());
    1617     else
     1507    else if(set_socket_timeout(s, info->idle))
    16181508    {
    16191509      char buf[FTPD_BUFSIZE];
     
    16281518
    16291519      info->pasv_socket = accept(s, (struct sockaddr *)&addr, &addrLen);
    1630       close_socket(s);
    16311520      if (0 > info->pasv_socket)
    16321521        syslog(LOG_ERR, "ftpd: Error accepting PASV connection: %s", serr());
    16331522      else
     1523      {
     1524        close_socket(s);
     1525        s = -1;
    16341526        err = 0;
     1527      }
    16351528    }
    16361529  }
     
    17471640 *   cmd  - command to be executed (upper-case)
    17481641 *   args - arguments of the command
    1749  *   buf  - beginning of buffer where 'cmd' and 'args' reside.
    17501642 *
    17511643 * Output parameters:
     
    17531645 */
    17541646static void
    1755 exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
     1647exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args)
    17561648{
    17571649  char fname[FTPD_BUFSIZE];
    17581650  int wrong_command = 0;
    17591651
     1652  fname[0] = '\0';
     1653
    17601654  if (!strcmp("PORT", cmd))
    17611655  {
     
    18251719    else if (
    18261720      1 == sscanf(args, "%254s", fname) &&
    1827       NULL != make_path(buf, info->cwd, fname) &&
    1828       unlink(buf) == 0)
     1721      unlink(fname) == 0)
    18291722    {
    18301723      send_reply(info, 257, "DELE successful.");
     
    18491742      else if(
    18501743        2 == sscanf(args, "%o %254s", &mask, fname) &&
    1851         NULL != make_path(buf, info->cwd, fname) &&
    1852         chmod(buf, (mode_t)mask) == 0)
     1744        chmod(fname, (mode_t)mask) == 0)
    18531745      {
    18541746        send_reply(info, 257, "CHMOD successful.");
     
    18701762    else if (
    18711763      1 == sscanf(args, "%254s", fname) &&
    1872       NULL != make_path(buf, info->cwd, fname) &&
    1873       rmdir(buf) == 0)
     1764      rmdir(fname) == 0)
    18741765    {
    18751766      send_reply(info, 257, "RMD successful.");
     
    18881779    else if (
    18891780      1 == sscanf(args, "%254s", fname) &&
    1890       NULL != make_path(buf, info->cwd, fname) &&
    1891       mkdir(buf, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
     1781      mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
    18921782    {
    18931783      send_reply(info, 257, "MKD successful.");
     
    19011791  {
    19021792    sscanf(args, "%254s", fname);
    1903     rtems_ftpd_cwd(info, fname);
     1793    command_cwd(info, fname);
    19041794  }
    19051795  else if (!strcmp("CDUP", cmd))
    19061796  {
    1907     rtems_ftpd_cwd(info, "..");
     1797    command_cwd(info, "..");
    19081798  }
    19091799  else if (!strcmp("PWD", cmd))
    19101800  {
    1911     char const* cwd = "/";
    1912     if(info->cwd[0])
    1913       cwd = info->cwd;
    1914     snprintf(buf, FTPD_BUFSIZE,
    1915       "\"%s\" is the current directory.", cwd);
    1916     send_reply(info, 250, buf);
     1801    command_pwd(info);
    19171802  }
    19181803  else
     
    19441829{
    19451830  FTPD_SessionInfo_t  *const info = (FTPD_SessionInfo_t  *)arg;
     1831  int chroot_made = 0;
     1832
     1833  rtems_libio_set_private_env();
     1834
     1835  /* chroot() can fail here because the directory may not exist yet. */
     1836  chroot_made = chroot(ftpd_root) == 0;
    19461837
    19471838  while(1)
    19481839  {
    19491840    rtems_event_set set;
     1841    char buf[128];
    19501842
    19511843    rtems_event_receive(FTPD_RTEMS_EVENT, RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT,
    19521844      &set);
     1845
     1846    chroot_made = chroot_made || chroot(ftpd_root) == 0;
     1847    chdir("/");
     1848
     1849    errno = 0;
    19531850
    19541851    send_reply(info, 220, FTPD_SERVER_MESSAGE);
     
    19741871      else
    19751872      {
    1976         exec_command(info, cmd, args, buf);
     1873        exec_command(info, cmd, args);
    19771874      }
    19781875    }
     
    20621959            info->ctrl_addr  = addr;
    20631960            info->pasv_socket = -1;
    2064             info->xfer_mode = TYPE_A;
    2065             info->cwd[0] = '\0';
     1961            info->data_socket = -1;
     1962            info->xfer_mode   = TYPE_A;
    20661963            info->data_addr.sin_port =
    20671964              htons(ntohs(info->ctrl_addr.sin_port) - 1);
     
    21502047  }
    21512048
    2152   ftpd_root[0] = '\0';
     2049  ftpd_root = "/";
    21532050  if (
    21542051    rtems_ftpd_configuration.root &&
    2155     strlen(rtems_ftpd_configuration.root) < FTPD_BUFSIZE &&
    2156     rtems_ftpd_configuration.root[0] == '/')
    2157   {
    2158     strcpy(ftpd_root, rtems_ftpd_configuration.root);
    2159     squeeze_path(ftpd_root, NULL);
    2160     rtems_ftpd_configuration.root = ftpd_root;
    2161   }
     2052    rtems_ftpd_configuration.root[0] == '/'
     2053  )
     2054    ftpd_root = rtems_ftpd_configuration.root;
     2055
     2056  rtems_ftpd_configuration.root = ftpd_root;
    21622057
    21632058  syslog(LOG_INFO, "ftpd: FTP daemon started (%d session%s max)",
    21642059    count, ((count > 1) ? "s" : ""));
     2060
    21652061  return RTEMS_SUCCESSFUL;
    21662062}
  • cpukit/ftpd/ftpd.c

    r1fc16ff r07fbfced  
    1515 *
    1616 *  Changes:
     17 *
     18 *    2001-01-31        Sergei Organov <osv@javad.ru>
     19 *
     20 *      * Hacks with current dir and root dir removed in favor of new libio
     21 *        support for task-local current and root directories.
     22 *
     23 *    2001-01-30        Sergei Organov <osv@javad.ru>
     24 *
     25 *      * Bug in `close_data_socket()' introduced by previous change fixed.
     26 *      * `command_pasv()' changed to set timeout on socket we are listening on
     27 *        and code fixed to don't close socket twice on error.
     28 *      * `serr()' changed to clear `errno'.
     29 *      * `data_socket()' changed to clear `errno' before `bind()'.
     30 *      * `session()' changed to clear `errno' before processing session.
     31 *
     32 *    2001-01-29        Sergei Organov <osv@javad.ru>
     33 *
     34 *      * `close_data_socket()' fixed to close both active and passive sockets
     35 *      * Initialize info->data_socket to -1 in `daemon()'
     36 *      * Initialize `fname' to empty string  in `exec_command()'
    1737 *
    1838 *    2001-01-22        Sergei Organov <osv@javad.ru>
     
    170190#include <rtems/rtems_bsdnet.h>
    171191#include <rtems/error.h>
     192#include <rtems/libio.h>
    172193#include <syslog.h>
    173194
     
    236257  int                 data_socket; /* Socket for data connection */
    237258  int                 idle;        /* Timeout in seconds */
    238   char                cwd[FTPD_BUFSIZE];  /* Current working directory */
    239259  int                 xfer_mode;   /* Transfer mode (ASCII/binary) */
    240260  rtems_id            tid;         /* Task id */
     
    262282
    263283/*
    264  * Root node for FTPD without trailing slash.  Even '/' node is denoted as
    265  * empty string here.
    266  */
    267 static char ftpd_root[FTPD_BUFSIZE];
     284 * Root directory
     285 */
     286
     287static char const* ftpd_root = "/";
    268288
    269289/*
     
    287307serr(void)
    288308{
    289   return strerror(errno);
     309  int err = errno;
     310  errno = 0;
     311  return strerror(err);
    290312}
    291313
     
    306328{
    307329  return (ftpd_access & FTPD_NO_WRITE) == 0;
    308 }
    309 
    310 /*PAGE
    311  *
    312  *  Utility routines to manage root directory and session local
    313  *  current working directory.
    314  *
    315  */
    316 
    317 
    318 /*PAGE
    319  *
    320  * is_dir
    321  *
    322  * Return 1 if file with given 'name' exists and is directory, 0 otherwise.
    323  *
    324  */
    325 static int
    326 is_dir(char const* name)
    327 {
    328   struct stat s;
    329   int res = stat(name, &s) == 0 && S_ISDIR(s.st_mode);
    330   return res;
    331 }
    332 
    333 /*PAGE
    334  *
    335  * squeeze_path
    336  *
    337  * Squeezes path according to OS rules, i.e., eliminates /./, /../, and //
    338  * from the path.  Does nothing if the path is relative, i.e. doesn't begin
    339  * with '/'.  The trailing slash is always removed, even when alone, i.e. "/"
    340  * will be "" after squeeze.
    341  *
    342  * Input parameters:
    343  *   path - the path to be squeezed
    344  *   full - full file name or NULL (assumed that it points to the beginning of
    345  *          buffer, and 'path' also points somewhere into the same buffer). Is
    346  *          used to check if intermediate names are directories.
    347  *
    348  * Output parameters:
    349  *   path - squeezed path
    350  *   returns 1 on success, 0 on failure (if any name that supposed to denote
    351  *     directory is not a directory).
    352  *
    353  */
    354 static int
    355 squeeze_path(char* path, char* full)
    356 {
    357   if(path[0] == '/')
    358   {
    359     char* e = path + 1;
    360     int rest = strlen(e);
    361     while(rest >= 0)
    362     {
    363       int len;
    364       char* s = e;
    365       e = strchr(s, '/');
    366       if(e)
    367       {
    368         char c = *e;
    369         *e = '\0';
    370         if(full && !is_dir(full))
    371         {
    372           *e = c;
    373           return 0;
    374         }
    375         *e++ = c;
    376       }
    377       else
    378         e = s + rest + 1;
    379       len = e - s;
    380       rest -= len;
    381       if(len == 1 || (len == 2 && s[0] == '.'))
    382       {
    383         if(rest >= 0)
    384           memmove(s, e, rest + 1);
    385         else
    386           *s++ = '\0';
    387         e = s;
    388       }
    389       else if(len == 3 && s[0] == '.' && s[1] == '.')
    390       {
    391         char* ps = s;
    392         if(ps - 1 > path) {
    393           do
    394             --ps;
    395           while(ps[-1] != '/');
    396         }
    397         if(rest >= 0)
    398           memmove(ps, e, rest + 1);
    399         else
    400           *ps++ = '\0';
    401         e = ps;
    402       }
    403     }
    404     if(e[-2] == '/')
    405     {
    406       e[-2] = '\0';
    407       if(full && !is_dir(full))
    408         return 0;
    409     }
    410   }
    411   return 1;
    412 }
    413 
    414 
    415 /*PAGE
    416  *
    417  * make_path
    418  *
    419  * Makes full path given file name, current working directory and root
    420  * directory (file scope variable 'root').
    421  *
    422  * Input parameters:
    423  *   cwd  - current working directory
    424  *   name - file name
    425  *   root (file scope variable) - FTPD root directory
    426  *
    427  * Output parameters:
    428  *   buf - full path
    429  *   returns pointer to non-root part of the 'buf', i.e. to first character
    430  *           different from '/' after root part.
    431  *
    432  */
    433 static char const*
    434 make_path(char* buf, char const* cwd, char const* name)
    435 {
    436   char* res = NULL;
    437 
    438   int rlen = strlen(ftpd_root);
    439   int clen = strlen(cwd);
    440   int nlen = strlen(name);
    441   int len = rlen + nlen;
    442 
    443   if (name[0] != '/')
    444   {
    445     ++len;
    446     if (clen > 0)
    447       len += clen + 1;
    448   }
    449 
    450   if (FTPD_BUFSIZE > len)
    451   {
    452     char* b = buf;
    453     memcpy(b, ftpd_root, rlen); b += rlen;
    454     if (name[0] != '/')
    455     {
    456       *b++ = '/';
    457       if (clen > 0)
    458       {
    459         memcpy(b, cwd, clen); b += clen;
    460         *b++ = '/';
    461       }
    462     }
    463     memcpy(b, name, nlen); b += nlen;
    464     *b = '\0';
    465 
    466     res = buf + rlen;
    467     while(rlen-- > 0 && res[-1] == '/')
    468       --res;
    469     if(!squeeze_path(res, buf))
    470       res = NULL;
    471   }
    472 
    473   return res;
    474330}
    475331
     
    603459    }
    604460    task_pool.queue[i] = task_pool.info + i;
    605     info->ctrl_fp = NULL;
    606     info->ctrl_socket  = -1;
    607461    if (++id > 'z')
    608462      id = 'a';
     
    638492    if(++task_pool.head >= task_pool.count)
    639493      task_pool.head = 0;
    640     info->ctrl_socket = -1;
    641     info->ctrl_fp = NULL;
    642494    rtems_semaphore_release(task_pool.mutex);
    643495  }
     
    801653      for(tries = 1; tries < 10; ++tries)
    802654      {
     655        errno = 0;
    803656        if(bind(s, (struct sockaddr *)&data_source, sizeof(data_source)) >= 0)
    804657          break;
     
    850703close_data_socket(FTPD_SessionInfo_t *info)
    851704{
    852   int s = info->pasv_socket;
     705  /* As at most one data socket could be open simultaneously and in some cases
     706     data_socket == pasv_socket, we select socket to close, then close it. */
     707  int s = info->data_socket;
    853708  if(0 > s)
    854     s = info->data_socket;
     709    s = info->pasv_socket;
    855710  if(!close_socket(s))
    856711    syslog(LOG_ERR, "ftpd: Error closing data socket.");
     
    937792  char                buf[FTPD_DATASIZE];
    938793  int                 res = 0;
    939   char const* r = NULL;
    940794
    941795  if(!can_read())
     
    945799  }
    946800
    947   r = make_path(buf, info->cwd, filename);
    948 
    949   if (NULL == r || 0 > (fd = open(buf, O_RDONLY)))
     801  if (0 > (fd = open(filename, O_RDONLY)))
    950802  {
    951803    send_reply(info, 550, "Error opening file.");
     
    1031883/*PAGE
    1032884 *
     885 * discard
     886 *
     887 * Analog of `write' routine that just discards passed data
     888 *
     889 * Input parameters:
     890 *   fd    - file descriptor (ignored)
     891 *   buf   - data to write (ignored)
     892 *   count - number of bytes in `buf'
     893 *
     894 * Output parameters:
     895 *   returns `count'
     896 *
     897 */
     898static ssize_t
     899discard(int fd, void const* buf, size_t count)
     900{
     901  (void)fd;
     902  (void)buf;
     903  return count;
     904}
     905
     906/*PAGE
     907 *
    1033908 * command_store
    1034909 *
     
    1052927  int                    res = 1;
    1053928  int                    bare_lfs = 0;
    1054 
    1055   int null = !strcmp("/dev/null", filename);
     929  int                    null = 0;
     930  typedef ssize_t (*WriteProc)(int, void const*, size_t);
     931  WriteProc              wrt = &write;
    1056932
    1057933  if(!can_write())
     
    1059935    send_reply(info, 550, "Access denied.");
    1060936    return;
    1061   }
    1062 
    1063   if(!null)
    1064   {
    1065     if (NULL == make_path(buf, info->cwd, filename))
    1066     {
    1067       send_reply(info, 550, "Error creating file.");
    1068       return;
    1069     }
    1070937  }
    1071938
     
    1076943    return;
    1077944
    1078 
     945  null = !strcmp("/dev/null", filename);
    1079946  if (null)
    1080947  {
    1081948    /* File "/dev/null" just throws data away.
    1082      *  FIXME: this is hack.  Using /dev/null filesystem entry would be
    1083      *  better.  However, it's not clear how to handle root directory other
    1084      *  than '/' then.
     949     *  FIXME: this is hack.  Using `/dev/null' filesystem entry would be
     950     *  better.
    1085951     */
    1086     while ((n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
    1087       ;
    1088   }
    1089   else if (rtems_ftpd_configuration.hooks != NULL)
     952    wrt = &discard;
     953  }
     954
     955  if (!null && rtems_ftpd_configuration.hooks != NULL)
    1090956  {
    1091957
     
    11601026  else
    11611027  {
    1162     /* Data transfer to regular file. */
    1163     int fd =
    1164       creat(buf, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
     1028    /* Data transfer to regular file or /dev/null. */
     1029    int fd = 0;
     1030
     1031    if(!null)
     1032      fd = creat(filename,
     1033        S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
    11651034
    11661035    if (0 > fd)
     
    11751044      while ((n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
    11761045      {
    1177         if (write(fd, buf, n) != n)
     1046        if (wrt(fd, buf, n) != n)
    11781047        {
    11791048          res = 0;
     
    11971066          char const lf = '\r';
    11981067          pended_cr = 0;
    1199           if(write(fd, &lf, 1) != 1)
     1068          if(wrt(fd, &lf, 1) != 1)
    12001069          {
    12011070            res = 0;
     
    12321101            break;
    12331102          count = i - sub - pended_cr;
    1234           if(count > 0 && write(fd, b, count) != count)
     1103          if(count > 0 && wrt(fd, b, count) != count)
    12351104          {
    12361105            res = 0;
    12371106            break;
    12381107          }
    1239           if(sub == 2 && write(fd, e - 1, 1) != 1)
     1108          if(sub == 2 && wrt(fd, e - 1, 1) != 1)
    12401109            res = 0;
    12411110        }
     
    13851254  struct stat         stat_buf;
    13861255  char                buf[FTPD_BUFSIZE];
    1387   char                path[FTPD_BUFSIZE];
    13881256  time_t curTime;
    1389   char const* res;
    1390   char const* cwd = info->cwd;
    13911257  int sc = 1;
    13921258
     
    14031269    fname = ".";
    14041270
    1405   res = make_path(path, cwd, fname);
    1406 
    1407   if (NULL == res || 0 > stat(path, &stat_buf))
     1271  if (0 > stat(fname, &stat_buf))
    14081272  {
    14091273    snprintf(buf, FTPD_BUFSIZE,
     
    14111275    send(s, buf, strlen(buf), 0);
    14121276  }
    1413   else if (S_ISDIR(stat_buf.st_mode) && (NULL == (dirp = opendir(path))))
     1277  else if (S_ISDIR(stat_buf.st_mode) && (NULL == (dirp = opendir(fname))))
    14141278  {
    14151279    snprintf(buf, FTPD_BUFSIZE,
     
    14211285    time(&curTime);
    14221286    if(!dirp && *fname)
    1423       sc = sc && send_dirline(s, wide, curTime, path, "", fname, buf);
     1287      sc = sc && send_dirline(s, wide, curTime, fname, "", fname, buf);
    14241288    else {
    14251289      /* FIXME: need "." and ".." only when '-a' option is given */
    1426       sc = sc && send_dirline(s, wide, curTime, path, "", ".", buf);
    1427       sc = sc && send_dirline(s, wide, curTime, path,
    1428         (strcmp(path, ftpd_root) ? ".." : ""), "..", buf);
     1290      sc = sc && send_dirline(s, wide, curTime, fname, "", ".", buf);
     1291      sc = sc && send_dirline(s, wide, curTime, fname,
     1292        (strcmp(fname, ftpd_root) ? ".." : ""), "..", buf);
    14291293      while (sc && (dp = readdir(dirp)) != NULL)
    14301294        sc = sc &&
    1431           send_dirline(s, wide, curTime, path, dp->d_name, dp->d_name, buf);
     1295          send_dirline(s, wide, curTime, fname, dp->d_name, dp->d_name, buf);
    14321296    }
    14331297  }
     
    14461310/*PAGE
    14471311 *
    1448  * rtems_ftpd_cwd
    1449  *
    1450  * Change current working directory.  We use 'chdir' here only to validate the
    1451  * new directory.  We keep track of current working directory ourselves because
    1452  * current working directory in RTEMS isn't thread local, but we need it to be
    1453  * session local.
     1312 * command_cwd
     1313 *
     1314 * Change current working directory.
    14541315 *
    14551316 * Input parameters:
     
    14581319 *
    14591320 * Output parameters:
    1460  *   info->cwd is set to new CWD value.
     1321 *   NONE
    14611322 *
    14621323 */
    14631324static void
    1464 rtems_ftpd_cwd(FTPD_SessionInfo_t  *info, char *dir)
     1325command_cwd(FTPD_SessionInfo_t  *info, char *dir)
     1326{
     1327  if(chdir(dir) == 0)
     1328    send_reply(info, 250, "CWD command successful.");
     1329  else
     1330    send_reply(info, 550, "CWD command failed.");
     1331}
     1332
     1333
     1334/*PAGE
     1335 *
     1336 * command_pwd
     1337 *
     1338 * Send current working directory to client.
     1339 *
     1340 * Input parameters:
     1341 *   info - corresponding SessionInfo structure
     1342 *
     1343 * Output parameters:
     1344 *   NONE
     1345 */
     1346static void
     1347command_pwd(FTPD_SessionInfo_t  *info)
    14651348{
    14661349  char buf[FTPD_BUFSIZE];
    1467   char const* cwd = make_path(buf, info->cwd, dir);
    1468   if(cwd && chdir(buf) == 0)
    1469   {
    1470     send_reply(info, 250, "CWD command successful.");
    1471     strcpy(info->cwd, cwd);
    1472   }
    1473   else
    1474   {
    1475     send_reply(info, 550, "CWD command failed.");
    1476   }
    1477 }
    1478 
    1479 
     1350  char const* cwd;
     1351  errno = 0;
     1352  buf[0] = '"';
     1353  cwd = getcwd(buf + 1, FTPD_BUFSIZE - 4);
     1354  if(cwd)
     1355  {
     1356    int len = strlen(cwd);
     1357    static char const txt[] = "\" is the current directory.";
     1358    int size = sizeof(txt);
     1359    if(len + size + 1 >= FTPD_BUFSIZE)
     1360      size = FTPD_BUFSIZE - len - 2;
     1361    memcpy(buf + len + 1, txt, size);
     1362    buf[len + size] = '\0';
     1363    send_reply(info, 250, buf);
     1364  }
     1365  else {
     1366    snprintf(buf, FTPD_BUFSIZE, "Error: %s.", serr());
     1367    send_reply(info, 452, buf);
     1368  }
     1369}
    14801370
    14811371/*PAGE
     
    14981388  char buf[FTPD_BUFSIZE];
    14991389
    1500   if (NULL == make_path(buf, info->cwd, fname) || 0 > stat(buf, &stbuf))
     1390  if (0 > stat(fname, &stbuf))
    15011391  {
    15021392    snprintf(buf, FTPD_BUFSIZE, "%s: %s.", fname, serr());
     
    16151505    else if (0 > listen(s, 1))
    16161506      syslog(LOG_ERR, "ftpd: Error listening on PASV socket: %s", serr());
    1617     else
     1507    else if(set_socket_timeout(s, info->idle))
    16181508    {
    16191509      char buf[FTPD_BUFSIZE];
     
    16281518
    16291519      info->pasv_socket = accept(s, (struct sockaddr *)&addr, &addrLen);
    1630       close_socket(s);
    16311520      if (0 > info->pasv_socket)
    16321521        syslog(LOG_ERR, "ftpd: Error accepting PASV connection: %s", serr());
    16331522      else
     1523      {
     1524        close_socket(s);
     1525        s = -1;
    16341526        err = 0;
     1527      }
    16351528    }
    16361529  }
     
    17471640 *   cmd  - command to be executed (upper-case)
    17481641 *   args - arguments of the command
    1749  *   buf  - beginning of buffer where 'cmd' and 'args' reside.
    17501642 *
    17511643 * Output parameters:
     
    17531645 */
    17541646static void
    1755 exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
     1647exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args)
    17561648{
    17571649  char fname[FTPD_BUFSIZE];
    17581650  int wrong_command = 0;
    17591651
     1652  fname[0] = '\0';
     1653
    17601654  if (!strcmp("PORT", cmd))
    17611655  {
     
    18251719    else if (
    18261720      1 == sscanf(args, "%254s", fname) &&
    1827       NULL != make_path(buf, info->cwd, fname) &&
    1828       unlink(buf) == 0)
     1721      unlink(fname) == 0)
    18291722    {
    18301723      send_reply(info, 257, "DELE successful.");
     
    18491742      else if(
    18501743        2 == sscanf(args, "%o %254s", &mask, fname) &&
    1851         NULL != make_path(buf, info->cwd, fname) &&
    1852         chmod(buf, (mode_t)mask) == 0)
     1744        chmod(fname, (mode_t)mask) == 0)
    18531745      {
    18541746        send_reply(info, 257, "CHMOD successful.");
     
    18701762    else if (
    18711763      1 == sscanf(args, "%254s", fname) &&
    1872       NULL != make_path(buf, info->cwd, fname) &&
    1873       rmdir(buf) == 0)
     1764      rmdir(fname) == 0)
    18741765    {
    18751766      send_reply(info, 257, "RMD successful.");
     
    18881779    else if (
    18891780      1 == sscanf(args, "%254s", fname) &&
    1890       NULL != make_path(buf, info->cwd, fname) &&
    1891       mkdir(buf, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
     1781      mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
    18921782    {
    18931783      send_reply(info, 257, "MKD successful.");
     
    19011791  {
    19021792    sscanf(args, "%254s", fname);
    1903     rtems_ftpd_cwd(info, fname);
     1793    command_cwd(info, fname);
    19041794  }
    19051795  else if (!strcmp("CDUP", cmd))
    19061796  {
    1907     rtems_ftpd_cwd(info, "..");
     1797    command_cwd(info, "..");
    19081798  }
    19091799  else if (!strcmp("PWD", cmd))
    19101800  {
    1911     char const* cwd = "/";
    1912     if(info->cwd[0])
    1913       cwd = info->cwd;
    1914     snprintf(buf, FTPD_BUFSIZE,
    1915       "\"%s\" is the current directory.", cwd);
    1916     send_reply(info, 250, buf);
     1801    command_pwd(info);
    19171802  }
    19181803  else
     
    19441829{
    19451830  FTPD_SessionInfo_t  *const info = (FTPD_SessionInfo_t  *)arg;
     1831  int chroot_made = 0;
     1832
     1833  rtems_libio_set_private_env();
     1834
     1835  /* chroot() can fail here because the directory may not exist yet. */
     1836  chroot_made = chroot(ftpd_root) == 0;
    19461837
    19471838  while(1)
    19481839  {
    19491840    rtems_event_set set;
     1841    char buf[128];
    19501842
    19511843    rtems_event_receive(FTPD_RTEMS_EVENT, RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT,
    19521844      &set);
     1845
     1846    chroot_made = chroot_made || chroot(ftpd_root) == 0;
     1847    chdir("/");
     1848
     1849    errno = 0;
    19531850
    19541851    send_reply(info, 220, FTPD_SERVER_MESSAGE);
     
    19741871      else
    19751872      {
    1976         exec_command(info, cmd, args, buf);
     1873        exec_command(info, cmd, args);
    19771874      }
    19781875    }
     
    20621959            info->ctrl_addr  = addr;
    20631960            info->pasv_socket = -1;
    2064             info->xfer_mode = TYPE_A;
    2065             info->cwd[0] = '\0';
     1961            info->data_socket = -1;
     1962            info->xfer_mode   = TYPE_A;
    20661963            info->data_addr.sin_port =
    20671964              htons(ntohs(info->ctrl_addr.sin_port) - 1);
     
    21502047  }
    21512048
    2152   ftpd_root[0] = '\0';
     2049  ftpd_root = "/";
    21532050  if (
    21542051    rtems_ftpd_configuration.root &&
    2155     strlen(rtems_ftpd_configuration.root) < FTPD_BUFSIZE &&
    2156     rtems_ftpd_configuration.root[0] == '/')
    2157   {
    2158     strcpy(ftpd_root, rtems_ftpd_configuration.root);
    2159     squeeze_path(ftpd_root, NULL);
    2160     rtems_ftpd_configuration.root = ftpd_root;
    2161   }
     2052    rtems_ftpd_configuration.root[0] == '/'
     2053  )
     2054    ftpd_root = rtems_ftpd_configuration.root;
     2055
     2056  rtems_ftpd_configuration.root = ftpd_root;
    21622057
    21632058  syslog(LOG_INFO, "ftpd: FTP daemon started (%d session%s max)",
    21642059    count, ((count > 1) ? "s" : ""));
     2060
    21652061  return RTEMS_SUCCESSFUL;
    21662062}
  • cpukit/libnetworking/ChangeLog

    r1fc16ff r07fbfced  
     12001-01-31        Sergei Organov <osv@javad.ru>
     2
     3        * rtems_servers/ftp.d: Following changes:
     4          - Hacks with current dir and root dir removed in favor of new libio
     5            support for task-local current and root directories.
     6          - Bug in `close_data_socket()' introduced by previous change fixed.
     7          - `command_pasv()' changed to set timeout on socket we are listening
     8            on and code fixed to don't close socket twice on error.
     9          - `serr()' changed to clear `errno'.
     10          - `data_socket()' changed to clear `errno' before `bind()'.
     11          - `session()' changed to clear `errno' before processing session.
     12          - `close_data_socket()' fixed to close both active and passive sockets
     13          - Initialize info->data_socket to -1 in `daemon()'
     14          - Initialize `fname' to empty string  in `exec_command()'
     15
    1162001-02-03      Ralf Corsepius <corsepiu@faw.uni-ulm.de>
    217
Note: See TracChangeset for help on using the changeset viewer.