移植ftp客户端到A1200

来源:互联网 发布:墨尔本大学 知乎 编辑:程序博客网 时间:2024/05/12 23:26

A1200的samba不是很稳定,现在有一个FTP服务器的软件,今天移植了个FTP的客户端到1200上

1. 下载一个inetutils的源代码包,我是从Cygwin上下载的,可以去www.cygwin.com上找一个镜像下载即可,文件inetutils-1.5-4.src.tar.tar解压后有个文件是inetutils-1.5.tar.gz,这个是1.5版本的源文件,还有一个文件是补丁inetutils-1.5-4.src.patch

2. 将inetutils-1.5-4.tar.gz解压到任意一个目录

$tar xvf inetutils-1.5-4.tar.gz

然后,进入到然后后的inetutil-1.5目录,打补丁

$ cd inetutils-1.5
$ patch -p2 < inetutils-1.5-4.src.patch

3. 我本来想使用里面的自动配置文件配置的,看起来比较长,修改起来也很费劲,因为这个包里的很多命令工具并用不着,ifconfig,ping在A1200里已经有了,我只想移植FTP,就对症下药了,其它的都不管。进到inetutils-1.5/ftp目录,然后创建两个文件

xinc.h文件,这个文件摘录了在ftp的源代码里面用到的几个函数,这些函数在inetutils-1.5/lib目录中,因为用到的比较少,却编译整个库,不如摘出来编译快。还有一些是必要的宏,根据编译时的需要一个个加的,文件内容:

/*
* xinc.h
* created by nocky for the ftp project
* Nocky Tian
* 2008-09-20
*/
#ifndef FTP_XINC_H
#define FTP_XINC_H

#ifdef USE_MYINC
////////////////////////////////////////////////////////////
#ifndef RETSIGTYPE
    #define RETSIGTYPE    void
#endif

////////////////////////////////////////////////////////////
// configuration
#define HAVE_STDARG_H

#define ARG_UNUSED

#ifndef PATH_TMP
    #define    PATH_TMP    "/tmp/"
#endif
#ifndef PATH_BSHELL
    #define    PATH_BSHELL    "/bin/sh"
#endif

#define PACKAGE_NAME "GNU inetutils"
#define PACKAGE_TARNAME "inetutils"
#define PACKAGE_VERSION "1.5"
#define PACKAGE_STRING "GNU inetutils 1.5"
#define PACKAGE_BUGREPORT "nocky.tian@gmail.com"

// from lib/xgetcwd.h
extern char *xgetcwd (void);

////////////////////////////////////////////////
// from lib/xalloc.h
# include

# ifdef __cplusplus
extern "C" {
# endif

# ifndef __attribute__
#  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
#   define __attribute__(x)
#  endif
# endif

#define ATTRIBUTE_NORETURN        // nocky
# ifndef ATTRIBUTE_NORETURN
#  define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
# endif

/* This function is always triggered when memory is exhausted.
   It must be defined by the application, either explicitly
   or by using gnulib's xalloc-die module.  This is the
   function to call when one wants the program to die because of a
   memory allocation failure.  */
extern void xalloc_die (void) ATTRIBUTE_NORETURN;

void *xmalloc (size_t s);
void *xnmalloc (size_t n, size_t s);
void *xzalloc (size_t s);
void *xcalloc (size_t n, size_t s);
void *xrealloc (void *p, size_t s);
void *xnrealloc (void *p, size_t n, size_t s);
void *x2realloc (void *p, size_t *pn);
void *x2nrealloc (void *p, size_t *pn, size_t s);
void *xmemdup (void const *p, size_t s);
char *xstrdup (char const *str);

/* Return 1 if an array of N objects, each of size S, cannot exist due
   to size arithmetic overflow.  S must be positive and N must be
   nonnegative.  This is a macro, not an inline function, so that it
   works correctly even when SIZE_MAX < N.

   By gnulib convention, SIZE_MAX represents overflow in size
   calculations, so the conservative dividend to use here is
   SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
   However, malloc (SIZE_MAX) fails on all known hosts where
   sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
   exactly-SIZE_MAX allocations on such hosts; this avoids a test and
   branch when S is known to be 1.  */
# define xalloc_oversized(n, s) /
    ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))

# ifdef __cplusplus
}
# endif
////////////////////////////////////////////////////////////
#endif
#endif

然后,再创建一个源代码文件,xsrc.c,文件内容:

/*
* xrc.h
* 从lib, libinetutil中的文件中摘出来,以独立该程序
* Nocky Tian
* 2008-09-20
*/
#include "xinc.h"
#include
#include
// required by xgetcwd
void xalloc_die (void) ATTRIBUTE_NORETURN
{
     fprintf(stderr, "memory exhausted/n");
}
////////////////////////////////////////////////////
// from lib/xgetcwd.c
/* Return the current directory, newly allocated.
   Upon an out-of-memory error, call xalloc_die.
   Upon any other type of error, return NULL.  */

char *
xgetcwd (void)
{
  char *cwd = getcwd (NULL, 0);
  if (! cwd && errno == ENOMEM)
    xalloc_die ();
  return cwd;
}

/////////////////////////////////////////////////////////
// from lib/xalloc.c
#include
#include

#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif

/* Allocate an array of N objects, each with S bytes of memory,
   dynamically, with error checking.  S must be nonzero.  */

static inline void *
xnmalloc_inline (size_t n, size_t s)
{
  void *p;
  if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0))
    xalloc_die ();
  return p;
}

void *
xnmalloc (size_t n, size_t s)
{
  return xnmalloc_inline (n, s);
}

/* Allocate N bytes of memory dynamically, with error checking.  */

void *
xmalloc (size_t n)
{
  return xnmalloc_inline (n, 1);
}

/* Change the size of an allocated block of memory P to an array of N
   objects each of S bytes, with error checking.  S must be nonzero.  */

static inline void *
xnrealloc_inline (void *p, size_t n, size_t s)
{
  if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
    xalloc_die ();
  return p;
}

void *
xnrealloc (void *p, size_t n, size_t s)
{
  return xnrealloc_inline (p, n, s);
}

/* Change the size of an allocated block of memory P to N bytes,
   with error checking.  */

void *
xrealloc (void *p, size_t n)
{
  return xnrealloc_inline (p, n, 1);
}

/* If P is null, allocate a block of at least *PN such objects;
   otherwise, reallocate P so that it contains more than *PN objects
   each of S bytes.  *PN must be nonzero unless P is null, and S must
   be nonzero.  Set *PN to the new number of objects, and return the
   pointer to the new block.  *PN is never set to zero, and the
   returned pointer is never null.

   Repeated reallocations are guaranteed to make progress, either by
   allocating an initial block with a nonzero size, or by allocating a
   larger block.

   In the following implementation, nonzero sizes are doubled so that
   repeated reallocations have O(N log N) overall cost rather than
   O(N**2) cost, but the specification for this function does not
   guarantee that sizes are doubled.

   Here is an example of use:

     int *p = NULL;
     size_t used = 0;
     size_t allocated = 0;

     void
     append_int (int value)
       {
     if (used == allocated)
       p = x2nrealloc (p, &allocated, sizeof *p);
     p[used++] = value;
       }

   This causes x2nrealloc to allocate a block of some nonzero size the
   first time it is called.

   To have finer-grained control over the initial size, set *PN to a
   nonzero value before calling this function with P == NULL.  For
   example:

     int *p = NULL;
     size_t used = 0;
     size_t allocated = 0;
     size_t allocated1 = 1000;

     void
     append_int (int value)
       {
     if (used == allocated)
       {
         p = x2nrealloc (p, &allocated1, sizeof *p);
         allocated = allocated1;
       }
     p[used++] = value;
       }

   */

static inline void *
x2nrealloc_inline (void *p, size_t *pn, size_t s)
{
  size_t n = *pn;

  if (! p)
    {
      if (! n)
    {
      /* The approximate size to use for initial small allocation
         requests, when the invoking code specifies an old size of
         zero.  64 bytes is the largest "small" request for the
         GNU C library malloc.  */
      enum { DEFAULT_MXFAST = 64 };

      n = DEFAULT_MXFAST / s;
      n += !n;
    }
    }
  else
    {
      if (SIZE_MAX / 2 / s < n)
    xalloc_die ();
      n *= 2;
    }

  *pn = n;
  return xrealloc (p, n * s);
}

void *
x2nrealloc (void *p, size_t *pn, size_t s)
{
  return x2nrealloc_inline (p, pn, s);
}

/* If P is null, allocate a block of at least *PN bytes; otherwise,
   reallocate P so that it contains more than *PN bytes.  *PN must be
   nonzero unless P is null.  Set *PN to the new block's size, and
   return the pointer to the new block.  *PN is never set to zero, and
   the returned pointer is never null.  */

void *
x2realloc (void *p, size_t *pn)
{
  return x2nrealloc_inline (p, pn, 1);
}

/* Allocate S bytes of zeroed memory dynamically, with error checking.
   There's no need for xnzalloc (N, S), since it would be equivalent
   to xcalloc (N, S).  */

void *
xzalloc (size_t s)
{
  return memset (xmalloc (s), 0, s);
}

/* Clone an object P of size S, with error checking.  There's no need
   for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
   need for an arithmetic overflow check.  */

void *
xmemdup (void const *p, size_t s)
{
  return memcpy (xmalloc (s), p, s);
}

/* Clone STRING.  */

char *
xstrdup (char const *string)
{
  return xmemdup (string, strlen (string) + 1);
}

4. 在ftp几个文件中加入对头文件xinc.h的引用

#include "xinc.h"

另外,在ruserpass.c中引用了hostname( )函数调用,好像在A1200的库中没有这个函数,于是把它给省掉了,改成如下代码

#ifdef NO_LOCALHOST_FUN
    myname=xstrdup("A1200");
#else
  myname = localhost ();
#endif

你随便给一个吧。

5. 写个Makefile,内容如下:

EZX_BASE=/home/Guest/moto/dev-ezx-0.2.0
XPREFIX=arm-linux-
CXX=$(XPREFIX)g++
CC=$(XPREFIX)gcc -g -O2 -DUSE_MYINC -DNO_LOCALHOST_FUN
STRIP=$(XPREFIX)strip
CXXFLAGS=-fno-exceptions -fno-rtti -DQWS -Wall -g
MOC=$(EZX_BASE)/moc/moc
INCLUDE=-I/home/Guest/moto/app/inetutils-1.5/libinetutils -I../lib #-I$(EZX_BASE)/include/qt -I$(EZX_BASE)/include/ezx
LIBDIRS=#-L$(EZX_BASE)/lib -L$(EZX_BASE)/lib/ezx/lib
##LIBS=-lezxappbase -lezximagebase -lezxjpeg -lipp-jp -lipp-miscGen -lqte-mt
LIBS= #-lezxappsdk -lezxappbase #-lqte-mt #-lezxjpeg -lezxpm -lipp-jp -lezxopenwindow -lipp-miscGen
OBJS=cmds.o cmdtab.o domacro.o ftp.o main.o ruserpass.o xsrc.o
APP=ftp1200

all: $(APP)

clean:
    rm -f $(OBJS) $(APP) *.moc
%.o: %.c
    $(CC)  $(INCLUDE) -c $<
%.moc: %.c
    $(MOC) $< -o $@
$(APP): $(OBJS)
    $(CC) $^ -o $@ $(LIBDIRS) $(LIBS)

其中,=/home/Guest/moto/dev-ezx-0.2.0是交叉编译环境SDK的目录,实际用不到,留着便于基于QT的开发, 编译输出为二进制文件ftp1200,随便放到A1200上的某个位置执行就OK了

有一个问题就是USBLAN能不能设置网关,如果能够设置网关,然后将PC的外网连接共享,A1200就可以上网了,看了一下ifconfig的帮助输出没有发现设置网关的,也可能对ifconfig而且,在PC上的虚拟USBLAN一旦设成静态IP,连telnet都上不去,不知道什么原因,如果能再设置一下通过PC上网就更爽了

原创粉丝点击