Toolbox中ls不支持超过2G文件的问题
2016-11-17 09:51
330 查看
一般的嵌入式系统是32位的。所以默认都支持不了超过2G的文件。实测了一下,放一个3G的文件到U盘。然后ls
17:10:16.305:uid=0 gid=0@gold:/mnt/udisk/4g # ls
17:10:18.108: lstat './4gfile.img' failed: Value too largefor defined data type
因为整个系统的升级包是超过2G的,所以需要toolbox能够支持超过2G的文件。上网搜索一下,说如果在32位系统中支持大文件的话,只需要打开一个配置:-D_FILE_OFFSET_BITS=64
在系统中grep了一下,发现系统中有其它模块已经有打开此功能了,所以就参考了一下。拷贝了两个宏定义,放在所有的include之前。
#define_FILE_OFFSET_BITS 64
#define_LARGEFILE64_SOURCE 1
编译了一版,测试,发现不报错,但加-l参数时文件名显示不出来,另外文件大小也是错误的。
15:50:33.112: uid=0gid=0@gold:/mnt/udisk/4g # ls
15:50:34.008: 3gFile.img
15:50:34.008: UPDATE_G.KEY
15:50:34.012: uid=0gid=0@gold:/mnt/udisk/4g # ls -l
15:50:36.116: ----rwxr-x 1000 1023 -551550976 (null)
2016-11-01 10:15
15:50:36.121: ----r-xr-x 1000 1023 0 (null)2016-08-30 15:08
看了一下ls的代码。system/core/toolbox/ls.c,实现比较简单,如果加了-l,会调用listfile_long()这个函数。如果是普通文件,打印是在
case S_IFREG:
printf("%s %-8s %-8s %8ld %s%s\n",
mode, user, group, s.st_size,date, name);
break;
如果超过2G,算了一下,长度应该是10,所以修改了一下此函数。
case S_IFREG:
- printf("%s %-8s %-8s %8ld %s%s\n",
- mode, user, group, s.st_size,date, name);
+ printf("%s %-8s %-8s %10lu %s%s\n",
+ mode, user, group, (unsignedlong)s.st_size, date, name);
break;
再测试,文件名和大小显示正常了。
16:48:14.758: uid=0gid=0@gold:/mnt/udisk/4g # ls -l
16:48:16.286: ----rwxr-x1000 1023 3743416320 2016-11-01 10:15 3gFile.img
16:48:16.291: ----r-xr-x 1000 1023 0 2016-08-30 15:08 UPDATE_G.KEY
但还有点小毛病,就是不对齐。把其它文件格式显示也增加两个空格,问题
4000
解决。本想把这两个宏定义放在Make文件中,但cp.c会提示编译错误:error: #error <fts.h> cannot be used with-D_FILE_OFFSET_BITS==64
暂时就不去解决cp的问题了。所以就把宏定义在单独的工具中。最终的修改如下:
--- a/system/core/toolbox/dd.c
+++ b/system/core/toolbox/dd.c
@@ -33,6 +33,8 @@
*SUCH DAMAGE.
*/
+#define_FILE_OFFSET_BITS 64
+#define_LARGEFILE64_SOURCE 1
#include <sys/cdefs.h>
#ifndef lint
diff --git a/system/core/toolbox/ls.cb/system/core/toolbox/ls.c
index 357c5c7..29bd795 100644 (file)
--- a/system/core/toolbox/ls.c
+++ b/system/core/toolbox/ls.c
@@ -1,3 +1,6 @@
+#define_FILE_OFFSET_BITS 64
+#define_LARGEFILE64_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -101,7 +104,7 @@ static intshow_total_size(const char *dirname, DIR *d, int flags)
struct dirent *de;
char tmp[1024];
struct stat s;
- int sum = 0;
+ int64_t sum = 0;
/* run through the directory and sum up the file block sizes */
while ((de = readdir(d)) != 0) {
@@ -124,7 +127,7 @@ static intshow_total_size(const char *dirname, DIR *d, int flags)
sum += s.st_blocks / 2;
}
- printf("total %d\n", sum);
+ printf("total %lld\n", sum);
rewinddir(d);
return 0;
}
@@ -140,7 +143,7 @@ static int listfile_size(constchar *path, const char *filename, int flags)
/* blocks are 512 bytes, we want output to be KB */
if ((flags & LIST_SIZE) != 0) {
- printf("%ld ", s.st_blocks /2);
+ printf("%lld ", s.st_blocks /2);
}
if ((flags & LIST_CLASSIFY) != 0) {
@@ -202,14 +205,14 @@ static intlistfile_long(const char *path, int flags)
switch(s.st_mode & S_IFMT) {
case S_IFBLK:
case S_IFCHR:
- printf("%s %-8s %-8s %3d, %3d %s%s\n",
+ printf("%s %-8s %-8s %3d, %3d %s %s\n",
mode, user, group,
(int) MAJOR(s.st_rdev), (int)MINOR(s.st_rdev),
date, name);
break;
case S_IFREG:
- printf("%s %-8s %-8s %8ld %s%s\n",
- mode, user, group, s.st_size,date, name);
+ printf("%s %-8s %-8s %10lu %s%s\n",
+ mode, user, group, (unsignedlong)s.st_size, date, name);
break;
case S_IFLNK: {
char linkto[256];
@@ -227,12 +230,12 @@ static int listfile_long(constchar *path, int flags)
linkto[len] = 0;
}
- printf("%s %-8s %-8s %s %s -> %s\n",
+ printf("%s %-8s %-8s %s %s -> %s\n",
mode, user, group, date, name,linkto);
break;
}
default:
- printf("%s %-8s %-8s %s %s\n",
+ printf("%s %-8s %-8s %s %s\n",
mode, user, group, date, name);
}
看了一下代码,dd默认应该是可以支持超过2G的文件的。但在调用dd时好象也会去调用stat相关函数,所以会报同样的错,加上两个宏就可以了。实测可以正常dd操作超过2G的文件。
Toolbox中的ls及dd可以支持2G文件了,但在shell脚本中,if [ -fxxx ] 还不能支持超过2G的文件,还需要查一下。看了一下当前系统的shell,使用的是mksh,文件在externals/mksh目录下,if [ -f xxx ] 的判断应该是在funcs.c文件的test_eval()函数中:
/*-a */
caseTO_FILAXST:
/* -e */
caseTO_FILEXST:
return(stat(opnd1, &b1) == 0);
和之前一样,试着在Makefile中增加两个宏定义,编译出版本测试了一下。问题解决。
@@ -61,6 +61,8 @@ LOCAL_CFLAGS:= -DMKSH_DEFAULT_EXECSHELL=\"/bin/sh\" \
-DHAVE_REVOKE_DECL=1-DHAVE_SYS_SIGLIST_DECL=1 \
-DHAVE_PERSISTENT_HISTORY=0
+LOCAL_CFLAGS +=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1
+
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/bin
17:10:16.305:uid=0 gid=0@gold:/mnt/udisk/4g # ls
17:10:18.108: lstat './4gfile.img' failed: Value too largefor defined data type
因为整个系统的升级包是超过2G的,所以需要toolbox能够支持超过2G的文件。上网搜索一下,说如果在32位系统中支持大文件的话,只需要打开一个配置:-D_FILE_OFFSET_BITS=64
在系统中grep了一下,发现系统中有其它模块已经有打开此功能了,所以就参考了一下。拷贝了两个宏定义,放在所有的include之前。
#define_FILE_OFFSET_BITS 64
#define_LARGEFILE64_SOURCE 1
编译了一版,测试,发现不报错,但加-l参数时文件名显示不出来,另外文件大小也是错误的。
15:50:33.112: uid=0gid=0@gold:/mnt/udisk/4g # ls
15:50:34.008: 3gFile.img
15:50:34.008: UPDATE_G.KEY
15:50:34.012: uid=0gid=0@gold:/mnt/udisk/4g # ls -l
15:50:36.116: ----rwxr-x 1000 1023 -551550976 (null)
2016-11-01 10:15
15:50:36.121: ----r-xr-x 1000 1023 0 (null)2016-08-30 15:08
看了一下ls的代码。system/core/toolbox/ls.c,实现比较简单,如果加了-l,会调用listfile_long()这个函数。如果是普通文件,打印是在
case S_IFREG:
printf("%s %-8s %-8s %8ld %s%s\n",
mode, user, group, s.st_size,date, name);
break;
如果超过2G,算了一下,长度应该是10,所以修改了一下此函数。
case S_IFREG:
- printf("%s %-8s %-8s %8ld %s%s\n",
- mode, user, group, s.st_size,date, name);
+ printf("%s %-8s %-8s %10lu %s%s\n",
+ mode, user, group, (unsignedlong)s.st_size, date, name);
break;
再测试,文件名和大小显示正常了。
16:48:14.758: uid=0gid=0@gold:/mnt/udisk/4g # ls -l
16:48:16.286: ----rwxr-x1000 1023 3743416320 2016-11-01 10:15 3gFile.img
16:48:16.291: ----r-xr-x 1000 1023 0 2016-08-30 15:08 UPDATE_G.KEY
但还有点小毛病,就是不对齐。把其它文件格式显示也增加两个空格,问题
4000
解决。本想把这两个宏定义放在Make文件中,但cp.c会提示编译错误:error: #error <fts.h> cannot be used with-D_FILE_OFFSET_BITS==64
暂时就不去解决cp的问题了。所以就把宏定义在单独的工具中。最终的修改如下:
--- a/system/core/toolbox/dd.c
+++ b/system/core/toolbox/dd.c
@@ -33,6 +33,8 @@
*SUCH DAMAGE.
*/
+#define_FILE_OFFSET_BITS 64
+#define_LARGEFILE64_SOURCE 1
#include <sys/cdefs.h>
#ifndef lint
diff --git a/system/core/toolbox/ls.cb/system/core/toolbox/ls.c
index 357c5c7..29bd795 100644 (file)
--- a/system/core/toolbox/ls.c
+++ b/system/core/toolbox/ls.c
@@ -1,3 +1,6 @@
+#define_FILE_OFFSET_BITS 64
+#define_LARGEFILE64_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -101,7 +104,7 @@ static intshow_total_size(const char *dirname, DIR *d, int flags)
struct dirent *de;
char tmp[1024];
struct stat s;
- int sum = 0;
+ int64_t sum = 0;
/* run through the directory and sum up the file block sizes */
while ((de = readdir(d)) != 0) {
@@ -124,7 +127,7 @@ static intshow_total_size(const char *dirname, DIR *d, int flags)
sum += s.st_blocks / 2;
}
- printf("total %d\n", sum);
+ printf("total %lld\n", sum);
rewinddir(d);
return 0;
}
@@ -140,7 +143,7 @@ static int listfile_size(constchar *path, const char *filename, int flags)
/* blocks are 512 bytes, we want output to be KB */
if ((flags & LIST_SIZE) != 0) {
- printf("%ld ", s.st_blocks /2);
+ printf("%lld ", s.st_blocks /2);
}
if ((flags & LIST_CLASSIFY) != 0) {
@@ -202,14 +205,14 @@ static intlistfile_long(const char *path, int flags)
switch(s.st_mode & S_IFMT) {
case S_IFBLK:
case S_IFCHR:
- printf("%s %-8s %-8s %3d, %3d %s%s\n",
+ printf("%s %-8s %-8s %3d, %3d %s %s\n",
mode, user, group,
(int) MAJOR(s.st_rdev), (int)MINOR(s.st_rdev),
date, name);
break;
case S_IFREG:
- printf("%s %-8s %-8s %8ld %s%s\n",
- mode, user, group, s.st_size,date, name);
+ printf("%s %-8s %-8s %10lu %s%s\n",
+ mode, user, group, (unsignedlong)s.st_size, date, name);
break;
case S_IFLNK: {
char linkto[256];
@@ -227,12 +230,12 @@ static int listfile_long(constchar *path, int flags)
linkto[len] = 0;
}
- printf("%s %-8s %-8s %s %s -> %s\n",
+ printf("%s %-8s %-8s %s %s -> %s\n",
mode, user, group, date, name,linkto);
break;
}
default:
- printf("%s %-8s %-8s %s %s\n",
+ printf("%s %-8s %-8s %s %s\n",
mode, user, group, date, name);
}
看了一下代码,dd默认应该是可以支持超过2G的文件的。但在调用dd时好象也会去调用stat相关函数,所以会报同样的错,加上两个宏就可以了。实测可以正常dd操作超过2G的文件。
Toolbox中的ls及dd可以支持2G文件了,但在shell脚本中,if [ -fxxx ] 还不能支持超过2G的文件,还需要查一下。看了一下当前系统的shell,使用的是mksh,文件在externals/mksh目录下,if [ -f xxx ] 的判断应该是在funcs.c文件的test_eval()函数中:
/*-a */
caseTO_FILAXST:
/* -e */
caseTO_FILEXST:
return(stat(opnd1, &b1) == 0);
和之前一样,试着在Makefile中增加两个宏定义,编译出版本测试了一下。问题解决。
@@ -61,6 +61,8 @@ LOCAL_CFLAGS:= -DMKSH_DEFAULT_EXECSHELL=\"/bin/sh\" \
-DHAVE_REVOKE_DECL=1-DHAVE_SYS_SIGLIST_DECL=1 \
-DHAVE_PERSISTENT_HISTORY=0
+LOCAL_CFLAGS +=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1
+
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/bin
相关文章推荐
- 工作笔记-Outlook Express dbx文件超过2G导致邮件丢失问题的处理
- 解决TCP/UDP传输文件时不能超过2G大小的问题
- 工作笔记-Outlook Express dbx文件超过2G导致邮件丢失问题的处理
- [代码]Delphi实现获取文件及文件夹大小(支持超过2G的大文件)
- Outlook Express dbx文件超过2G导致邮件丢失问题的处理
- 2个小问题:Struts2 国际化支持和下载文件的开发思路
- Serv-U 8 不支持以中文命名文件上传问题的解决
- 解决Android单个dex文件不能超过65536个方法问题
- 关于获得文件超过2G,超过4G文件大小的方法
- aix无法创建2G以上大文件的问题
- Aix 下打开超过2G的文件
- Apache+PHP,swfupload做批量上传时遇到的文件类型支持问题和文件上传大小限制问题的相应解决方案
- AIX/linux/unix fopen 打开2G文件问题
- 解决Struts中ApplicationResources.properties文件不支持中文问题
- mongodb 32位系统下不支持超过2G的数据库
- 关于在eclipse中解决struts中ApplicationResources.properties文件的中文支持问题
- HP-unix支持大于2G的文件的配置方法
- 文件编码、charset、sublime编辑器支持GBK等问题
- outlook express 经常崩溃2G文件问题
- 关于“打开项目**时发生问题,尝试退出并重新启动应用程序。如果问题仍然存在,则可能是由于正在使用不支持的项目版本,或者项目文件可能损坏”的问题的解决办法。