samba移植到android

参考了网上一篇文章,开始编译不过,一直报错undefine的错误,后面参考另一篇文章,发现前篇文章里的

--host= 和--target= 写得不对,错误帖子害死人哪!!!


本文中使用的源码是samba-3.5.22,交叉编译工具是公司自有的编译器。

本文件中使用的路径为相对于源码根目录的路径。
第一步要修改一下源码,不然不能正常运行,因为在android中不知什么原因getpwnam等不能使用的,总是失败。

lib/system.c
中的4个函数
struct passwd *sys_getpwnam(const char *name)
struct passwd *sys_getpwuid(uid_t uid)
struct group *sys_getgrnam(const char *name)
struct group *sys_getgrgid(gid_t gid)

改为:
static struct passwd rootpw = {
     "root",
     "root",
     0,
     0,
     "root",
     "/root"
     "/system/bin/sh",
};
struct passwd *sys_getpwnam(const char *name)
{
//    return getpwnam(name);
     return &rootpw;
}

struct passwd *sys_getpwuid(uid_t uid)
{
//    return getpwuid(uid);
     return &rootpw;
}

static char *rootmem[] = {
     "root"
};
static struct group rootgr = {
     "root",
     "root",
     0,
     rootmem,
};

struct group *sys_getgrnam(const char *name)
{
     return &rootgr;
//    return getgrnam(name);
}

struct group *sys_getgrgid(gid_t gid)
{
     return &rootgr;
//    return getgrgid(gid);
}


配置脚本:

#!/bin/bash

#这个根据自己编译器的情况要改下。

CROSS_COMPILE=/home/wzh/work/cross/4.4.3/bin/arm-none-linux-gnueabi-  
RUNTIME_DIR=/data/data/samba
./configure \
CC="$CROSS_COMPILE"gcc \
AR="$CROSS_COMPILE"ar \
LD="$CROSS_COMPILE"ld \
RANLIB="$CROSS_COMPILE"ranlib \
--host=i686 \
--target=arm-linux \
--disable-cups \
--disable-iprint \
--prefix=$RUNTIME_DIR \
--exec-prefix=$RUNTIME_DIR \
--with-logfilebase=$RUNTIME_DIR/var/log \
--with-swatdir=$RUNTIME_DIR/usr/local/swat \
--with-rootsbindir=$RUNTIME_DIR/sbin \
--with-lockdir=$RUNTIME_DIR/var/lock \
--with-piddir=$RUNTIME_DIR/var/lock \
--with-privatedir=$RUNTIME_DIR/etc/samba \
--with-configdir=$RUNTIME_DIR/etc/samba \
--cache-file=armsel-linux.cache \
--with-static-modules=vfs_fake_perms \

把它放到source3目录下执行。

执行该编译脚本过程中会出现问题,如下:
       3.1 error: cannot run test program while cross compiling错误
           checking that the C compiler understands negative enum values... configure: error: in `/root/samba-3.3.3/source':
           configure: error: cannot run test program while cross compiling


解决方法:
echo samba_cv_CC_NEGATIVE_ENUM_VALUES=yes>armsel-linux.cache

再一下执行脚本

然后在source3目录下执行:
make LDFLAGS="-all-static -static"

上面这外是为把smbd, nmbd等编译为静态的。(不然在Android上执行会出现 no such file or directory问题

对于samba的配置文件在:
/data/data/samba/etc/samba/smb.conf
内容如下:
[global]
interfaces =  wlan0 eth0 lo
workgroup = WORKGROUP
server string = Samba on Android
netbios name = ANDROID
remote announce = 255.255.255.255
encrypt passwords = yes
security = USER
restrict anonymous = 1
load printers = no
printcap name = /dev/null
disable spoolss = yes
deadtime = 5
delete readonly = yes
nt acl support = no
inherit permissions = yes
socket options = SO_SNDBUF=16384 SO_RCVBUF=16384
[sdcard]
vfs objects = fake_perms
comment = Android /mnt/sdcard
path = /mnt/sdcard
force user = root
read only = no
writable = yes
guest ok = no


注意下面这几行:
vfs objects = fake_perms
force user = root

samba的环境设置:

注意配置脚本中的:
RUNTIME_DIR=/data/data/samba

创建几个文件夹:
mkdir /data/data/samba/etc
mkdir /data/data/samba/var/log
mkdir /data/data/samba/var/lock
mkdir /data/data/samba/lib
mkdir /data/data/samba/etc/samba
mkdir /tmp

/tmp这个目录是必须的,不然看不到共享目录。
这个目录应该可以放到任一位置。
这个目录可能通过下面的命令来指定:
export TMPDIR=/data/data/samba/var/tmp/

在lib/util/util.c
中有这样的函数:
_PUBLIC_ const char *tmpdir(void)
{
    char *p;
    if ((p = getenv("TMPDIR")))
        return p;
    return "/tmp";
}

创建几个空文件:
/data/data/samba/etc/printcap
/data/data/samba/lib/valid.dat

要用编译生成的程序:
nmbd
smbd
smbpasswd
testparm

使用时首先要用smbpasswd新加一个用户,不然,在共享目录下不然看到文件夹。

$smbdpasswd -a root

$nmbd -D

$smbd -D

 

======================

为什么要加s

为什么用system 和popen调不起来

http://os.chinaunix.net/a2007/0429/960/000000960387.shtml

应用的话,可以参考Samba Filesharing,google play 可以下载。

 

    内核会给每个进程关联两个和进程ID无关的用户ID,一个是真实用户ID,还有一个是有效用户ID或者称为setuid(set user ID)。真实用户ID用于标识由谁为正在运行的进程负责。有效用户ID用于为新创建的文件分配所有权、检查文件访问许可,还用于通过kill系统调用向其它进程发送信号时的许可检查。内核允许一个进程以调用exec一个setuid程序或者显式执行setuid系统调用的方式改变它的有效用户ID

    所谓setuid程序是指一个设置了许可模式字段中的setuid bit的可执行文件。当一个进程exec一个setuid程序的时候,内核会把进程表以及u区中的有效用户ID设置成该文件所有者的ID。为了区分这两个字段,我们把进程表中的那个字段称作保存用户ID。可以通过一个例子来演示这两个字段的区别。

    setuid系统调用的语法是 setuid(uid) ,其中,uid是新的用户ID,该系统调用的结果取决于有效用户ID的当前值。

如果调用进程的有效用户ID是超级用户,内核会把进程表以及u区中真实有效用户ID都设置成uid。

如果调用进程的有效用户ID不是超级用户,仅当uid等于真实用户ID保存用户ID时,内核才会把u区中的有效用户ID设置成uid。否则,该系统调用将返回错误。一般来说,一个进程会在fork系统调用期间从父进程那儿继承它的真实和有效用户ID,这些数值即使经过exec系统调用也会保持不变。

    存储在u区中的有效用户ID是最近一次setuid系统调用或是exec一个setuid程序的结果;只有它会被用于文件访问许可。进程表中的保存用户ID使得一个进程可以通过执行setuid系统调用把有效用户ID设置成它的值,以此来恢复最初的有效用户ID。

.......

     一个用户还可以通过调用setuid或setgid来改变它的凭证。超级用户可以通过这些系统调用改变真实的和有效的UID以及GID。普通用户则只能通过这些调用来把它们的有效UID或GID改回到真实的数值。

 

========================================================

我觉得,关于setuid权限这个东西,应该详细说明下,很多人都并不够了解。

1. ls -l显示出来的这个叫做suid位,就是如rwS-r-x-r-x这样中的S(故意大写了)。
当S出现在所有用户的执行位时,其他凡是对此文件有执行权的用户执行时权限自动提升为所有者的权限。
LZ的问题是SH不具备suid位的权限,但为什么不能让sh具备suid位权限呢?
很显然,/bin/sh的所属用户是root,当其具备suid位权限的时候,任何能执行/bin/sh的用户都是root。
另:suid位改变的是执行用户的euid,这可以通过简单的程序来看出。

2. 系统api里有setuid(2)以及setgid(2)以及seteuid(2)等系统调用。作用同样是改变程序执行时的所属权限,但这些跟suid位有什么区别呢?
简要说明一下两者的大部分用途:
  * suid位大多用于提升权限;
  * setuid(2)等调用大多用于降低权限;
setuid(2)这些调用是只有root用户才能执行成功的,普通用户执行包含了setuid(2)的程序时,是不会成功的。原因很简单:
如果一个普通用户都能随便更改自己的执行权限到其它用户,那么系统中出现一些问题也不知道是谁干的。

实例程序分析:su工具:
  su工具具备了suid位,程序代码中还包括了setuid(2)等调用,何故?
  su工具用途是用来切换用户权限的,而且可以在任何用户之间切换:
  纯粹的suid位是解决不了多用户权限切换的,总不至于频繁更改程序的所属用户吧。
  而api中的setuid(2)能解决多用户切换问题,可是普通用户没有权限执行啊......
  两者结合呢?让su用户有suid位的权限,再通过setuid(2)切换用户权限,如此:
  先用户执行su的时候具备root权限,再接着有权执行setuid(2)切换到自己想要的用户的权限......
  如果看su的源码,会发现其中有对文件系统mount时时候挂载了suid特性的检测,由此你会了解到setuid特性可以在mount的-o中关闭掉。
  具体可以参考man 2 setuid,man mount等等。

你可能感兴趣的:(samba移植到android)