66// our own file functions allows us to provide transparent support of
77// different line endings, gzip'd print files, etc.
88//
9- // Copyright © 2021-2023 by OpenPrinting.
9+ // Copyright © 2021-2024 by OpenPrinting.
1010// Copyright © 2007-2019 by Apple Inc.
1111// Copyright © 1997-2007 by Easy Software Products, all rights reserved.
1212//
@@ -53,7 +53,7 @@ struct _cups_file_s // CUPS file structure...
5353
5454static bool cups_compress (cups_file_t * fp , const char * buf , size_t bytes );
5555static ssize_t cups_fill (cups_file_t * fp );
56- static int cups_open (const char * filename , int mode );
56+ static int cups_open (const char * filename , int oflag , int mode );
5757static ssize_t cups_read (cups_file_t * fp , char * buf , size_t bytes );
5858static bool cups_write (cups_file_t * fp , const char * buf , size_t bytes );
5959
@@ -611,6 +611,9 @@ cupsFileNumber(cups_file_t *fp) // I - CUPS file
611611// supplied which enables Flate compression of the file. Compression is
612612// not supported for the "a" (append) mode.
613613//
614+ // When opening for writing ("w") or append ("a"), an optional 'm###' suffix
615+ // can be used to set the permissions of the opened file.
616+ //
614617// When opening a socket connection, the filename is a string of the form
615618// "address:port" or "hostname:port". The socket will make an IPv4 or IPv6
616619// connection as needed, generally preferring IPv6 connections when there is
@@ -626,30 +629,38 @@ cupsFileOpen(const char *filename, // I - Name of file
626629 char hostname [1024 ], // Hostname
627630 * portname ; // Port "name" (number or service)
628631 http_addrlist_t * addrlist ; // Host address list
632+ int perm = 0664 ; // Permissions for write/append
633+ const char * ptr ; // Pointer into mode string
629634
630635
631636 // Range check input...
632637 if (!filename || !mode || (* mode != 'r' && * mode != 'w' && * mode != 'a' && * mode != 's' ) || (* mode == 'a' && isdigit (mode [1 ] & 255 )))
633638 return (NULL );
634639
640+ if ((ptr = strchr (mode , 'm' )) != NULL && ptr [1 ] >= '0' && ptr [1 ] <= '7' )
641+ {
642+ // Get permissions from mode string...
643+ perm = (int )strtol (mode + 1 , NULL , 8 );
644+ }
645+
635646 // Open the file...
636647 switch (* mode )
637648 {
638649 case 'a' : // Append file
639- fd = cups_open (filename , O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY );
650+ fd = cups_open (filename , O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY , perm );
640651 break ;
641652
642653 case 'r' : // Read file
643654 fd = open (filename , O_RDONLY | O_LARGEFILE | O_BINARY , 0 );
644655 break ;
645656
646657 case 'w' : // Write file
647- fd = cups_open (filename , O_WRONLY | O_LARGEFILE | O_BINARY );
658+ fd = cups_open (filename , O_WRONLY | O_LARGEFILE | O_BINARY , perm );
648659 if (fd < 0 && errno == ENOENT )
649660 {
650- fd = cups_open (filename , O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE | O_BINARY );
661+ fd = cups_open (filename , O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE | O_BINARY , perm );
651662 if (fd < 0 && errno == EEXIST )
652- fd = cups_open (filename , O_WRONLY | O_LARGEFILE | O_BINARY );
663+ fd = cups_open (filename , O_WRONLY | O_LARGEFILE | O_BINARY , perm );
653664 }
654665
655666 if (fd >= 0 )
@@ -1748,7 +1759,8 @@ cups_fill(cups_file_t *fp) // I - CUPS file
17481759
17491760static int // O - File descriptor or -1 otherwise
17501761cups_open (const char * filename , // I - Filename
1751- int mode ) // I - Open mode
1762+ int oflag , // I - Open flags
1763+ int mode ) // I - Open permissions
17521764{
17531765 int fd ; // File descriptor
17541766 struct stat fileinfo ; // File information
@@ -1758,7 +1770,7 @@ cups_open(const char *filename, // I - Filename
17581770
17591771
17601772 // Open the file...
1761- if ((fd = open (filename , mode , 0666 )) < 0 )
1773+ if ((fd = open (filename , oflag , mode )) < 0 )
17621774 return (-1 );
17631775
17641776 // Then verify that the file descriptor doesn't point to a directory or hard-linked file.
0 commit comments