]> git.sven.stormbind.net Git - sven/exfat-utils.git/blobdiff - libexfat/io.c
New upstream version 1.2.7
[sven/exfat-utils.git] / libexfat / io.c
index 514383ca4bedb64bf12ed4a28c6e4bbf3c87d6f6..63ccfdbfdf9cc02e21cda76f38840bbdf9a7d751 100644 (file)
@@ -45,6 +45,11 @@ struct exfat_dev
        off_t size; /* in bytes */
 };
 
+static bool is_open(int fd)
+{
+       return fcntl(fd, F_GETFD) != -1;
+}
+
 static int open_ro(const char* spec)
 {
        return open(spec, O_RDONLY);
@@ -75,6 +80,24 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
        struct exfat_dev* dev;
        struct stat stbuf;
 
+       /* The system allocates file descriptors sequentially. If we have been
+          started with stdin (0), stdout (1) or stderr (2) closed, the system
+          will give us descriptor 0, 1 or 2 later when we open block device,
+          FUSE communication pipe, etc. As a result, functions using stdin,
+          stdout or stderr will actualy work with a different thing and can
+          corrupt it. Protect descriptors 0, 1 and 2 from such misuse. */
+       while (!is_open(STDIN_FILENO)
+               || !is_open(STDOUT_FILENO)
+               || !is_open(STDERR_FILENO))
+       {
+               /* we don't need those descriptors, let them leak */
+               if (open("/dev/null", O_RDWR) == -1)
+               {
+                       exfat_error("failed to open /dev/null");
+                       return NULL;
+               }
+       }
+
        dev = malloc(sizeof(struct exfat_dev));
        if (dev == NULL)
        {
@@ -289,7 +312,7 @@ ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node,
                return 0;
 
        cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb));
-       if (CLUSTER_INVALID(cluster))
+       if (CLUSTER_INVALID(*ef->sb, cluster))
        {
                exfat_error("invalid cluster 0x%x while reading", cluster);
                return -EIO;
@@ -299,7 +322,7 @@ ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node,
        remainder = MIN(size, node->size - offset);
        while (remainder > 0)
        {
-               if (CLUSTER_INVALID(cluster))
+               if (CLUSTER_INVALID(*ef->sb, cluster))
                {
                        exfat_error("invalid cluster 0x%x while reading", cluster);
                        return -EIO;
@@ -345,7 +368,7 @@ ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node,
                return 0;
 
        cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb));
-       if (CLUSTER_INVALID(cluster))
+       if (CLUSTER_INVALID(*ef->sb, cluster))
        {
                exfat_error("invalid cluster 0x%x while writing", cluster);
                return -EIO;
@@ -355,7 +378,7 @@ ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node,
        remainder = size;
        while (remainder > 0)
        {
-               if (CLUSTER_INVALID(cluster))
+               if (CLUSTER_INVALID(*ef->sb, cluster))
                {
                        exfat_error("invalid cluster 0x%x while writing", cluster);
                        return -EIO;