access_ok | 检查用户空间内存块是否可用

access_ok()函数详解
本文详细介绍了access_ok()函数的用途及其替代verify_area()的原因。该函数用于验证用户空间指针的有效性,确保指定地址范围内的内存块可以进行读取或写入操作。文中提供了具体的函数原型及使用示例。
access_ok() 函数是用来代替老版本的 verify_area() 函数的。它的作用也是检查用户空间指针是否可用。

函数原型
access_ok (type, addr, size);

变量说明
type   :   访问类型,其值可为 VERIFY_READ 或者 VERIFY_WRITE 。注意,VERIFY_WRITE 是 VERIFY_READ 的超集 -- 如果可以安全的写内存块,那么自然也总能读到内存块。

addr    用户空间的指针变量,其指向一个要检查的内存块开始处。

size   :   要检查内存块的大小。

返回值
此函数检查用户空间中的内存块是否可用。如果可用,则返回真(非0值),否则返回假 (0) 。

代码片段
if (_IOC_DIR(cmd& _IOC_READ)
    err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd& _IOC_WRITE)
    err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
if (err)
    return -EFAULT;
/****************************************************************************** * Copyright (c) 2020-2020 TP-Link Technologies CO.,LTD. * * Filename: sd_backup.c * Version: 1.0 * Description: SD卡固件备份源文件 * Author: He Shunzhan <heshunzhan@tp-link.com.cn> * Date: 2021-1-12 ******************************************************************************/ #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/statfs.h> #include <errno.h> #include "common.h" #include "sd_backup.h" #define SD_EXTRA_RESERVER_MEM (32 * 1024 * 1024) /* 32M */ #define SD_DEVICE_NAME "/dev/mmcblk0" /* SD卡设备名 */ #define SD_MOUNT_DIR "/tmp/mnt/harddisk_1/" /* SD卡挂载目录 */ #define SD_FIRMWARE_PATH "/tmp/mnt/harddisk_1/firmware_upboot_backup.bin" /* SD卡固件备份路径 */ /****************************************************************************** * 函数名称: full_safe_write() * 函数描述: 重写write函数,确保写固件操作完整且安全 * 输 入: fd--文件描述符 * buf--升级固件的缓存起始地址 * len--固件大小 * 输 出: N/A * 返 回 值: 成功,返回写入的数据大小;失败,返回-1 ******************************************************************************/ LOCAL ssize_t full_safe_write(int fd, const void *buf, size_t len) { ssize_t len_write = 0; ssize_t len_left = 0; /* 剩余待写入数据长度 */ ssize_t len_total = 0; /* 成功写入数据的总长度 */ const void* buf_ptr = NULL; if ((fd < 0) || (NULL == buf) || (len <= 0)) { return ERROR; } len_left = len; buf_ptr = buf; while (len_left) { do { len_write = write(fd, buf_ptr, len_left); } while ((len_write < 0) && (errno == EINTR)); /* 写数据失败 */ if (len_write <= 0) { /* 若已写入部分数据,则返回已写入数据长度;否则,返回错误码-1 */ if(len_total) { return len_total; } return len_write; } len_total += len_write; buf = ((const char *)buf_ptr) + len_write; len_left -= len_write; } return len_total; } /****************************************************************************** * 函数名称: sd_recovery_check_sd_avail() * 函数描述: 检查SD卡状态:是否在线、是否挂载、能否读写等 * 输 入: fw_size--固件大小 * 输 出: N/A * 返 回 值: 成功,返回0;失败,返回-1 ******************************************************************************/ LOCAL S32 sd_recovery_check_sd_avail(S32 fw_size) { struct statfs sd_info = {0}; U64 block_size = 0; U64 avail_size = 0; #ifndef MASK_LOW_LEVEL_LOG U64 total_size = 0; U64 free_size = 0; #endif if (fw_size <= 0) { return ERROR; } /* 检查SD卡设备是否在线 */ if (0 != access(SD_DEVICE_NAME, F_OK)) { UPGRADE_ERROR("can't find sd/mmc device: %s", SD_DEVICE_NAME); return ERROR; } /* 检查SD卡挂载目录 */ if (0 != access(SD_MOUNT_DIR, F_OK | R_OK | W_OK | X_OK)) { UPGRADE_ERROR("sdcard check mount dir fail: %s ([%d] %s)", SD_MOUNT_DIR, errno, strerror(errno)); return ERROR; } /* 获取SD卡文件系统的统计信息 */ if (0 != statfs(SD_MOUNT_DIR, &sd_info)) { return ERROR; } block_size = sd_info.f_bsize; avail_size = block_size * sd_info.f_bavail; #ifndef MASK_LOW_LEVEL_LOG total_size = block_size * sd_info.f_blocks; free_size = block_size * sd_info.f_bfree; UPGRADE_DEBUG("sdcard(bytes): total %llu, free %llu, available %llu \nfw_size: %d", total_size, free_size, avail_size, fw_size); #endif /* 判断SD卡可用内存是否足够 */ if (avail_size < SD_EXTRA_RESERVER_MEM + fw_size) { UPGRADE_ERROR("sdcard available memory not enough!"); return ERROR; } return OK; } /****************************************************************************** * 函数名称: sd_recovery_write_fw() * 函数描述: 将升级固件写入SD卡根目录 * 输 入: buf--升级固件的缓存起始地址 * len--固件大小 * 输 出: N/A * 返 回 值: 错误码,OK表示写入成功,ERROR表示写入失败 ******************************************************************************/ LOCAL S32 sd_recovery_write_fw(U8 *buf, S32 len) { S32 fd = -1; if ((NULL == buf) || (len <= 0)) { UPGRADE_ERROR("invalid parameter"); return ERROR; } /* 先删除上次保存的固件备份文件 */ if (0 == access(SD_FIRMWARE_PATH, F_OK)) { if (0 != unlink(SD_FIRMWARE_PATH)) { UPGRADE_ERROR("delete %s fail ([%d] %s)", SD_FIRMWARE_PATH, errno, strerror(errno)); return ERROR; } } /* 创建并打开固件备份文件,O_SYNC防止写入固件不完整 */ fd = open(SD_FIRMWARE_PATH, O_RDWR | O_CREAT | O_SYNC, 0777); if (fd < 0) { UPGRADE_ERROR("fail to create and open %s ([%d] %s)", SD_FIRMWARE_PATH, errno, strerror(errno)); return ERROR; } /* 向SD卡写入固件文件 */ if (len != full_safe_write(fd, buf, len)) { UPGRADE_ERROR("fail to write firmware %s ([%d] %s)", SD_FIRMWARE_PATH, errno, strerror(errno)); close(fd); return ERROR; } close(fd); return OK; } /****************************************************************************** * 函数名称: sd_recovery_save_fw() * 函数描述: 将升级固件备份到SD卡 * 输 入: buf--升级固件的缓存起始地址 * len--固件大小 * 输 出: N/A * 返 回 值: 错误码,OK表示备份成功,ERROR表示备份失败 ******************************************************************************/ S32 sd_recovery_save_fw(U8 *buf, S32 len) { if ((NULL == buf) || (len <= 0)) { UPGRADE_ERROR("invalid parameter"); return ERROR; } if (OK != sd_recovery_check_sd_avail(len)) /* 检查SD卡 */ { goto error_out; } if (OK != sd_recovery_write_fw(buf, len)) /* 固件备份到SD卡 */ { goto error_out; } UPGRADE_ERROR("firmware sdcard backup success!"); return OK; error_out: UPGRADE_ERROR("firmware sdcard backup fail!"); return ERROR; }
最新发布
09-08
/* * fn char * io_getCmdLine(char * pBuffer, unsigned int * pSize); * * brief get a command line from console. * * param[in/out]pBuffer -- retrieve command buffer * param[in/out]pSize -- buffer size is valid when pBuffer isn't NULL. * * return the pointer to the buffer. After you call this function, you * should use this pointer to access buffer data. * retval NULL -- failed * retval non-NULL -- success */ char * io_getCmdLine(char * pBuffer, unsigned int * pSize) { unsigned int nInputIdx = 0; int nLinkFlag = MINI_CODE_ERROR; char ch = 0; char * pRetBuffer = NULL; int ret = 0; struct termios termConfig; tcgetattr(0 /*STDIN_FILENO*/, &termConfig); termConfig.c_lflag &= ~ICANON; /* disable canonical mode */ termConfig.c_lflag &= ~ECHO; /* disable echo */ termConfig.c_lflag &= ~ECHONL; /* disable echo NL */ termConfig.c_lflag &= ~ISIG; /* disable terminal signal, CTRL-C */ tcsetattr(0 /*STDIN_FILENO*/, TCSANOW, &termConfig); if (NULL == pBuffer) { pBuffer = (char *) malloc (sizeof(char) * MINI_DEFAULT_BUFF_SIZE); *pSize = MINI_DEFAULT_BUFF_SIZE; /* malloc failed */ if (NULL == pBuffer) { return NULL; } } pRetBuffer = pBuffer; memset(pRetBuffer, 0, *pSize); while(1) { ch = getchar(); ret = io_parseKey(ch, pBuffer, *pSize, &nInputIdx); if (io_isStoreKeyCode(ret) || (IO_KC_ENTER == ret && nLinkFlag == MINI_CODE_ERROR)) { /* we still have space */ if (nInputIdx < *pSize) { pBuffer[nInputIdx++] = ch; } else { /* not enough space, expand it */ pRetBuffer = io_expandBuffer(pBuffer, *pSize + MINI_DEFAULT_BUFF_SIZE); if (NULL == pRetBuffer) { goto GET_CMD_LINE_QUIT_FLAG; } memset(pRetBuffer + *pSize, 0, MINI_DEFAULT_BUFF_SIZE); (*pSize) += MINI_DEFAULT_BUFF_SIZE; pBuffer = pRetBuffer; pBuffer[nInputIdx++] = ch; CS_DEBUGH("string(%s)", pRetBuffer); } nLinkFlag = MINI_CODE_ERROR; /* input over, break while(1) */ if (IO_KC_ENTER == ret) { nInputIdx--; pBuffer[nInputIdx] = '\0'; break; } } else if (IO_KC_LINK == ret && nLinkFlag == MINI_CODE_ERROR) { /* conjunction symbol. mark it but don't save it */ nLinkFlag = MINI_CODE_OK; } else if (IO_KC_ENTER == ret && nLinkFlag == MINI_CODE_OK) { /* use conjunction symbol to input another comand line. Skip it */ nLinkFlag = MINI_CODE_ERROR; } } CS_DEBUGH("Read cmd Line: %s\n", pRetBuffer); GET_CMD_LINE_QUIT_FLAG: tcgetattr(0 /*STDIN_FILENO*/, &termConfig); termConfig.c_lflag |= ICANON; /* enable canonical mode */ termConfig.c_lflag |= ECHO; /* enable echo */ termConfig.c_lflag |= ECHONL; /* enable echo NL */ termConfig.c_lflag |= ISIG; /* enable terminal signal, CTRL-C */ tcsetattr(0 /*STDIN_FILENO*/, TCSANOW, &termConfig); return pRetBuffer; } ret = io_parseKey(ch, pBuffer, *pSize, &nInputIdx);解释这几个参数ch pBuffer *pSize &nInputldx
09-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值