Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1256203
  • 博文数量: 548
  • 博客积分: 7597
  • 博客等级: 少将
  • 技术积分: 4224
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-15 13:21
个人简介

嵌入式软件工程师&&太极拳

文章分类

全部博文(548)

文章存档

2014年(10)

2013年(76)

2012年(175)

2011年(287)

分类: 嵌入式

2012-01-07 10:45:49

3 vsftpd 移植
         vsftpd 的移植费尽周折,一开始遇到错误 500 OOPS: vsftpd: cannot locate user
specified in ftp_username:ftp,
凭以往的经验,就是 /etc/vsftpd.conf 或/etc/passwd , /etc/group 等 的配置问题然而
反反复复跌跌撞撞不停地修改配置,
最后还是回到了原点。实在逼得山穷水尽了, 没办法,只有分析代码了!
         在源码目录中 sysutil.c 文件定义了结构体 vsf_sysutil_user,然而却没有主动实
现其定义(有哪些成员变量啊等等),编译
器没报错,那是因为在代码中对 struct, vsf_sysutil_user 的引用只是引用了指针形式,
如下代码所示
#######################################################################
#include
20 struct ppa;
21 int main()
22 {
23      int a;
24       struct ppa *p= (struct ppa *)&a;
25        return 0;
26 }
#######################################################################

追踪其调用流程,找到如下函数:
struct vsf_sysutil_user*
vsf_sysutil_getpwnam(const char* p_user)
{
   return (struct vsf_sysutil_user*) getpwnam(p_user);
}
看样子作者的意思是将 libc 中函数调用中 getpwnam 的返回值(struct password *)传给
vsf_sysutil_user ,也就是说
struct vsf_sysutil_user 其实对 struct password 作了虚拟映射,来实现 作者代码函数
形式的统一(都是 vsf_前缀)。
然后就突发奇想, 是不是 getpwnam 函数调用出了问题了呢? 编写测试程序如下:
#######################################################################
#include
#include
int main(int ac, char * av[])
{
     struct passwd * pw;
     char *username = "root";
     pw = getpwnam(username);
     if (!pw) {
           printf("%s is not exist\n", username);
           return -1;
     }
     printf("pw->pw_name       = %s\n", pw->pw_name);
     printf("pw->pw_passwd = %s\n", pw->pw_passwd);
     printf("pw->pw_uid        = %d\n", pw->pw_uid);
     printf("pw->pw_gid        = %d\n", pw->pw_gid);
     printf("pw->pw_gecos = %s\n", pw->pw_gecos);
     printf("pw->pw_dir        = %s\n", pw->pw_dir);
     printf("pw->pw_shell = %s\n", pw->pw_shell);
     return 0;
}
#######################################################################

下到板子上运行 测试,不管用户名是什么,总是返回:
xxx is not exist !
认真 检查 /etc/passwd /etc/group /etc/shadow /etc/nsswitch.conf 等文件都没问题
(直接从主机 copy 到板子上都不行),
总之,libc 中的函数调用 getpwnam 总返回 NULL !
那可以在代码中验证用户的时候直接给服务器一个指定用户,用不着再调用 getnam, 试了
好久,把返回 struct vsf_util_user *
的函数都替换掉了,可惜函数调用的关系 太复杂,搞不清哪个 libc 中的无效调用还未修
改!登陆时总是返回 service not avaliable !
崩溃的感觉就如连绵江水,涛涛不绝!
为什么 libc 中的函数调用 getpwnam 总返回 NULL 呢? 到网上去查,busybox 的作者好
像也避开了此问题,它的源码中自己改写了
帐户管理的库 libpwdgrp,而没用标准 libc 中的帐户管理 API, 从网上找到 busybox 改写
的 getpwnam 等 API
地址http://busybox-cvs.sourcearchive.com/documentation/20040623/dir_fe9411c1513842ef0aae9ea9305e6e1d.html
把改写后的 API: getpwnam,作了个测试:
#######################################################################
#include
#include
#include
#include
#include "pwd.h"
#include
#define PWD_BUFFER_SIZE 256
char bb_path_passwd_file[]="/etc/passwd" ;
struct passwd *__getpwent(int pwd_fd)
{
        。。。。 详见下方
}
struct passwd *getpwnam(const char *name)
{
        。。。。 详见下方
}
int main(int ac, char * av[])
{
      struct passwd * pw;
      char *username = "root";
     pw = getpwnam(username);
     if (!pw) {
           printf("%s is not exist\n", username);
           return -1;
     }
     printf("pw->pw_name         = %s\n", pw->pw_name);
     printf("pw->pw_passwd = %s\n", pw->pw_passwd);
     printf("pw->pw_uid          = %d\n", pw->pw_uid);
     printf("pw->pw_gid          = %d\n", pw->pw_gid);
     printf("pw->pw_gecos = %s\n", pw->pw_gecos);
    printf("pw->pw_dir            = %s\n", pw->pw_dir);
    printf("pw->pw_shell = %s\n", pw->pw_shell);
    return 0;
}
#######################################################################
成功返回了帐户信息! 我看行! 于是把 busybox 中的几个帐户管理 API 移植到 vsftpd
下, 反复尝试,成功了!
登陆信息如下:
#ftp 192.168.0.51
Connected to 192.168.0.51 (192.168.0.51).
220 (vsFTPd 2.1.0)
Name (192.168.0.51:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
修改过程如下:
首先在 sysutil.h 中增加函数声明

#######################################################################
int setgroups(size_t size, const gid_t * list);
struct passwd *__getpwent(int pwd_fd);
struct passwd *getpwuid(uid_t uid);
struct group *getgrgid(const gid_t gid);
#######################################################################
然后在 sysutil.c 中增加函数定义
#######################################################################
#define PWD_BUFFER_SIZE 256
char bb_path_passwd_file[]="/etc/passwd" ;
struct passwd *__getpwent(int pwd_fd)
{
       static char line_buff[PWD_BUFFER_SIZE];
       static struct passwd passwd;
       char *field_begin;
        char *endptr;
        char *gid_ptr=NULL;
        char *uid_ptr=NULL;
        int line_len;
        int i;
        /* We use the restart label to handle malformatted lines */
        restart:
        /* Read the passwd line into the static buffer using a minimal of
syscalls.
*/
        if ((line_len = read(pwd_fd, line_buff, PWD_BUFFER_SIZE)) <= 0)
                return NULL;
        field_begin = strchr(line_buff, '\n');
        if (field_begin != NULL)
                lseek(pwd_fd, (long) (1 + field_begin - (line_buff +
line_len)),SEEK_CUR);
        else
           {                                              /* The line is too long -
skip
it. :-\ */
                do
                {
                       if ((line_len = read(pwd_fd, line_buff, PWD_BUFFER_SIZE)) <=
0)
                                       return NULL;
                } while (!(field_begin = strchr(line_buff, '\n')));
                lseek(pwd_fd, (long) (field_begin - line_buff) - line_len +
1,SEEK_CUR);
                goto restart;
        }
        if (*line_buff == '#' || *line_buff == ' ' || *line_buff == '\n' ||*line_buff ==
'\t')
                goto restart;
        *field_begin = '\0';
        /* We've read the line; now parse it. */
        field_begin = line_buff;
        for (i = 0; i < 7; i++)
        {
                 switch (i)
                 {
                       case 0:
                               passwd.pw_name = field_begin;
                               break;
                      case 1:
                               passwd.pw_passwd = field_begin;
                               break;
                      case 2:
                               uid_ptr = field_begin;
                               break;
                      case 3:
                               gid_ptr = field_begin;
                               break;
                      case 4:
                      passwd.pw_gecos = field_begin;
                               break;
                      case 5:
                               passwd.pw_dir = field_begin;
                               break;
                      case 6:
                               passwd.pw_shell = field_begin;
                               break;
               }
               if (i < 6)
                   {
                      field_begin = strchr(field_begin, ':');
                      *field_begin++ = '\0';
               }
      }
      passwd.pw_gid = (gid_t) strtoul(gid_ptr, &endptr, 10);
      if (*endptr != '\0')
               passwd.pw_uid = (uid_t) strtoul(uid_ptr, &endptr, 10);
      if (*endptr != '\0')
               goto restart;
      return &passwd;
}
struct passwd *getpwnam(const char *name)
{
      int passwd_fd;
      struct passwd *passwd;
      if (name == NULL)
      {
               errno = EINVAL;
               return NULL;
      }
      if ((passwd_fd = open(bb_path_passwd_file, O_RDONLY)) < 0)
               return NULL;
      while ((passwd = __getpwent(passwd_fd)) != NULL)
               if (!strcmp(passwd->pw_name, name))
               {
                       close(passwd_fd);
                       return passwd;
               }
      close(passwd_fd);
      return NULL;
}
struct passwd *getpwuid(uid_t uid)
{
      int passwd_fd;
         struct passwd *passwd;
         if ((passwd_fd = open("/etc/passwd", O_RDONLY)) < 0)
                 return NULL;
         while ((passwd = __getpwent(passwd_fd)) != NULL)
                 if (passwd->pw_uid == uid) {
                          close(passwd_fd);
                          return passwd;
                  }
         close(passwd_fd);
         return NULL;
}
int setgroups(size_t size, const gid_t * list)
{
        // return(syscall(__NR_setgroups, size, list));
        return 0;
}
#######################################################################

vsftpd 移植总结
1) 下载 vsftpd-2.1.0.tar.gz,解压并在 shell 中进入目录
2)修改文件 vsf_fildlibs.sh

' /lib/' 全都替换成' /usr/local/arm/3.4.1/arm-linux/lib/'
' /usr/lib' 全都替换成 ' /usr/local/arm/3.4.1/arm-linux/lib/'
3)修改 builddefs.h 将
#define VSF_BUILD_PAM 改成 #undef VSF_BUILD_PAM
4) 修改 Makefile ,将 CC 改成
CC        =         /usr/local/arm/3.4.1/bin/arm-linux-gcc
5) 如上所示在 sysutl 文件中添加 4 个帐户管理的函数(屏蔽 libc 中的调用)
int setgroups(size_t size, const gid_t * list);
struct passwd *__getpwent(int pwd_fd);
struct passwd *getpwuid(uid_t uid);
struct group *getgrgid(const gid_t gid);
6)make
7) 编写 vsftpd.conf 并下到板子上去
vsftpd.conf 如下
#######################################################################
anonymous_enable=YES
local_enable=NO
write_enable=YES
local_umask=022
anon_upload_enable=YES
anon_mkdir_write_enable=YES
dirmessage_enable=NO
xferlog_enable=YES
connect_from_port_20=YES
chown_uploads=YES
anon_root=/
xferlog_file=/var/log/vsftpd.log
pam_service_name=vsftpd
listen=YES
secure_chroot_dir=/tmp/empty
#######################################################################

8)生成的 vsftpd 放在根文件系统下 sbin 目录中, 在 rcS 中添加启动代码和目录创建
#######################################################################
touch /var/log/vsftpd.log
mkdir -p /tmp/empty
vsftpd &
#######################################################################

五 zlib,libpng,libjpeg,opencv tslib, Qt 移植
        移植目标意在构建一个 Qt+OpenCV 共享库环境.其中 libpng,libjpeg 为 OpenCV 的
依赖库,而 zlib 为 libpng 的依赖库, tslib 为 Qt 的触摸屏校准所依赖的
其中 zlib,libpng,libjpeg,opencv,tslib 安装目录为/usr/local/arm ,而 Qt 安装路径
为/usr/local/Qt, 有关 configue 配置详细信息请参考 ./configure --help
1 前期准备
      系统环境: Fedora 8
      hostcc: gcc 4.1.2
     crosscc: arm-linux-gcc 3.4.1
      首先在/usr/local/arm 下建立相关目录:
      mkdir -p /usr/local/arm/include /usr/local/arm/lib /usr/local/arm/man /usr/local/arm/ man/man1 /usr/local/arm/bin
2 zlib 移植
      源码版本:zlib-1.2.3.tar.gz
      安装路径: /usr/local/arm/
      配置及安装
#######################################################################
export CC=arm-linux-gcc &&./configure --shared --prefix=/usr/local/arm --
exec_prefix=/usr/local/arm/bin --libdir=/usr/local/arm/lib --
includedir=/usr/local/arm/include && make && make install

#######################################################################

3 libpng移植
      源码版本: libpng-1.2.35.tar.bz2
      安装路径: /usr/local/arm
      配置及安装
#######################################################################
./configure --libdir=/usr/local/arm/lib --includedir=/usr/local/arm/include --
host=arm-linux --enable-shared CC=arm-linux-gcc --prefix=/usr/local/arm
CFLAGS=-I/usr/local/arm/include LIBS=-L/usr/local/arm/lib && make && make
install
#
#######################################################################

4 libjpeg 移植
      源码版本:jpegsrc.v6b.tar.gz
       安装路径 : /usr/local/arm
       配置及安装:
             直接用 arm-linux-gcc 编译将会出现错误:
         ./libtool --mode=compile arm-linux-gcc -O2 -I. -c ./jcapimin.c
          make: ./libtool:命令未找到
             原因: ./configure 时若指定 CC=arm-linux-gcc 则不会在工程目录下生成
libtool(即使生成了也不能在主机端运行),所以必须先用主机的环境 configure 一遍,生成
libtool,然后再指定 CC=arm-linux-gcc 进行配置编译安装:
#######################################################################
./configure --enable-shared
./configure --libdir=/usr/local/arm/lib --includedir=/usr/local/arm/include --
host=arm-linux --enable-shared CC=arm-linux-gcc --prefix=/usr/local/arm/ &&
make && make install
#######################################################################

5 opencv 移植
       源码版本: opencv-1.0.0.tar.gz
       安装路径: /usr/local/arm
       配
       配置及安装
             直接编译会有有关文件 cvpyrsegmentation.cpp 的提示错误,需要修改源代码:
(参考:)
             进入 opencv-1.0.0/cv/src/ 目录,打开 cvpyrsegmentation.cpp
修改函数 icvPyrSegmentation8uC3R (只是一个 check 的作用很少用到) 的内容,将所有函数
实体都去掉,直接返回 CV_OK
             然后再:
#######################################################################
./configure --host=arm-linux --without-gtk --without-carbon --without-
quicktime --without-1394libs --without-ffmpeg --without-python --without-swig
--enable-static --enable-shared --disable-apps CXX=arm-linux-g++ CPPFLAGS=-
I/usr/local/arm/include LDFLAGS=-L/usr/local/arm/lib --with-v4l --
prefix=/usr/local/arm --libdir=/usr/local/arm/lib --
includedir=/usr/local/arm/include && make && make install
#######################################################################

configure 后的信息如下:
#######################################################################
     Install path:            /usr/local/arm
General configuration ================================================
     Compiler:                 arm-linux-g++
     CXXFLAGS:                  -Wall -fno-rtti -pipe -O3 -fomit-frame-pointer
     Install path:               /usr/local/arm
HighGUI configuration ================================================
H
     Windowing system --------------
     Use Carbon / Mac OS X:       no
     Use gtk+ 2.x:               no
     U
     Use gthread:                no
     Image I/O ---------------------
     Use libjpeg:                yes
     Use zlib:                   yes
     Use libpng:                 yes
     Use libtiff:                no
     Use libjasper:              no
     U
     Use libIlmImf:              no
     Video I/O ---------------------
     Use QuickTime / Mac OS X: no
     Use xine:                    no
     Use ffmpeg:                  no
     Use dc1394 & raw1394:       no
     Use v4l:                     yes
     U
     Use v4l2:                    yes
Wrappers for other languages =========================================
     SWIG
     P
     Python                        no
Additional build settings ============================================
     Build demo apps              no
#######################################################################

6 tslib 移植
       源码版本:        tslib-1.0.tar.bz2
       安装路径: /usr/local/arm
       配置及安装:
#######################################################################
./autogen.sh
     C
./configure --prefix=/usr/local/arm --libdir=/usr/local/arm/lib --
includedir=/usr/local/arm/include         --host=arm-linux
ac_cv_func_malloc_0_nonnull=yes && make && make install
#######################################################################

7 qte4 移植
      源码版本:              qt-embedded-linux-opensource-src-4.4.3.tar.gz
      安装路径: /usr/local/Qt
      配置及安装:
#######################################################################
./configure -prefix /usr/local/Qt         -release -shared -fast -pch -no-qt3support -
qt-sql-sqlite -no-libtiff -no-libmng -qt-libjpeg -qt-zlib -qt-libpng -qt-
freetype -no-openssl -nomake examples -nomake demos -nomake tools -optimized-
qmake -no-phonon -no-nis -no-opengl -no-cups -no-xcursor -no-webkit -no-
xfixes -no-xrandr -no-xrender -no-xkb -no-sm -no-xinerama -no-xshape -no-
separate-debug-info -xplatform qws/linux-arm-g++ -embedded arm -depths 16 -no-
qvfb -qt-gfx-linuxfb -no-gfx-qvfb -no-kbd-qvfb -no-mouse-qvfb -qt-kbd-usb
-confirm-license -qt-mouse-tslib -I/usr/local/arm/include -L/usr/local/arm/lib
#
#######################################################################

      configure 后显示信息:
#######################################################################
Debug ............... no
Qt 3 compatibility .. no
QtDBus module ....... no
QtXmlPatterns module no
Phonon module ....... no
SVG module .......... yes
WebKit module ....... no
WebKit in Assistant          no
STL support ......... yes
PCH support ......... yes
MMX/3DNOW/SSE/SSE2.. no/no/no/no
iWMMXt support ...... no
IPv6 support ........ yes
IPv6 ifname support . yes
getaddrinfo support . yes
getifaddrs support .. yes
Accessibility ....... yes
NIS support ......... no
CUPS support ........ no
Iconv support ....... no
Glib support ........ no
GStreamer support ... auto
Large File support .. yes
GIF support ......... plugin
TIFF support ........ plugin (no)
JPEG support ........ plugin (qt)
PNG support ......... yes (qt)
MNG support ......... plugin (no)
zlib support ........ yes
Embedded support .... arm
Freetype2 support ... yes
Graphics (qt) ....... linuxfb multiscreen linuxfb
Graphics (plugin) ...
Decorations (qt) .... styled windows default
Decorations (plugin)
Keyboard driver (qt). tty usb
Keyboard driver (plugin)
Mouse driver (qt) ... pc linuxtp tslib
Mouse driver (plugin)
OpenGL support ...... no
SQLite support ...... qt (qt)
OpenSSL support ..... no
#
#######################################################################

六 Qt+OpenCv库的复制和环境变量的配置
由于大部分库在编译时安装于目录 /usr/local/arm/lib 下,可以创建shell 脚本方便地复制
#######################################################################
#!/bin/bash
LIB_PATH=/usr/local/arm/3.4.1/arm-linux/lib
CUR_PATH=`pwd`
QT_LIB_PATH=/usr/local/Qt/lib
EXTRA_LIB_PATH=/usr/local/arm/lib
DST=$1

if [ $1 = "" ]
then DST=./
fi
echo "copy Qt libs....."
mkdir -p $DST/usr/lib $DST/usr/local/Qt/lib/fonts
cp     $QT_LIB_PATH/fonts/wenquanyi_160_75.qpf $DST/usr/local/Qt/lib/fonts/wenquanyi_160_75.qpf
cd $QT_LIB_PATH
for file in libQtCore libQtGui libQtNetwork libQtScript libQtSvg libQtXml
do
    cp -a $file*so* $DST/usr/lib/

done
echo "..........done!"
echo "copy extra libs......"
cd $EXTRA_LIB_PATH
for file in libz libts libml libpng libhighgui libcxcore libcv libcvaux libjpeg
do
    cp -a $file*so* $DST/usr/lib/
done
mkdir -p $DST/usr/lib/ts
cp -a ts/*so* $DST/usr/lib/ts/
arm-linux-strip $DST/usr/lib/*so*
arm-linux-strip $DST/usr/lib/ts/*so*
arm-linux-strip $DST/lib/*so*
echo "..........done!"
#######################################################################

环境变量的添加,在/etc/profile 下添加
#######################################################################
export QTDIR=/usr
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
export QT_QWS_FONTDIR=$QTDIR/local/Qt/lib/fonts
#######################################################################

七 小结
      
       本文件系统实现了 busybox+bash+ftp+vsftpd+telnetd+zlib,png,jpeg,tslib,opencv,qte4
的移植,已通过一个Qt+OpenCv 控制摄像头程序的测试
系统启动 IP 为 192.168.0.51
       vsftpd 服务只允许匿名用户 ftp 访问,密码为空
       telnetd 服务只允许 root 用户访问,密码也为空
       有问题请联系 QQ:547268476 Email:supertiger@yahoo.cn

http://hi.baidu.com/hzau_wall_e/blog/item/1c2bd462d458a5680c33facd.html
阅读(843) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~