0

我要疯了。我正在尝试编写一个可以存储和提取文件的存档库。存档文件如下所示:

<0,/home/user/file.txt,154,0755>
file contents (154 byte)

每个文件都由一个标头( <...> )标识,有四个“标签”(用逗号分隔)、文件类型(0 代表文件,1 代表目录)、路径、字节大小、权限(八进制)。我使用 stat 系统调用(我在 Linux 上)检索大小和权限。我的问题是我必须将八进制值从 st_mode 转换为字符串,将其存储在存档文件中(标题中的第四个标签),然后将其提取并与 chmod 系统调用一起使用。

要将其转换为字符串,我使用:

char mode[6];
sprintf (mode, "%o", statr.st_mode);

并检索它我使用 atoi,但它似乎不起作用。例如,存储在第 4 个标签中的值是 100644,但是 chmod 设置的权限错误(我的用户无法读取文件)。

我不确定我是否解释得很好,如果需要,我会发布整个代码(但它认为没有实现问题,只是从八进制转换为字符串之间的问题)

编辑:解决了!实际上 strtol 方法有效,但我也忘记将它应用于目录(因此,由于错误文件夹的权限掩码,提取包含文件的目录导致 Segfault)。谢谢大家的帮助!

4

3 回答 3

1

据我所知,没有一个unix标准函数可以做到这一点。

您很可能必须进行掩码st_mode以获取所需的每个权限位并将其转换为对您有意义的内容。

相关帖子

可能有一种更简单的方法可以做到这一点,但我提供了一个简单的示例,该示例展示了如何获取您感兴趣的每一位。这确实可以编译并且似乎可以按预期运行。

st_mode.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


#define SET_UID_BIT     0x4000
#define SET_GID_BIT     0x2000
#define STICKY_BIT      0x1000

// Readable USER bits defined here
#define USR_READ_BIT    0x400
#define USR_WRITE_BIT   0x200
#define USR_EXEC_BIT    0x100

// Readable GROUP bits defined here
#define GRP_READ_BIT    0x040
#define GRP_WRITE_BIT   0x020
#define GRP_EXEC_BIT    0x010

// Readable OTHER bits defined here
#define OTH_READ_BIT    0x004
#define OTH_WRITE_BIT   0x002
#define OTH_EXEC_BIT    0x001


int main()
{
    // The file I'm opening
    const char fp[] = "myfile.txt"; // -rw-rw-r--
    struct stat stats;

    // Get the stats
    if ( 0 == stat( fp, &stats ) )
    {
        // store st_mode
        mode_t mode = stats.st_mode;
        // init printable_mode
        unsigned int printable_mode = 0;        


        // Test for each permission bit in mode.
        // If the bit is present, mark the corresponding bit in printable_mode
        // using defined bits above.
        if( mode & S_ISUID )
        printable_mode |= SET_UID_BIT;

        if( mode & S_ISGID )
        printable_mode |= SET_GID_BIT;

        if( mode & S_ISVTX )
        printable_mode |= STICKY_BIT;

        if( mode & S_IRUSR )
        printable_mode |= USR_READ_BIT;

        if( mode & S_IWUSR )
        printable_mode |= USR_WRITE_BIT;

        if( mode & S_IXUSR )
        printable_mode |= USR_EXEC_BIT;

        if( mode & S_IRGRP )
        printable_mode |= GRP_READ_BIT;

        if( mode & S_IWGRP )
        printable_mode |= GRP_WRITE_BIT;

        if( mode & S_IXGRP )
        printable_mode |= GRP_EXEC_BIT;

        if( mode & S_IROTH )
        printable_mode |= OTH_READ_BIT;

        if( mode & S_IWOTH )
        printable_mode |= OTH_WRITE_BIT;

        if( mode & S_IXOTH )
        printable_mode |= OTH_EXEC_BIT;

        // Let's see what it looks like....
        printf("%04x\n", printable_mode);
        printf("%x\n", mode);
    }

    return 0;
}
于 2012-07-26T14:10:16.427 回答
0

使用 strtoul。例如,以下测试程序正确解释“100644”(八进制)。转换后,*endptr指向第一个转换的字符。如果*endptr == 0,则整个字符串已被消耗,否则会出现错误(例如,使用“1234X”调用 strtoul 会在“X”处停止)。请注意,八进制 10644 等于 33188(十进制)。

#include <stdlib.h>
#include <stdio.h>

int main() {

   char *s = "100644";
   char *endptr;

   unsigned long result = strtoul(s, &endptr, 8);

   if (*endptr)
      printf("conversion error!\n");

   printf("result: %lu == octal %lo\n", result, result);

   return 0;
}
于 2012-07-26T14:24:20.393 回答
0

如果您以八进制格式写入数据并带有前导0,则可以使用以下命令读取它strtol

char mode[8];
snprintf(mode, 8, "0%o", statr.st_mode);
strtol(mode, NULL, 0);

或者,您可以使用strtol提供8作为base参数来阅读它,在这种情况下,前导0是不必要的:

char mode[7];
snprintf(mode, 8, "%o", statr.st_mode);
strtol(mode, NULL, 8);
于 2012-07-26T14:23:13.393 回答